Mon Compte
Créez un compte pour garder vos analyses privées
/* * ============================================================================= * VibeQuant (vquant) — AI-Powered Financial Intelligence Platform * ----------------------------------------------------------------------------- * File: client/src/pages/auth.tsx * * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai * Website: https://www.spboucher.ai * Demo: https://www.vquant.ai * License: MIT (see LICENSE) * * Copyright © 2026 Simon-Pierre Boucher. All rights reserved. * ============================================================================= */ import { useState } from "react"; import { User, KeyRound, Sparkles, Copy, Check, ArrowLeft } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { useLocation } from "wouter"; export default function Auth() { const [, setLocation] = useLocation(); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(""); const [success, setSuccess] = useState(""); // Create account state const [name, setName] = useState(""); const [generatedToken, setGeneratedToken] = useState(""); const [copied, setCopied] = useState(false); // Login state const [loginToken, setLoginToken] = useState(""); const handleCreate = async (e: React.FormEvent) => { e.preventDefault(); setError(""); setSuccess(""); setGeneratedToken(""); setIsLoading(true); try { const response = await fetch("/api/auth/register", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: name.trim() }), }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || "Erreur lors de la création du compte"); } setGeneratedToken(data.token); setSuccess(`Compte créé avec succès! Bienvenue, ${data.user.displayName}!`); } catch (err: any) { setError(err.message || "Erreur lors de la création du compte"); } finally { setIsLoading(false); } }; const handleLogin = async (e: React.FormEvent) => { e.preventDefault(); setError(""); setSuccess(""); setIsLoading(true); try { const response = await fetch("/api/auth/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ token: loginToken.trim() }), }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || "Token invalide"); } setSuccess(`Bienvenue, ${data.user.displayName}!`); setTimeout(() => { setLocation('/'); }, 1000); } catch (err: any) { setError(err.message || "Erreur de connexion"); } finally { setIsLoading(false); } }; const handleCopyToken = async () => { try { await navigator.clipboard.writeText(generatedToken); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch { // Fallback for mobile const textarea = document.createElement('textarea'); textarea.value = generatedToken; document.body.appendChild(textarea); textarea.select(); document.execCommand('copy'); document.body.removeChild(textarea); setCopied(true); setTimeout(() => setCopied(false), 2000); } }; const handleGoHome = () => { setLocation('/'); }; return (
Créez un compte pour garder vos analyses privées