@mytec Phase 1 - Core UI & Manual Input, Phase 2 - RF Calculation Engine, Phase 3 - Heatmap Visualization
This commit is contained in:
99
frontend/src/store/sites.ts
Normal file
99
frontend/src/store/sites.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { create } from 'zustand';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import type { Site, SiteFormData } from '@/types/index.ts';
|
||||
import { db } from '@/db/schema.ts';
|
||||
|
||||
const SITE_COLORS = [
|
||||
'#ef4444', '#3b82f6', '#22c55e', '#f59e0b', '#8b5cf6',
|
||||
'#ec4899', '#14b8a6', '#f97316', '#6366f1', '#84cc16',
|
||||
];
|
||||
|
||||
interface SitesState {
|
||||
sites: Site[];
|
||||
selectedSiteId: string | null;
|
||||
editingSiteId: string | null;
|
||||
isPlacingMode: boolean;
|
||||
|
||||
loadSites: () => Promise<void>;
|
||||
addSite: (data: SiteFormData) => Promise<Site>;
|
||||
updateSite: (id: string, data: Partial<Site>) => Promise<void>;
|
||||
deleteSite: (id: string) => Promise<void>;
|
||||
selectSite: (id: string | null) => void;
|
||||
setEditingSite: (id: string | null) => void;
|
||||
togglePlacingMode: () => void;
|
||||
setPlacingMode: (val: boolean) => void;
|
||||
}
|
||||
|
||||
export const useSitesStore = create<SitesState>((set, get) => ({
|
||||
sites: [],
|
||||
selectedSiteId: null,
|
||||
editingSiteId: null,
|
||||
isPlacingMode: false,
|
||||
|
||||
loadSites: async () => {
|
||||
const dbSites = await db.sites.toArray();
|
||||
const sites: Site[] = dbSites.map((s) => ({
|
||||
...JSON.parse(s.data),
|
||||
createdAt: new Date(s.createdAt),
|
||||
updatedAt: new Date(s.updatedAt),
|
||||
}));
|
||||
set({ sites });
|
||||
},
|
||||
|
||||
addSite: async (data: SiteFormData) => {
|
||||
const id = uuidv4();
|
||||
const now = new Date();
|
||||
const colorIndex = get().sites.length % SITE_COLORS.length;
|
||||
const site: Site = {
|
||||
...data,
|
||||
id,
|
||||
color: data.color || SITE_COLORS[colorIndex],
|
||||
visible: true,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
await db.sites.put({
|
||||
id,
|
||||
data: JSON.stringify(site),
|
||||
createdAt: now.getTime(),
|
||||
updatedAt: now.getTime(),
|
||||
});
|
||||
set((state) => ({ sites: [...state.sites, site] }));
|
||||
return site;
|
||||
},
|
||||
|
||||
updateSite: async (id: string, data: Partial<Site>) => {
|
||||
const sites = get().sites;
|
||||
const existing = sites.find((s) => s.id === id);
|
||||
if (!existing) return;
|
||||
|
||||
const updated: Site = {
|
||||
...existing,
|
||||
...data,
|
||||
updatedAt: new Date(),
|
||||
};
|
||||
await db.sites.put({
|
||||
id,
|
||||
data: JSON.stringify(updated),
|
||||
createdAt: existing.createdAt.getTime(),
|
||||
updatedAt: updated.updatedAt.getTime(),
|
||||
});
|
||||
set((state) => ({
|
||||
sites: state.sites.map((s) => (s.id === id ? updated : s)),
|
||||
}));
|
||||
},
|
||||
|
||||
deleteSite: async (id: string) => {
|
||||
await db.sites.delete(id);
|
||||
set((state) => ({
|
||||
sites: state.sites.filter((s) => s.id !== id),
|
||||
selectedSiteId: state.selectedSiteId === id ? null : state.selectedSiteId,
|
||||
editingSiteId: state.editingSiteId === id ? null : state.editingSiteId,
|
||||
}));
|
||||
},
|
||||
|
||||
selectSite: (id: string | null) => set({ selectedSiteId: id }),
|
||||
setEditingSite: (id: string | null) => set({ editingSiteId: id }),
|
||||
togglePlacingMode: () => set((s) => ({ isPlacingMode: !s.isPlacingMode })),
|
||||
setPlacingMode: (val: boolean) => set({ isPlacingMode: val }),
|
||||
}));
|
||||
Reference in New Issue
Block a user