Deepvest/ProfilingAI
0
1import React, { useState } from 'react';2 3interface ProfileData {4 // Informations personnelles5 age: string;6 annual_income: string;7 monthly_savings: string;8 family_status: string;9 dependents: number;10 11 // Profil d'investissement12 risk_tolerance: number;13 investment_horizon: number;14 financial_knowledge: number;15 income_stability: number;16 17 // Objectifs et préférences18 investment_goals: string[];19 life_events: string[];20 investment_preferences: {21 esg: boolean;22 crypto: boolean;23 real_estate: boolean;24 alternative: boolean;25 };26 27 // Situation financière28 total_assets: string;29 total_debt: string;30}31 32interface UserProfileFormProps {33 onSubmit: (data: ProfileData) => Promise<void>;34}35 36const UserProfileForm: React.FC<UserProfileFormProps> = ({ onSubmit }) => {37 const [formData, setFormData] = useState<ProfileData>({38 age: '',39 annual_income: '',40 monthly_savings: '',41 family_status: 'single',42 dependents: 0,43 risk_tolerance: 3,44 investment_horizon: 5,45 financial_knowledge: 3,46 income_stability: 3,47 investment_goals: [],48 life_events: [],49 investment_preferences: {50 esg: false,51 crypto: false,52 real_estate: false,53 alternative: false54 },55 total_assets: '',56 total_debt: ''57 });58 59 const [error, setError] = useState('');60 const [success, setSuccess] = useState(false);61 62 // Options pour les sélections63 const investmentGoals = [64 'Retraite',65 'Achat immobilier', 66 'Études enfants',67 'Création entreprise',68 'Épargne générale',69 'Revenus passifs',70 'Croissance patrimoine'71 ];72 73 const lifeEvents = [74 'Mariage prévu',75 'Naissance attendue',76 'Changement emploi',77 'Déménagement',78 'Héritage attendu',79 'Projet entrepreneurial'80 ];81 82 const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {83 const { name, value, type } = e.target;84 const checked = type === 'checkbox' ? (e.target as HTMLInputElement).checked : undefined;85 86 if (name.startsWith('investment_preferences.')) {87 const preference = name.split('.')[1];88 setFormData(prev => ({89 ...prev,90 investment_preferences: {91 ...prev.investment_preferences,92 [preference]: checked93 }94 }));95 return;96 }97 98 if (type === 'checkbox') {99 const array = name === 'investment_goals' ? 'investment_goals' : 'life_events';100 setFormData(prev => ({101 ...prev,102 [array]: checked103 ? [...prev[array], value]104 : prev[array].filter(item => item !== value)105 }));106 return;107 }108 109 setFormData(prev => ({ ...prev, [name]: value }));110 };111 112 const handleSubmit = async (e: React.FormEvent) => {113 e.preventDefault();114 try {115 setError('');116 setSuccess(false);117 118 if (parseInt(formData.age) < 18) {119 setError('Vous devez avoir au moins 18 ans');120 return;121 }122 123 await onSubmit(formData);124 setSuccess(true);125 } catch (err) {126 setError(err instanceof Error ? err.message : 'Une erreur est survenue');127 }128 };129 130 return (131 <div className="max-w-4xl mx-auto bg-white shadow-lg rounded-lg">132 <div className="p-6">133 <h2 className="text-2xl font-semibold mb-6">Votre Profil Investisseur</h2>134 135 <form onSubmit={handleSubmit} className="space-y-8">136 {/* Section 1: Informations personnelles */}137 <div>138 <h3 className="text-lg font-medium mb-4">Informations personnelles</h3>139 <div className="grid grid-cols-1 md:grid-cols-2 gap-4">140 <div>141 <label className="block text-sm font-medium mb-1">142 Âge143 <input144 type="number"145 name="age"146 value={formData.age}147 onChange={handleChange}148 className="mt-1 block w-full rounded"149 required150 />151 </label>152 </div>153 <div>154 <label className="block text-sm font-medium mb-1">155 Revenu annuel (€)156 <input157 type="number"158 name="annual_income"159 value={formData.annual_income}160 onChange={handleChange}161 className="mt-1 block w-full rounded"162 required163 />164 </label>165 </div>166 <div>167 <label className="block text-sm font-medium mb-1">168 Situation familiale169 <select170 name="family_status"171 value={formData.family_status}172 onChange={handleChange}173 className="mt-1 block w-full rounded"174 >175 <option value="single">Célibataire</option>176 <option value="married">Marié(e)</option>177 <option value="divorced">Divorcé(e)</option>178 <option value="widowed">Veuf/Veuve</option>179 </select>180 </label>181 </div>182 <div>183 <label className="block text-sm font-medium mb-1">184 Personnes à charge185 <input186 type="number"187 name="dependents"188 value={formData.dependents}189 onChange={handleChange}190 min="0"191 className="mt-1 block w-full rounded"192 />193 </label>194 </div>195 </div>196 </div>197 198 {/* Section 2: Profil d'investissement */}199 <div>200 <h3 className="text-lg font-medium mb-4">Profil d'investissement</h3>201 <div className="space-y-4">202 <div>203 <label className="block text-sm font-medium mb-1">204 Tolérance au risque (1-5)205 <input206 type="range"207 name="risk_tolerance"208 min="1"209 max="5"210 value={formData.risk_tolerance}211 onChange={handleChange}212 className="w-full"213 />214 <div className="flex justify-between text-xs">215 <span>Très prudent</span>216 <span>Équilibré</span>217 <span>Dynamique</span>218 </div>219 </label>220 </div>221 222 <div className="grid grid-cols-1 md:grid-cols-2 gap-4">223 <div>224 <label className="block text-sm font-medium mb-1">225 Horizon d'investissement (années)226 <input227 type="number"228 name="investment_horizon"229 value={formData.investment_horizon}230 onChange={handleChange}231 className="mt-1 block w-full rounded"232 min="1"233 />234 </label>235 </div>236 <div>237 <label className="block text-sm font-medium mb-1">238 Niveau de connaissance financière (1-5)239 <input240 type="range"241 name="financial_knowledge"242 min="1"243 max="5"244 value={formData.financial_knowledge}245 onChange={handleChange}246 className="w-full"247 />248 </label>249 </div>250 </div>251 </div>252 </div>253 254 {/* Section 3: Objectifs et événements de vie */}255 <div>256 <h3 className="text-lg font-medium mb-4">Objectifs et événements de vie</h3>257 258 <div className="mb-4">259 <label className="block text-sm font-medium mb-2">260 Objectifs d'investissement261 </label>262 <div className="grid grid-cols-2 gap-2">263 {investmentGoals.map(goal => (264 <label key={goal} className="flex items-center space-x-2">265 <input266 type="checkbox"267 name="investment_goals"268 value={goal}269 checked={formData.investment_goals.includes(goal)}270 onChange={handleChange}271 className="rounded"272 />273 <span className="text-sm">{goal}</span>274 </label>275 ))}276 </div>277 </div>278 279 <div>280 <label className="block text-sm font-medium mb-2">281 Événements de vie prévus282 </label>283 <div className="grid grid-cols-2 gap-2">284 {lifeEvents.map(event => (285 <label key={event} className="flex items-center space-x-2">286 <input287 type="checkbox"288 name="life_events"289 value={event}290 checked={formData.life_events.includes(event)}291 onChange={handleChange}292 className="rounded"293 />294 <span className="text-sm">{event}</span>295 </label>296 ))}297 </div>298 </div>299 </div>300 301 {/* Section 4: Préférences d'investissement */}302 <div>303 <h3 className="text-lg font-medium mb-4">Préférences d'investissement</h3>304 <div className="grid grid-cols-2 gap-4">305 <label className="flex items-center space-x-2">306 <input307 type="checkbox"308 name="investment_preferences.esg"309 checked={formData.investment_preferences.esg}310 onChange={handleChange}311 className="rounded"312 />313 <span className="text-sm">Investissement responsable (ESG)</span>314 </label>315 <label className="flex items-center space-x-2">316 <input317 type="checkbox"318 name="investment_preferences.crypto"319 checked={formData.investment_preferences.crypto}320 onChange={handleChange}321 className="rounded"322 />323 <span className="text-sm">Cryptomonnaies</span>324 </label>325 <label className="flex items-center space-x-2">326 <input327 type="checkbox"328 name="investment_preferences.real_estate"329 checked={formData.investment_preferences.real_estate}330 onChange={handleChange}331 className="rounded"332 />333 <span className="text-sm">Immobilier</span>334 </label>335 <label className="flex items-center space-x-2">336 <input337 type="checkbox"338 name="investment_preferences.alternative"339 checked={formData.investment_preferences.alternative}340 onChange={handleChange}341 className="rounded"342 />343 <span className="text-sm">Investissements alternatifs</span>344 </label>345 </div>346 </div>347 348 {/* Messages d'erreur/succès */}349 {error && (350 <div className="bg-red-50 text-red-800 p-4 rounded-md">351 {error}352 </div>353 )}354 355 {success && (356 <div className="bg-green-50 text-green-800 p-4 rounded-md">357 Profil créé avec succès!358 </div>359 )}360 361 <button362 type="submit"363 className="w-full bg-blue-600 text-white p-3 rounded-lg hover:bg-blue-700 transition-colors"364 >365 Créer mon profil366 </button>367 </form>368 </div>369 </div>370 );371};372 373export default UserProfileForm;