import { create } from 'zustand'; import { devtools, persist } from 'zustand/middleware'; import { User, Medication, HealthStat, DrugInteraction } from '../types/api'; import apiService from '../services/api'; interface AuthState { user: User | null; token: string | null; isAuthenticated: boolean; isLoading: boolean; error: string | null; // Actions login: (email: string, password: string) => Promise; register: (username: string, email: string, password: string) => Promise; logout: () => Promise; clearError: () => void; loadUser: () => Promise; } interface MedicationState { medications: Medication[]; selectedMedication: Medication | null; isLoading: boolean; error: string | null; // Actions loadMedications: () => Promise; createMedication: (data: any) => Promise; updateMedication: (id: string, data: any) => Promise; deleteMedication: (id: string) => Promise; selectMedication: (medication: Medication | null) => void; clearError: () => void; } interface HealthState { stats: HealthStat[]; trends: any[]; isLoading: boolean; error: string | null; // Actions loadStats: () => Promise; createStat: (data: any) => Promise; updateStat: (id: string, data: any) => Promise; deleteStat: (id: string) => Promise; loadTrends: () => Promise; clearError: () => void; } interface InteractionState { interactions: DrugInteraction[]; isChecking: boolean; error: string | null; // Actions checkInteractions: (medications: string[]) => Promise; checkNewMedication: (name: string, dosage: string) => Promise; clearInteractions: () => void; clearError: () => void; } // Auth Store export const useAuthStore = create()( devtools( persist( (set, get) => ({ user: null, token: null, isAuthenticated: false, isLoading: false, error: null, login: async (email: string, password: string) => { set({ isLoading: true, error: null }); try { const response = await apiService.login(email, password); set({ user: { user_id: response.user_id, username: response.username, email: email, role: 'patient', }, token: response.token, isAuthenticated: true, isLoading: false, }); } catch (error: any) { set({ error: error.message || 'Login failed', isLoading: false, isAuthenticated: false, }); throw error; } }, register: async (username: string, email: string, password: string) => { set({ isLoading: true, error: null }); try { const response = await apiService.register({ username, email, password, role: 'patient', }); set({ user: { user_id: response.user_id, username: response.username, email: email, role: 'patient', }, token: response.token, isAuthenticated: true, isLoading: false, }); } catch (error: any) { set({ error: error.message || 'Registration failed', isLoading: false, isAuthenticated: false, }); throw error; } }, logout: async () => { await apiService.logout(); set({ user: null, token: null, isAuthenticated: false, error: null, }); }, clearError: () => set({ error: null }), loadUser: async () => { const token = get().token; if (!token) return; set({ isLoading: true }); try { const user = await apiService.getCurrentUser(); set({ user, isAuthenticated: true, isLoading: false, }); } catch (error: any) { set({ error: error.message, isLoading: false, isAuthenticated: false, }); } }, }), { name: 'normogen-auth', partialize: (state) => ({ token: state.token, user: state.user, isAuthenticated: state.isAuthenticated, }), } ) ) ); // Medication Store export const useMedicationStore = create()( devtools((set, get) => ({ medications: [], selectedMedication: null, isLoading: false, error: null, loadMedications: async () => { set({ isLoading: true, error: null }); try { const medications = await apiService.getMedications(); set({ medications, isLoading: false }); } catch (error: any) { set({ error: error.message || 'Failed to load medications', isLoading: false, }); } }, createMedication: async (data: any) => { set({ isLoading: true, error: null }); try { const medication = await apiService.createMedication(data); set((state) => ({ medications: [...state.medications, medication], isLoading: false, })); } catch (error: any) { set({ error: error.message || 'Failed to create medication', isLoading: false, }); throw error; } }, updateMedication: async (id: string, data: any) => { set({ isLoading: true, error: null }); try { const updated = await apiService.updateMedication(id, data); set((state) => ({ medications: state.medications.map((med) => med.medication_id === id ? updated : med ), isLoading: false, })); } catch (error: any) { set({ error: error.message || 'Failed to update medication', isLoading: false, }); throw error; } }, deleteMedication: async (id: string) => { set({ isLoading: true, error: null }); try { await apiService.deleteMedication(id); set((state) => ({ medications: state.medications.filter( (med) => med.medication_id !== id ), isLoading: false, })); } catch (error: any) { set({ error: error.message || 'Failed to delete medication', isLoading: false, }); throw error; } }, selectMedication: (medication) => { set({ selectedMedication: medication }); }, clearError: () => set({ error: null }), })) ); // Health Store export const useHealthStore = create()( devtools((set, get) => ({ stats: [], trends: [], isLoading: false, error: null, loadStats: async () => { set({ isLoading: true, error: null }); try { const stats = await apiService.getHealthStats(); set({ stats, isLoading: false }); } catch (error: any) { set({ error: error.message || 'Failed to load health stats', isLoading: false, }); } }, createStat: async (data: any) => { set({ isLoading: true, error: null }); try { const stat = await apiService.createHealthStat(data); set((state) => ({ stats: [...state.stats, stat], isLoading: false, })); } catch (error: any) { set({ error: error.message || 'Failed to create stat', isLoading: false, }); throw error; } }, updateStat: async (id: string, data: any) => { set({ isLoading: true, error: null }); try { const updated = await apiService.updateHealthStat(id, data); set((state) => ({ stats: state.stats.map((stat) => stat.stat_id === id ? updated : stat ), isLoading: false, })); } catch (error: any) { set({ error: error.message || 'Failed to update stat', isLoading: false, }); throw error; } }, deleteStat: async (id: string) => { set({ isLoading: true, error: null }); try { await apiService.deleteHealthStat(id); set((state) => ({ stats: state.stats.filter((stat) => stat.stat_id !== id), isLoading: false, })); } catch (error: any) { set({ error: error.message || 'Failed to delete stat', isLoading: false, }); throw error; } }, loadTrends: async () => { set({ isLoading: true, error: null }); try { const trends = await apiService.getHealthTrends(); set({ trends, isLoading: false }); } catch (error: any) { set({ error: error.message || 'Failed to load trends', isLoading: false, }); } }, clearError: () => set({ error: null }), })) ); // Interaction Store (Phase 2.8) export const useInteractionStore = create()( devtools((set, get) => ({ interactions: [], isChecking: false, error: null, checkInteractions: async (medications: string[]) => { set({ isChecking: true, error: null }); try { const interactions = await apiService.checkInteractions(medications); set({ interactions, isChecking: false }); } catch (error: any) { set({ error: error.message || 'Failed to check interactions', isChecking: false, }); } }, checkNewMedication: async (name: string, dosage: string) => { set({ isChecking: true, error: null }); try { const interactions = await apiService.checkNewMedication(name, dosage); set({ interactions, isChecking: false }); } catch (error: any) { set({ error: error.message || 'Failed to check medication', isChecking: false, }); } }, clearInteractions: () => set({ interactions: [] }), clearError: () => set({ error: null }), })) );