diff --git a/src/app/us-284/page.tsx b/src/app/us-284/page.tsx
new file mode 100644
index 00000000..49764069
--- /dev/null
+++ b/src/app/us-284/page.tsx
@@ -0,0 +1,11 @@
+import SapronakCalculationTable from '@/components/pages/us-284/SapronakCalculationTable';
+
+const PerhitunganSapronak = () => {
+ return (
+
+
+
+ );
+};
+
+export default PerhitunganSapronak;
diff --git a/src/components/pages/production/project-flock/detail/ProjectFlockDetail.tsx b/src/components/pages/production/project-flock/detail/ProjectFlockDetail.tsx
index e2d8018f..5b54b10e 100644
--- a/src/components/pages/production/project-flock/detail/ProjectFlockDetail.tsx
+++ b/src/components/pages/production/project-flock/detail/ProjectFlockDetail.tsx
@@ -20,6 +20,10 @@ import ConfirmationModal from '@/components/modal/ConfirmationModal';
import { ProjectFlockApi } from '@/services/api/production/project-flock';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import toast from 'react-hot-toast';
+import ApprovalSteps, {
+ useApprovalSteps,
+} from '@/components/pages/ApprovalSteps';
+import { PROJECT_FLOCK_APPROVAL_LINE } from '@/config/approval-line';
const ProjectFlockDetail = ({
projectFlock,
@@ -38,6 +42,17 @@ const ProjectFlockDetail = ({
(kandang) => kandang.id === Number(selectedKandangId)
);
+ const {
+ approvals,
+ isLoading: approvalsLoading,
+ refresh: refreshApprovals,
+ } = useApprovalSteps({
+ latestApproval: projectFlock?.approval,
+ approvalLines: PROJECT_FLOCK_APPROVAL_LINE,
+ moduleName: 'PROJECT_FLOCKS',
+ moduleId: projectFlock?.id.toString() ?? '',
+ });
+
const confirmationModalDeleteClickHandler = async () => {
setIsDeleteLoading(true);
const deleteProjectFlockRes = await ProjectFlockApi.delete(
@@ -90,6 +105,12 @@ const ProjectFlockDetail = ({
Informasi Umum
+ {/* Status Approval */}
+ {approvals && !approvalsLoading && (
+
+ )}
{/* Badge Row */}
-
+ {/*
History
@@ -163,7 +184,7 @@ const ProjectFlockDetail = ({
height={11}
/>
-
+
*/}
{/* BARIS 1 */}
{
+ constructor(basePath: string = '') {
+ super(basePath);
+ }
+
+ async getPerhitunganSapronak(
+ projectFlockId: number
+ ): Promise
| undefined> {
+ // Dummy implementation - simulate API call with delay
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve({
+ code: 200,
+ status: 'success',
+ message: 'Retrieved sapronak calculation successfully',
+ data: DUMMY_SAPRONAK_CALCULATION,
+ });
+ }, 500); // Simulate 500ms network delay
+ });
+
+ /*
+ // Real API implementation - uncomment when backend is ready
+ try {
+ const path = `${this.basePath}/project-flock/${projectFlockId}/sapronak-calculation`;
+
+ return await httpClient>(path, {
+ method: 'GET',
+ });
+ } catch (error: unknown) {
+ if (axios.isAxiosError>(error)) {
+ return error.response?.data;
+ }
+ return undefined;
+ }
+ */
+ }
+}
+
+export const ClosingApi = new ClosingService(`/closing`);
diff --git a/src/components/pages/us-284/SapronakCalculationTable.tsx b/src/components/pages/us-284/SapronakCalculationTable.tsx
new file mode 100644
index 00000000..dea01068
--- /dev/null
+++ b/src/components/pages/us-284/SapronakCalculationTable.tsx
@@ -0,0 +1,204 @@
+'use client';
+
+import Card from '@/components/Card';
+import {
+ ClosingApi,
+ RowSapronakCalculation,
+} from '@/components/pages/us-284/DummyDataSapronakCalculation';
+import Table from '@/components/Table';
+import { isResponseSuccess } from '@/lib/api-helper';
+import { cn, formatCurrency, formatNumber } from '@/lib/helper';
+import { ColumnDef } from '@tanstack/react-table';
+import { useMemo } from 'react';
+import useSWR from 'swr';
+
+const SapronakCalculationTable = ({
+ projectFlockId,
+}: {
+ projectFlockId: number;
+}) => {
+ const { data: sapronakCalculation, isLoading } = useSWR(
+ `/sapronak-calculation`,
+ () => ClosingApi.getPerhitunganSapronak(projectFlockId)
+ );
+
+ const columns: ColumnDef[] = useMemo(
+ () => [
+ {
+ header: 'Tanggal',
+ accessorKey: 'tanggal',
+ cell: (props) => {
+ const value = props.getValue() as string;
+ // Data already in DD-MMM-YYYY format, just display it
+ return value || '-';
+ },
+ },
+ {
+ header: 'No. Referensi',
+ accessorKey: 'no_referensi',
+ },
+ {
+ header: 'QTY Masuk',
+ accessorKey: 'qty_masuk',
+ cell: (props) => {
+ const value = props.getValue() as number;
+ return formatNumber(value);
+ },
+ },
+ {
+ header: 'QTY Keluar',
+ accessorKey: 'qty_keluar',
+ cell: (props) => {
+ const value = props.getValue() as number;
+ return formatNumber(value);
+ },
+ },
+ {
+ header: 'QTY Pakai',
+ accessorKey: 'qty_pakai',
+ cell: (props) => {
+ const value = props.getValue() as number;
+ return formatNumber(value);
+ },
+ },
+ {
+ header: 'Uraian',
+ accessorKey: 'uraian',
+ },
+ {
+ header: 'Kategori Produk',
+ accessorKey: 'kategori_produk',
+ },
+ {
+ header: 'Harga Beli/Qty (Rp)',
+ accessorKey: 'harga_beli_per_qty',
+ cell: (props) => {
+ const value = props.getValue() as number;
+ return formatCurrency(value);
+ },
+ },
+ {
+ header: 'Total Harga (Rp)',
+ accessorKey: 'total_harga',
+ cell: (props) => {
+ const value = props.getValue() as number;
+ return formatCurrency(value);
+ },
+ },
+ {
+ header: 'Keterangan',
+ accessorKey: 'keterangan',
+ cell: (props) => {
+ const value = props.getValue() as string;
+ return value || '-';
+ },
+ },
+ ],
+ []
+ );
+
+ return (
+
+ {isLoading && (
+
+
+
+ )}
+ {isResponseSuccess(sapronakCalculation) && (
+ <>
+
+
+ data={sapronakCalculation.data.doc_broiler.rows}
+ columns={columns}
+ className={{
+ containerClassName: cn({
+ 'mb-20':
+ isResponseSuccess(sapronakCalculation) &&
+ sapronakCalculation?.data.doc_broiler.rows.length === 0,
+ }),
+ tableWrapperClassName: 'overflow-x-auto min-h-full!',
+ tableClassName: 'font-inter w-full table-auto min-h-full!',
+ headerRowClassName: 'border-b border-b-gray-200',
+ headerColumnClassName:
+ 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
+ bodyRowClassName: 'border-b border-b-gray-200',
+ bodyColumnClassName:
+ 'px-6 py-3 last:flex last:flex-row last:justify-end',
+ }}
+ />
+
+
+
+
+ data={sapronakCalculation.data.ovk.rows}
+ columns={columns}
+ className={{
+ containerClassName: cn({
+ 'mb-20':
+ isResponseSuccess(sapronakCalculation) &&
+ sapronakCalculation?.data.ovk.rows.length === 0,
+ }),
+ tableWrapperClassName: 'overflow-x-auto min-h-full!',
+ tableClassName: 'font-inter w-full table-auto min-h-full!',
+ headerRowClassName: 'border-b border-b-gray-200',
+ headerColumnClassName:
+ 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
+ bodyRowClassName: 'border-b border-b-gray-200',
+ bodyColumnClassName:
+ 'px-6 py-3 last:flex last:flex-row last:justify-end',
+ }}
+ />
+
+
+
+
+ data={sapronakCalculation.data.pakan.rows}
+ columns={columns}
+ className={{
+ containerClassName: cn({
+ 'mb-20':
+ isResponseSuccess(sapronakCalculation) &&
+ sapronakCalculation?.data.pakan.rows.length === 0,
+ }),
+ tableWrapperClassName: 'overflow-x-auto min-h-full!',
+ tableClassName: 'font-inter w-full table-auto min-h-full!',
+ headerRowClassName: 'border-b border-b-gray-200',
+ headerColumnClassName:
+ 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
+ bodyRowClassName: 'border-b border-b-gray-200',
+ bodyColumnClassName:
+ 'px-6 py-3 last:flex last:flex-row last:justify-end',
+ }}
+ />
+
+ >
+ )}
+
+ );
+};
+
+export default SapronakCalculationTable;
diff --git a/src/config/constant.ts b/src/config/constant.ts
index 8af85bc1..4611bb90 100644
--- a/src/config/constant.ts
+++ b/src/config/constant.ts
@@ -58,6 +58,12 @@ export const MAIN_DRAWER_LINKS: MAIN_DRAWER_MENU[] = [
icon: 'uil:wallet',
},
+ {
+ title: 'Perhitungan Sapronak',
+ link: '/us-284',
+ icon: 'uil:calculator',
+ },
+
{
title: 'Persediaan',
link: '/inventory',