mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE-438): Handle approve/reject via URL and add buttons
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import React, { useCallback, useState, useEffect, useMemo } from 'react';
|
import React, { useCallback, useState, useEffect, useMemo } from 'react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter, useSearchParams } from 'next/navigation';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import { ColumnDef, SortingState } from '@tanstack/react-table';
|
import { ColumnDef, SortingState } from '@tanstack/react-table';
|
||||||
@@ -61,6 +61,7 @@ const isUniformityLocked = (uniformity: Uniformity): boolean => {
|
|||||||
|
|
||||||
const UniformityTable = ({ refresh }: { refresh?: () => void }) => {
|
const UniformityTable = ({ refresh }: { refresh?: () => void }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
const isSuccess = useUniformityStore((s) => s.isSuccess);
|
const isSuccess = useUniformityStore((s) => s.isSuccess);
|
||||||
const setIsSuccess = useUniformityStore((s) => s.setIsSuccess);
|
const setIsSuccess = useUniformityStore((s) => s.setIsSuccess);
|
||||||
|
|
||||||
@@ -81,7 +82,9 @@ const UniformityTable = ({ refresh }: { refresh?: () => void }) => {
|
|||||||
|
|
||||||
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 [selectedUniformity] = useState<Uniformity | undefined>(undefined);
|
const [selectedUniformity, setSelectedUniformity] = useState<
|
||||||
|
Uniformity | undefined
|
||||||
|
>(undefined);
|
||||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||||
const [isBulkActionLoading, setIsBulkActionLoading] = useState(false);
|
const [isBulkActionLoading, setIsBulkActionLoading] = useState(false);
|
||||||
|
|
||||||
@@ -120,6 +123,28 @@ const UniformityTable = ({ refresh }: { refresh?: () => void }) => {
|
|||||||
);
|
);
|
||||||
}, [selectedUniformities]);
|
}, [selectedUniformities]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const action = searchParams.get('action');
|
||||||
|
const id = searchParams.get('id');
|
||||||
|
|
||||||
|
if (action && id) {
|
||||||
|
if (isResponseSuccess(uniformities)) {
|
||||||
|
const uniformity = uniformities.data.find((u) => u.id === parseInt(id));
|
||||||
|
if (uniformity) {
|
||||||
|
setSelectedUniformity(uniformity);
|
||||||
|
|
||||||
|
if (action === 'approve') {
|
||||||
|
singleApproveModal.openModal();
|
||||||
|
} else if (action === 'reject') {
|
||||||
|
singleRejectModal.openModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
router.replace('/uniformity', { scroll: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [searchParams, uniformities]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
successModal.openModal();
|
successModal.openModal();
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import DrawerHeader from '@/components/helper/drawer/DrawerHeader';
|
|||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import { formatNumber } from '@/lib/helper';
|
import { formatNumber } from '@/lib/helper';
|
||||||
import { type OptionType } from '@/components/input/SelectInput';
|
import { type OptionType } from '@/components/input/SelectInput';
|
||||||
|
import RequirePermission from '@/components/helper/RequirePermission';
|
||||||
import { UniformityDetail as UniformityDetailType } from '@/types/api/uniformity/uniformity';
|
import { UniformityDetail as UniformityDetailType } from '@/types/api/uniformity/uniformity';
|
||||||
|
|
||||||
type DetailOptionType = OptionType & {
|
type DetailOptionType = OptionType & {
|
||||||
@@ -29,9 +30,19 @@ const UniformityDetail: React.FC<UniformityDetailProps> = ({
|
|||||||
router.back();
|
router.back();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleApprove = () => {
|
||||||
|
router.push(`/uniformity?action=approve&id=${initialValues.id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReject = () => {
|
||||||
|
router.push(`/uniformity?action=reject&id=${initialValues.id}`);
|
||||||
|
};
|
||||||
|
|
||||||
const infoUmumTableData: DetailOptionType[] = useMemo(() => {
|
const infoUmumTableData: DetailOptionType[] = useMemo(() => {
|
||||||
if (!initialValues) return [];
|
if (!initialValues) return [];
|
||||||
|
|
||||||
|
const { info_umum } = initialValues;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
id: 'tanggal',
|
id: 'tanggal',
|
||||||
@@ -90,116 +101,6 @@ const UniformityDetail: React.FC<UniformityDetailProps> = ({
|
|||||||
[initialValues]
|
[initialValues]
|
||||||
);
|
);
|
||||||
|
|
||||||
const samplingTableData: DetailOptionType[] = useMemo(() => {
|
|
||||||
if (!initialValues) return [];
|
|
||||||
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
id: 'sampling-size',
|
|
||||||
value: 'sampling-size',
|
|
||||||
label: 'Sampling size',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'mean-weight',
|
|
||||||
value: 'mean-weight',
|
|
||||||
label: 'Mean Weight',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'min-limit',
|
|
||||||
value: 'min-limit',
|
|
||||||
label: 'Min Limit (-10%)',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'max-limit',
|
|
||||||
value: 'max-limit',
|
|
||||||
label: 'Max Limit (+10%)',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}, [initialValues]);
|
|
||||||
|
|
||||||
const columnsSampling: ColumnDef<DetailOptionType>[] = useMemo(
|
|
||||||
() => [
|
|
||||||
{
|
|
||||||
accessorKey: 'label',
|
|
||||||
header: 'Label',
|
|
||||||
cell: (props) => props.row.original.label,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'value',
|
|
||||||
header: 'Value',
|
|
||||||
cell: (props) => {
|
|
||||||
const id = props.row.original.id;
|
|
||||||
const { sampling } = initialValues!;
|
|
||||||
|
|
||||||
const valueMap: Record<string, string> = {
|
|
||||||
'sampling-size': `${formatNumber(sampling.chick_qty_of_weight)} of Birds`,
|
|
||||||
'mean-weight': `${formatNumber(sampling.mean_weight)} g`,
|
|
||||||
'min-limit': `${formatNumber(sampling.mean_down)} g`,
|
|
||||||
'max-limit': `${formatNumber(sampling.mean_up)} g`,
|
|
||||||
};
|
|
||||||
|
|
||||||
return <span>{valueMap[id] || '-'}</span>;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[initialValues]
|
|
||||||
);
|
|
||||||
|
|
||||||
const resultTableData: DetailOptionType[] = useMemo(() => {
|
|
||||||
if (!initialValues) return [];
|
|
||||||
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
id: 'ideal-birds',
|
|
||||||
value: 'ideal-birds',
|
|
||||||
label: 'Ideal Birds',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'outside-range',
|
|
||||||
value: 'outside-range',
|
|
||||||
label: 'Outside Range',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'uniformity',
|
|
||||||
value: 'uniformity',
|
|
||||||
label: 'Uniformity',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'cv',
|
|
||||||
value: 'cv',
|
|
||||||
label: 'CV',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}, [initialValues]);
|
|
||||||
|
|
||||||
const columnsResult: ColumnDef<DetailOptionType>[] = useMemo(
|
|
||||||
() => [
|
|
||||||
{
|
|
||||||
accessorKey: 'label',
|
|
||||||
header: 'Label',
|
|
||||||
cell: (props) => props.row.original.label,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: 'value',
|
|
||||||
header: 'Value',
|
|
||||||
cell: (props) => {
|
|
||||||
const id = props.row.original.id;
|
|
||||||
const { result } = initialValues!;
|
|
||||||
|
|
||||||
const valueMap: Record<string, string> = {
|
|
||||||
'ideal-birds': `${formatNumber(result.uniform_qty)} of Birds`,
|
|
||||||
'outside-range': `${formatNumber(result.outside_qty)} of Birds`,
|
|
||||||
uniformity: `${result.uniformity} %`,
|
|
||||||
cv: `${result.cv}`,
|
|
||||||
};
|
|
||||||
|
|
||||||
return <span>{valueMap[id] || '-'}</span>;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[initialValues]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className='w-full h-full bg-white border-l border-gray-200'>
|
<section className='w-full h-full bg-white border-l border-gray-200'>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
@@ -233,34 +134,19 @@ const UniformityDetail: React.FC<UniformityDetailProps> = ({
|
|||||||
paginationClassName: 'hidden',
|
paginationClassName: 'hidden',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Sampling */}
|
<div className='divider my-3.5' />
|
||||||
<div className=''>
|
{/* Approve/Reject Buttons */}
|
||||||
<p className='text-sm font-medium mb-5'>Sampling and Range</p>
|
{initialValues.result && (
|
||||||
<Table<DetailOptionType>
|
<RequirePermission permissions='lti.production.uniformity.approve'>
|
||||||
data={samplingTableData}
|
<div className='grid grid-cols-1 sm:grid-cols-2 gap-4 [&_button]:rounded-lg'>
|
||||||
columns={columnsSampling}
|
<Button variant='outline' onClick={handleReject}>
|
||||||
pageSize={4}
|
Reject
|
||||||
className={{
|
</Button>
|
||||||
containerClassName: 'mb-0',
|
<Button onClick={handleApprove}>Approve</Button>
|
||||||
paginationClassName: 'hidden',
|
</div>
|
||||||
}}
|
</RequirePermission>
|
||||||
/>
|
)}
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Result */}
|
|
||||||
<div className=''>
|
|
||||||
<p className='text-sm font-medium mb-5'>Result</p>
|
|
||||||
<Table<DetailOptionType>
|
|
||||||
data={resultTableData}
|
|
||||||
columns={columnsResult}
|
|
||||||
pageSize={4}
|
|
||||||
className={{
|
|
||||||
containerClassName: 'mb-0',
|
|
||||||
paginationClassName: 'hidden',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
Reference in New Issue
Block a user