diff --git a/src/components/pages/dashboard/DashboardProduction.tsx b/src/components/pages/dashboard/DashboardProduction.tsx index 41cf0e2b..079b082c 100644 --- a/src/components/pages/dashboard/DashboardProduction.tsx +++ b/src/components/pages/dashboard/DashboardProduction.tsx @@ -15,7 +15,6 @@ import { useFormik } from 'formik'; import { ProjectFlockApi } from '@/services/api/production'; import { KandangApi, LocationApi } from '@/services/api/master-data'; import { generateDashboardPDF } from '@/components/pages/dashboard/export/DashboardPDF'; - import { DashboardFilterType, getDashboardFilterSchema, @@ -38,6 +37,7 @@ import ButtonFilter from '@/components/helper/ButtonFilter'; import Dropdown from '@/components/Dropdown'; import Menu from '@/components/menu/Menu'; import MenuItem from '@/components/menu/MenuItem'; +import { useDashboardStore } from '@/stores/dashboard'; // Helper function to normalize values to array const normalizeToArray = ( @@ -52,11 +52,18 @@ const normalizeToArray = ( const DashboardProduction = () => { const filterModal = useModal(); + + // ===== DASHBOARD STORE ===== + const { filterValues, setFilterValues, resetFilterValues } = + useDashboardStore(); + const [analysisMode, setAnalysisMode] = useState<'OVERVIEW' | 'COMPARISON'>( - 'OVERVIEW' + (filterValues.analysisMode as 'OVERVIEW' | 'COMPARISON') || 'OVERVIEW' ); const [endpointUrl, setEndpointUrl] = useState('/dashboards'); - const [selectedLocationIds, setSelectedLocationIds] = useState([]); + const [selectedLocationIds, setSelectedLocationIds] = useState( + normalizeToArray(filterValues.location) + ); const [exporting, setExporting] = useState(false); const statsRef = useRef(null); const chartRef = useRef(null); @@ -111,19 +118,22 @@ const DashboardProduction = () => { // ===== FORMIK ===== const formik = useFormik({ initialValues: { - startDate: '', - endDate: '', - flock: [] as OptionType[], - location: [] as OptionType[], - kandang: [] as OptionType[], - analysisMode: analysisMode, - comparisonType: '', - lokasiIds: [], - flockIds: [], - kandangIds: [], + startDate: filterValues.startDate || '', + endDate: filterValues.endDate || '', + flock: filterValues.flock || ([] as OptionType[]), + location: filterValues.location || ([] as OptionType[]), + kandang: filterValues.kandang || ([] as OptionType[]), + analysisMode: filterValues.analysisMode || analysisMode, + comparisonType: filterValues.comparisonType || '', + locationIds: filterValues.locationIds || [], + flockIds: filterValues.flockIds || [], + kandangIds: filterValues.kandangIds || [], } as DashboardFilterType, validationSchema: getDashboardFilterSchema(analysisMode), onSubmit: (values) => { + // Save filter values to store + setFilterValues(values); + handleApplyFilter({ start_date: values.startDate || '', end_date: values.endDate || '', @@ -138,8 +148,10 @@ const DashboardProduction = () => { const handleResetFilter = () => { formik.resetForm(); + resetFilterValues(); // Clear stored filter values setAnalysisMode('OVERVIEW'); setEndpointUrl('/dashboards'); + setSelectedLocationIds([]); }; const handleApplyFilter = (values: DashboardFilter) => { @@ -162,6 +174,20 @@ const DashboardProduction = () => { refreshDashboardProductionData(); }; + // ===== Load filter from store on mount ===== + useEffect(() => { + if (!filterValues) return; + handleApplyFilter({ + start_date: filterValues.startDate, + end_date: filterValues.endDate, + analysis_mode: filterValues.analysisMode as 'OVERVIEW' | 'COMPARISON', + location_ids: normalizeToArray(filterValues.location), + flock_ids: normalizeToArray(filterValues.flock), + kandang_ids: normalizeToArray(filterValues.kandang), + comparison_type: filterValues.comparisonType, + }); + }, [filterValues]); + // ===== Formik Error List ===== const { formErrorList, close, handleFormSubmit } = useFormikErrorList(formik); @@ -512,7 +538,6 @@ const DashboardProduction = () => { type='reset' variant='soft' className='ms-4 min-w-36 rounded-lg' - onClick={handleResetFilter} > Reset Filter diff --git a/src/components/pages/dashboard/chart/DashboardAllCharts.tsx b/src/components/pages/dashboard/chart/DashboardAllCharts.tsx index 8b99d06e..fe0db0a7 100644 --- a/src/components/pages/dashboard/chart/DashboardAllCharts.tsx +++ b/src/components/pages/dashboard/chart/DashboardAllCharts.tsx @@ -32,8 +32,9 @@ export type DashboardAllChartsRef = { // Type guard to check if charts is DashboardOverviewCharts function isOverviewCharts( - charts: DashboardOverviewCharts | DashboardComparisonCharts + charts: DashboardOverviewCharts | DashboardComparisonCharts | undefined ): charts is DashboardOverviewCharts { + if (!charts) return false; return ( 'deplesi' in charts || 'body_weight' in charts || @@ -45,8 +46,9 @@ function isOverviewCharts( // Type guard to check if charts is DashboardComparisonCharts function isComparisonCharts( - charts: DashboardOverviewCharts | DashboardComparisonCharts + charts: DashboardOverviewCharts | DashboardComparisonCharts | undefined ): charts is DashboardComparisonCharts { + if (!charts) return false; return 'farm' in charts || 'flock' in charts || 'kandang' in charts; } diff --git a/src/components/pages/dashboard/chart/DashboardLineChart.tsx b/src/components/pages/dashboard/chart/DashboardLineChart.tsx index 3f34b673..f2449795 100644 --- a/src/components/pages/dashboard/chart/DashboardLineChart.tsx +++ b/src/components/pages/dashboard/chart/DashboardLineChart.tsx @@ -32,8 +32,9 @@ type DashboardLineChartProps = { // Type guard to check if charts is DashboardOverviewCharts function isOverviewCharts( - charts: DashboardOverviewCharts | DashboardComparisonCharts + charts: DashboardOverviewCharts | DashboardComparisonCharts | undefined ): charts is DashboardOverviewCharts { + if (!charts) return false; return ( 'deplesi' in charts || 'body_weight' in charts || @@ -45,8 +46,9 @@ function isOverviewCharts( // Type guard to check if charts is DashboardComparisonCharts function isComparisonCharts( - charts: DashboardOverviewCharts | DashboardComparisonCharts + charts: DashboardOverviewCharts | DashboardComparisonCharts | undefined ): charts is DashboardComparisonCharts { + if (!charts) return false; return 'farm' in charts || 'flock' in charts || 'kandang' in charts; } diff --git a/src/components/pages/dashboard/filter/DashboardProductionFilter.schema.ts b/src/components/pages/dashboard/filter/DashboardProductionFilter.schema.ts index d62157a8..1e03252b 100644 --- a/src/components/pages/dashboard/filter/DashboardProductionFilter.schema.ts +++ b/src/components/pages/dashboard/filter/DashboardProductionFilter.schema.ts @@ -7,7 +7,7 @@ export type DashboardFilterType = { analysisMode: string; comparisonType: string | undefined; location: OptionType | OptionType[]; - lokasiIds: number[] | undefined; + locationIds: number[] | undefined; flock: OptionType | OptionType[] | undefined; flockIds: number[] | undefined; kandang: OptionType | OptionType[] | undefined; @@ -25,7 +25,7 @@ export const DashboardFilterOverviewSchema: yup.ObjectSchema schema.required('Compared by is required'), otherwise: (schema) => schema.optional(), }), - lokasiIds: yup.array().optional(), + locationIds: yup.array().optional(), flockIds: yup.array().optional(), kandangIds: yup.array().optional(), location: yup @@ -68,7 +68,7 @@ export const DashboardFilterComparisonSchema: yup.ObjectSchema schema.required('Compared by is required'), otherwise: (schema) => schema.optional(), }), - lokasiIds: yup.array().optional(), + locationIds: yup.array().optional(), flockIds: yup.array().optional(), kandangIds: yup.array().optional(), location: yup diff --git a/src/stores/dashboard/dashboard.store.ts b/src/stores/dashboard/dashboard.store.ts new file mode 100644 index 00000000..439ab3d3 --- /dev/null +++ b/src/stores/dashboard/dashboard.store.ts @@ -0,0 +1,24 @@ +'use client'; + +import { create } from 'zustand'; +import { devtools, persist } from 'zustand/middleware'; +import { createDashboardFilterSlice } from '@/stores/dashboard/slices/dashboard-filter.slice'; +import { DashboardFilterSlice } from '@/types/stores'; + +export type DashboardStore = DashboardFilterSlice; + +export const useDashboardStore = create()( + devtools( + persist( + (...args) => ({ + ...createDashboardFilterSlice(...args), + }), + { + name: 'dashboard-filter-cache', + } + ), + { + name: 'DashboardStore', + } + ) +); diff --git a/src/stores/dashboard/index.ts b/src/stores/dashboard/index.ts new file mode 100644 index 00000000..3ccba369 --- /dev/null +++ b/src/stores/dashboard/index.ts @@ -0,0 +1,2 @@ +export { useDashboardStore } from './dashboard.store'; +export type { DashboardStore } from './dashboard.store'; diff --git a/src/stores/dashboard/slices/dashboard-filter.slice.ts b/src/stores/dashboard/slices/dashboard-filter.slice.ts new file mode 100644 index 00000000..086ea959 --- /dev/null +++ b/src/stores/dashboard/slices/dashboard-filter.slice.ts @@ -0,0 +1,45 @@ +import { DashboardFilterSlice } from '@/types/stores'; +import { StateCreator } from 'zustand'; + +export const createDashboardFilterSlice: StateCreator< + DashboardFilterSlice, + [], + [], + DashboardFilterSlice +> = (set) => ({ + // Initial state + filterValues: { + startDate: '', + endDate: '', + analysisMode: 'OVERVIEW', + comparisonType: undefined, + location: [], + locationIds: undefined, + flock: undefined, + flockIds: undefined, + kandang: undefined, + kandangIds: undefined, + }, + + // Actions + setFilterValues: (values) => set({ filterValues: values }), + + resetFilterValues: () => { + alert('reset filter values'); + + return set({ + filterValues: { + startDate: '', + endDate: '', + analysisMode: 'OVERVIEW', + comparisonType: undefined, + location: [], + locationIds: undefined, + flock: undefined, + flockIds: undefined, + kandang: undefined, + kandangIds: undefined, + }, + }); + }, +}); diff --git a/src/types/stores.d.ts b/src/types/stores.d.ts index 48873805..528309c7 100644 --- a/src/types/stores.d.ts +++ b/src/types/stores.d.ts @@ -1,3 +1,4 @@ +import { DashboardFilterType } from '@/components/pages/dashboard/filter/DashboardProductionFilter.schema'; import type { ProductionStandardRepeaterFormSchemaValues } from '@/components/pages/master-data/production-standard/form/ProductionStandardForm.schema'; import type { UniformityFormData, @@ -70,3 +71,13 @@ export type UniformitySlice = { setCreatedUniformity: (data: UniformityDetail | null) => void; resetUniformity: () => void; }; + +// Dashboard Filter Slice +export type DashboardFilterSlice = { + // State + filterValues: DashboardFilterType; + + // Actions + setFilterValues: (values: DashboardFilterType) => void; + resetFilterValues: () => void; +};