From 8bddbec43cdebecb674a36174d6a6102bc4fa9eb Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Sat, 18 Apr 2026 17:56:37 -0700 Subject: [PATCH] feat(web): TODO-001 kill switch maintenance banner + disable timer creation --- web/src/app/providers.tsx | 29 +++++++++++++----------- web/src/components/CreateTimerModal.tsx | 7 ++++-- web/src/components/MaintenanceBanner.tsx | 25 ++++++++++++++++++++ 3 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 web/src/components/MaintenanceBanner.tsx diff --git a/web/src/app/providers.tsx b/web/src/app/providers.tsx index d0ab2d2..354da37 100644 --- a/web/src/app/providers.tsx +++ b/web/src/app/providers.tsx @@ -1,34 +1,32 @@ 'use client'; -import { useEffect } from 'react'; +import { createContext, useContext, useEffect, useState } from 'react'; import { usePathname } from 'next/navigation'; import { AuthProvider } from '@/lib/auth-context'; import { initTelemetry, trackPageView } from '@/lib/telemetry'; import { initFeatureFlags } from '@/lib/feature-flags'; import { initDiagnostics } from '@/lib/diagnostics'; import { checkKillSwitch } from '@/lib/kill-switch'; +import { MaintenanceBanner } from '@/components/MaintenanceBanner'; import { ToastProvider } from '@bytelyst/ui'; import type { ReactNode } from 'react'; +const MaintenanceContext = createContext(false); + +export function useMaintenanceMode(): boolean { + return useContext(MaintenanceContext); +} + export function Providers({ children }: { children: ReactNode }) { const pathname = usePathname(); + const [isMaintenanceMode, setIsMaintenanceMode] = useState(false); useEffect(() => { initTelemetry(); initFeatureFlags(); initDiagnostics(); - // TODO-001: Kill switch maintenance banner - // Priority: medium | Phase: 0 - // When checkKillSwitch() returns disabled=true: - // 1. Set a React state flag (e.g. `isMaintenanceMode`) - // 2. Render a component at the top of the app - // 3. Disable timer creation buttons (pass flag via context or prop) - // 4. Use --cm-warning-* design tokens for the banner styling - // File to create: web/src/components/MaintenanceBanner.tsx checkKillSwitch().then((disabled) => { - if (disabled) { - // TODO-001: Surface this in the UI (see instructions above) - } + setIsMaintenanceMode(disabled); }); }, []); @@ -40,7 +38,12 @@ export function Providers({ children }: { children: ReactNode }) { return ( - {children} + + + {isMaintenanceMode && } + {children} + + ); } diff --git a/web/src/components/CreateTimerModal.tsx b/web/src/components/CreateTimerModal.tsx index 45ac2af..eec61d6 100644 --- a/web/src/components/CreateTimerModal.tsx +++ b/web/src/components/CreateTimerModal.tsx @@ -7,6 +7,7 @@ import type { UrgencyLevel } from '@/lib/urgency'; import { CASCADE_PRESET_LABELS } from '@/lib/cascade'; import type { CascadePreset } from '@/lib/cascade'; import { X, AlarmClock, Timer, Coffee, Sparkles, CalendarDays } from 'lucide-react'; +import { useMaintenanceMode } from '@/app/providers'; import { BUILT_IN_CATEGORIES, getCategoryById } from '@/lib/categories'; import { parseNaturalLanguage } from '@/lib/nl-parser'; import type { ParseResult } from '@/lib/nl-parser'; @@ -21,6 +22,7 @@ interface CreateTimerModalProps { export function CreateTimerModal({ isOpen, onClose }: CreateTimerModalProps) { const { addAlarm, addCountdown, addPomodoro, addEvent } = useTimerStore(); + const maintenanceMode = useMaintenanceMode(); const [tab, setTab] = useState('countdown'); const [nlInput, setNlInput] = useState(''); @@ -570,13 +572,14 @@ export function CreateTimerModal({ isOpen, onClose }: CreateTimerModalProps) { {/* Create button */} diff --git a/web/src/components/MaintenanceBanner.tsx b/web/src/components/MaintenanceBanner.tsx new file mode 100644 index 0000000..4d46e60 --- /dev/null +++ b/web/src/components/MaintenanceBanner.tsx @@ -0,0 +1,25 @@ +'use client'; + +import { AlertTriangle } from 'lucide-react'; + +interface MaintenanceBannerProps { + message?: string; +} + +export function MaintenanceBanner({ message }: MaintenanceBannerProps) { + return ( +
+
+ ); +}