diff --git a/package-lock.json b/package-lock.json
index e1f28d3e..b82b5c06 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,7 @@
"moment": "^2.30.1",
"next": "15.5.3",
"react": "19.1.0",
+ "react-day-picker": "^9.11.1",
"react-dom": "19.1.0",
"react-hot-toast": "^2.6.0",
"react-number-format": "^5.4.4",
@@ -195,6 +196,12 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@date-fns/tz": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.4.1.tgz",
+ "integrity": "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==",
+ "license": "MIT"
+ },
"node_modules/@emnapi/core": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.6.0.tgz",
@@ -2872,6 +2879,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/date-fns": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
+ "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/kossnocorp"
+ }
+ },
+ "node_modules/date-fns-jalali": {
+ "version": "4.1.0-0",
+ "resolved": "https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-4.1.0-0.tgz",
+ "integrity": "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==",
+ "license": "MIT"
+ },
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@@ -5732,6 +5755,27 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-day-picker": {
+ "version": "9.11.1",
+ "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.11.1.tgz",
+ "integrity": "sha512-l3ub6o8NlchqIjPKrRFUCkTUEq6KwemQlfv3XZzzwpUeGwmDJ+0u0Upmt38hJyd7D/vn2dQoOoLV/qAp0o3uUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@date-fns/tz": "^1.4.1",
+ "date-fns": "^4.1.0",
+ "date-fns-jalali": "^4.1.0-0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://github.com/sponsors/gpbl"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
"node_modules/react-dom": {
"version": "19.1.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
diff --git a/package.json b/package.json
index b371e4e7..10e8de5c 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"moment": "^2.30.1",
"next": "15.5.3",
"react": "19.1.0",
+ "react-day-picker": "^9.11.1",
"react-dom": "19.1.0",
"react-hot-toast": "^2.6.0",
"react-number-format": "^5.4.4",
diff --git a/src/app/production/chickin/add/kandang/layout.tsx b/src/app/production/chickin/add/kandang/layout.tsx
new file mode 100644
index 00000000..7220dfa1
--- /dev/null
+++ b/src/app/production/chickin/add/kandang/layout.tsx
@@ -0,0 +1,11 @@
+import SuspenseHelper from '@/components/helper/SuspenseHelper';
+
+const Layout = ({
+ children,
+}: Readonly<{
+ children: React.ReactNode;
+}>) => {
+ return {children};
+};
+
+export default Layout;
diff --git a/src/app/production/chickin/add/kandang/page.tsx b/src/app/production/chickin/add/kandang/page.tsx
new file mode 100644
index 00000000..6f624672
--- /dev/null
+++ b/src/app/production/chickin/add/kandang/page.tsx
@@ -0,0 +1,15 @@
+'use client';
+
+import { useRouter, useSearchParams } from 'next/navigation';
+
+export default function AddChickinKandang() {
+ const router = useRouter();
+ const searchParams = useSearchParams();
+ const kandangId = searchParams.get('kandangId');
+
+ return (
+
+
Tambah Chickin untuk Kandang ID: {kandangId}
+
+ );
+}
diff --git a/src/app/production/chickin/add/page.tsx b/src/app/production/chickin/add/page.tsx
index a52dbe10..2f68e86c 100644
--- a/src/app/production/chickin/add/page.tsx
+++ b/src/app/production/chickin/add/page.tsx
@@ -2,10 +2,12 @@
import Badge from '@/components/Badge';
import Button from '@/components/Button';
+import Card from '@/components/Card';
import SelectInput, { OptionType } from '@/components/input/SelectInput';
import Modal, { useModal } from '@/components/Modal';
import ConfirmationModal from '@/components/modal/ConfirmationModal';
import ChickinForm from '@/components/pages/production/chickin/form/ChickinForm';
+import PillBadge from '@/components/PillBadge';
import Table from '@/components/Table';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { cn } from '@/lib/helper';
@@ -13,10 +15,12 @@ import { ProjectFlockApi } from '@/services/api/production';
import { useTableFilter } from '@/services/hooks/useTableFilter';
import { BaseApiResponse } from '@/types/api/api-general';
import { Kandang } from '@/types/api/master-data/kandang';
+import { ProjectFlock } from '@/types/api/production/project-flock';
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
import { Icon } from '@iconify/react';
import { useRouter, useSearchParams } from 'next/navigation';
import { useState } from 'react';
+import { is } from 'react-day-picker/locale';
import useSWR from 'swr';
@@ -113,21 +117,27 @@ const AddChickin = () => {
<>
-
- emptyContent={
-
- {projectFlockId && isResponseError(projectFlock) ? (
-
- {projectFlock.message}
-
- ) : (
-
- Pilih project flock terlebih dahulu...
-
- )}
-
- }
- data={
- isResponseSuccess(projectFlock) ? projectFlock.data?.kandangs : []
- }
- columns={[
- {
- header: '#',
- cell: (props) =>
- tableFilterState.pageSize * (tableFilterState.page - 1) +
- props.row.index +
- 1,
- },
- {
- accessorKey: 'name',
- header: 'Nama Kandang',
- },
- {
- header: 'Aksi',
- cell: (props) => {
- return (
- <>
-
- >
- );
- },
- },
- ]}
- page={undefined}
+
+ >
+
+ emptyContent={
+
+ {projectFlockId && isResponseError(projectFlock) ? (
+
+ {projectFlock.message}
+
+ ) : (
+
+ Pilih project flock terlebih dahulu...
+
+ )}
+
+ }
+ data={isResponseSuccess(projectFlock) ? [projectFlock.data] : []}
+ columns={[
+ {
+ header: 'Area',
+ accessorKey: 'area.name',
+ },
+ {
+ header: 'Lokasi',
+ accessorKey: 'location.name',
+ },
+ {
+ header: 'Nama Flock',
+ accessorKey: 'flock.name',
+ },
+ {
+ header: 'Kategori',
+ accessorKey: 'category',
+ },
+ {
+ header: 'Status',
+ accessorKey: 'status',
+ cell: (props) => {
+ return props.row.original.approval.step_name ? (
+ {
+ switch (
+ props.row.original.approval.step_name.toUpperCase()
+ ) {
+ case 'AKTIF':
+ return 'red';
+ case 'PENGAJUAN':
+ return 'green';
+ default:
+ return 'gray';
+ }
+ })()}
+ content={props.row.original.approval.step_name
+ .toLowerCase()
+ .replace(/_/g, ' ')
+ .replace(/\b\w/g, (char) => char.toUpperCase())}
+ />
+ ) : (
+ '-'
+ );
+ },
+ },
+ {
+ header: 'Periode',
+ accessorKey: 'period',
+ },
+ {
+ header: 'FCR Layer',
+ accessorKey: 'fcr.name',
+ },
+ ]}
+ page={undefined}
+ className={{
+ containerClassName: cn({
+ 'mb-20':
+ isResponseSuccess(projectFlock) &&
+ projectFlock.data?.kandangs?.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',
+ paginationClassName: 'hidden',
+ }}
+ />
+
+
+
+ emptyContent={
+
+ {projectFlockId && isResponseError(projectFlock) ? (
+
+ {projectFlock.message}
+
+ ) : (
+
+ Pilih project flock terlebih dahulu...
+
+ )}
+
+ }
+ data={
+ isResponseSuccess(projectFlock)
+ ? projectFlock.data?.kandangs
+ : []
+ }
+ columns={[
+ {
+ header: '#',
+ cell: (props) =>
+ tableFilterState.pageSize * (tableFilterState.page - 1) +
+ props.row.index +
+ 1,
+ },
+ {
+ accessorFn: () =>
+ isResponseSuccess(projectFlock)
+ ? projectFlock.data.area.name
+ : '',
+ header: 'Area',
+ },
+ {
+ accessorFn: () =>
+ isResponseSuccess(projectFlock)
+ ? projectFlock.data.location.name
+ : '',
+ header: 'Lokasi',
+ },
+ {
+ accessorKey: 'name',
+ header: 'Kandang',
+ },
+ {
+ accessorKey: 'capacity',
+ header: 'Kapasitas',
+ },
+ {
+ accessorKey: 'pic.name',
+ header: 'Penanggung Jawab',
+ },
+ {
+ header: 'Aksi',
+ cell: (props) => {
+ return (
+ <>
+
+ >
+ );
+ },
+ },
+ ]}
+ page={undefined}
+ className={{
+ containerClassName: cn({
+ 'mb-20':
+ isResponseSuccess(projectFlock) &&
+ projectFlock.data?.kandangs?.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',
+ paginationClassName: 'hidden',
+ }}
+ />
+
diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx
index a84c1827..958d88dd 100644
--- a/src/components/Modal.tsx
+++ b/src/components/Modal.tsx
@@ -1,6 +1,13 @@
'use client';
-import { ReactNode, RefObject, useCallback, useRef, useState } from 'react';
+import {
+ ReactNode,
+ RefObject,
+ useCallback,
+ useEffect,
+ useRef,
+ useState,
+} from 'react';
import { cn } from '@/lib/helper';
export const useModal = () => {
@@ -8,31 +15,35 @@ export const useModal = () => {
const [open, setOpen] = useState(false);
const openModal = useCallback(() => {
+ if (!ref.current) return;
+ ref.current.showModal();
setOpen(true);
-
- ref.current?.showModal();
}, []);
const closeModal = useCallback(() => {
+ if (!ref.current) return;
+ ref.current.close();
setOpen(false);
- ref.current?.close();
}, []);
const toggle = useCallback(() => {
- if (open) {
- closeModal();
- } else {
- openModal();
- }
+ open ? closeModal() : openModal();
}, [open, closeModal, openModal]);
- if (ref.current) {
- ref.current.addEventListener('close', () => {
- closeModal();
- });
- }
+ // Gunakan useEffect agar event listener tidak didaftarkan berulang kali
+ useEffect(() => {
+ const dialog = ref.current;
+ if (!dialog) return;
- return { ref, open, setOpen, openModal, closeModal, toggle } as const;
+ const handleClose = () => setOpen(false);
+ dialog.addEventListener('close', handleClose);
+
+ return () => {
+ dialog.removeEventListener('close', handleClose);
+ };
+ }, []);
+
+ return { ref, open, openModal, closeModal, toggle } as const;
};
interface ModalProps {
@@ -46,15 +57,19 @@ interface ModalProps {
}
const Modal = ({ ref, children, closeOnBackdrop, className }: ModalProps) => {
- return (
-
}
+ disabled={
+ [
+ minDate ? { before: minDate } : undefined,
+ maxDate ? { after: maxDate } : undefined,
+ ].filter(Boolean) as Matcher[]
+ }
+ />
+ ) : (
+
+ )}
+
+ {isRange && (
+
+ Tekan dua kali untuk memilih tanggal awal
+
+ )}
+
+
+
+ {isRange && (
+
+ )}
+
+
+
);
};
diff --git a/src/components/pages/production/project-flock/ProjectFlockTable.tsx b/src/components/pages/production/project-flock/ProjectFlockTable.tsx
index 2958a3f5..73282123 100644
--- a/src/components/pages/production/project-flock/ProjectFlockTable.tsx
+++ b/src/components/pages/production/project-flock/ProjectFlockTable.tsx
@@ -44,54 +44,56 @@ const RowOptionsMenu = ({
'dropdown-content': type === 'dropdown',
'mt-2': type === 'collapse',
},
- 'p-2.5 mr-2 flex flex-col gap-1 bg-base-100 rounded-box z-10 border border-black/10 shadow'
+ 'p-2.5 mr-2 bg-base-100 rounded-box z-10 border border-black/10 shadow'
)}
>
-
- {props.row.original.approval.step_name === 'Aktif' && (
+
- )}
- {props.row.original.approval.step_name === 'Pengajuan' && (
+ {props.row.original.approval.step_name === 'Aktif' && (
+
+ )}
+ {props.row.original.approval.step_name === 'Pengajuan' && (
+
+ )}
- )}
-
+
);
};