import type { IChartBreakdown, IChartEvent, IChartInput, IChartRange, IChartType, IInterval, } from '@/types'; import { alphabetIds, isMinuteIntervalEnabledByRange } from '@/utils/constants'; import { createSlice } from '@reduxjs/toolkit'; import type { PayloadAction } from '@reduxjs/toolkit'; type InitialState = IChartInput & { dirty: boolean; startDate: string | null; endDate: string | null; }; // First approach: define the initial state using that type const initialState: InitialState = { dirty: false, name: 'Untitled', chartType: 'linear', interval: 'day', breakdowns: [], events: [], range: 30, startDate: null, endDate: null, }; export const reportSlice = createSlice({ name: 'report', initialState, reducers: { resetDirty(state) { return { ...state, dirty: false, }; }, reset() { return initialState; }, setReport(state, action: PayloadAction) { return { ...action.payload, startDate: null, endDate: null, dirty: false, }; }, setName(state, action: PayloadAction) { state.dirty = true; state.name = action.payload; }, // Events addEvent: (state, action: PayloadAction>) => { state.dirty = true; state.events.push({ id: alphabetIds[state.events.length]!, ...action.payload, }); }, removeEvent: ( state, action: PayloadAction<{ id: string; }> ) => { state.dirty = true; state.events = state.events.filter( (event) => event.id !== action.payload.id ); }, changeEvent: (state, action: PayloadAction) => { state.dirty = true; state.events = state.events.map((event) => { if (event.id === action.payload.id) { return action.payload; } return event; }); }, // Breakdowns addBreakdown: ( state, action: PayloadAction> ) => { state.dirty = true; state.breakdowns.push({ id: alphabetIds[state.breakdowns.length]!, ...action.payload, }); }, removeBreakdown: ( state, action: PayloadAction<{ id: string; }> ) => { state.dirty = true; state.breakdowns = state.breakdowns.filter( (event) => event.id !== action.payload.id ); }, changeBreakdown: (state, action: PayloadAction) => { state.dirty = true; state.breakdowns = state.breakdowns.map((breakdown) => { if (breakdown.id === action.payload.id) { return action.payload; } return breakdown; }); }, // Interval changeInterval: (state, action: PayloadAction) => { state.dirty = true; state.interval = action.payload; }, // Chart type changeChartType: (state, action: PayloadAction) => { state.dirty = true; state.chartType = action.payload; if ( !isMinuteIntervalEnabledByRange(state.range) && state.interval === 'minute' ) { state.interval = 'hour'; } }, // Date range changeStartDate: (state, action: PayloadAction) => { state.dirty = true; state.startDate = action.payload; }, // Date range changeEndDate: (state, action: PayloadAction) => { state.dirty = true; state.endDate = action.payload; }, changeDateRanges: (state, action: PayloadAction) => { state.dirty = true; state.range = action.payload; if (action.payload === 0.3 || action.payload === 0.6) { state.interval = 'minute'; } else if (action.payload === 0 || action.payload === 1) { state.interval = 'hour'; } else if (action.payload <= 30) { state.interval = 'day'; } else { state.interval = 'month'; } }, }, }); // Action creators are generated for each case reducer function export const { reset, setReport, setName, addEvent, removeEvent, changeEvent, addBreakdown, removeBreakdown, changeBreakdown, changeInterval, changeDateRanges, changeChartType, resetDirty, } = reportSlice.actions; export default reportSlice.reducer;