Files
CPLv4.0/components/main/kabelueberwachung/kue705FO/SlotActivityOverlay.tsx

153 lines
5.4 KiB
TypeScript

"use client";
import React, { useEffect, useState } from "react";
import { useAppSelector } from "@/redux/store";
export default function SlotActivityOverlay({
slotIndex,
}: {
slotIndex: number;
}) {
const ksx = useAppSelector((s) => s.deviceEvents.ksx);
const ksy = useAppSelector((s) => s.deviceEvents.ksy);
const ksz = useAppSelector((s) => s.deviceEvents.ksz);
const loopStartedAt = useAppSelector((s) => s.deviceEvents.loopStartedAt);
const tdrStartedAt = useAppSelector((s) => s.deviceEvents.tdrStartedAt);
const comparisonStartedAt = useAppSelector(
(s) => s.deviceEvents.comparisonStartedAt
);
const loopStartedAtBySlot = useAppSelector(
(s) => s.deviceEvents.loopStartedAtBySlot
);
const tdrStartedAtBySlot = useAppSelector(
(s) => s.deviceEvents.tdrStartedAtBySlot
);
const comparisonStartedAtBySlot = useAppSelector(
(s) => s.deviceEvents.comparisonStartedAtBySlot
);
const loopActive = Array.isArray(ksx) && ksx[slotIndex] === 1;
const tdrActive = Array.isArray(ksy) && ksy[slotIndex] === 1;
const comparisonActive = Array.isArray(ksz) && ksz[slotIndex] === 1;
// Persist whenever arrays change
useEffect(() => {
try {
localStorage.setItem(
"deviceEventsTimingsV1",
JSON.stringify({
loop: loopStartedAtBySlot,
tdr: tdrStartedAtBySlot,
compare: comparisonStartedAtBySlot,
})
);
} catch (e) {
// eslint-disable-next-line no-console
console.warn("Failed to persist timings", e);
}
}, [loopStartedAtBySlot, tdrStartedAtBySlot, comparisonStartedAtBySlot]);
// Progress ticker
const [now, setNow] = useState<number>(Date.now());
useEffect(() => {
const any = loopActive || tdrActive || comparisonActive;
if (!any) return;
const id = setInterval(() => setNow(Date.now()), 1000);
return () => clearInterval(id);
}, [loopActive, tdrActive, comparisonActive]);
const clamp = (v: number, min = 0, max = 1) =>
Math.max(min, Math.min(max, v));
const compute = (startedAt: number | null, durationMs: number) => {
if (!startedAt) return { pct: 0 };
const elapsed = now - startedAt;
const pct = clamp(elapsed / durationMs) * 100;
return { pct };
};
// Durations
const LOOP_MS = 2 * 60 * 1000; // ~2 min
const TDR_MS = 30 * 1000; // ~30 s
const ALIGN_MS = 10 * 60 * 1000; // ~10 min
if (!loopActive && !tdrActive && !comparisonActive) return null;
return (
<div className="absolute inset-0 z-20 flex items-center justify-center bg-white/70 backdrop-blur-sm">
<div className="p-2 rounded-md shadow bg-white/90 border border-gray-200 w-[min(90%,12rem)]">
<div className="text-[0.75rem] font-semibold mb-2 text-gray-800">
Bitte warten
</div>
<div className="space-y-2">
{loopActive && (
<div>
<div className="text-[0.7rem] text-gray-800 mb-1">Schleife</div>
{(() => {
const started = loopStartedAtBySlot[slotIndex] ?? loopStartedAt;
const { pct } = compute(started, LOOP_MS);
return (
<div>
<div className="h-2 w-full bg-gray-200 rounded overflow-hidden">
<div
className="h-full bg-littwin-blue transition-all"
style={{ width: `${pct}%` }}
/>
</div>
<div className="text-[0.65rem] text-gray-700 mt-1">
{Math.round(pct)}%
</div>
</div>
);
})()}
</div>
)}
{tdrActive && (
<div>
<div className="text-[0.7rem] text-gray-800 mb-1">TDR</div>
{(() => {
const started = tdrStartedAtBySlot[slotIndex] ?? tdrStartedAt;
const { pct } = compute(started, TDR_MS);
return (
<div>
<div className="h-2 w-full bg-gray-200 rounded overflow-hidden">
<div
className="h-full bg-littwin-blue transition-all"
style={{ width: `${pct}%` }}
/>
</div>
<div className="text-[0.65rem] text-gray-700 mt-1">
{Math.round(pct)}%
</div>
</div>
);
})()}
</div>
)}
{comparisonActive && (
<div>
<div className="text-[0.7rem] text-gray-800 mb-1">Abgleich</div>
{(() => {
const started =
comparisonStartedAtBySlot[slotIndex] ?? comparisonStartedAt;
const { pct } = compute(started, ALIGN_MS);
return (
<div>
<div className="h-2 w-full bg-gray-200 rounded overflow-hidden">
<div
className="h-full bg-littwin-blue transition-all"
style={{ width: `${pct}%` }}
/>
</div>
<div className="text-[0.65rem] text-gray-700 mt-1">
{Math.round(pct)}%
</div>
</div>
);
})()}
</div>
)}
</div>
</div>
</div>
);
}