Files
Auditor-Portal-Revamp/src/store/feedStore.ts
2026-07-15 14:24:26 +05:30

209 lines
7.0 KiB
TypeScript

import { create } from 'zustand';
import { persist } from 'zustand/middleware';
// Feed/session sort. '' = backend default order (id DESC on the pending
// feed). One choice drives the whole chain: feed table, session pages,
// dashboard batch numbering and the "continue auditing" start page - they
// must all use the same order or batch N stops matching session page N.
export type FeedSortBy = '' | 'id' | 'date' | 'chainage' | 'latlong';
export type FeedSortDir = 'asc' | 'desc';
export interface FeedTab {
// '' = pending tab; 'YYYY-MM-DD' or 'YYYY-MM-DD_YYYY-MM-DD' (range) = history tab
date: string;
isRectificationTab: boolean;
// History tabs only: show records audited BY the logged-in user
auditedByMe?: boolean;
totalAnomalyCount: number;
anomalies: any[];
anomaliesCopy: any[];
selectedAnomalyIndex: number;
filters: any;
page: number;
rowsPerPage: number;
}
// Tracks what filter params were last used to fetch dashboard stats
interface DashboardCache {
siteId: string;
auditStatus: string;
fromDate: string;
tillDate: string;
assetIds: string;
minChainage: string;
maxChainage: string;
searchAnomalyId: string;
filterPlaza: string;
isRectificationEnabled?: boolean;
date?: string;
sortBy?: string;
sortDir?: string;
stats: {
globalTotal: number;
batchTotal: number;
batchAudited: number;
batchPending: number;
batchAnomaliesFound: number;
firstPendingIndex: number;
} | null;
}
interface FeedState {
tabs: FeedTab[];
selectedTabIndex: number;
assets: any[];
assetTypes: any[];
filterFromDate: string;
filterTillDate: string;
filterMinChainage: string;
filterMaxChainage: string;
filterPlaza: string;
selectedAssetIds: number[];
sites: any[];
auditStatus: string;
selectedSite: any;
isFiltersModalOpen: boolean;
isInitialized: boolean;
// Cache: last filter key used for the second GlobalFeed effect
lastFetchedFilterKey: string;
// Dashboard stats cache
dashboardCache: DashboardCache;
searchAnomalyId: string;
isRectificationEnabled: boolean;
isFeedLoading: boolean;
sortBy: FeedSortBy;
sortDir: FeedSortDir;
// Actions
setTabs: (tabs: FeedTab[]) => void;
setSelectedTabIndex: (index: number) => void;
setAssets: (assets: any[]) => void;
setAssetTypes: (assetTypes: any[]) => void;
setSelectedAssetIds: (ids: number[]) => void;
setSites: (sites: any[]) => void;
setSelectedSite: (site: any) => void;
setAuditStatus: (status: string) => void;
setIsFiltersModalOpen: (isOpen: boolean) => void;
setIsInitialized: (val: boolean) => void;
setLastFetchedFilterKey: (key: string) => void;
setDashboardCache: (cache: DashboardCache) => void;
addTab: (tab: FeedTab) => void;
closeTab: (index: number) => void;
updateTab: (index: number, partialTab: Partial<FeedTab>) => void;
setFilterFromDate: (date: string) => void;
setFilterTillDate: (date: string) => void;
setFilterMinChainage: (val: string) => void;
setFilterMaxChainage: (val: string) => void;
setFilterPlaza: (val: string) => void;
setSearchAnomalyId: (id: string) => void;
setIsRectificationEnabled: (val: boolean) => void;
setIsFeedLoading: (val: boolean) => void;
setSortBy: (val: FeedSortBy) => void;
setSortDir: (val: FeedSortDir) => void;
resetStore: () => void;
}
const EMPTY_DASHBOARD_CACHE: DashboardCache = {
siteId: '__unset__',
auditStatus: '__unset__',
fromDate: '__unset__',
tillDate: '__unset__',
assetIds: '__unset__',
minChainage: '__unset__',
maxChainage: '__unset__',
searchAnomalyId: '__unset__',
filterPlaza: '__unset__',
isRectificationEnabled: false,
date: '',
stats: null,
};
const initialFeedState = {
tabs: [],
selectedTabIndex: -1,
assets: [],
assetTypes: [],
filterFromDate: '',
filterTillDate: '',
filterMinChainage: '',
filterMaxChainage: '',
filterPlaza: '',
selectedAssetIds: [],
selectedSite: null,
sites: [],
auditStatus: 'Manual',
isFiltersModalOpen: false,
isInitialized: false,
lastFetchedFilterKey: '',
dashboardCache: EMPTY_DASHBOARD_CACHE,
searchAnomalyId: '',
isRectificationEnabled: false,
isFeedLoading: false,
sortBy: '' as FeedSortBy,
sortDir: 'asc' as FeedSortDir,
};
export const useFeedStore = create<FeedState>()(
persist(
(set) => ({
...initialFeedState,
resetStore: () => set(initialFeedState),
setTabs: (tabs) => set({ tabs }),
setSelectedTabIndex: (index) => set({ selectedTabIndex: index }),
setAssets: (assets) => set({ assets }),
setAssetTypes: (assetTypes) => set({ assetTypes }),
setSelectedAssetIds: (selectedAssetIds) => set({ selectedAssetIds }),
setSites: (sites) => set({ sites }),
setSelectedSite: (selectedSite) => set({ selectedSite }),
setAuditStatus: (auditStatus) => set({ auditStatus }),
setIsFiltersModalOpen: (isFiltersModalOpen) => set({ isFiltersModalOpen }),
setIsInitialized: (isInitialized) => set({ isInitialized }),
setLastFetchedFilterKey: (lastFetchedFilterKey) => set({ lastFetchedFilterKey }),
setDashboardCache: (dashboardCache) => set({ dashboardCache }),
setFilterFromDate: (filterFromDate) => set({ filterFromDate }),
setFilterTillDate: (filterTillDate) => set({ filterTillDate }),
setFilterMinChainage: (filterMinChainage) => set({ filterMinChainage }),
setFilterMaxChainage: (filterMaxChainage) => set({ filterMaxChainage }),
setFilterPlaza: (filterPlaza) => set({ filterPlaza }),
setSearchAnomalyId: (searchAnomalyId) => set({ searchAnomalyId }),
setIsRectificationEnabled: (isRectificationEnabled) => set({ isRectificationEnabled }),
setIsFeedLoading: (isFeedLoading) => set({ isFeedLoading }),
setSortBy: (sortBy) => set({ sortBy }),
setSortDir: (sortDir) => set({ sortDir }),
addTab: (tab) => set((state) => ({ tabs: [...state.tabs, tab], selectedTabIndex: state.tabs.length })),
closeTab: (index) => set((state) => {
const newTabs = [...state.tabs];
newTabs.splice(index, 1);
const newIndex = state.selectedTabIndex >= newTabs.length ? newTabs.length - 1 : state.selectedTabIndex;
return { tabs: newTabs, selectedTabIndex: newIndex };
}),
updateTab: (index, partialTab) => set((state) => {
const newTabs = [...state.tabs];
newTabs[index] = { ...newTabs[index], ...partialTab };
return { tabs: newTabs };
})
}),
{
name: 'feed-store-storage',
partialize: (state) => ({
tabs: state.tabs,
selectedTabIndex: state.selectedTabIndex,
filterFromDate: state.filterFromDate,
filterTillDate: state.filterTillDate,
filterMinChainage: state.filterMinChainage,
filterMaxChainage: state.filterMaxChainage,
filterPlaza: state.filterPlaza,
selectedAssetIds: state.selectedAssetIds,
selectedSite: state.selectedSite,
auditStatus: state.auditStatus,
searchAnomalyId: state.searchAnomalyId,
isRectificationEnabled: state.isRectificationEnabled,
sortBy: state.sortBy,
sortDir: state.sortDir,
}),
}
)
);