sms-extension/client/src/context/BusinessContext.jsx

147 lines
5.0 KiB
JavaScript

/* eslint-disable react-refresh/only-export-components */
import { createContext, useContext, useState, useEffect, useCallback } from 'react';
import apiClient from '../api/client';
import { getRuntimeCompanyId } from '../utils/runtimeContext';
const BusinessContext = createContext(null);
const SESSION_KEY = 'sms_active_business';
export function BusinessProvider({ children }) {
const [activeBusiness, setActiveBusinessState] = useState(null);
const [hasGlobalSms, setHasGlobalSms] = useState(false);
const [isSetupComplete, setIsSetupComplete] = useState(false);
const [hasSelectedTemplates, setHasSelectedTemplates] = useState(false);
const [loading, setLoading] = useState(true);
const updateReadyState = useCallback((activeProfile, templates = []) => {
const hasProfile = !!activeProfile;
setHasGlobalSms(hasProfile);
const p = activeProfile?.provider || {};
const nextIsSetupComplete = hasProfile && !!p.providerName && !!p.senderId && !!p.dltEntityId;
setIsSetupComplete(nextIsSetupComplete);
const nextHasSelectedTemplates = Array.isArray(templates)
? templates.some((template) => !!template?.selectedTemplate)
: false;
setHasSelectedTemplates(nextHasSelectedTemplates);
return {
hasGlobalSms: hasProfile,
isSetupComplete: nextIsSetupComplete,
hasSelectedTemplates: nextHasSelectedTemplates,
};
}, []);
const refreshOnboardingState = useCallback(async (businessIdOverride) => {
const targetBusinessId = businessIdOverride || activeBusiness?.businessId;
if (!targetBusinessId) {
setHasGlobalSms(false);
setIsSetupComplete(false);
setHasSelectedTemplates(false);
return {
hasGlobalSms: false,
isSetupComplete: false,
hasSelectedTemplates: false,
};
}
const [smsRes, templatesRes] = await Promise.all([
apiClient.get(`/api/businesses/${targetBusinessId}/global-sms/active`).catch(() => ({ data: {} })),
apiClient.get(`/api/businesses/${targetBusinessId}/templates`).catch(() => ({ data: { templates: [] } })),
]);
return updateReadyState(smsRes.data?.activeProfile, templatesRes.data?.templates || []);
}, [activeBusiness?.businessId, updateReadyState]);
// On mount: rehydrate from sessionStorage and refresh from API
useEffect(() => {
async function rehydrate() {
const stored = sessionStorage.getItem(SESSION_KEY);
if (!stored) { setLoading(false); return; }
try {
const { businessId, companyId } = JSON.parse(stored);
const runtimeCompanyId = getRuntimeCompanyId();
if (runtimeCompanyId && companyId && runtimeCompanyId !== companyId) {
throw new Error('Stored business belongs to a different company context');
}
const [bizRes, smsRes] = await Promise.all([
apiClient.get(`/api/businesses/${businessId}`),
Promise.all([
apiClient.get(`/api/businesses/${businessId}/global-sms/active`).catch(() => ({ data: {} })),
apiClient.get(`/api/businesses/${businessId}/templates`).catch(() => ({ data: { templates: [] } })),
]),
]);
setActiveBusinessState(bizRes.data);
updateReadyState(smsRes[0].data?.activeProfile, smsRes[1].data?.templates || []);
sessionStorage.setItem(SESSION_KEY, JSON.stringify({
businessId,
companyId: runtimeCompanyId || companyId || '',
}));
} catch {
// Business no longer exists — clear stale session
sessionStorage.removeItem(SESSION_KEY);
setActiveBusinessState(null);
setHasGlobalSms(false);
setIsSetupComplete(false);
setHasSelectedTemplates(false);
} finally {
setLoading(false);
}
}
rehydrate();
}, [updateReadyState]);
const setActiveBusiness = useCallback(async (business) => {
setActiveBusinessState(business);
sessionStorage.setItem(SESSION_KEY, JSON.stringify({
businessId: business.businessId,
companyId: getRuntimeCompanyId(),
}));
try {
const progress = await refreshOnboardingState(business.businessId);
return progress.isSetupComplete;
} catch {
setHasGlobalSms(false);
setIsSetupComplete(false);
setHasSelectedTemplates(false);
return false;
}
}, [refreshOnboardingState]);
const clearBusiness = useCallback(() => {
setActiveBusinessState(null);
setHasGlobalSms(false);
setIsSetupComplete(false);
setHasSelectedTemplates(false);
sessionStorage.removeItem(SESSION_KEY);
}, []);
const activeBusinessId = activeBusiness?.businessId || null;
return (
<BusinessContext.Provider value={{
activeBusiness,
activeBusinessId,
setActiveBusiness,
clearBusiness,
loading,
hasGlobalSms,
setHasGlobalSms,
isSetupComplete,
setIsSetupComplete,
hasSelectedTemplates,
setHasSelectedTemplates,
refreshOnboardingState,
}}>
{children}
</BusinessContext.Provider>
);
}
export function useBusiness() {
return useContext(BusinessContext);
}