-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFocusModeContext.tsx
More file actions
98 lines (84 loc) · 3.18 KB
/
FocusModeContext.tsx
File metadata and controls
98 lines (84 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import React, { createContext, useContext, useState, useEffect } from 'react';
export type FocusModeId = 'menstrual' | 'fertility' | 'post_partum' | 'perimenopause' | null;
const FOCUS_MODE_STORAGE_KEY = 'medly_focus_mode';
interface FocusModeContextType {
focusMode: FocusModeId;
setFocusMode: (mode: FocusModeId) => void;
clearFocusMode: () => void;
getFocusModeLabel: (modeId: FocusModeId) => string;
}
const FocusModeContext = createContext<FocusModeContextType | undefined>(undefined);
const VALID_MODE_IDS: FocusModeId[] = ['menstrual', 'fertility', 'post_partum', 'perimenopause'];
const MODE_LABELS: Record<NonNullable<FocusModeId>, string> = {
menstrual: 'Menstrual Health',
fertility: 'Fertility',
post_partum: 'Post-Partum Recovery',
perimenopause: 'Perimenopause',
};
export const FocusModeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [focusMode, setFocusModeState] = useState<FocusModeId>(null);
const [isHydrated, setIsHydrated] = useState(false);
// Load from localStorage on mount (client-side only)
useEffect(() => {
try {
const stored = localStorage.getItem(FOCUS_MODE_STORAGE_KEY);
if (stored) {
const parsed = stored as FocusModeId;
// Validate stored value - ignore unknown values
if (VALID_MODE_IDS.includes(parsed)) {
setFocusModeState(parsed);
} else {
// Invalid value, clear it
localStorage.removeItem(FOCUS_MODE_STORAGE_KEY);
}
}
} catch (error) {
console.error('Failed to load focus mode from localStorage:', error);
} finally {
setIsHydrated(true);
}
}, []);
const setFocusMode = (mode: FocusModeId) => {
// Validate mode before setting
if (mode !== null && !VALID_MODE_IDS.includes(mode)) {
console.warn(`Invalid focus mode: ${mode}. Ignoring.`);
return;
}
setFocusModeState(mode);
try {
if (mode === null) {
localStorage.removeItem(FOCUS_MODE_STORAGE_KEY);
} else {
localStorage.setItem(FOCUS_MODE_STORAGE_KEY, mode);
}
} catch (error) {
console.error('Failed to save focus mode to localStorage:', error);
}
};
const clearFocusMode = () => {
setFocusMode(null);
};
const getFocusModeLabel = (modeId: FocusModeId): string => {
if (!modeId) return 'None';
return MODE_LABELS[modeId] || 'Unknown';
};
return (
<FocusModeContext.Provider
value={{
focusMode: isHydrated ? focusMode : null, // Return null during SSR/hydration to avoid mismatch
setFocusMode,
clearFocusMode,
getFocusModeLabel,
}}
>
{children}
</FocusModeContext.Provider>
);
};
export const useFocusMode = () => {
const context = useContext(FocusModeContext);
if (!context) {
throw new Error('useFocusMode must be used within a FocusModeProvider');
}
return context;
};