diff --git a/src/components/pages/production/recording/RecordingTable.tsx b/src/components/pages/production/recording/RecordingTable.tsx index 8d8caad1..cd98b597 100644 --- a/src/components/pages/production/recording/RecordingTable.tsx +++ b/src/components/pages/production/recording/RecordingTable.tsx @@ -1,6 +1,12 @@ 'use client'; -import React, { useCallback, useState, useMemo, useEffect } from 'react'; +import React, { + useCallback, + useState, + useMemo, + useEffect, + useRef, +} from 'react'; import { RefObject } from 'react'; import useSWR from 'swr'; import { Icon } from '@iconify/react'; @@ -28,6 +34,7 @@ import { useTableFilter } from '@/services/hooks/useTableFilter'; import toast from 'react-hot-toast'; import Badge from '@/components/Badge'; import CheckboxInput from '@/components/input/CheckboxInput'; +import { useUiStore } from '@/stores/ui/ui.store'; import { BaseApproval, BaseApiResponse } from '@/types/api/api-general'; const RowOptionsMenu = ({ @@ -344,6 +351,9 @@ const ApprovalHistoryModal = ({ }; const RecordingTable = () => { + const { searchValue, setSearchValue, resetSearchValue } = useUiStore(); + const previousPathRef = useRef(null); + const { state: tableFilterState, updateFilter, @@ -352,7 +362,7 @@ const RecordingTable = () => { toQueryString: getTableFilterQueryString, } = useTableFilter({ initial: { - search: '', + search: searchValue, areaFilter: '', locationFilter: '', kandangFilter: '', @@ -403,12 +413,35 @@ const RecordingTable = () => { ); }, []); + useEffect(() => { + // Store current path on mount + previousPathRef.current = window.location.pathname; + + return () => { + const currentPath = window.location.pathname; + + // if both paths are within /production/recording module + const isCurrentPathRecording = currentPath.includes( + '/production/recording' + ); + const isPreviousPathRecording = previousPathRef.current?.includes( + '/production/recording' + ); + + // reset if we outside recording module entirely + if (isPreviousPathRecording && !isCurrentPathRecording) { + resetSearchValue(); + } + }; + }, [resetSearchValue]); + const searchChangeHandler = useCallback( (e: React.ChangeEvent) => { updateFilter('search', e.target.value); + setSearchValue(e.target.value); setPage(1); }, - [updateFilter, setPage] + [updateFilter, setSearchValue, setPage] ); const pageSizeChangeHandler = useCallback( diff --git a/src/components/pages/production/recording/form/RecordingForm.tsx b/src/components/pages/production/recording/form/RecordingForm.tsx index 7365c6ca..a000f4a3 100644 --- a/src/components/pages/production/recording/form/RecordingForm.tsx +++ b/src/components/pages/production/recording/form/RecordingForm.tsx @@ -23,6 +23,7 @@ import ConfirmationModalWithNotes from '@/components/modal/ConfirmationModalWith import Modal, { useModal } from '@/components/Modal'; import AlertErrorList from '@/components/helper/form/FormErrors'; import Table from '@/components/Table'; +import Tooltip from '@/components/Tooltip'; import { type ColumnDef } from '@tanstack/react-table'; import { @@ -197,6 +198,11 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { const router = useRouter(); // ===== STATE MANAGEMENT ===== + const [selectedRecordDate, setSelectedRecordDate] = useState( + initialValues?.record_datetime + ? new Date(initialValues.record_datetime).toISOString().split('T')[0] + : new Date().toISOString().split('T')[0] + ); const [selectedStocks, setSelectedStocks] = useState([]); const [selectedDepletions, setSelectedDepletions] = useState([]); const [selectedEggs, setSelectedEggs] = useState([]); @@ -911,6 +917,8 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { baseValues = getRecordingGrowingFormInitialValues(initialValues); } + baseValues.record_date = selectedRecordDate; + if (type === 'add') { baseValues.location = selectedLocation ? { @@ -967,13 +975,22 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { } return baseValues; - }, [initialValues, isLayingCategory, projectFlockKandangDetail, type]); + }, [ + initialValues, + isLayingCategory, + projectFlockKandangDetail, + type, + selectedRecordDate, + selectedLocation, + selectedProjectFlock, + selectedKandang, + ]); const formik = useFormik< RecordingGrowingFormValues | RecordingLayingFormValues >({ initialValues: formikInitialValues, - enableReinitialize: true, + enableReinitialize: false, validationSchema: (() => { let schema; if (isLayingCategory) { @@ -1333,6 +1350,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { (e: React.ChangeEvent) => { const newDate = e.target.value; formik.setFieldValue('record_date', newDate); + setSelectedRecordDate(newDate); setCurrentRecordDate(newDate); if (duplicateErrorShown) { toast.dismiss(); @@ -2799,7 +2817,23 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { )} Kondisi Telur Jumlah - Total Berat (Kilogram) + + Total Berat (Kilogram) + + + + {(type as 'add' | 'edit' | 'detail') !== 'detail' && ( Action )} @@ -2905,7 +2939,7 @@ const RecordingForm = ({ type = 'add', initialValues }: RecordingFormProps) => { value={egg.weight ?? ''} onChange={handleEggWeightChangeWrapper(idx)} onBlur={formik.handleBlur} - decimalScale={0} + decimalScale={3} allowNegative={false} thousandSeparator=',' decimalSeparator='.' diff --git a/src/stores/ui/slices/table.slice.ts b/src/stores/ui/slices/table.slice.ts new file mode 100644 index 00000000..eb6e7cc2 --- /dev/null +++ b/src/stores/ui/slices/table.slice.ts @@ -0,0 +1,28 @@ +import { StateCreator } from 'zustand'; + +export interface TableState { + searchValue: string; +} + +export interface TableUISlice { + searchValue: string; + setSearchValue: (value: string) => void; + resetSearchValue: () => void; +} + +export const createTableUISlice: StateCreator< + TableUISlice, + [], + [], + TableUISlice +> = (set) => ({ + // Initial state + searchValue: '', + + // Actions + setSearchValue: (value) => set({ searchValue: value }), + + resetSearchValue: () => { + return set({ searchValue: '' }); + }, +}); diff --git a/src/stores/ui/ui.store.ts b/src/stores/ui/ui.store.ts index cbc5785d..05adbb9b 100644 --- a/src/stores/ui/ui.store.ts +++ b/src/stores/ui/ui.store.ts @@ -1,18 +1,28 @@ 'use client'; import { create } from 'zustand'; -import { devtools } from 'zustand/middleware'; +import { devtools, persist } from 'zustand/middleware'; import { UIStore } from '@/types/stores'; import { createMainUiSlice } from '@/stores/ui/slices/main.slice'; import { createDrawerUISlice } from '@/stores/ui/slices/drawer.slice'; +import { createTableUISlice } from '@/stores/ui/slices/table.slice'; export const useUiStore = create()( devtools( - (...args) => ({ - ...createMainUiSlice(...args), - ...createDrawerUISlice(...args), - }), + persist( + (...args) => ({ + ...createMainUiSlice(...args), + ...createDrawerUISlice(...args), + ...createTableUISlice(...args), + }), + { + name: 'ui-cache', + partialize: (state) => ({ + searchValue: state.searchValue, + }), + } + ), { name: 'UIStore', } diff --git a/src/types/stores.d.ts b/src/types/stores.d.ts index 528309c7..5b0be6f3 100644 --- a/src/types/stores.d.ts +++ b/src/types/stores.d.ts @@ -26,7 +26,13 @@ type DrawerUISlice = { setIsNextStep: (v: boolean) => void; }; -export type UIStore = MainUiSlice & DrawerUISlice; +type TableUISlice = { + searchValue: string; + setSearchValue: (value: string) => void; + resetSearchValue: () => void; +}; + +export type UIStore = MainUiSlice & DrawerUISlice & TableUISlice; type ProductionStandardFormSlice = { formData: {