diff --git a/Dockerfile b/Dockerfile index 52d4e93..5ae6588 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:18-bullseye +FROM WORKDIR /app diff --git a/LogIQ/src/Components/PreviewGrid.jsx b/LogIQ/src/Components/PreviewGrid.jsx new file mode 100644 index 0000000..8102d50 --- /dev/null +++ b/LogIQ/src/Components/PreviewGrid.jsx @@ -0,0 +1,125 @@ +import { useEffect, useMemo, useState } from "react"; + +const FRAME_COUNT = 6; +const FRAME_INTERVAL = 1200; + +function getStatusLabel(state) { + switch (state) { + case "loading": + return "Loading…"; + case "ready": + return "Rendered"; + case "error": + return "Blocked"; + default: + return "Queued"; + } +} + +function PreviewFrame({ url, index, delayMs }) { + const [source, setSource] = useState(""); + const [state, setState] = useState("queued"); + const [startedAt, setStartedAt] = useState(null); + const [loadedAt, setLoadedAt] = useState(null); + + useEffect(() => { + if (!url) { + setSource(""); + setState("idle"); + setStartedAt(null); + setLoadedAt(null); + return; + } + + setState("queued"); + const timer = setTimeout(() => { + setSource(url); + setStartedAt(performance.now()); + setState("loading"); + }, delayMs); + + return () => { + clearTimeout(timer); + setSource(""); + setState("queued"); + setStartedAt(null); + setLoadedAt(null); + }; + }, [url, delayMs]); + + const handleLoad = () => { + setState("ready"); + setLoadedAt(performance.now()); + }; + + const handleError = () => { + setState("error"); + }; + + const deltaMs = + startedAt && loadedAt ? Math.max(0, loadedAt - startedAt).toFixed(0) : null; + + return ( +
+ {source ? ( +