This commit is contained in:
ponzischeme89
2026-08-17 07:34:23 +12:00
parent 93fb0fd728
commit 36cb1324fd
56 changed files with 1177 additions and 168 deletions
+62 -2
View File
@@ -3,7 +3,7 @@ import { api } from '../api/client';
import { useAction } from '../lib/hooks';
import { useGateway } from '../lib/gateway';
import { useToast } from '../lib/toast';
import { Banner, Button, Card, Confirm, Field, Loading, PageHead, Tag } from '../components/ui';
import { Banner, Button, Card, Confirm, Field, Loading, PageHead, Tag, Toggle } from '../components/ui';
export function MaintenancePage() {
const { status, error, loading, reload } = useGateway();
@@ -12,6 +12,11 @@ export function MaintenancePage() {
const [message, setMessage] = useState('');
const [confirming, setConfirming] = useState(false);
const [touched, setTouched] = useState(false);
const [quietEnabled, setQuietEnabled] = useState(false);
const [quietStart, setQuietStart] = useState('23:00');
const [quietEnd, setQuietEnd] = useState('07:00');
const [quietMessage, setQuietMessage] = useState('');
const [quietTouched, setQuietTouched] = useState(false);
const enabled = Boolean(status?.maintenance?.enabled);
@@ -23,6 +28,14 @@ export function MaintenancePage() {
if (!touched && status) setMessage(status.maintenance?.message ?? '');
}, [status, touched]);
useEffect(() => {
if (quietTouched || !status?.quietTime) return;
setQuietEnabled(status.quietTime.enabled);
setQuietStart(status.quietTime.startTime);
setQuietEnd(status.quietTime.endTime);
setQuietMessage(status.quietTime.message);
}, [status, quietTouched]);
const set = (next: boolean) =>
run(next ? 'on' : 'off', async () => {
await wrap(
@@ -34,9 +47,24 @@ export function MaintenancePage() {
await reload();
});
const saveQuietTime = () =>
run('quiet', async () => {
await wrap(
() => api.post('/admin/api/quiet-time', {
enabled: quietEnabled,
startTime: quietStart,
endTime: quietEnd,
message: quietMessage,
}),
quietEnabled ? 'Quiet time saved.' : 'Quiet time turned off.',
);
setQuietTouched(false);
await reload();
});
return (
<>
<PageHead title="Maintenance" intro="Take Memby offline for every television." />
<PageHead title="Maintenance" intro="Take Memby offline now or schedule daily quiet time." />
<Banner message={error} />
{loading ? (
@@ -76,6 +104,38 @@ export function MaintenancePage() {
</Card>
)}
{!loading ? (
<Card
title="Quiet time"
intro={`Pause new television requests and server background work every day in ${status?.quietTime?.timeZone ?? 'the household timezone'}. Work already under way finishes safely. The admin console and health checks stay available so the schedule can always be changed.`}
icon="clock"
tone={status?.quietTime?.active ? 'warn' : 'info'}
actions={status?.quietTime?.active ? <Tag tone="warn">active now</Tag> : quietEnabled ? <Tag tone="ok">scheduled</Tag> : <Tag>off</Tag>}
footer={
<Button variant="primary" busy={busy === 'quiet'} onClick={() => void saveQuietTime()}>
Save quiet time
</Button>
}
>
<Toggle
label="Pause server activity during quiet time"
checked={quietEnabled}
onChange={(next) => { setQuietEnabled(next); setQuietTouched(true); }}
/>
<div className="fields">
<Field label="Starts" hint="Uses the household's 24-hour clock.">
<input type="time" value={quietStart} onChange={(event) => { setQuietStart(event.target.value); setQuietTouched(true); }} />
</Field>
<Field label="Ends" hint="May be on the following day, for example 23:00 to 07:00.">
<input type="time" value={quietEnd} onChange={(event) => { setQuietEnd(event.target.value); setQuietTouched(true); }} />
</Field>
</div>
<Field label="Message shown on the television" hint="Shown when a television contacts Memby during quiet time.">
<input type="text" value={quietMessage} placeholder="Quiet time — try again after 7 am" onChange={(event) => { setQuietMessage(event.target.value); setQuietTouched(true); }} />
</Field>
</Card>
) : null}
{confirming ? (
<Confirm
title="Take Memby offline?"
+2
View File
@@ -108,6 +108,8 @@ export function OverviewPage() {
label: 'Availability',
value: status.maintenance?.enabled ? (
<Tag tone="bad">offline for maintenance</Tag>
) : status.quietTime?.active ? (
<Tag tone="warn">quiet time active</Tag>
) : (
<Tag tone="ok">online</Tag>
),