'use client';
import { useState } from 'react';
/**
* The panel, at a readable size.
*
* Rendered by the same code path that serves the device, so this is not an
* impression of the screen: it is the screen.
*
* With `timeTravel`, it also answers the question the shop actually asks
* before a holiday — "what will the window say while I'm away?" — without
* waiting until someone is standing in front of a locked door to find out.
*/
export default function ScreenPreview({
className = '',
timeTravel = false,
}: {
className?: string;
timeTravel?: boolean;
}) {
const [at, setAt] = useState('');
const [nonce, setNonce] = useState(() => Date.now());
const source = at
? `/api/admin/preview?at=${encodeURIComponent(at)}&t=${nonce}`
: `/api/admin/preview?t=${nonce}`;
function jumpTo(date: Date) {
setAt(toLocalInput(date));
setNonce(Date.now());
}
return (
) : null}
{at
? 'Projection : l’écran tel qu’il sera à cette date, avec les horaires et fermetures enregistrés.'
: '800 × 480, noir et blanc — rendu réellement envoyé à l’écran.'}
);
}
function Jump({ label, onClick }: { label: string; onClick: () => void }) {
return (
);
}
/** `datetime-local` speaks local wall-clock time with no zone, so build one. */
function toLocalInput(date: Date): string {
const pad = (value: number) => value.toString().padStart(2, '0');
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(
date.getHours(),
)}:${pad(date.getMinutes())}`;
}
function tomorrowAt(hour: number): Date {
return inDays(1, hour);
}
function inDays(days: number, hour: number): Date {
const date = new Date();
date.setDate(date.getDate() + days);
date.setHours(hour, 0, 0, 0);
return date;
}
/** The next occurrence of a weekday, 0 = Sunday. */
function nextWeekdayAt(weekday: number, hour: number): Date {
const date = new Date();
const ahead = (weekday - date.getDay() + 7) % 7 || 7;
return inDays(ahead, hour);
}