import { useEffect, useState } from "react"; const API_BASE_URL = (import.meta.env.VITE_API_BASE_URL || "").replace(/\/$/, ""); const EXAMPLES = [ "Un film d'une elegance rare, chaque scene est precise et emouvante.", "La mise en scene est confuse et les dialogues sonnent faux du debut a la fin.", "J'etais sceptique, mais le rythme et les acteurs m'ont completement embarque." ]; function getApiUrl(path) { return API_BASE_URL ? `${API_BASE_URL}${path}` : path; } function clampConfidence(value) { return Math.max(0, Math.min(100, Number((value * 100).toFixed(1)))); } export default function App() { const [text, setText] = useState(EXAMPLES[0]); const [result, setResult] = useState(null); const [error, setError] = useState(""); const [loading, setLoading] = useState(false); const [health, setHealth] = useState({ loading: true, ready: false, message: "" }); useEffect(() => { let isMounted = true; async function fetchHealth() { try { const response = await fetch(getApiUrl("/health")); if (!response.ok) { throw new Error("API indisponible"); } const data = await response.json(); if (!isMounted) { return; } setHealth({ loading: false, ready: Boolean(data.model_loaded), message: data.model_loaded ? "Modele pret pour l'inference" : "API joignable, modele encore en chargement" }); } catch (fetchError) { if (!isMounted) { return; } setHealth({ loading: false, ready: false, message: "Impossible de joindre l'API" }); } } fetchHealth(); return () => { isMounted = false; }; }, []); async function handleSubmit(event) { event.preventDefault(); const trimmed = text.trim(); if (!trimmed) { setError("Saisis un avis avant de lancer l'analyse."); setResult(null); return; } setLoading(true); setError(""); try { const response = await fetch(getApiUrl("/predict"), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ text: trimmed }) }); const data = await response.json(); if (!response.ok) { throw new Error(data.detail || "Prediction impossible"); } setResult(data); } catch (requestError) { setResult(null); setError(requestError.message || "Prediction impossible"); } finally { setLoading(false); } } const positive = result?.label === "positif"; const confidence = result ? clampConfidence(result.confidence) : 0; return (
AvisSense / Sentiment cinema francais

Une interface front qui vend le modele sans cacher l'incertitude.

Ce front React parle a une API FastAPI hebergee sur Hugging Face et renvoie un verdict lisible, un niveau de confiance et un etat de service.

{health.loading ? "Verification de l'API..." : health.message}
Voir la doc API
{EXAMPLES.map((example) => ( ))}
POST /predict JSON