169 lines
5.8 KiB
TypeScript
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,
|
|
}),
|
|
}
|
|
)
|
|
);
|
|
|