enable wizard admin features
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
|
||||
import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
|
||||
import { STEP_FLOW } from './data/questions';
|
||||
import { getTenantConfig } from './data/tenantConfig';
|
||||
import { getTenantConfig, CONFIG_CHANGE_EVENT } from './data/tenantConfig';
|
||||
|
||||
const STORAGE_KEY = 'lup_estimate_wizard_session_v1';
|
||||
|
||||
@@ -92,10 +92,26 @@ function loadSession() {
|
||||
}
|
||||
|
||||
export function EstimateWizardProvider({ children, source = 'public' }) {
|
||||
const [tenantConfig] = useState(getTenantConfig);
|
||||
// Snapshot tenant config at mount, but stay reactive: the admin can publish flags
|
||||
// (kill-switch, AI copy, conservative mode), pricing, and package content while a
|
||||
// wizard is open. Refresh on same-tab publish, cross-tab storage writes, and on
|
||||
// tab focus so toggles take effect without a hard reload (spec §14/§18).
|
||||
const [tenantConfig, setTenantConfig] = useState(getTenantConfig);
|
||||
const [session, setSession] = useState(() => loadSession() || freshSession(source));
|
||||
const [resumed] = useState(() => !!loadSession());
|
||||
|
||||
useEffect(() => {
|
||||
const refresh = () => setTenantConfig(getTenantConfig());
|
||||
window.addEventListener(CONFIG_CHANGE_EVENT, refresh); // same-tab admin publish
|
||||
window.addEventListener('storage', refresh); // another tab published
|
||||
window.addEventListener('focus', refresh); // returning to this tab
|
||||
return () => {
|
||||
window.removeEventListener(CONFIG_CHANGE_EVENT, refresh);
|
||||
window.removeEventListener('storage', refresh);
|
||||
window.removeEventListener('focus', refresh);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Autosave on every change (debounced via microtask coalescing not needed at this scale).
|
||||
useEffect(() => {
|
||||
try { localStorage.setItem(STORAGE_KEY, JSON.stringify(session)); } catch { /* quota */ }
|
||||
|
||||
@@ -183,6 +183,15 @@ export const DISCLAIMER_VERSION = 'disclaimer-v1';
|
||||
// the defaults so pricing/branding/feature flags are tenant-controlled, not code.
|
||||
const CONFIG_STORAGE_KEY = 'lup_estimate_wizard_config_v1';
|
||||
|
||||
// Same-tab change signal. The public wizard snapshots config at mount, so when the
|
||||
// admin publishes in the SAME tab/SPA there's no `storage` event to react to — we
|
||||
// dispatch this so an open wizard can refresh without a hard reload.
|
||||
export const CONFIG_CHANGE_EVENT = 'lup-estimate-wizard-config-changed';
|
||||
|
||||
function notifyConfigChanged() {
|
||||
try { window.dispatchEvent(new Event(CONFIG_CHANGE_EVENT)); } catch { /* SSR/no window */ }
|
||||
}
|
||||
|
||||
function defaults() {
|
||||
return {
|
||||
version: TENANT_CONFIG_VERSION,
|
||||
@@ -211,10 +220,12 @@ export function loadConfigOverrides() {
|
||||
|
||||
export function saveConfigOverrides(overrides) {
|
||||
try { localStorage.setItem(CONFIG_STORAGE_KEY, JSON.stringify(overrides || {})); } catch { /* quota */ }
|
||||
notifyConfigChanged();
|
||||
}
|
||||
|
||||
export function resetConfigOverrides() {
|
||||
try { localStorage.removeItem(CONFIG_STORAGE_KEY); } catch { /* ignore */ }
|
||||
notifyConfigChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user