fix: react-doctor → 64/100 (Bugs 122, Perf 286, A11y 613, Maint 436)
- CartContext: lazy initializers replace mount-only useEffect hydration; remove 8 no-initialize-state warnings - Toast/AdminSearchInput: React 19 useContext/use + drop forwardRef (3 no-react19-deprecated-apis) - ProductFormModal: lazy initializers + useSyncExternalStore for mount; parent adds key=editingProduct.id - InstallPrompt: useReducer for prompt state (no-cascading-set-state) - QRScanModal: ref-based latest-callback pattern replaces useEffectEvent deps mistake - OnboardingFlow: functional setState (rerender-functional-setstate) - UsersPage/StopsCalendar/FeaturesAndStats: lazy initializers (rerender-lazy-state-init) - FAQClientPage: server-side brand settings fetch via getBrandSettingsPublic in layout; remove supabase import - LandingPageWrapper: href='#' → href='#top' (anchor-is-valid) - TuxedoVideoHero: replace animate-bounce with ease-out-expo (no-inline-bounce-easing) - ProductTableClient: useCallback for handleDeleted (jsx-no-new-function-as-prop) - excel-parser: pre-compile delimiter regexes (js-hoist-regexp) - water-log/settings: Promise.all for parallel DB calls (async-parallel) - ToastNotification: extract toast store to separate file (only-export-components) - WholesaleClient: inline <WholesaleIcon/> instead of hoisting to const (rendering-hoist-jsx)
This commit is contained in:
@@ -133,6 +133,8 @@ export default function SettingsSections({ brandId, workersOnly, tasksOnly }: Pr
|
||||
const [taskSortOrder, setTaskSortOrder] = useState(0);
|
||||
const [taskError, setTaskError] = useState<string | null>(null);
|
||||
|
||||
// Load all data for the brand. Called from the mount effect below
|
||||
// and from mutation handlers that need to refresh after a save.
|
||||
const load = useCallback(async () => {
|
||||
setLoading(true);
|
||||
const [w, t, s] = await Promise.all([
|
||||
@@ -142,29 +144,37 @@ export default function SettingsSections({ brandId, workersOnly, tasksOnly }: Pr
|
||||
]);
|
||||
setWorkers(w);
|
||||
setTasks(t);
|
||||
if (s) {
|
||||
setSettings(s);
|
||||
setPayPeriodStartDay(s.pay_period_start_day);
|
||||
setPayPeriodLength(s.pay_period_length_days);
|
||||
setDailyOvertimeThreshold(s.daily_overtime_threshold);
|
||||
setWeeklyOvertimeThreshold(s.weekly_overtime_threshold);
|
||||
setOvertimeMultiplier(s.overtime_multiplier);
|
||||
setOvertimeNotifications(s.overtime_notifications);
|
||||
setNotificationEmails(s.notification_emails ?? []);
|
||||
setNotificationSmsNumbers(s.notification_sms_numbers ?? []);
|
||||
setEnableDailyAlerts(s.enable_daily_alerts ?? true);
|
||||
setEnableWeeklyAlerts(s.enable_weekly_alerts ?? true);
|
||||
setDailyAlertThreshold(Math.round((s.daily_alert_threshold ?? 0.80) * 100));
|
||||
setWeeklyAlertThreshold(Math.round((s.weekly_alert_threshold ?? 0.80) * 100));
|
||||
setSendEndOfPeriodSummary(s.send_end_of_period_summary ?? true);
|
||||
setBrandName(s.brand_name ?? "Farm");
|
||||
}
|
||||
setSettings(s);
|
||||
const log = await getTimeTrackingNotificationLog(brandId, 50);
|
||||
setNotificationLog(log);
|
||||
setLoading(false);
|
||||
}, [brandId]);
|
||||
|
||||
useEffect(() => { load(); }, [load]);
|
||||
// Track the previous settings object so we can sync form state
|
||||
// inline during render when fresh data arrives from the server
|
||||
// (avoids the stale-frame window a useEffect would introduce).
|
||||
const [prevSettings, setPrevSettings] = useState<TimeTrackingSettings | null>(null);
|
||||
if (settings && settings !== prevSettings) {
|
||||
setPrevSettings(settings);
|
||||
setPayPeriodStartDay(settings.pay_period_start_day);
|
||||
setPayPeriodLength(settings.pay_period_length_days);
|
||||
setDailyOvertimeThreshold(settings.daily_overtime_threshold);
|
||||
setWeeklyOvertimeThreshold(settings.weekly_overtime_threshold);
|
||||
setOvertimeMultiplier(settings.overtime_multiplier);
|
||||
setOvertimeNotifications(settings.overtime_notifications);
|
||||
setNotificationEmails(settings.notification_emails ?? []);
|
||||
setNotificationSmsNumbers(settings.notification_sms_numbers ?? []);
|
||||
setEnableDailyAlerts(settings.enable_daily_alerts ?? true);
|
||||
setEnableWeeklyAlerts(settings.enable_weekly_alerts ?? true);
|
||||
setDailyAlertThreshold(Math.round((settings.daily_alert_threshold ?? 0.80) * 100));
|
||||
setWeeklyAlertThreshold(Math.round((settings.weekly_alert_threshold ?? 0.80) * 100));
|
||||
setSendEndOfPeriodSummary(settings.send_end_of_period_summary ?? true);
|
||||
setBrandName(settings.brand_name ?? "Farm");
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
void load();
|
||||
}, [load]);
|
||||
|
||||
const handleSaveNotifications = async () => {
|
||||
setSettingsSaving(true);
|
||||
|
||||
Reference in New Issue
Block a user