65 lines
1.9 KiB
TypeScript
65 lines
1.9 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import type { WorkSession } from '@solelog/shared';
|
|
import { useActiveSessions } from '../api/admin-sessions';
|
|
import { formatTime } from '../lib/elapsed';
|
|
|
|
export default function Live() {
|
|
const { data, isLoading, isError } = useActiveSessions();
|
|
|
|
// Client-side 1s tick so the elapsed timer on each card keeps counting up
|
|
// between the 5s server refreshes.
|
|
const [now, setNow] = useState(() => Date.now());
|
|
useEffect(() => {
|
|
const id = setInterval(() => setNow(Date.now()), 1000);
|
|
return () => clearInterval(id);
|
|
}, []);
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="screen">
|
|
<p className="muted">Laden…</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (isError) {
|
|
return (
|
|
<div className="screen">
|
|
<p className="muted">Kon gegevens niet laden.</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const sessions = Array.isArray(data) ? data : [];
|
|
|
|
return (
|
|
<div className="screen">
|
|
<h1 className="screen-title">Actief nu ({sessions.length})</h1>
|
|
{sessions.length === 0 ? (
|
|
<p className="muted">Niemand is nu aan het werk.</p>
|
|
) : (
|
|
<div className="live-grid">
|
|
{sessions.map((session) => (
|
|
<LiveCard key={session.id} session={session} now={now} />
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function LiveCard({ session, now }: { session: WorkSession; now: number }) {
|
|
const elapsed = formatTime((now - Date.parse(session.start_time)) / 1000);
|
|
return (
|
|
<article className="live-card">
|
|
<div className="live-card-head">
|
|
<span className="live-name">{session.user_name ?? 'Onbekend'}</span>
|
|
{session.insole_type && <span className="live-pill">{session.insole_type}</span>}
|
|
</div>
|
|
<div className="live-activity">{session.activity_name ?? 'Onbekende handeling'}</div>
|
|
<div className="live-meta">{session.pair_count} zolen</div>
|
|
<div className="live-timer">{elapsed}</div>
|
|
</article>
|
|
);
|
|
}
|