/** * useStore Hook * * Manages feature store interactions: loading catalog, activating/deactivating features. * After each mutation, refreshes featureStore and dispatches 'features-changed' event * so navigation and other components update in real-time. */ import { useState, useCallback, useEffect } from 'react'; import { fetchStoreFeatures, activateStoreFeature, deactivateStoreFeature, fetchUserMandates, fetchSubscriptionInfo, type StoreFeature, type UserMandate, type SubscriptionInfo, } from '../api/storeApi'; import { useFeatureStore } from '../stores/featureStore'; interface UseStoreReturn { features: StoreFeature[]; mandates: UserMandate[]; subscriptionInfo: SubscriptionInfo | null; loading: boolean; actionLoading: string | null; error: string | null; loadStore: () => Promise; loadSubscriptionInfo: (mandateId?: string) => Promise; activate: (featureCode: string, mandateId?: string) => Promise; deactivate: (featureCode: string, mandateId: string, instanceId: string) => Promise; } export function useStore(): UseStoreReturn { const [features, setFeatures] = useState([]); const [mandates, setMandates] = useState([]); const [subscriptionInfo, setSubscriptionInfo] = useState(null); const [loading, setLoading] = useState(true); const [actionLoading, setActionLoading] = useState(null); const [error, setError] = useState(null); const featureStore = useFeatureStore(); const loadSubscriptionInfo = useCallback(async (mandateId?: string) => { try { const info = await fetchSubscriptionInfo(mandateId); setSubscriptionInfo(info); } catch { // non-critical } }, []); const loadStore = useCallback(async () => { setLoading(true); setError(null); try { const [data, userMandates] = await Promise.all([ fetchStoreFeatures(), fetchUserMandates(), ]); setFeatures(data); setMandates(userMandates); const firstMandateId = userMandates.length > 0 ? userMandates[0].id : undefined; await loadSubscriptionInfo(firstMandateId); } catch (err: unknown) { const msg = err instanceof Error ? err.message : 'Failed to load store'; setError(msg); } finally { setLoading(false); } }, [loadSubscriptionInfo]); useEffect(() => { loadStore(); }, [loadStore]); const _refreshAfterAction = useCallback(async () => { await featureStore.loadFeatures(); window.dispatchEvent(new CustomEvent('features-changed')); await loadStore(); }, [featureStore, loadStore]); const activate = useCallback(async (featureCode: string, mandateId?: string) => { setActionLoading(featureCode); setError(null); try { await activateStoreFeature(featureCode, mandateId); await _refreshAfterAction(); } catch (err: unknown) { const msg = err instanceof Error ? err.message : 'Activation failed'; setError(msg); } finally { setActionLoading(null); } }, [_refreshAfterAction]); const deactivate = useCallback(async (featureCode: string, mandateId: string, instanceId: string) => { setActionLoading(featureCode); setError(null); try { await deactivateStoreFeature(featureCode, mandateId, instanceId); await _refreshAfterAction(); } catch (err: unknown) { const msg = err instanceof Error ? err.message : 'Deactivation failed'; setError(msg); } finally { setActionLoading(null); } }, [_refreshAfterAction]); return { features, mandates, subscriptionInfo, loading, actionLoading, error, loadStore, loadSubscriptionInfo, activate, deactivate }; } export default useStore;