Extract ScheduleScreen from App.tsx into screens/SchedulesScreen.tsx + schedules/ domain folder (itemRules, pickers, inspector, ScheduleForm). Draft model with explicit Save (single destructive PUT), Discard, dirty guard (navigationGuard + beforeunload), schedule CRUD, and all Blazor item fields/gates/resets. Rewrite api/schedules.ts to the flat DTO + CRUD + languages/filler-by-kind pickers. Live TopBar Add Schedule via a window CustomEvent. Screen + nav-guard tests; App.test updated for the extracted screen. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
29 lines
1.0 KiB
TypeScript
29 lines
1.0 KiB
TypeScript
// A tiny shared guard so a screen with unsaved changes can veto in-app navigation. A screen
|
|
// registers a predicate (returns true when it is safe to leave, e.g. after a confirm()); App.tsx's
|
|
// nav handler consults `canLeaveCurrentScreen()` before pushing a new route. Only one guard is
|
|
// active at a time (the mounted screen) — registering returns an unregister fn for cleanup.
|
|
//
|
|
// This does NOT cover full-page unloads (reload / close tab / external link) — a screen additionally
|
|
// installs its own `beforeunload` listener while dirty for that path.
|
|
|
|
type NavigationGuard = () => boolean;
|
|
|
|
let activeGuard: NavigationGuard | null = null;
|
|
|
|
export function registerNavigationGuard(guard: NavigationGuard): () => void {
|
|
activeGuard = guard;
|
|
return () => {
|
|
if (activeGuard === guard) {
|
|
activeGuard = null;
|
|
}
|
|
};
|
|
}
|
|
|
|
// Returns true when navigation may proceed. With no guard registered, always true.
|
|
export function canLeaveCurrentScreen(): boolean {
|
|
if (!activeGuard) {
|
|
return true;
|
|
}
|
|
return activeGuard();
|
|
}
|