Portal: per-system daily/weekly schedule editor
System picker lists the account's License Keys labelled by System Name (fallback: key). Schedule type selector (Daily|Weekly) with a confirmation before switching a populated schedule (daily->weekly prefills all seven days; otherwise clears). Weekly shows a per-day editor. Blocks use TimeInput, allow adjacent/midnight-crossing ranges (labelled 'ends next day'), block empty blocks client-side, default dynamic audio on, and show title/category/group only. Adds gap helper text and an informational kiosk-timezone note (browser fallback; no external/paid dependency).
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
hmToMinutes,
|
||||
isOvernight,
|
||||
toHm,
|
||||
validateBlock,
|
||||
validateBlockAgainstSchedule,
|
||||
type BlockSibling
|
||||
} from '$lib/schedule-utils';
|
||||
|
||||
@@ -25,10 +25,13 @@
|
||||
open = false,
|
||||
mode = 'create',
|
||||
blockId,
|
||||
day = null,
|
||||
licenseKeyId = '',
|
||||
initialStartMinutes = 9 * 60,
|
||||
initialEndMinutes = 10 * 60,
|
||||
initialProclamationIds = [],
|
||||
initialDynamicAudio = true,
|
||||
scheduleType = 'daily' as 'daily' | 'weekly' | null,
|
||||
categories = [],
|
||||
groups = [],
|
||||
proclamations = [],
|
||||
@@ -42,10 +45,13 @@
|
||||
open?: boolean;
|
||||
mode?: 'create' | 'edit';
|
||||
blockId?: string;
|
||||
day?: string | null;
|
||||
licenseKeyId?: string;
|
||||
initialStartMinutes?: number;
|
||||
initialEndMinutes?: number;
|
||||
initialProclamationIds?: string[];
|
||||
initialDynamicAudio?: boolean;
|
||||
scheduleType?: 'daily' | 'weekly' | null;
|
||||
categories?: BrowserCategory[];
|
||||
groups?: BrowserGroup[];
|
||||
proclamations?: BrowserProclamation[];
|
||||
@@ -105,10 +111,11 @@
|
||||
|
||||
function validate(): string | null {
|
||||
if (!startValid || !endValid) return 'Enter a valid start and end time.';
|
||||
const result = validateBlock(
|
||||
{ startMinutes, endMinutes, proclamationIds: selectedIds },
|
||||
siblings,
|
||||
{ isCreate: mode === 'create' }
|
||||
if (scheduleType === null) return 'Set a schedule type first.';
|
||||
const result = validateBlockAgainstSchedule(
|
||||
scheduleType,
|
||||
{ day, startMinutes, endMinutes, proclamationIds: selectedIds },
|
||||
siblings
|
||||
);
|
||||
return result.ok ? null : result.error;
|
||||
}
|
||||
@@ -193,6 +200,10 @@
|
||||
{#if mode === 'edit' && blockId}
|
||||
<input type="hidden" name="id" value={blockId} />
|
||||
{/if}
|
||||
<input type="hidden" name="licenseKeyId" value={licenseKeyId} />
|
||||
{#if day}
|
||||
<input type="hidden" name="day" value={day} />
|
||||
{/if}
|
||||
<input type="hidden" name="startMinutes" value={startMinutes} />
|
||||
<input type="hidden" name="endMinutes" value={endMinutes} />
|
||||
<input type="hidden" name="proclamationIds" value={JSON.stringify(selectedIds)} />
|
||||
@@ -280,7 +291,7 @@
|
||||
<h3 class="text-sm font-semibold text-slate-800 dark:text-slate-200">Review</h3>
|
||||
<p class="mt-2 text-sm text-slate-600 dark:text-slate-400">
|
||||
{formatTime(startMinutes)} – {formatTime(endMinutes)}{overnight
|
||||
? ' (next day)'
|
||||
? ' (ends next day)'
|
||||
: ''}
|
||||
</p>
|
||||
{#if selectedTitles.length === 0}
|
||||
|
||||
Reference in New Issue
Block a user