From d0d323954bcdf7e2167e8f3a55665b60d9bd1716 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 23 Oct 2025 13:10:03 +0700 Subject: [PATCH 1/4] feat: install husky --- package-lock.json | 17 +++++++++++++++++ package.json | 4 +++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 1aa69d33..a39060ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,6 +35,7 @@ "daisyui": "^5.1.12", "eslint": "^9", "eslint-config-next": "15.5.3", + "husky": "^9.1.7", "tailwindcss": "^4", "typescript": "^5" } @@ -4176,6 +4177,22 @@ "react-is": "^16.7.0" } }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", diff --git a/package.json b/package.json index 8adf6787..e970499c 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "dev": "eslint && next dev --turbopack", "build": "next build --turbopack", "start": "next start", - "lint": "eslint" + "lint": "eslint", + "prepare": "husky" }, "dependencies": { "@tanstack/match-sorter-utils": "^8.19.4", @@ -36,6 +37,7 @@ "daisyui": "^5.1.12", "eslint": "^9", "eslint-config-next": "15.5.3", + "husky": "^9.1.7", "tailwindcss": "^4", "typescript": "^5" } From 70e1aca6c7ee48f1d7e3a31eb71060e3c08f7961 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 23 Oct 2025 13:13:34 +0700 Subject: [PATCH 2/4] feat: create husky pre-commit file --- .husky/pre-commit | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .husky/pre-commit diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 00000000..66ff6a67 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,2 @@ +npm run lint +npm run build From 7e44226a6def1e298f24b39690791a537025d224 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 23 Oct 2025 17:34:14 +0700 Subject: [PATCH 3/4] feat(FE-141): add approve and reject functionality in Transfer to Laying Detail Page --- .../form/TransferToLayingForm.tsx | 128 +++++++++++++++++- 1 file changed, 124 insertions(+), 4 deletions(-) diff --git a/src/components/pages/production/transfer-to-laying/form/TransferToLayingForm.tsx b/src/components/pages/production/transfer-to-laying/form/TransferToLayingForm.tsx index b026b47f..def2cde8 100644 --- a/src/components/pages/production/transfer-to-laying/form/TransferToLayingForm.tsx +++ b/src/components/pages/production/transfer-to-laying/form/TransferToLayingForm.tsx @@ -42,10 +42,18 @@ const TransferToLayingForm = ({ initialValues, }: TransferToLayingFormProps) => { const router = useRouter(); + + // Modal hooks const deleteModal = useModal(); + const approveModal = useModal(); + const rejectModal = useModal(); const [formErrorMessage, setFormErrorMessage] = useState(''); + + // Modal loading state const [isDeleteLoading, setIsDeleteLoading] = useState(false); + const [isApproveLoading, setIsApproveLoading] = useState(false); + const [isRejectLoading, setIsRejectLoading] = useState(false); const createTransferToLayingHandler = useCallback( async (payload: CreateTransferToLayingPayload) => { @@ -152,15 +160,65 @@ const TransferToLayingForm = ({ deleteModal.openModal(); }; + const approveClickHandler = () => { + approveModal.openModal(); + }; + + const rejectClickHandler = () => { + rejectModal.openModal(); + }; + + // Modal confirm click handler const confirmationModalDeleteClickHandler = async () => { setIsDeleteLoading(true); + // TODO: delete data and integrate to real API deleteModal.closeModal(); - toast.success('Successfully delete TransferToLaying!'); + toast.success('Berhasil menghapus data transfer ke laying!'); setIsDeleteLoading(false); }; + const confirmationModalApproveClickHandler = async () => { + setIsApproveLoading(true); + + const approveResponse = await TransferToLayingApi.approve( + initialValues?.id as number + ); + + if (isResponseSuccess(approveResponse)) { + approveModal.closeModal(); + + toast.success('Berhasil approve data transfer ke laying!'); + } else { + approveModal.closeModal(); + + toast.error('Gagal approve data transfer ke laying!'); + } + + setIsApproveLoading(false); + }; + + const confirmationModalRejectClickHandler = async () => { + setIsRejectLoading(true); + + const rejectResponse = await TransferToLayingApi.reject( + initialValues?.id as number + ); + + if (isResponseSuccess(rejectResponse)) { + rejectModal.closeModal(); + + toast.success('Berhasil reject data transfer ke laying!'); + } else { + rejectModal.closeModal(); + + toast.error('Gagal reject data transfer ke laying!'); + } + + setIsRejectLoading(false); + }; + const isRepeaterInputError = ( column: keyof TransferToLayingFormValues['kandangs'][0], idx: number @@ -303,10 +361,38 @@ const TransferToLayingForm = ({ +
+ {type === 'detail' && ( + <> + + + + + )} +
+
)} + + {type === 'detail' && ( + <> + + + + + )} ); }; From 3110b96305e2d26a63b520f89a096dd8a0dbd775 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Thu, 23 Oct 2025 17:34:52 +0700 Subject: [PATCH 4/4] feat(FE-141): add approve and reject method --- .../api/production/transfer-to-laying.ts | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/services/api/production/transfer-to-laying.ts b/src/services/api/production/transfer-to-laying.ts index 00bf8080..6f808a8c 100644 --- a/src/services/api/production/transfer-to-laying.ts +++ b/src/services/api/production/transfer-to-laying.ts @@ -776,6 +776,30 @@ export class TransferToLayingService extends BaseApiService< } } + // TODO: remove dummy data and integrate to real API + async approve( + id: number + ): Promise | undefined> { + try { + await sleep(750); + + return { + code: 200, + status: 'success', + message: 'Berhasil approve data transfer ke laying!', + data: { + message: 'Berhasil approve data transfer ke laying!', + }, + }; + } catch (error) { + // if (axios.isAxiosError>(error)) { + // return error.response?.data; + // } + + return undefined; + } + } + // TODO: remove dummy data and integrate to real API async bulkApprove( ids: number[] @@ -800,6 +824,30 @@ export class TransferToLayingService extends BaseApiService< } } + // TODO: remove dummy data and integrate to real API + async reject( + id: number + ): Promise | undefined> { + try { + await sleep(750); + + return { + code: 200, + status: 'success', + message: 'Berhasil reject data transfer ke laying!', + data: { + message: 'Berhasil reject data transfer ke laying!', + }, + }; + } catch (error) { + // if (axios.isAxiosError>(error)) { + // return error.response?.data; + // } + + return undefined; + } + } + // TODO: remove dummy data and integrate to real API async bulkReject( ids: number[]