From df8e594d57dbfc66be38b4cc43d01c28adc9e3c2 Mon Sep 17 00:00:00 2001 From: Tetardtek Date: Sun, 15 Mar 2026 00:53:46 +0100 Subject: [PATCH] =?UTF-8?q?fix(frontend):=20Error=20Boundary,=20HomePage?= =?UTF-8?q?=20error=20state,=20HLS=20catch=20=E2=80=94=20quick=20wins=20pr?= =?UTF-8?q?e-Bloc-B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/ErrorBoundary.tsx | 31 +++++++++++++++++++++++ frontend/src/components/VideoPlayer.tsx | 2 +- frontend/src/main.tsx | 5 +++- frontend/src/pages/HomePage.tsx | 9 +++++-- 4 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 frontend/src/components/ErrorBoundary.tsx diff --git a/frontend/src/components/ErrorBoundary.tsx b/frontend/src/components/ErrorBoundary.tsx new file mode 100644 index 0000000..0c90701 --- /dev/null +++ b/frontend/src/components/ErrorBoundary.tsx @@ -0,0 +1,31 @@ +import { Component, type ReactNode } from 'react'; + +interface Props { children: ReactNode; } +interface State { hasError: boolean; } + +export default class ErrorBoundary extends Component { + state: State = { hasError: false }; + + static getDerivedStateFromError(): State { + return { hasError: true }; + } + + render() { + if (this.state.hasError) { + return ( +
+
+

Une erreur inattendue s'est produite.

+ +
+
+ ); + } + return this.props.children; + } +} diff --git a/frontend/src/components/VideoPlayer.tsx b/frontend/src/components/VideoPlayer.tsx index 33a74a9..c808a45 100644 --- a/frontend/src/components/VideoPlayer.tsx +++ b/frontend/src/components/VideoPlayer.tsx @@ -69,7 +69,7 @@ function NativePlayer({ url }: { url: string }) { hls = new Hls(); hls.loadSource(url); hls.attachMedia(video); - }); + }).catch(() => { /* HLS non disponible — dégradation silencieuse */ }); } return () => { hls?.destroy(); }; diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 1398a70..caf7410 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -2,9 +2,12 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import "./styles/index.css"; import App from "./App"; +import ErrorBoundary from "./components/ErrorBoundary"; createRoot(document.getElementById("root")!).render( - + + + ); diff --git a/frontend/src/pages/HomePage.tsx b/frontend/src/pages/HomePage.tsx index 48644c2..5b9fc6b 100644 --- a/frontend/src/pages/HomePage.tsx +++ b/frontend/src/pages/HomePage.tsx @@ -19,11 +19,12 @@ interface VideosResponse { export default function HomePage() { const [videos, setVideos] = useState([]); const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); useEffect(() => { apiFetch('/videos') .then((res) => setVideos(res.data.videos)) - .catch(() => setVideos([])) + .catch(() => setError(true)) .finally(() => setLoading(false)); }, []); @@ -47,7 +48,11 @@ export default function HomePage() { )} - {!loading && ( + {error && ( +

Impossible de charger les vidéos. Réessaie plus tard.

+ )} + + {!loading && !error && ( <> {free.length > 0 && (