import { create } from 'zustand' import { persist } from 'zustand/middleware' import type { MarathonResponse, AssignmentResponse } from '@shared/types' interface MarathonState { marathons: MarathonResponse[] selectedMarathonId: number | null currentAssignment: AssignmentResponse | null isLoading: boolean error: string | null loadMarathons: () => Promise selectMarathon: (marathonId: number) => Promise loadCurrentAssignment: () => Promise syncTime: (minutes: number) => Promise reset: () => void } export const useMarathonStore = create()( persist( (set, get) => ({ marathons: [], selectedMarathonId: null, currentAssignment: null, isLoading: false, error: null, loadMarathons: async () => { set({ isLoading: true, error: null }) const result = await window.electronAPI.apiRequest('GET', '/marathons') if (!result.success) { set({ isLoading: false, error: result.error || 'Failed to load marathons' }) return } const marathons = result.data || [] const activeMarathons = marathons.filter(m => m.status === 'active') set({ marathons: activeMarathons, isLoading: false }) // If we have a selected marathon, verify it's still valid const { selectedMarathonId } = get() if (selectedMarathonId) { const stillExists = activeMarathons.some(m => m.id === selectedMarathonId) if (!stillExists && activeMarathons.length > 0) { // Select first available marathon await get().selectMarathon(activeMarathons[0].id) } else if (stillExists) { // Reload assignment for current selection await get().loadCurrentAssignment() } } else if (activeMarathons.length > 0) { // No selection, select first marathon await get().selectMarathon(activeMarathons[0].id) } }, selectMarathon: async (marathonId: number) => { set({ selectedMarathonId: marathonId, currentAssignment: null }) await get().loadCurrentAssignment() }, loadCurrentAssignment: async () => { const { selectedMarathonId } = get() if (!selectedMarathonId) { set({ currentAssignment: null }) return } const result = await window.electronAPI.apiRequest( 'GET', `/marathons/${selectedMarathonId}/current-assignment` ) if (result.success) { set({ currentAssignment: result.data ?? null }) } else { // User might not be participant of this marathon set({ currentAssignment: null, error: result.error }) } }, syncTime: async (minutes: number) => { const { currentAssignment } = get() if (!currentAssignment || currentAssignment.status !== 'active') { return } const result = await window.electronAPI.apiRequest( 'PATCH', `/assignments/${currentAssignment.id}/track-time`, { minutes } ) if (result.success) { // Update local assignment with new tracked time set({ currentAssignment: { ...currentAssignment, tracked_time_minutes: minutes } }) } }, reset: () => { set({ marathons: [], selectedMarathonId: null, currentAssignment: null, isLoading: false, error: null }) } }), { name: 'marathon-storage', partialize: (state) => ({ selectedMarathonId: state.selectedMarathonId }) } ) )