All files / src/stores eventStore.ts

100% Statements 18/18
100% Branches 0/0
100% Functions 15/15
100% Lines 14/14

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117                                                                                        2x           2x       2x   2x                   54x               39x         3x         2x         49x     9x 39x       14x         40x               249x            
/**
 * Event Management Zustand Store
 *
 * Story 2.5.3 - Task 6b (GREEN Phase)
 * AC18: State Management
 *
 * Manages UI state for event management feature:
 * - Filter state (persisted in localStorage)
 * - Selected event code (transient, not persisted) - Story 1.16.2: uses eventCode as identifier
 * - Modal states (transient, not persisted)
 *
 * Uses Zustand with persist middleware for filter persistence only.
 * Modal states and selected event are NOT persisted (transient UI state).
 */
 
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { EventFilters } from '@/types/event.types';
 
export interface EventPagination {
  page: number;
  limit: number;
}
 
export interface EventStore {
  // State
  filters: EventFilters;
  pagination: EventPagination;
  selectedEventCode?: string;
  isCreateModalOpen: boolean;
  isEditModalOpen: boolean;
 
  // Actions
  setFilters: (filters: EventFilters) => void;
  setPagination: (pagination: Partial<EventPagination>) => void;
  setPage: (page: number) => void;
  setLimit: (limit: number) => void;
  setSelectedEventCode: (eventCode?: string) => void;
  openCreateModal: () => void;
  closeCreateModal: () => void;
  openEditModal: (eventCode: string) => void;
  closeEditModal: () => void;
}
 
const DEFAULT_PAGINATION: EventPagination = {
  page: 1,
  limit: 20,
};
 
// Default filter: exclude ARCHIVED events via includeArchived flag
const DEFAULT_FILTERS: EventFilters = {
  includeArchived: false,
};
 
export const useEventStore = create<EventStore>()(
  persist(
    (set) => ({
      // Initial state
      filters: DEFAULT_FILTERS,
      pagination: DEFAULT_PAGINATION,
      selectedEventCode: undefined,
      isCreateModalOpen: false,
      isEditModalOpen: false,
 
      // Filter management
      setFilters: (filters: EventFilters) =>
        set((state) => ({
          filters,
          // Reset to page 1 when filters change
          pagination: { ...state.pagination, page: 1 },
        })),
 
      // Pagination management
      setPagination: (pagination: Partial<EventPagination>) =>
        set((state) => ({
          pagination: { ...state.pagination, ...pagination },
        })),
 
      setPage: (page: number) =>
        set((state) => ({
          pagination: { ...state.pagination, page },
        })),
 
      setLimit: (limit: number) =>
        set((state) => ({
          pagination: { ...state.pagination, limit, page: 1 }, // Reset to page 1 when limit changes
        })),
 
      // Selected event management (Story 1.16.2: uses eventCode as identifier)
      setSelectedEventCode: (eventCode?: string) => set({ selectedEventCode: eventCode }),
 
      // Create modal management
      openCreateModal: () => set({ isCreateModalOpen: true }),
      closeCreateModal: () => set({ isCreateModalOpen: false }),
 
      // Edit modal management
      openEditModal: (eventCode: string) =>
        set({
          selectedEventCode: eventCode,
          isEditModalOpen: true,
        }),
      closeEditModal: () =>
        set({
          isEditModalOpen: false,
          selectedEventCode: undefined,
        }),
    }),
    {
      name: 'event-store', // localStorage key
      // Partial persist: only persist filters (NOT modals, pagination, or selectedEventCode)
      partialize: (state) => ({
        filters: state.filters,
      }),
    }
  )
);