Files
igny8/frontend/src/store/sectorStore.ts
2025-11-09 10:27:02 +00:00

169 lines
5.8 KiB
TypeScript

/**
* Sector Store (Zustand)
* Manages the currently selected/active sector for filtering data globally
* Sectors are scoped under the selected site, so sector selection depends on site selection.
*/
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { fetchSiteSectors } from '../services/api';
export interface Sector {
id: number;
name: string;
slug: string;
site_id: number;
is_active: boolean;
industry_sector?: number | null; // IndustrySector ID (FK to IndustrySector template)
}
interface SectorState {
activeSector: Sector | null;
sectors: Sector[]; // List of sectors for the current site
loading: boolean;
error: string | null;
// Actions
setActiveSector: (sector: Sector | null) => void;
loadSectorsForSite: (siteId: number) => Promise<Sector[]>;
clearActiveSector: () => void;
}
export const useSectorStore = create<SectorState>()(
persist<SectorState>(
(set, get) => ({
activeSector: null,
sectors: [],
loading: false,
error: null,
setActiveSector: (sector) => {
set({ activeSector: sector, error: null });
// Ensure sector is persisted immediately
if (typeof window !== 'undefined') {
try {
const state = get();
localStorage.setItem('sector-storage', JSON.stringify({
state: { activeSector: sector },
version: 0
}));
} catch (e) {
console.warn('Failed to persist sector to localStorage:', e);
}
}
// Dispatch event for components to refresh data
window.dispatchEvent(new CustomEvent('sectorChanged', { detail: { sectorId: sector?.id, siteId: sector?.site_id } }));
},
loadSectorsForSite: async (siteId: number) => {
set({ loading: true, error: null });
try {
// Don't try to load sectors if siteId is invalid
if (!siteId) {
set({ sectors: [], loading: false });
return [];
}
const sectorsData = await fetchSiteSectors(siteId);
const sectors: Sector[] = sectorsData.map((s: any) => ({
id: s.id,
name: s.name,
slug: s.slug,
site_id: siteId,
is_active: s.is_active !== false,
industry_sector: s.industry_sector || null, // Include industry_sector from API
}));
// Store sectors list in state
set({ sectors, loading: false });
// Default to "All Sectors" (null) - don't auto-select first sector
// Only update if current sector belongs to a different site
const currentSector = get().activeSector;
if (currentSector && currentSector.site_id !== siteId) {
// Current sector belongs to different site, reset to null (All Sectors)
set({ activeSector: null });
// Persist immediately
if (typeof window !== 'undefined') {
try {
localStorage.setItem('sector-storage', JSON.stringify({
state: { activeSector: null },
version: 0
}));
} catch (e) {
console.warn('Failed to persist sector to localStorage:', e);
}
}
// Dispatch event
window.dispatchEvent(new CustomEvent('sectorChanged', { detail: { sectorId: null, siteId } }));
} else if (currentSector && currentSector.site_id === siteId) {
// Verify current sector still exists in the list
const sectorStillExists = sectors.find(s => s.id === currentSector.id);
if (!sectorStillExists) {
// Current sector was deleted, reset to null (All Sectors)
set({ activeSector: null });
// Persist and dispatch event
if (typeof window !== 'undefined') {
try {
localStorage.setItem('sector-storage', JSON.stringify({
state: { activeSector: null },
version: 0
}));
} catch (e) {
console.warn('Failed to persist sector to localStorage:', e);
}
}
window.dispatchEvent(new CustomEvent('sectorChanged', { detail: { sectorId: null, siteId } }));
}
}
// If no current sector, keep it as null (All Sectors) - default behavior
return sectors;
} catch (error: any) {
// If 403 or 404, the site might be inactive or inaccessible - clear sectors silently
const isAccessError = error.status === 403 || error.status === 404;
if (isAccessError) {
console.warn(`Cannot load sectors for site ${siteId}: site may be inactive or inaccessible`);
set({
sectors: [],
activeSector: null, // Clear active sector if site is inaccessible
loading: false,
error: null // Don't show error for access issues
});
return [];
}
set({
error: error.message || 'Failed to load sectors',
loading: false
});
return [];
}
},
clearActiveSector: () => {
set({ activeSector: null, sectors: [], error: null });
if (typeof window !== 'undefined') {
try {
localStorage.setItem('sector-storage', JSON.stringify({
state: { activeSector: null },
version: 0
}));
} catch (e) {
console.warn('Failed to persist sector to localStorage:', e);
}
}
},
}),
{
name: 'sector-storage',
partialize: (state) => ({
activeSector: state.activeSector,
}),
}
)
);