From f98e9d693020ec52eacc7246a40f78e253636bcf Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Mon, 26 Jan 2026 21:22:57 +0700 Subject: [PATCH] feat: create TransferToLayingConfirmationModal component --- .../TransferToLayingConfirmationModal.tsx | 276 ++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 src/components/pages/production/transfer-to-laying/TransferToLayingConfirmationModal.tsx diff --git a/src/components/pages/production/transfer-to-laying/TransferToLayingConfirmationModal.tsx b/src/components/pages/production/transfer-to-laying/TransferToLayingConfirmationModal.tsx new file mode 100644 index 00000000..3cedf839 --- /dev/null +++ b/src/components/pages/production/transfer-to-laying/TransferToLayingConfirmationModal.tsx @@ -0,0 +1,276 @@ +'use client'; + +import { ChangeEventHandler, RefObject, useId, useState } from 'react'; +import useSWR from 'swr'; + +import ConfirmationModal, { + ConfirmationModalProps, +} from '@/components/modal/ConfirmationModal'; +import Table from '@/components/Table'; +import TextArea from '@/components/input/TextArea'; + +import { ColumnDef } from '@tanstack/react-table'; +import { cn, formatDate, formatNumber } from '@/lib/helper'; +import { TransferToLayingFormValues } from '@/components/pages/production/transfer-to-laying/form/TransferToLayingForm.schema'; +import { Color } from '@/types/theme'; +import { TransferToLayingApi } from '@/services/api/production/transfer-to-laying'; +import { isResponseSuccess } from '@/lib/api-helper'; + +interface TransferToLayingConfirmationModalProps + extends Omit { + ref: RefObject; + type?: 'info' | 'success' | 'error'; + transferToLayingIds?: number[]; + transferToLayingForm?: TransferToLayingFormValues; + onClose?: () => void; + + withNote?: boolean; + noteLabel?: string; + rows?: number; + placeholder?: string; + + primaryButton?: { + text?: string; + color?: Color; + isLoading?: boolean; + onClick?: (notes: string) => void; + }; +} + +interface TransferToLayingConfirmationTableDataType { + label: string; + value: string; + subRows?: TransferToLayingConfirmationTableDataType[]; +} + +const TransferToLayingConfirmationModalTable = ({ + transferToLayingForm, + transferToLayingId, +}: { + transferToLayingForm?: TransferToLayingFormValues; + transferToLayingId?: number; +}) => { + const { data: transferToLaying, isLoading: isLoadingTransferToLaying } = + useSWR( + transferToLayingId + ? ['detail-transfer-to-laying', String(transferToLayingId)] + : undefined, + ([_, id]) => TransferToLayingApi.getSingle(Number(id)) + ); + + const confirmationTableColumns: ColumnDef[] = + [ + { + header: 'Label', + accessorKey: 'label', + enableSorting: false, + cell: ({ row }) => { + const isSubRow = row.depth > 0; + + return ( + <> + {!isSubRow && row.original.label} + + {isSubRow && ( +
+
+ {row.original.label} +
+ )} + + ); + }, + }, + { + header: 'Value', + accessorKey: 'value', + enableSorting: false, + }, + ]; + + const confirmationTableData: TransferToLayingConfirmationTableDataType[] = [ + { + label: 'Tanggal', + value: formatDate( + transferToLayingId && isResponseSuccess(transferToLaying) + ? transferToLaying.data.transfer_date + : transferToLayingForm?.transfer_date, + 'DD MMMM YYYY' + ), + }, + { + label: 'Flock Asal', + value: + transferToLayingId && isResponseSuccess(transferToLaying) + ? transferToLaying.data.from_project_flock.flock_name + : (transferToLayingForm?.flockSource?.label ?? '-'), + subRows: + transferToLayingId && isResponseSuccess(transferToLaying) + ? (transferToLaying.data.sources?.map( + (sourceProjectFlockKandang) => ({ + label: + sourceProjectFlockKandang.source_project_flock_kandang.kandang + .name, + value: formatNumber( + Number(sourceProjectFlockKandang.qty), + 'en-US' + ), + }) + ) ?? []) + : (transferToLayingForm?.flockSourceKandangs?.map((kandang) => ({ + label: kandang.kandang.label, + value: formatNumber(Number(kandang.quantity), 'en-US'), + })) ?? []), + }, + { + label: 'Flock Tujuan', + value: + transferToLayingId && isResponseSuccess(transferToLaying) + ? transferToLaying.data.to_project_flock.flock_name + : (transferToLayingForm?.flockDestination?.label ?? '-'), + subRows: + transferToLayingId && isResponseSuccess(transferToLaying) + ? (transferToLaying.data.targets?.map( + (targetProjectFlockKandang) => ({ + label: + targetProjectFlockKandang.target_project_flock_kandang.kandang + .name, + value: formatNumber( + Number(targetProjectFlockKandang.qty), + 'en-US' + ), + }) + ) ?? []) + : (transferToLayingForm?.flockDestinationKandangs?.map((kandang) => ({ + label: kandang.kandang.label, + value: formatNumber(Number(kandang.quantity), 'en-US'), + })) ?? []), + }, + { + label: 'Jumlah Transfer', + value: formatNumber( + transferToLayingId && isResponseSuccess(transferToLaying) + ? Number( + transferToLaying.data.sources.reduce( + (total, source) => total + Number(source.qty), + 0 + ) + ) + : Number(transferToLayingForm?.totalQuantity), + 'en-US' + ), + }, + { + label: 'Notes', + value: + transferToLayingId && isResponseSuccess(transferToLaying) + ? (transferToLaying.data.notes ?? '-') + : (transferToLayingForm?.reason ?? '-'), + }, + ]; + + return ( + + columns={confirmationTableColumns} + data={confirmationTableData} + withPagination={false} + pageSize={10000} + expanded={true} + getSubRows={(row) => row.subRows} + className={{ + bodyRowClassName: 'border-none', + bodySubRowClassName: () => 'border-none', + bodySubRowColumnClassName: () => 'first:p-0', + }} + /> + ); +}; + +const TransferToLayingConfirmationModal = ({ + ref, + type = 'success', + transferToLayingForm, + transferToLayingIds, + onClose, + withNote, + rows = 4, + noteLabel, + placeholder = 'Alasan Transfer', + primaryButton, + ...props +}: TransferToLayingConfirmationModalProps) => { + const randomId = useId(); + + const [notes, setNotes] = useState(''); + + const notesChangeHandler: ChangeEventHandler = (e) => { + setNotes(e.target.value); + }; + + const closeModalHandler = () => { + onClose?.(); + ref.current?.close(); + }; + + return ( + { + if (withNote) { + primaryButton?.onClick?.(notes); + } else { + closeModalHandler(); + } + }, + }} + secondaryButton={{ + text: 'Cancel', + color: 'none', + onClick: closeModalHandler, + }} + className={{ + modalBox: 'max-h-full', + }} + {...props} + > +
+ {!transferToLayingIds && transferToLayingForm && ( + + )} + + {transferToLayingIds && + !transferToLayingForm && + transferToLayingIds.map((transferToLayingId, idx) => ( + + ))} + + {withNote && ( +