grocery-app/frontend/src/context/SettingsContext.jsx
2026-05-26 00:38:53 -07:00

135 lines
3.3 KiB
JavaScript

import { createContext, useContext, useEffect, useState } from "react";
import { AuthContext } from "./AuthContext";
const DEFAULT_SETTINGS = {
// Appearance
theme: "auto", // "light" | "dark" | "auto"
compactView: false,
// List Display
showRecentlyBought: true,
recentlyBoughtCount: 10,
recentlyBoughtCollapsed: false,
// Behavior
confirmBeforeBuy: true,
autoReloadInterval: 0, // 0 = disabled, else minutes
hapticFeedback: true,
// Advanced
debugMode: false,
};
const SETTINGS_KEYS = Object.keys(DEFAULT_SETTINGS);
function normalizeSettings(savedSettings = {}) {
return SETTINGS_KEYS.reduce((normalized, key) => {
normalized[key] = Object.prototype.hasOwnProperty.call(savedSettings, key)
? savedSettings[key]
: DEFAULT_SETTINGS[key];
return normalized;
}, {});
}
export const SettingsContext = createContext({
settings: DEFAULT_SETTINGS,
updateSettings: () => { },
resetSettings: () => { },
});
export const SettingsProvider = ({ children }) => {
const { username } = useContext(AuthContext);
const [settings, setSettings] = useState(DEFAULT_SETTINGS);
// Load settings from localStorage when user changes
useEffect(() => {
if (!username) {
setSettings(DEFAULT_SETTINGS);
return;
}
const storageKey = `user_preferences_${username}`;
const savedSettings = localStorage.getItem(storageKey);
if (savedSettings) {
try {
const parsed = JSON.parse(savedSettings);
const normalized = normalizeSettings(parsed);
setSettings(normalized);
localStorage.setItem(storageKey, JSON.stringify(normalized));
} catch (error) {
console.error("Failed to parse settings:", error);
setSettings(DEFAULT_SETTINGS);
}
} else {
setSettings(DEFAULT_SETTINGS);
}
}, [username]);
// Apply theme to document
useEffect(() => {
const applyTheme = () => {
let theme = settings.theme;
if (theme === "auto") {
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
theme = prefersDark ? "dark" : "light";
}
document.documentElement.setAttribute("data-theme", theme);
};
applyTheme();
// Listen for system theme changes if in auto mode
if (settings.theme === "auto") {
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const handler = () => applyTheme();
mediaQuery.addEventListener("change", handler);
return () => mediaQuery.removeEventListener("change", handler);
}
}, [settings.theme]);
// Save settings to localStorage
const updateSettings = (newSettings) => {
if (!username) return;
const updated = normalizeSettings({ ...settings, ...newSettings });
setSettings(updated);
const storageKey = `user_preferences_${username}`;
localStorage.setItem(storageKey, JSON.stringify(updated));
};
// Reset to defaults
const resetSettings = () => {
if (!username) return;
setSettings(DEFAULT_SETTINGS);
const storageKey = `user_preferences_${username}`;
localStorage.setItem(storageKey, JSON.stringify(DEFAULT_SETTINGS));
};
const value = {
settings,
updateSettings,
resetSettings,
};
return (
<SettingsContext.Provider value={value}>
{children}
</SettingsContext.Provider>
);
};