Team Ai
Apppublic

Deepvest/ProfilingAI

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
UserProfileForm.tsx373 linesDownload Raw Back to components
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;