"use client" import { useState, useEffect, useRef } from "react" import MetricsPanel from "@/components/neurolink/metrics-panel" import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Play, Square, RotateCcw, Zap, User, Fingerprint, Shield, Target } from "lucide-react" import { io, Socket } from "socket.io-client" import Link from "next/link" // --- CORRECTION ICI : ON UTILISE L'ADRESSE DU CLOUD --- const API_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000" interface MetricData { timestamp: number; value: number; engagement: number; satisfaction: number; trust: number; } interface UserInfo { firstName: string; lastName: string; clientId: string } export default function Dashboard() { const [userInfo, setUserInfo] = useState(null) const [socket, setSocket] = useState(null) const [isConnected, setIsConnected] = useState(false) const [isRecording, setIsRecording] = useState(false) const [sessionTime, setSessionTime] = useState(0) const [formData, setFormData] = useState({ firstName: "", lastName: "", clientId: "" }) const [currentMetrics, setCurrentMetrics] = useState({ engagement: 0, satisfaction: 50, trust: 50, loyalty: 50, opinion: 50, emotion: "neutral" }) const [history, setHistory] = useState([]) const videoRef = useRef(null) const canvasRef = useRef(null) const [faceCoords, setFaceCoords] = useState(null) const [cameraActive, setCameraActive] = useState(false) // 1. Démarrer Webcam Locale useEffect(() => { if (userInfo && !cameraActive) { navigator.mediaDevices.getUserMedia({ video: { width: 480, height: 360 } }) .then(stream => { if (videoRef.current) { videoRef.current.srcObject = stream; setCameraActive(true) } }) .catch(err => console.error("Erreur Webcam:", err)) } }, [userInfo, cameraActive]) // 2. Logique Socket & Envoi d'images useEffect(() => { if (!userInfo) return; // --- CORRECTION ICI : CONNEXION AU CLOUD --- const newSocket = io(API_URL, { transports: ["websocket", "polling"] }) newSocket.on("connect", () => setIsConnected(true)) newSocket.on("disconnect", () => setIsConnected(false)) newSocket.on("metrics_update", (data: any) => { setSessionTime(data.session_time); setIsRecording(data.is_recording) setFaceCoords(data.face_coords) const newMetrics = { emotion: data.emotion, engagement: data.metrics.engagement, satisfaction: data.metrics.satisfaction, trust: data.metrics.trust, loyalty: data.metrics.loyalty, opinion: data.metrics.opinion } setCurrentMetrics(newMetrics) if (data.is_recording) { setHistory(prev => [...prev.slice(-29), { timestamp: data.session_time, value: newMetrics.engagement, engagement: newMetrics.engagement, satisfaction: newMetrics.satisfaction, trust: newMetrics.trust }]) } }) setSocket(newSocket) // Envoi 5 fois par seconde const interval = setInterval(() => { if (videoRef.current && canvasRef.current && newSocket.connected) { const ctx = canvasRef.current.getContext('2d') if (ctx) { ctx.drawImage(videoRef.current, 0, 0, 480, 360) const dataUrl = canvasRef.current.toDataURL('image/jpeg', 0.5) newSocket.emit('process_frame', dataUrl) } } }, 200) return () => { clearInterval(interval); newSocket.close() } }, [userInfo]) const handleLogin = (e: React.FormEvent) => { e.preventDefault(); if (formData.firstName && formData.lastName) setUserInfo(formData) } const handleStartStop = () => { if (socket && userInfo) { isRecording ? socket.emit("stop_session") : (sessionTime === 0 && setHistory([]), socket.emit("start_session", userInfo)) } } const handleReset = () => { if (socket) socket.emit("stop_session"); setHistory([]); setSessionTime(0); setCurrentMetrics(prev => ({ ...prev, engagement: 0, emotion: "neutral" })) } const handleLogout = () => { setUserInfo(null); setHistory([]); setSessionTime(0); setCameraActive(false); if(socket) socket.disconnect() } const formatTime = (s: number) => `${Math.floor(s/60).toString().padStart(2,'0')}:${(s%60).toString().padStart(2,'0')}` const getEmotionDisplay = (e: string) => { const map: any = { happy: "😄 JOIE", sad: "😢 TRISTESSE", angry: "😠 COLÈRE", surprise: "😲 SURPRISE", fear: "😨 PEUR", neutral: "😐 NEUTRE" }; return map[e] || e.toUpperCase() } if (!userInfo) { return (
STARTECH IDIdentification biométrique du sujet
setFormData({...formData, firstName: e.target.value})} required />
setFormData({...formData, lastName: e.target.value})} required />
setFormData({...formData, clientId: e.target.value})} />
) } return (
STARTECH VISION
{userInfo.firstName.charAt(0)}{userInfo.lastName.charAt(0)}
{userInfo.firstName} {userInfo.lastName}{userInfo.clientId || "ID: GUEST"}
{isRecording &&
} {isRecording &&
}
) }