Files
sam-react-prod/src/stores/useCalendarScheduleStore.ts

123 lines
4.2 KiB
TypeScript
Raw Normal View History

/**
* Zustand Store
*
* (CalendarManagement) //
* ScheduleCalendar, DatePicker .
*
* :
* 1. ScheduleCalendar fetchSchedules(year)
* 2. API schedulesByYear에
* 3. calendarEvents.ts (isHoliday )
* 4. API calendarEvents.ts
*/
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
import type { CalendarSchedule } from '@/components/hr/CalendarManagement/types';
import { getCalendarSchedules } from '@/components/hr/CalendarManagement/actions';
interface CalendarScheduleStore {
/** 연도별 캐시된 일정 */
schedulesByYear: Record<number, CalendarSchedule[]>;
/** 연도별 로딩 완료 여부 */
loadedYears: Record<number, boolean>;
/** 연도별 로딩 중 여부 */
loadingYears: Record<number, boolean>;
/** 연도별 일정 조회 (캐시 히트 시 API 호출 안 함) */
fetchSchedules: (year: number) => Promise<CalendarSchedule[]>;
/** 이미 가져온 데이터를 스토어에 직접 설정 (추가 API 호출 없음) */
setSchedulesForYear: (year: number, schedules: CalendarSchedule[]) => void;
/** 특정 연도 캐시 무효화 (달력관리에서 등록/수정/삭제 후 호출) */
invalidateYear: (year: number) => void;
}
export const useCalendarScheduleStore = create<CalendarScheduleStore>()(
devtools(
(set, get) => ({
schedulesByYear: {},
loadedYears: {},
loadingYears: {},
fetchSchedules: async (year: number) => {
const { loadedYears, loadingYears, schedulesByYear } = get();
// 이미 로드됨
if (loadedYears[year]) {
return schedulesByYear[year] || [];
}
// 이미 로딩 중 (중복 호출 방지)
if (loadingYears[year]) {
return schedulesByYear[year] || [];
}
set(
(state) => ({
loadingYears: { ...state.loadingYears, [year]: true },
}),
false,
'fetchSchedules/start'
);
try {
const result = await getCalendarSchedules(year);
const schedules = result.success && result.data ? result.data : [];
set(
(state) => ({
schedulesByYear: { ...state.schedulesByYear, [year]: schedules },
loadedYears: { ...state.loadedYears, [year]: true },
loadingYears: { ...state.loadingYears, [year]: false },
}),
false,
'fetchSchedules/success'
);
return schedules;
} catch {
// API 실패 시에도 loaded 처리 → 같은 연도 반복 호출 방지
// (폴백 상수 데이터 사용, 달력관리에서 등록 시 invalidateYear로 재시도)
set(
(state) => ({
schedulesByYear: { ...state.schedulesByYear, [year]: [] },
loadedYears: { ...state.loadedYears, [year]: true },
loadingYears: { ...state.loadingYears, [year]: false },
}),
false,
'fetchSchedules/error'
);
return [];
}
},
setSchedulesForYear: (year: number, schedules: CalendarSchedule[]) => {
set(
(state) => ({
schedulesByYear: { ...state.schedulesByYear, [year]: schedules },
loadedYears: { ...state.loadedYears, [year]: true },
loadingYears: { ...state.loadingYears, [year]: false },
}),
false,
'setSchedulesForYear'
);
},
invalidateYear: (year: number) => {
set(
(state) => {
const newSchedules = { ...state.schedulesByYear };
const newLoaded = { ...state.loadedYears };
delete newSchedules[year];
delete newLoaded[year];
return { schedulesByYear: newSchedules, loadedYears: newLoaded };
},
false,
'invalidateYear'
);
},
}),
{ name: 'CalendarScheduleStore' }
)
);