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} -
-