mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
fix: implement table persist state in recording filter
This commit is contained in:
@@ -1,13 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import axios from 'axios';
|
import React, { useCallback, useState, useMemo, useEffect } from 'react';
|
||||||
import React, {
|
|
||||||
useCallback,
|
|
||||||
useState,
|
|
||||||
useMemo,
|
|
||||||
useEffect,
|
|
||||||
useRef,
|
|
||||||
} from 'react';
|
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import { SortingState, CellContext, ColumnDef } from '@tanstack/react-table';
|
import { SortingState, CellContext, ColumnDef } from '@tanstack/react-table';
|
||||||
@@ -46,8 +39,6 @@ import { useTableFilter } from '@/services/hooks/useTableFilter';
|
|||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import StatusBadge from '@/components/helper/StatusBadge';
|
import StatusBadge from '@/components/helper/StatusBadge';
|
||||||
import CheckboxInput from '@/components/input/CheckboxInput';
|
import CheckboxInput from '@/components/input/CheckboxInput';
|
||||||
import { useUiStore } from '@/stores/ui/ui.store';
|
|
||||||
import { usePathname } from 'next/navigation';
|
|
||||||
import { Color } from '@/types/theme';
|
import { Color } from '@/types/theme';
|
||||||
import ButtonFilter from '@/components/helper/ButtonFilter';
|
import ButtonFilter from '@/components/helper/ButtonFilter';
|
||||||
import Dropdown from '@/components/Dropdown';
|
import Dropdown from '@/components/Dropdown';
|
||||||
@@ -77,6 +68,26 @@ const getStatusBadgeColor = (status: string): Color => {
|
|||||||
return statusBadgeColorMap[normalizedStatus] || 'neutral';
|
return statusBadgeColorMap[normalizedStatus] || 'neutral';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isRecordingApproved = (recording: Recording): boolean => {
|
||||||
|
return (
|
||||||
|
recording.approval?.action === 'APPROVED' &&
|
||||||
|
recording.approval?.step_name === 'Disetujui'
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// ===== FILTER HELPERS =====
|
||||||
|
const recordingApprovalStatusOptions: OptionType<string>[] = [
|
||||||
|
{ value: 'CREATED', label: 'Pengajuan' },
|
||||||
|
{ value: 'UPDATED', label: 'Diperbarui' },
|
||||||
|
{ value: 'APPROVED', label: 'Disetujui' },
|
||||||
|
{ value: 'REJECTED', label: 'Ditolak' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const projectFlockCategoryOptions: OptionType<string>[] = [
|
||||||
|
{ value: 'GROWING', label: 'Growing' },
|
||||||
|
{ value: 'LAYING', label: 'Laying' },
|
||||||
|
];
|
||||||
|
|
||||||
const RowOptionsMenu = ({
|
const RowOptionsMenu = ({
|
||||||
popoverPosition = 'bottom',
|
popoverPosition = 'bottom',
|
||||||
props,
|
props,
|
||||||
@@ -268,25 +279,31 @@ const RowOptionsMenu = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const RecordingTable = () => {
|
const RecordingTable = () => {
|
||||||
const { searchValue, setSearchValue, setTableState } = useUiStore();
|
|
||||||
const pathname = usePathname();
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
state: tableFilterState,
|
state: tableFilterState,
|
||||||
updateFilter,
|
updateFilter,
|
||||||
setPage,
|
setPage,
|
||||||
setPageSize,
|
setPageSize,
|
||||||
toQueryString: getTableFilterQueryString,
|
toQueryString: getTableFilterQueryString,
|
||||||
} = useTableFilter({
|
} = useTableFilter<{
|
||||||
|
search: string;
|
||||||
|
areaFilter: OptionType<number> | null;
|
||||||
|
locationFilter: OptionType<number> | null;
|
||||||
|
projectFlockFilter: OptionType<number> | null;
|
||||||
|
kandangFilter: OptionType<number> | null;
|
||||||
|
projectFlockKandangFilter: number | null;
|
||||||
|
approvalStatusFilter: OptionType<string> | null;
|
||||||
|
projectFlockCategoryFilter: OptionType<string> | null;
|
||||||
|
}>({
|
||||||
initial: {
|
initial: {
|
||||||
search: '',
|
search: '',
|
||||||
areaFilter: '',
|
areaFilter: null,
|
||||||
locationFilter: '',
|
locationFilter: null,
|
||||||
projectFlockFilter: '',
|
projectFlockFilter: null,
|
||||||
kandangFilter: '',
|
kandangFilter: null,
|
||||||
projectFlockKandangFilter: '',
|
projectFlockKandangFilter: null,
|
||||||
approvalStatusFilter: '',
|
approvalStatusFilter: null,
|
||||||
projectFlockCategoryFilter: '',
|
projectFlockCategoryFilter: null,
|
||||||
},
|
},
|
||||||
paramMap: {
|
paramMap: {
|
||||||
page: 'page',
|
page: 'page',
|
||||||
@@ -300,31 +317,58 @@ const RecordingTable = () => {
|
|||||||
approvalStatusFilter: 'approval_status',
|
approvalStatusFilter: 'approval_status',
|
||||||
projectFlockCategoryFilter: 'project_flock_category',
|
projectFlockCategoryFilter: 'project_flock_category',
|
||||||
},
|
},
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
persist: true,
|
||||||
updateFilter('search', searchValue);
|
storeName: 'recording-table',
|
||||||
}, [searchValue, updateFilter]);
|
});
|
||||||
|
|
||||||
// ===== FILTER MODAL STATE =====
|
// ===== FILTER MODAL STATE =====
|
||||||
const filterModal = useModal();
|
const filterModal = useModal();
|
||||||
|
|
||||||
// ===== FILTER STATE =====
|
|
||||||
const [filterArea, setFilterArea] = useState<OptionType | null>(null);
|
|
||||||
const [filterLocation, setFilterLocation] = useState<OptionType | null>(null);
|
|
||||||
const [filterProjectFlock, setFilterProjectFlock] =
|
|
||||||
useState<OptionType | null>(null);
|
|
||||||
const [filterKandang, setFilterKandang] = useState<OptionType | null>(null);
|
|
||||||
const [, setFilterProjectFlockKandangId] = useState<number | undefined>(
|
|
||||||
undefined
|
|
||||||
);
|
|
||||||
const [filterLocationAreaId, setFilterLocationAreaId] = useState<string>('');
|
|
||||||
const [filterProjectFlockLocationId, setFilterProjectFlockLocationId] =
|
|
||||||
useState<string>('');
|
|
||||||
|
|
||||||
// ===== FORMIK SETUP =====
|
// ===== FORMIK SETUP =====
|
||||||
const formik = useFormik<RecordingFilterType>({
|
const formik = useFormik<RecordingFilterType>({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
|
area_id: tableFilterState.areaFilter,
|
||||||
|
location_id: tableFilterState.locationFilter,
|
||||||
|
project_flock_id: tableFilterState.projectFlockFilter,
|
||||||
|
kandang_id: tableFilterState.kandangFilter,
|
||||||
|
project_flock_kandang_id: tableFilterState.projectFlockKandangFilter,
|
||||||
|
approval_status: tableFilterState.approvalStatusFilter,
|
||||||
|
project_flock_category: tableFilterState.projectFlockCategoryFilter,
|
||||||
|
},
|
||||||
|
validationSchema: RecordingFilterSchema,
|
||||||
|
onSubmit: (values, { setSubmitting }) => {
|
||||||
|
updateFilter('areaFilter', values.area_id, true);
|
||||||
|
updateFilter('locationFilter', values.location_id, true);
|
||||||
|
updateFilter('projectFlockFilter', values.project_flock_id, true);
|
||||||
|
updateFilter('kandangFilter', values.kandang_id, true);
|
||||||
|
updateFilter(
|
||||||
|
'projectFlockKandangFilter',
|
||||||
|
values.project_flock_kandang_id,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
updateFilter('approvalStatusFilter', values.approval_status, true);
|
||||||
|
updateFilter(
|
||||||
|
'projectFlockCategoryFilter',
|
||||||
|
values.project_flock_category,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
filterModal.closeModal();
|
||||||
|
setSubmitting(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const formikResetHandler = () => {
|
||||||
|
updateFilter('areaFilter', null, true);
|
||||||
|
updateFilter('locationFilter', null, true);
|
||||||
|
updateFilter('projectFlockFilter', null, true);
|
||||||
|
updateFilter('kandangFilter', null, true);
|
||||||
|
updateFilter('projectFlockKandangFilter', null, true);
|
||||||
|
updateFilter('approvalStatusFilter', null, true);
|
||||||
|
updateFilter('projectFlockCategoryFilter', null, true);
|
||||||
|
|
||||||
|
formik.resetForm({
|
||||||
|
values: {
|
||||||
area_id: null,
|
area_id: null,
|
||||||
location_id: null,
|
location_id: null,
|
||||||
project_flock_id: null,
|
project_flock_id: null,
|
||||||
@@ -333,35 +377,13 @@ const RecordingTable = () => {
|
|||||||
approval_status: null,
|
approval_status: null,
|
||||||
project_flock_category: null,
|
project_flock_category: null,
|
||||||
},
|
},
|
||||||
validationSchema: RecordingFilterSchema,
|
|
||||||
onSubmit: (values, { setSubmitting }) => {
|
|
||||||
updateFilter('areaFilter', values.area_id || '');
|
|
||||||
updateFilter('locationFilter', values.location_id || '');
|
|
||||||
updateFilter('projectFlockFilter', values.project_flock_id || '');
|
|
||||||
updateFilter('kandangFilter', values.kandang_id || '');
|
|
||||||
updateFilter(
|
|
||||||
'projectFlockKandangFilter',
|
|
||||||
values.project_flock_kandang_id || ''
|
|
||||||
);
|
|
||||||
updateFilter('approvalStatusFilter', values.approval_status || '');
|
|
||||||
updateFilter(
|
|
||||||
'projectFlockCategoryFilter',
|
|
||||||
values.project_flock_category || ''
|
|
||||||
);
|
|
||||||
filterModal.closeModal();
|
|
||||||
setSubmitting(false);
|
|
||||||
},
|
|
||||||
onReset: () => {
|
|
||||||
updateFilter('areaFilter', '');
|
|
||||||
updateFilter('locationFilter', '');
|
|
||||||
updateFilter('projectFlockFilter', '');
|
|
||||||
updateFilter('kandangFilter', '');
|
|
||||||
updateFilter('projectFlockKandangFilter', '');
|
|
||||||
updateFilter('approvalStatusFilter', '');
|
|
||||||
updateFilter('projectFlockCategoryFilter', '');
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
filterModal.closeModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
const { project_flock_id, kandang_id } = formik.values;
|
||||||
|
|
||||||
const [sorting, setSorting] = useState<SortingState>([]);
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
|
const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});
|
||||||
const selectedRowIds = Object.keys(rowSelection).map((item) =>
|
const selectedRowIds = Object.keys(rowSelection).map((item) =>
|
||||||
@@ -396,13 +418,6 @@ const RecordingTable = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// ===== LOCATION, AREA, KANDANG OPTIONS =====
|
// ===== LOCATION, AREA, KANDANG OPTIONS =====
|
||||||
const locationParams = useMemo(() => {
|
|
||||||
if (filterLocationAreaId) {
|
|
||||||
return { area_id: filterLocationAreaId };
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}, [filterLocationAreaId]);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
setInputValue: setLocationInputValue,
|
setInputValue: setLocationInputValue,
|
||||||
options: locationOptions,
|
options: locationOptions,
|
||||||
@@ -413,7 +428,9 @@ const RecordingTable = () => {
|
|||||||
'id',
|
'id',
|
||||||
'name',
|
'name',
|
||||||
'search',
|
'search',
|
||||||
locationParams
|
{
|
||||||
|
area_id: String(formik.values.area_id?.value),
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -428,13 +445,6 @@ const RecordingTable = () => {
|
|||||||
'search'
|
'search'
|
||||||
);
|
);
|
||||||
|
|
||||||
const projectFlockParams = useMemo(() => {
|
|
||||||
if (filterProjectFlockLocationId) {
|
|
||||||
return { location_id: filterProjectFlockLocationId };
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}, [filterProjectFlockLocationId]);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
setInputValue: setProjectFlockInputValue,
|
setInputValue: setProjectFlockInputValue,
|
||||||
options: projectFlockOptions,
|
options: projectFlockOptions,
|
||||||
@@ -446,34 +456,41 @@ const RecordingTable = () => {
|
|||||||
'id',
|
'id',
|
||||||
'flock_name',
|
'flock_name',
|
||||||
'search',
|
'search',
|
||||||
projectFlockParams
|
{
|
||||||
|
location_id: String(formik.values.location_id?.value),
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const kandangOptions = useMemo(() => {
|
const kandangOptions = useMemo(() => {
|
||||||
if (!filterProjectFlock || !projectFlocksRawData) return [];
|
if (!project_flock_id || !projectFlocksRawData) return [];
|
||||||
if (!isResponseSuccess(projectFlocksRawData)) return [];
|
if (!isResponseSuccess(projectFlocksRawData)) return [];
|
||||||
|
|
||||||
const data = projectFlocksRawData.data as ProjectFlock[];
|
const data = projectFlocksRawData.data as ProjectFlock[];
|
||||||
const selectedProjectFlockData = data.find(
|
const selectedProjectFlockData = data.find((pf) =>
|
||||||
(pf) => pf.id === filterProjectFlock.value
|
pf.id === formik.values.project_flock_id?.value
|
||||||
|
? Number(formik.values.project_flock_id.value)
|
||||||
|
: 0
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!selectedProjectFlockData?.kandangs) return [];
|
if (!selectedProjectFlockData?.kandangs) return [];
|
||||||
|
|
||||||
return selectedProjectFlockData.kandangs.map((k) => ({
|
return selectedProjectFlockData.kandangs.map((k) => ({
|
||||||
value: k.id,
|
value: k.id,
|
||||||
label: k.name || '',
|
label: k.name || '',
|
||||||
}));
|
}));
|
||||||
}, [filterProjectFlock, projectFlocksRawData]);
|
}, [project_flock_id, projectFlocksRawData]);
|
||||||
|
|
||||||
// ===== PROJECT FLOCK KANDANG LOOKUP =====
|
// ===== PROJECT FLOCK KANDANG LOOKUP =====
|
||||||
const projectFlockKandangLookupUrl = useMemo(() => {
|
const projectFlockKandangLookupUrl = useMemo(() => {
|
||||||
if (!filterProjectFlock || !filterKandang) return null;
|
if (!project_flock_id?.value || !kandang_id?.value) return null;
|
||||||
|
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
project_flock_id: filterProjectFlock.value.toString(),
|
project_flock_id: project_flock_id.value.toString(),
|
||||||
kandang_id: filterKandang.value.toString(),
|
kandang_id: kandang_id.value.toString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
return `${ProjectFlockApi.basePath}/kandangs/lookup?${params.toString()}`;
|
return `${ProjectFlockApi.basePath}/kandangs/lookup?${params.toString()}`;
|
||||||
}, [filterProjectFlock, filterKandang]);
|
}, [project_flock_id, kandang_id]);
|
||||||
|
|
||||||
const { data: projectFlockKandangLookupData } = useSWR(
|
const { data: projectFlockKandangLookupData } = useSWR(
|
||||||
projectFlockKandangLookupUrl,
|
projectFlockKandangLookupUrl,
|
||||||
@@ -495,154 +512,45 @@ const RecordingTable = () => {
|
|||||||
? projectFlockKandangLookupData.data
|
? projectFlockKandangLookupData.data
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const formikRef = useRef(formik);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
formikRef.current = formik;
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (projectFlockKandangLookup?.id) {
|
if (projectFlockKandangLookup?.id) {
|
||||||
const pfkId = String(projectFlockKandangLookup.id);
|
const pfkId = String(projectFlockKandangLookup.id);
|
||||||
setFilterProjectFlockKandangId(projectFlockKandangLookup.id);
|
formik.setFieldValue('project_flock_kandang_id', pfkId);
|
||||||
formikRef.current.setFieldValue('project_flock_kandang_id', pfkId);
|
|
||||||
} else {
|
} else {
|
||||||
setFilterProjectFlockKandangId(undefined);
|
formik.setFieldValue('project_flock_kandang_id', null);
|
||||||
formikRef.current.setFieldValue('project_flock_kandang_id', null);
|
|
||||||
}
|
}
|
||||||
}, [projectFlockKandangLookup]);
|
}, [projectFlockKandangLookup]);
|
||||||
|
|
||||||
// ===== FILTER HANDLERS =====
|
// ===== FILTER HANDLERS =====
|
||||||
const handleFilterAreaChange = useCallback(
|
const handleFilterAreaChange = (val: OptionType | OptionType[] | null) => {
|
||||||
(val: OptionType | OptionType[] | null) => {
|
formik.setFieldValue('area_id', val);
|
||||||
const area = val as OptionType | null;
|
|
||||||
const areaId = area?.value ? String(area.value) : null;
|
|
||||||
|
|
||||||
formik.setFieldValue('area_id', areaId);
|
|
||||||
formik.setFieldValue('location_id', null);
|
formik.setFieldValue('location_id', null);
|
||||||
formik.setFieldValue('project_flock_id', null);
|
formik.setFieldValue('project_flock_id', null);
|
||||||
formik.setFieldValue('kandang_id', null);
|
formik.setFieldValue('kandang_id', null);
|
||||||
formik.setFieldValue('project_flock_kandang_id', null);
|
formik.setFieldValue('project_flock_kandang_id', null);
|
||||||
|
};
|
||||||
|
|
||||||
setFilterArea(area);
|
const handleFilterLocationChange = (
|
||||||
setFilterLocation(null);
|
val: OptionType | OptionType[] | null
|
||||||
setFilterProjectFlock(null);
|
) => {
|
||||||
setFilterKandang(null);
|
formik.setFieldValue('location_id', val);
|
||||||
setFilterLocationAreaId(areaId || '');
|
|
||||||
setFilterProjectFlockLocationId('');
|
|
||||||
},
|
|
||||||
[formik]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleFilterLocationChange = useCallback(
|
|
||||||
(val: OptionType | OptionType[] | null) => {
|
|
||||||
const location = val as OptionType | null;
|
|
||||||
const locationId = location?.value ? String(location.value) : null;
|
|
||||||
|
|
||||||
formik.setFieldValue('location_id', locationId);
|
|
||||||
formik.setFieldValue('project_flock_id', null);
|
formik.setFieldValue('project_flock_id', null);
|
||||||
formik.setFieldValue('kandang_id', null);
|
formik.setFieldValue('kandang_id', null);
|
||||||
formik.setFieldValue('project_flock_kandang_id', null);
|
formik.setFieldValue('project_flock_kandang_id', null);
|
||||||
|
};
|
||||||
|
|
||||||
setFilterLocation(location);
|
const handleFilterProjectFlockChange = (
|
||||||
setFilterProjectFlock(null);
|
val: OptionType | OptionType[] | null
|
||||||
setFilterKandang(null);
|
) => {
|
||||||
setFilterProjectFlockLocationId(locationId || '');
|
formik.setFieldValue('project_flock_id', val);
|
||||||
},
|
|
||||||
[formik]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleFilterProjectFlockChange = useCallback(
|
|
||||||
(val: OptionType | OptionType[] | null) => {
|
|
||||||
const projectFlock = val as OptionType | null;
|
|
||||||
const projectFlockId = projectFlock?.value
|
|
||||||
? String(projectFlock.value)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
formik.setFieldValue('project_flock_id', projectFlockId);
|
|
||||||
formik.setFieldValue('kandang_id', null);
|
formik.setFieldValue('kandang_id', null);
|
||||||
formik.setFieldValue('project_flock_kandang_id', null);
|
formik.setFieldValue('project_flock_kandang_id', null);
|
||||||
|
};
|
||||||
|
|
||||||
setFilterProjectFlock(projectFlock);
|
const handleFilterKandangChange = (val: OptionType | OptionType[] | null) => {
|
||||||
setFilterKandang(null);
|
formik.setFieldValue('kandang_id', val);
|
||||||
},
|
|
||||||
[formik]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleFilterKandangChange = useCallback(
|
|
||||||
(val: OptionType | OptionType[] | null) => {
|
|
||||||
const kandang = val as OptionType | null;
|
|
||||||
const kandangId = kandang?.value ? String(kandang.value) : null;
|
|
||||||
|
|
||||||
formik.setFieldValue('kandang_id', kandangId);
|
|
||||||
formik.setFieldValue('project_flock_kandang_id', null);
|
formik.setFieldValue('project_flock_kandang_id', null);
|
||||||
|
};
|
||||||
setFilterKandang(kandang);
|
|
||||||
},
|
|
||||||
[formik]
|
|
||||||
);
|
|
||||||
|
|
||||||
// ===== FILTER HELPERS =====
|
|
||||||
const areaIdValue = useMemo(() => {
|
|
||||||
if (!formik.values.area_id) return null;
|
|
||||||
return (
|
|
||||||
areaOptions.find((opt) => String(opt.value) === formik.values.area_id) ||
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}, [formik.values.area_id, areaOptions]);
|
|
||||||
|
|
||||||
const locationIdValue = useMemo(() => {
|
|
||||||
if (!formik.values.location_id) return null;
|
|
||||||
return (
|
|
||||||
locationOptions.find(
|
|
||||||
(opt) => String(opt.value) === formik.values.location_id
|
|
||||||
) || null
|
|
||||||
);
|
|
||||||
}, [formik.values.location_id, locationOptions]);
|
|
||||||
|
|
||||||
const projectFlockIdValue = useMemo(() => {
|
|
||||||
if (!filterProjectFlock) return null;
|
|
||||||
return filterProjectFlock;
|
|
||||||
}, [filterProjectFlock]);
|
|
||||||
|
|
||||||
const kandangIdValue = useMemo(() => {
|
|
||||||
if (!formik.values.kandang_id) return null;
|
|
||||||
return (
|
|
||||||
kandangOptions.find(
|
|
||||||
(opt) => String(opt.value) === formik.values.kandang_id
|
|
||||||
) || null
|
|
||||||
);
|
|
||||||
}, [formik.values.kandang_id, kandangOptions]);
|
|
||||||
|
|
||||||
const recordingApprovalStatusOptions: OptionType<string>[] = [
|
|
||||||
{ value: 'CREATED', label: 'Pengajuan' },
|
|
||||||
{ value: 'UPDATED', label: 'Diperbarui' },
|
|
||||||
{ value: 'APPROVED', label: 'Disetujui' },
|
|
||||||
{ value: 'REJECTED', label: 'Ditolak' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const projectFlockCategoryOptions: OptionType<string>[] = [
|
|
||||||
{ value: 'GROWING', label: 'Growing' },
|
|
||||||
{ value: 'LAYING', label: 'Laying' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const approvalStatusValue = useMemo(() => {
|
|
||||||
if (!formik.values.approval_status) return null;
|
|
||||||
return (
|
|
||||||
recordingApprovalStatusOptions.find(
|
|
||||||
(opt) => opt.value === formik.values.approval_status
|
|
||||||
) || null
|
|
||||||
);
|
|
||||||
}, [formik.values.approval_status]);
|
|
||||||
|
|
||||||
const projectFlockCategoryValue = useMemo(() => {
|
|
||||||
if (!formik.values.project_flock_category) return null;
|
|
||||||
return (
|
|
||||||
projectFlockCategoryOptions.find(
|
|
||||||
(opt) => opt.value === formik.values.project_flock_category
|
|
||||||
) || null
|
|
||||||
);
|
|
||||||
}, [formik.values.project_flock_category]);
|
|
||||||
|
|
||||||
// ===== HANDLE FILTER MODAL OPEN =====
|
// ===== HANDLE FILTER MODAL OPEN =====
|
||||||
const handleFilterModalOpen = () => {
|
const handleFilterModalOpen = () => {
|
||||||
@@ -650,25 +558,9 @@ const RecordingTable = () => {
|
|||||||
formik.validateForm();
|
formik.validateForm();
|
||||||
};
|
};
|
||||||
|
|
||||||
const isRecordingApproved = useCallback((recording: Recording): boolean => {
|
const searchChangeHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
return (
|
updateFilter('search', e.target.value, true);
|
||||||
recording.approval?.action === 'APPROVED' &&
|
};
|
||||||
recording.approval?.step_name === 'Disetujui'
|
|
||||||
);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setTableState('recording-table', pathname);
|
|
||||||
}, [pathname, setTableState]);
|
|
||||||
|
|
||||||
const searchChangeHandler = useCallback(
|
|
||||||
(e: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
updateFilter('search', e.target.value);
|
|
||||||
setSearchValue(e.target.value);
|
|
||||||
setPage(1);
|
|
||||||
},
|
|
||||||
[updateFilter, setSearchValue, setPage]
|
|
||||||
);
|
|
||||||
|
|
||||||
const singleDeleteHandler = async () => {
|
const singleDeleteHandler = async () => {
|
||||||
setIsDeleteLoading(true);
|
setIsDeleteLoading(true);
|
||||||
@@ -1220,7 +1112,7 @@ const RecordingTable = () => {
|
|||||||
return (
|
return (
|
||||||
<div className='text-center'>
|
<div className='text-center'>
|
||||||
{value !== null && value !== undefined
|
{value !== null && value !== undefined
|
||||||
? `${value.toFixed(2)}%`
|
? `${value.toFixed(2)} butir`
|
||||||
: '-'}
|
: '-'}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -1236,7 +1128,7 @@ const RecordingTable = () => {
|
|||||||
return (
|
return (
|
||||||
<div className='text-center text-gray-600'>
|
<div className='text-center text-gray-600'>
|
||||||
{value !== null && value !== undefined
|
{value !== null && value !== undefined
|
||||||
? `${value.toFixed(2)}%`
|
? `${value.toFixed(2)} btr`
|
||||||
: '-'}
|
: '-'}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -1572,13 +1464,13 @@ const RecordingTable = () => {
|
|||||||
<Icon icon='heroicons:x-mark' width={20} height={20} />
|
<Icon icon='heroicons:x-mark' width={20} height={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<form onSubmit={formik.handleSubmit} onReset={formik.handleReset}>
|
<form onSubmit={formik.handleSubmit} onReset={formikResetHandler}>
|
||||||
<div className='p-4 flex flex-col gap-1.5'>
|
<div className='p-4 flex flex-col gap-1.5'>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
label='Area'
|
label='Area'
|
||||||
placeholder='Pilih Area'
|
placeholder='Pilih Area'
|
||||||
options={areaOptions}
|
options={areaOptions}
|
||||||
value={areaIdValue}
|
value={formik.values.area_id}
|
||||||
onChange={handleFilterAreaChange}
|
onChange={handleFilterAreaChange}
|
||||||
onInputChange={setAreaInputValue}
|
onInputChange={setAreaInputValue}
|
||||||
isLoading={isLoadingAreaOptions}
|
isLoading={isLoadingAreaOptions}
|
||||||
@@ -1591,13 +1483,13 @@ const RecordingTable = () => {
|
|||||||
label='Lokasi'
|
label='Lokasi'
|
||||||
placeholder='Pilih Lokasi'
|
placeholder='Pilih Lokasi'
|
||||||
options={locationOptions}
|
options={locationOptions}
|
||||||
value={locationIdValue}
|
value={formik.values.location_id}
|
||||||
onChange={handleFilterLocationChange}
|
onChange={handleFilterLocationChange}
|
||||||
onInputChange={setLocationInputValue}
|
onInputChange={setLocationInputValue}
|
||||||
isLoading={isLoadingLocationOptions}
|
isLoading={isLoadingLocationOptions}
|
||||||
isClearable
|
isClearable
|
||||||
onMenuScrollToBottom={loadMoreLocations}
|
onMenuScrollToBottom={loadMoreLocations}
|
||||||
isDisabled={!filterArea}
|
isDisabled={!formik.values.area_id?.value}
|
||||||
className={{ wrapper: 'w-full' }}
|
className={{ wrapper: 'w-full' }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -1605,13 +1497,13 @@ const RecordingTable = () => {
|
|||||||
label='Project Flock'
|
label='Project Flock'
|
||||||
placeholder='Pilih Project Flock'
|
placeholder='Pilih Project Flock'
|
||||||
options={projectFlockOptions}
|
options={projectFlockOptions}
|
||||||
value={projectFlockIdValue}
|
value={formik.values.project_flock_id}
|
||||||
onChange={handleFilterProjectFlockChange}
|
onChange={handleFilterProjectFlockChange}
|
||||||
onInputChange={setProjectFlockInputValue}
|
onInputChange={setProjectFlockInputValue}
|
||||||
isLoading={isLoadingProjectFlocks}
|
isLoading={isLoadingProjectFlocks}
|
||||||
isClearable
|
isClearable
|
||||||
onMenuScrollToBottom={loadMoreProjectFlocks}
|
onMenuScrollToBottom={loadMoreProjectFlocks}
|
||||||
isDisabled={!filterLocation}
|
isDisabled={!formik.values.location_id?.value}
|
||||||
className={{ wrapper: 'w-full' }}
|
className={{ wrapper: 'w-full' }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -1619,11 +1511,11 @@ const RecordingTable = () => {
|
|||||||
label='Kandang'
|
label='Kandang'
|
||||||
placeholder='Pilih Kandang'
|
placeholder='Pilih Kandang'
|
||||||
options={kandangOptions}
|
options={kandangOptions}
|
||||||
value={kandangIdValue}
|
value={formik.values.kandang_id}
|
||||||
onChange={handleFilterKandangChange}
|
onChange={handleFilterKandangChange}
|
||||||
isLoading={!filterProjectFlock}
|
isLoading={!formik.values.project_flock_id?.value}
|
||||||
isClearable
|
isClearable
|
||||||
isDisabled={!filterProjectFlock}
|
isDisabled={!formik.values.project_flock_id?.value}
|
||||||
className={{ wrapper: 'w-full' }}
|
className={{ wrapper: 'w-full' }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -1631,12 +1523,9 @@ const RecordingTable = () => {
|
|||||||
label='Kategori'
|
label='Kategori'
|
||||||
placeholder='Pilih Kategori'
|
placeholder='Pilih Kategori'
|
||||||
options={projectFlockCategoryOptions}
|
options={projectFlockCategoryOptions}
|
||||||
value={projectFlockCategoryValue}
|
value={formik.values.project_flock_category}
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
formik.setFieldValue(
|
formik.setFieldValue('project_flock_category', val);
|
||||||
'project_flock_category',
|
|
||||||
!Array.isArray(val) && val ? String(val.value) : null
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
isClearable
|
isClearable
|
||||||
className={{ wrapper: 'w-full' }}
|
className={{ wrapper: 'w-full' }}
|
||||||
@@ -1646,12 +1535,9 @@ const RecordingTable = () => {
|
|||||||
label='Status Approval'
|
label='Status Approval'
|
||||||
placeholder='Pilih Status Approval'
|
placeholder='Pilih Status Approval'
|
||||||
options={recordingApprovalStatusOptions}
|
options={recordingApprovalStatusOptions}
|
||||||
value={approvalStatusValue}
|
value={formik.values.approval_status}
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
formik.setFieldValue(
|
formik.setFieldValue('approval_status', val);
|
||||||
'approval_status',
|
|
||||||
!Array.isArray(val) && val ? String(val.value) : null
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
isClearable
|
isClearable
|
||||||
className={{ wrapper: 'w-full' }}
|
className={{ wrapper: 'w-full' }}
|
||||||
@@ -1661,19 +1547,9 @@ const RecordingTable = () => {
|
|||||||
{/* Modal Footer */}
|
{/* Modal Footer */}
|
||||||
<div className='flex justify-between items-center gap-4 p-4 border-t border-base-content/10 bg-gray-50'>
|
<div className='flex justify-between items-center gap-4 p-4 border-t border-base-content/10 bg-gray-50'>
|
||||||
<Button
|
<Button
|
||||||
type='button'
|
type='reset'
|
||||||
variant='soft'
|
variant='soft'
|
||||||
className='rounded-lg text-base-content/65 bg-transparent border-none hover:bg-base-content/10 hover:text-base-content/65 transition-colors px-3 py-2'
|
className='rounded-lg text-base-content/65 bg-transparent border-none hover:bg-base-content/10 hover:text-base-content/65 transition-colors px-3 py-2'
|
||||||
onClick={() => {
|
|
||||||
formik.resetForm();
|
|
||||||
setFilterArea(null);
|
|
||||||
setFilterLocation(null);
|
|
||||||
setFilterProjectFlock(null);
|
|
||||||
setFilterKandang(null);
|
|
||||||
setFilterLocationAreaId('');
|
|
||||||
setFilterProjectFlockLocationId('');
|
|
||||||
filterModal.closeModal();
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Reset Filter
|
Reset Filter
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -1,21 +1,40 @@
|
|||||||
import { string, object } from 'yup';
|
import { OptionType } from '@/components/input/SelectInput';
|
||||||
|
import * as Yup from 'yup';
|
||||||
|
|
||||||
export const RecordingFilterSchema = object().shape({
|
export const RecordingFilterSchema = Yup.object().shape({
|
||||||
area_id: string().nullable(),
|
area_id: Yup.object({
|
||||||
location_id: string().nullable(),
|
value: Yup.number().nullable(),
|
||||||
project_flock_id: string().nullable(),
|
label: Yup.string().nullable(),
|
||||||
kandang_id: string().nullable(),
|
}).nullable(),
|
||||||
project_flock_kandang_id: string().nullable(),
|
location_id: Yup.object({
|
||||||
approval_status: string().nullable(),
|
value: Yup.number().nullable(),
|
||||||
project_flock_category: string().nullable(),
|
label: Yup.string().nullable(),
|
||||||
|
}).nullable(),
|
||||||
|
project_flock_id: Yup.object({
|
||||||
|
value: Yup.number().nullable(),
|
||||||
|
label: Yup.string().nullable(),
|
||||||
|
}).nullable(),
|
||||||
|
kandang_id: Yup.object({
|
||||||
|
value: Yup.number().nullable(),
|
||||||
|
label: Yup.string().nullable(),
|
||||||
|
}).nullable(),
|
||||||
|
project_flock_kandang_id: Yup.number().nullable(),
|
||||||
|
approval_status: Yup.object({
|
||||||
|
value: Yup.string().nullable(),
|
||||||
|
label: Yup.string().nullable(),
|
||||||
|
}).nullable(),
|
||||||
|
project_flock_category: Yup.object({
|
||||||
|
value: Yup.string().nullable(),
|
||||||
|
label: Yup.string().nullable(),
|
||||||
|
}).nullable(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type RecordingFilterType = {
|
export type RecordingFilterType = {
|
||||||
area_id: string | null;
|
area_id: OptionType<number> | null;
|
||||||
location_id: string | null;
|
location_id: OptionType<number> | null;
|
||||||
project_flock_id: string | null;
|
project_flock_id: OptionType<number> | null;
|
||||||
kandang_id: string | null;
|
kandang_id: OptionType<number> | null;
|
||||||
project_flock_kandang_id: string | null;
|
project_flock_kandang_id: number | null;
|
||||||
approval_status: string | null;
|
approval_status: OptionType<string> | null;
|
||||||
project_flock_category: string | null;
|
project_flock_category: OptionType<string> | null;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user