diff --git a/package-lock.json b/package-lock.json
index 937b53d8..ec1316ae 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1855,7 +1855,6 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz",
"integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"csstype": "^3.0.2"
}
@@ -1925,7 +1924,6 @@
"integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.46.2",
"@typescript-eslint/types": "8.46.2",
@@ -2449,7 +2447,6 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -3063,8 +3060,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/daisyui": {
"version": "5.3.10",
@@ -3520,7 +3516,6 @@
"integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -3694,7 +3689,6 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9",
@@ -6173,7 +6167,6 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -6204,7 +6197,6 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
"license": "MIT",
- "peer": true,
"dependencies": {
"scheduler": "^0.26.0"
},
@@ -7091,7 +7083,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -7259,7 +7250,6 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
diff --git a/src/app/marketing/sales-orders/detail/layout.tsx b/src/app/marketing/add/delivery-orders/layout.tsx
similarity index 100%
rename from src/app/marketing/sales-orders/detail/layout.tsx
rename to src/app/marketing/add/delivery-orders/layout.tsx
diff --git a/src/app/marketing/add/delivery-orders/page.tsx b/src/app/marketing/add/delivery-orders/page.tsx
new file mode 100644
index 00000000..4d92acda
--- /dev/null
+++ b/src/app/marketing/add/delivery-orders/page.tsx
@@ -0,0 +1,54 @@
+'use client';
+
+import MarketingForm from '@/components/pages/marketing/form/MarketingForm';
+import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
+import { MarketingApi } from '@/services/api/marketing/marketing';
+import { useRouter, useSearchParams } from 'next/navigation';
+import toast from 'react-hot-toast';
+import useSWR from 'swr';
+
+const EditMarketingDelivery = () => {
+ const router = useRouter();
+ const searchParams = useSearchParams();
+
+ const soId = searchParams.get('marketingId');
+
+ const {
+ data: marketing,
+ isLoading: isLoading,
+ mutate: refreshMarketing,
+ } = useSWR(`get-so-${soId}`, () =>
+ MarketingApi.getSingle(soId ? parseInt(soId) : 0)
+ );
+
+ if (!soId) {
+ router.back();
+
+ return (
+
+
+
+ );
+ }
+
+ if (!isLoading && (!marketing || isResponseError(marketing))) {
+ router.replace('/404');
+ return;
+ }
+
+ return (
+
+ {isLoading && }
+ {!isLoading && isResponseSuccess(marketing) && (
+ {
+ refreshMarketing();
+ }}
+ />
+ )}
+
+ );
+};
+export default EditMarketingDelivery;
diff --git a/src/app/marketing/sales-orders/add/page.tsx b/src/app/marketing/add/sales-orders/page.tsx
similarity index 52%
rename from src/app/marketing/sales-orders/add/page.tsx
rename to src/app/marketing/add/sales-orders/page.tsx
index e60085ef..9e33d304 100644
--- a/src/app/marketing/sales-orders/add/page.tsx
+++ b/src/app/marketing/add/sales-orders/page.tsx
@@ -1,9 +1,9 @@
-import SalesForm from '@/components/pages/marketing/sales-orders/form/SalesForm';
+import MarketingForm from '@/components/pages/marketing/form/MarketingForm';
const AddSalesOrder = () => {
return (
-
+
);
};
diff --git a/src/app/production/project-flock/chickin/detail/layout.tsx b/src/app/marketing/detail/delivery-orders/edit/layout.tsx
similarity index 100%
rename from src/app/production/project-flock/chickin/detail/layout.tsx
rename to src/app/marketing/detail/delivery-orders/edit/layout.tsx
diff --git a/src/app/marketing/detail/delivery-orders/edit/page.tsx b/src/app/marketing/detail/delivery-orders/edit/page.tsx
new file mode 100644
index 00000000..32625026
--- /dev/null
+++ b/src/app/marketing/detail/delivery-orders/edit/page.tsx
@@ -0,0 +1,62 @@
+'use client';
+
+import MarketingForm from '@/components/pages/marketing/form/MarketingForm';
+import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
+import { MarketingApi } from '@/services/api/marketing/marketing';
+import { useRouter, useSearchParams } from 'next/navigation';
+import toast from 'react-hot-toast';
+import useSWR from 'swr';
+
+const EditMarketingDelivery = () => {
+ const router = useRouter();
+ const searchParams = useSearchParams();
+
+ const soId = searchParams.get('marketingId');
+
+ const {
+ data: marketing,
+ isLoading: isLoading,
+ mutate: refreshMarketing,
+ } = useSWR(`get-so-${soId}`, () =>
+ MarketingApi.getSingle(soId ? parseInt(soId) : 0)
+ );
+
+ if (!soId) {
+ router.back();
+
+ return (
+
+
+
+ );
+ }
+
+ if (!isLoading && (!marketing || isResponseError(marketing))) {
+ router.replace('/404');
+ return;
+ }
+
+ if (
+ isResponseSuccess(marketing) &&
+ marketing.data.latest_approval.step_number != 3
+ ) {
+ toast.error('Data Marketing perlu dilakukan approval terlebih dahulu!');
+ router.back();
+ }
+
+ return (
+
+ {isLoading && }
+ {!isLoading && isResponseSuccess(marketing) && (
+ {
+ refreshMarketing();
+ }}
+ />
+ )}
+
+ );
+};
+export default EditMarketingDelivery;
diff --git a/src/app/marketing/detail/layout.tsx b/src/app/marketing/detail/layout.tsx
new file mode 100644
index 00000000..7220dfa1
--- /dev/null
+++ b/src/app/marketing/detail/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/marketing/sales-orders/detail/page.tsx b/src/app/marketing/detail/page.tsx
similarity index 64%
rename from src/app/marketing/sales-orders/detail/page.tsx
rename to src/app/marketing/detail/page.tsx
index 22d2651c..902251e8 100644
--- a/src/app/marketing/sales-orders/detail/page.tsx
+++ b/src/app/marketing/detail/page.tsx
@@ -1,20 +1,22 @@
'use client';
-import SalesOrderDetail from '@/components/pages/marketing/sales-orders/detail/SalesOrderDetail';
+import MarketingDetail from '@/components/pages/marketing/detail/MarketingDetail';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { MarketingApi } from '@/services/api/marketing/marketing';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
-const DetailSalesOrder = () => {
+const DetailMarketing = () => {
const router = useRouter();
const searchParams = useSearchParams();
- const soId = searchParams.get('salesOrderId');
+ const soId = searchParams.get('marketingId');
- const { data: marketing, isLoading: isLoading } = useSWR(soId, (id: number) =>
- MarketingApi.getSingle(id)
- );
+ const {
+ data: marketing,
+ isLoading: isLoading,
+ mutate: refreshMarketing,
+ } = useSWR(soId, (id: number) => MarketingApi.getSingle(id));
if (!soId) {
router.back();
@@ -35,10 +37,13 @@ const DetailSalesOrder = () => {
{isLoading && }
{!isLoading && isResponseSuccess(marketing) && (
-
+
)}
);
};
-export default DetailSalesOrder;
+export default DetailMarketing;
diff --git a/src/app/marketing/detail/sales-orders/edit/layout.tsx b/src/app/marketing/detail/sales-orders/edit/layout.tsx
new file mode 100644
index 00000000..7220dfa1
--- /dev/null
+++ b/src/app/marketing/detail/sales-orders/edit/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/marketing/sales-orders/detail/edit/page.tsx b/src/app/marketing/detail/sales-orders/edit/page.tsx
similarity index 65%
rename from src/app/marketing/sales-orders/detail/edit/page.tsx
rename to src/app/marketing/detail/sales-orders/edit/page.tsx
index 86cafcb6..19a098c5 100644
--- a/src/app/marketing/sales-orders/detail/edit/page.tsx
+++ b/src/app/marketing/detail/sales-orders/edit/page.tsx
@@ -1,6 +1,6 @@
'use client';
-import SalesForm from '@/components/pages/marketing/sales-orders/form/SalesForm';
+import MarketingForm from '@/components/pages/marketing/form/MarketingForm';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { MarketingApi } from '@/services/api/marketing/marketing';
import { useRouter, useSearchParams } from 'next/navigation';
@@ -10,10 +10,14 @@ const EditSalesOrder = () => {
const router = useRouter();
const searchParams = useSearchParams();
- const soId = searchParams.get('salesOrderId');
+ const soId = searchParams.get('marketingId');
- const { data: marketing, isLoading: isLoading } = useSWR(soId, (id: number) =>
- MarketingApi.getSingle(id)
+ const {
+ data: marketing,
+ isLoading: isLoading,
+ mutate: refreshMarketing,
+ } = useSWR(`get-so-${soId}`, () =>
+ MarketingApi.getSingle(soId ? parseInt(soId) : 0)
);
if (!soId) {
@@ -34,7 +38,13 @@ const EditSalesOrder = () => {
{isLoading && }
{!isLoading && isResponseSuccess(marketing) && (
-
+ {
+ refreshMarketing();
+ }}
+ />
)}
);
diff --git a/src/app/marketing/page.tsx b/src/app/marketing/page.tsx
new file mode 100644
index 00000000..99a80b64
--- /dev/null
+++ b/src/app/marketing/page.tsx
@@ -0,0 +1,10 @@
+import MarketingTable from '@/components/pages/marketing/MarketingTable';
+
+const Marketing = () => {
+ return (
+
+
+
+ );
+};
+export default Marketing;
diff --git a/src/app/marketing/sales-orders/page.tsx b/src/app/marketing/sales-orders/page.tsx
deleted file mode 100644
index 3494b6a1..00000000
--- a/src/app/marketing/sales-orders/page.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import SalesOrderTable from '@/components/pages/marketing/sales-orders/SalesOrderTable';
-
-const SalesOrder = () => {
- return (
-
-
-
- );
-};
-export default SalesOrder;
diff --git a/src/app/production/project-flock/chickin/add/page.tsx b/src/app/production/project-flock/chickin/add/page.tsx
index 3ca09c89..bcb4d612 100644
--- a/src/app/production/project-flock/chickin/add/page.tsx
+++ b/src/app/production/project-flock/chickin/add/page.tsx
@@ -11,10 +11,6 @@ const AddChickin = () => {
return (
<>
>
diff --git a/src/app/production/project-flock/chickin/detail/page.tsx b/src/app/production/project-flock/chickin/detail/page.tsx
deleted file mode 100644
index daea0f0a..00000000
--- a/src/app/production/project-flock/chickin/detail/page.tsx
+++ /dev/null
@@ -1,343 +0,0 @@
-'use client';
-
-import Button from '@/components/Button';
-import Card from '@/components/Card';
-import Modal, { useModal } from '@/components/Modal';
-import ConfirmationModal from '@/components/modal/ConfirmationModal';
-import ChickinForm from '@/components/pages/production/chickin/form/ChickinForm';
-import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
-import { ChickinApi } from '@/services/api/production/chickin';
-import { BaseApiResponse } from '@/types/api/api-general';
-import {
- Chickin,
- ChickinApprovalPayload,
-} from '@/types/api/production/chickin';
-import { Icon } from '@iconify/react';
-import { useRouter, useSearchParams } from 'next/navigation';
-import { useState } from 'react';
-import toast from 'react-hot-toast';
-import useSWR from 'swr';
-
-/**
- * TODO: Refactor code - pindahin detail ke reuseable component
- * setelah implement approval and reject
- */
-
-const DetailChickin = () => {
- const router = useRouter();
- const searchParams = useSearchParams();
- const chickinId = searchParams.get('chickinId');
- const [isApproveLoading, setIsApproveLoading] = useState(false);
- const [isDeleteLoading, setIsDeleteLoading] = useState(false);
-
- const confirmModal = useModal();
- const deleteModal = useModal();
- const chickinModal = useModal();
- const {
- data: chickin,
- isLoading,
- mutate: refreshChickin,
- } = useSWR(chickinId, (id: number) => ChickinApi.getSingle(id));
-
- const [isApprovedDisabled, setIsApprovedDisabled] = useState(
- // chickin.data?.approval.step_number == 1 ? false : true
- true
- );
- const [isRejectedDisabled, setIsRejectedDisabled] =
- useState(!isApprovedDisabled);
- const [approvalAction, setApprovalAction] = useState<'APPROVED' | 'REJECTED'>(
- !isApprovedDisabled ? 'APPROVED' : 'REJECTED'
- );
-
- if (!chickinId) {
- router.back();
-
- return (
-
-
-
- );
- }
-
- if (!isLoading && (!chickin || isResponseError(chickin))) {
- router.replace('/404');
- return;
- }
-
- if (!isResponseSuccess(chickin)) {
- return (
-
-
-
- );
- }
-
- const confirmationModalClickHandler = async ({
- action = 'APPROVED',
- }: {
- action: 'APPROVED' | 'REJECTED';
- }) => {
- if (chickin?.data.id === undefined) return;
- setIsApproveLoading(true);
- const approveChickinRes = await ChickinApi.customRequest<
- BaseApiResponse,
- ChickinApprovalPayload
- >(`/approvals`, {
- method: 'POST',
- payload: {
- action: action,
- approvable_ids: [chickin.data.id],
- },
- });
-
- if (isResponseSuccess(approveChickinRes)) {
- if (refreshChickin) {
- await refreshChickin();
- }
- toast.success(approveChickinRes.message as string);
- }
- if (isResponseError(approveChickinRes)) {
- toast.error(approveChickinRes?.message as string);
- }
- confirmModal.closeModal();
- setIsApproveLoading(false);
- };
-
- const confirmationModalDeleteClickHandler = async () => {
- setIsDeleteLoading(true);
- const deleteProjectFlockRes = await ChickinApi.delete(
- chickin.data?.id as number
- );
-
- if (isResponseSuccess(deleteProjectFlockRes)) {
- toast.success(deleteProjectFlockRes?.message as string);
- router.push('/production/chickin');
- }
- if (isResponseError(deleteProjectFlockRes)) {
- toast.error(deleteProjectFlockRes?.message as string);
- }
- deleteModal.closeModal();
- setIsDeleteLoading(false);
- };
-
- return (
- <>
-
- {isLoading &&
}
- {!isLoading && isResponseSuccess(chickin) && (
- <>
- {/*
-
-
-
*/}
-
-
-
-
Flock
-
- {
- chickin?.data?.project_flock_kandang?.project_flock?.flock
- ?.name
- }
-
-
-
-
Area
-
- {
- chickin.data.project_flock_kandang?.project_flock.area
- .name
- }
-
-
-
-
Kategori
-
- {chickin.data.project_flock_kandang?.project_flock.category}
-
-
-
-
Lokasi
-
- {
- chickin.data.project_flock_kandang?.project_flock.location
- .name
- }
-
-
-
-
Periode
-
- {chickin.data.project_flock_kandang?.project_flock.period}
-
-
-
-
Kandang
-
- {chickin.data.project_flock_kandang?.kandang.name}
-
-
-
-
-
-
-
-
Flock Kandang
-
- {
- chickin?.data?.project_flock_kandang?.project_flock?.flock
- ?.name
- }{' '}
- - {chickin.data.project_flock_kandang?.kandang.name}
-
-
-
-
Tanggal Chickin
-
- {chickin.data.chick_in_date
- ? new Date(chickin.data.chick_in_date).toLocaleDateString(
- 'id-ID'
- )
- : '-'}
-
-
-
-
Jumlah (Ekor)
-
- {chickin.data.quantity?.toLocaleString('id-ID')}
-
-
-
-
Catatan
-
{chickin.data.note}
-
-
-
-
-
-
-
- >
- )}
-
-
-
-
-
-
-
- Chickin Kandang -{' '}
- {chickin?.data?.project_flock_kandang &&
- chickin?.data?.project_flock_kandang.kandang?.name}
-
-
-
-
-
- {
- confirmationModalClickHandler({
- action: approvalAction,
- });
- },
- }}
- />
- >
- );
-};
-
-export default DetailChickin;
diff --git a/src/components/input/DateInput.tsx b/src/components/input/DateInput.tsx
index f5d9ac50..e6225d5e 100644
--- a/src/components/input/DateInput.tsx
+++ b/src/components/input/DateInput.tsx
@@ -80,7 +80,10 @@ const DateInput = ({
// --- Sync value props ---
useEffect(() => {
- if (!value) return;
+ if (!value) {
+ setDisplayValue('');
+ return;
+ }
if (isRange && typeof value === 'object') {
const from = value.from ? new Date(value.from) : undefined;
const to = value.to ? new Date(value.to) : undefined;
diff --git a/src/components/input/TextArea.tsx b/src/components/input/TextArea.tsx
index 10d1a92a..550dbc6b 100644
--- a/src/components/input/TextArea.tsx
+++ b/src/components/input/TextArea.tsx
@@ -8,7 +8,6 @@ export interface TextAreaProps {
label?: string;
bottomLabel?: string;
name: string;
- rows?: number;
value?: string | number;
placeholder?: string;
className?: {
@@ -24,8 +23,11 @@ export interface TextAreaProps {
required?: boolean;
isLoading?: boolean;
errorMessage?: string;
+ startAdornment?: ReactNode;
+ endAdornment?: ReactNode;
onChange?: ChangeEventHandler;
onBlur?: FocusEventHandler;
+ rows?: number;
}
const TextArea = ({
@@ -33,18 +35,20 @@ const TextArea = ({
bottomLabel,
name,
value,
- rows = 3,
placeholder,
className,
isError,
isValid,
errorMessage,
+ startAdornment,
+ endAdornment,
disabled = false,
required = false,
onChange,
onBlur,
readOnly = false,
isLoading = false,
+ rows = 3,
}: TextAreaProps) => {
return (
)}
+ {startAdornment && startAdornment}
-
-
-
- {isLoading && (
-
- {isLoading && }
-
+