From b97cc398549d4253d564aa175c2553d233fdd0e7 Mon Sep 17 00:00:00 2001 From: randy-ar Date: Sat, 6 Dec 2025 13:10:03 +0700 Subject: [PATCH] fix(FE): revert RequireAuth component and closing logic --- src/app/us-284/page.tsx | 11 - src/components/helper/RequireAuth.tsx | 199 ++---------- .../closing/ProjectFlockClosingForm.tsx | 11 +- .../us-284/DummyDataSapronakCalculation.ts | 298 ------------------ .../pages/us-284/SapronakCalculationTable.tsx | 204 ------------ 5 files changed, 40 insertions(+), 683 deletions(-) delete mode 100644 src/app/us-284/page.tsx delete mode 100644 src/components/pages/us-284/DummyDataSapronakCalculation.ts delete mode 100644 src/components/pages/us-284/SapronakCalculationTable.tsx diff --git a/src/app/us-284/page.tsx b/src/app/us-284/page.tsx deleted file mode 100644 index 49764069..00000000 --- a/src/app/us-284/page.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import SapronakCalculationTable from '@/components/pages/us-284/SapronakCalculationTable'; - -const PerhitunganSapronak = () => { - return ( -
- -
- ); -}; - -export default PerhitunganSapronak; diff --git a/src/components/helper/RequireAuth.tsx b/src/components/helper/RequireAuth.tsx index dbd4b6bc..119d74cb 100644 --- a/src/components/helper/RequireAuth.tsx +++ b/src/components/helper/RequireAuth.tsx @@ -6,147 +6,9 @@ import useSWRImmutable from 'swr/immutable'; import { useAuth } from '@/services/hooks/useAuth'; import { httpClientFetcher, SWRHttpKey } from '@/services/http/client'; -import { isResponseSuccess } from '@/lib/api-helper'; -import { GetMeResponse } from '@/types/api/api-general'; - -// TODO: delete this later, DONT HARDCODE USER DATA -const DUMMY_USER = { - id: 1, - email: 'admin@mbugroup.id', - npk: '0001', - name: 'Super Admin', - image: null, - created_at: '2025-09-30T03:24:20.899229Z', - updated_at: '2025-09-30T03:24:20.899229Z', - roles: [ - { - id: 1, - key: 'mbu.super_admin', - name: 'MBU Administrator', - client: { - id: 1, - name: 'PT Mitra Berlian Unggas', - alias: 'MBU', - }, - permissions: [ - { - id: 1, - name: 'mbu:purchase:read', - action: 'read', - client: { - id: 1, - name: 'PT Mitra Berlian Unggas', - alias: 'MBU', - }, - }, - { - id: 2, - name: 'mbu:purchase:create', - action: 'create', - client: { - id: 1, - name: 'PT Mitra Berlian Unggas', - alias: 'MBU', - }, - }, - { - id: 3, - name: 'mbu:purchase:approve', - action: 'approve', - client: { - id: 1, - name: 'PT Mitra Berlian Unggas', - alias: 'MBU', - }, - }, - ], - }, - { - id: 2, - key: 'lti.super_admin', - name: 'LTI Administrator', - client: { - id: 2, - name: 'PT Lumbung Telur Indonesia', - alias: 'LTI', - }, - permissions: [ - { - id: 4, - name: 'lti:purchase:read', - action: 'read', - client: { - id: 2, - name: 'PT Lumbung Telur Indonesia', - alias: 'LTI', - }, - }, - { - id: 5, - name: 'lti:purchase:create', - action: 'create', - client: { - id: 2, - name: 'PT Lumbung Telur Indonesia', - alias: 'LTI', - }, - }, - { - id: 6, - name: 'lti:purchase:approve', - action: 'approve', - client: { - id: 2, - name: 'PT Lumbung Telur Indonesia', - alias: 'LTI', - }, - }, - ], - }, - { - id: 3, - key: 'manbu.super_admin', - name: 'MANBU Administrator', - client: { - id: 3, - name: 'PT Mandiri Berlian Unggas', - alias: 'MANBU', - }, - permissions: [ - { - id: 7, - name: 'manbu:purchase:read', - action: 'read', - client: { - id: 3, - name: 'PT Mandiri Berlian Unggas', - alias: 'MANBU', - }, - }, - { - id: 8, - name: 'manbu:purchase:create', - action: 'create', - client: { - id: 3, - name: 'PT Mandiri Berlian Unggas', - alias: 'MANBU', - }, - }, - { - id: 9, - name: 'manbu:purchase:approve', - action: 'approve', - client: { - id: 3, - name: 'PT Mandiri Berlian Unggas', - alias: 'MANBU', - }, - }, - ], - }, - ], -}; +import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; +import { BaseApiResponse, GetMeResponse } from '@/types/api/api-general'; +import { AxiosError } from 'axios'; interface RequireAuthProps { children?: ReactNode; @@ -156,17 +18,20 @@ const RequireAuth = ({ children }: RequireAuthProps) => { const router = useRouter(); const { setUser, setIsLoadingUser } = useAuth(); - const { data: userResponse, isLoading: isLoadingUserResponse } = - useSWRImmutable( - '/auth/sso/userinfo', - httpClientFetcher, - { - shouldRetryOnError: false, - revalidateOnFocus: false, - revalidateOnReconnect: false, - refreshInterval: 0, - } - ); + const { + data: userResponse, + isLoading: isLoadingUserResponse, + error: userErrorResponse, + } = useSWRImmutable< + GetMeResponse & { ok?: boolean }, + AxiosError, + SWRHttpKey + >('/sso/userinfo', httpClientFetcher, { + shouldRetryOnError: false, + revalidateOnFocus: false, + revalidateOnReconnect: false, + refreshInterval: 0, + }); useEffect(() => { setIsLoadingUser(isLoadingUserResponse); @@ -175,23 +40,25 @@ const RequireAuth = ({ children }: RequireAuthProps) => { useEffect(() => { if (isResponseSuccess(userResponse)) { setUser(userResponse.data); - } else { - // router.replace(process.env.NEXT_PUBLIC_SSO_LOGIN_URL as string); - // TODO: remove this later, DONT HARDCODE USER DATA - setUser(DUMMY_USER); + } else if ( + isResponseError(userErrorResponse?.response?.data) && + typeof window !== 'undefined' + ) { + router.replace( + `${process.env.NEXT_PUBLIC_SSO_LOGIN_URL as string}?redirect_url=${window.location.href}` + ); } - }, [userResponse, setIsLoadingUser, setUser]); + }, [userResponse, userErrorResponse, setIsLoadingUser, setUser]); - // TODO: uncomment this later - // if (isLoadingUserResponse && !userResponse) { - // return ( - //
- // - //
- // ); - // } + if (isLoadingUserResponse && !userResponse && !userErrorResponse) { + return ( +
+ +
+ ); + } - return <>{children}; + return <>{isResponseSuccess(userResponse) && children}; }; export default RequireAuth; diff --git a/src/components/pages/production/project-flock/closing/ProjectFlockClosingForm.tsx b/src/components/pages/production/project-flock/closing/ProjectFlockClosingForm.tsx index 7d5f1f9b..bcfb7795 100644 --- a/src/components/pages/production/project-flock/closing/ProjectFlockClosingForm.tsx +++ b/src/components/pages/production/project-flock/closing/ProjectFlockClosingForm.tsx @@ -1,16 +1,15 @@ 'use client'; + import Button from '@/components/Button'; import DrawerHeader from '@/components/helper/drawer/DrawerHeader'; import Table from '@/components/Table'; import Badge from '@/components/Badge'; import { cn, formatDate, formatNumber, formatTitleCase } from '@/lib/helper'; -import { ProductWarehouse } from '@/types/api/inventory/product-warehouse'; import { ProjectFlock } from '@/types/api/production/project-flock'; import { ClosingExpense, ProjectFlockKandang, } from '@/types/api/production/project-flock-kandang'; -import { Purchase } from '@/types/api/purchase/purchase'; import { Icon } from '@iconify/react'; import useSWR from 'swr'; import { ProjectFlockKandangApi } from '@/services/api/production/project-flock-kandang'; @@ -19,6 +18,8 @@ import { useModal } from '@/components/Modal'; import ConfirmationModal from '@/components/modal/ConfirmationModal'; import { useMemo, useState } from 'react'; import toast from 'react-hot-toast'; +import { useRouter } from 'next/navigation'; +import { ProductWarehouse } from '@/types/api/inventory/product-warehouse'; const ProjectFlockClosingForm = ({ projectFlock, @@ -27,8 +28,9 @@ const ProjectFlockClosingForm = ({ projectFlock: ProjectFlock; projectFlockKandang: ProjectFlockKandang; }) => { + const router = useRouter(); const closeModal = useModal(); - const isCanClose = projectFlock.approval?.step_number <= 1; + const isCanClose = projectFlock.approval?.step_number <= 2; const [isClosingLoading, setIsClosingLoading] = useState(false); const { data: closingData, isLoading } = useSWR( @@ -48,6 +50,7 @@ const ProjectFlockClosingForm = ({ if (isResponseSuccess(deleteProjectFlockRes)) { toast.success(deleteProjectFlockRes?.message as string); + router.push(`/production/project-flock`); } if (isResponseError(deleteProjectFlockRes)) { toast.error(deleteProjectFlockRes?.message as string); @@ -280,7 +283,7 @@ const ProjectFlockClosingForm = ({ ref={closeModal.ref} type='error' text={ - projectFlock.approval?.step_number <= 1 + isCanClose ? 'Apakah kamu yakin ingin mengakhiri project ini ? *Pastikan persediaan produk di gudang terkait sudah kosong, dan BOP sudah selesai' : 'Apakah kamu yakin ingin membuka kembali project ini ? *Project ini akan kembali ke status aktif' } diff --git a/src/components/pages/us-284/DummyDataSapronakCalculation.ts b/src/components/pages/us-284/DummyDataSapronakCalculation.ts deleted file mode 100644 index 74a6313e..00000000 --- a/src/components/pages/us-284/DummyDataSapronakCalculation.ts +++ /dev/null @@ -1,298 +0,0 @@ -import { BaseApiService } from '@/services/api/base'; -import { BaseApiResponse } from '@/types/api/api-general'; - -export type RowSapronakCalculation = { - id: number; - tanggal: string; - no_referensi: string; - qty_masuk: number; - qty_keluar: number; - qty_pakai: number; - uraian: string; - kategori_produk: string; - harga_beli_per_qty: number; - total_harga: number; - keterangan: string; -}; - -export type TotalSapronakCalculation = { - label: string; - qty_masuk: number; - qty_keluar: number; - qty_pakai: number; - harga_beli_per_qty: number; - total_harga: number; -}; - -export type SapronakCalculationItem = { - rows: RowSapronakCalculation[]; - total: TotalSapronakCalculation; -}; - -export type SapronakCalculation = { - doc_broiler: SapronakCalculationItem; - ovk: SapronakCalculationItem; - pakan: SapronakCalculationItem; -}; - -// Dummy data -const DUMMY_SAPRONAK_CALCULATION: SapronakCalculation = { - doc_broiler: { - rows: [ - { - id: 1, - tanggal: '11-Sep-2025', - no_referensi: 'PO-PULLET-388', - qty_masuk: 32800, - qty_keluar: 0, - qty_pakai: 32800, - uraian: 'PULLET LOHMANN (16 MINGGU)', - kategori_produk: 'PULLET LAYER', - harga_beli_per_qty: 60136, - total_harga: 1972556800, - keterangan: '-', - }, - { - id: 2, - tanggal: '24-Sep-2025', - no_referensi: 'PO-PULLET-410', - qty_masuk: 14758, - qty_keluar: 0, - qty_pakai: 14758, - uraian: 'PULLET HY-LINE (17 MINGGU)', - kategori_produk: 'PULLET LAYER', - harga_beli_per_qty: 65421, - total_harga: 965908998, - keterangan: '-', - }, - { - id: 3, - tanggal: '29-Sep-2025', - no_referensi: 'PO-PULLET-196', - qty_masuk: 35439, - qty_keluar: 0, - qty_pakai: 35439, - uraian: 'PULLET ISA BROWN (15 MINGGU)', - kategori_produk: 'PULLET LAYER', - harga_beli_per_qty: 55909, - total_harga: 1981297351, - keterangan: '-', - }, - ], - total: { - label: 'TOTAL PULLET', - qty_masuk: 82997, - qty_keluar: 0, - qty_pakai: 82997, - harga_beli_per_qty: 59274.65, - total_harga: 4919963149, - }, - }, - ovk: { - rows: [ - { - id: 1, - tanggal: '28-Sep-2025', - no_referensi: 'PO-OVK-276', - qty_masuk: 52, - qty_keluar: 0, - qty_pakai: 52, - uraian: 'ND-IB VACCINE', - kategori_produk: 'OVK VAKSIN', - harga_beli_per_qty: 204652, - total_harga: 10641904, - keterangan: 'Program kesehatan & biosecurity', - }, - { - id: 2, - tanggal: '26-Sep-2025', - no_referensi: 'PO-OVK-811', - qty_masuk: 43, - qty_keluar: 0, - qty_pakai: 43, - uraian: 'GUMBORO VACCINE', - kategori_produk: 'OVK VAKSIN', - harga_beli_per_qty: 298379, - total_harga: 12830297, - keterangan: 'Program kesehatan & biosecurity', - }, - { - id: 3, - tanggal: '28-Sep-2025', - no_referensi: 'PO-OVK-879', - qty_masuk: 21, - qty_keluar: 0, - qty_pakai: 21, - uraian: 'AMOXITIN SOLUBLE', - kategori_produk: 'OVK OBAT', - harga_beli_per_qty: 145952, - total_harga: 3064992, - keterangan: 'Program kesehatan & biosecurity', - }, - { - id: 4, - tanggal: '11-Okt-2025', - no_referensi: 'PO-OVK-340', - qty_masuk: 38, - qty_keluar: 0, - qty_pakai: 38, - uraian: 'TILOXIN SOLUBLE', - kategori_produk: 'OVK OBAT', - harga_beli_per_qty: 200424, - total_harga: 7616112, - keterangan: 'Program kesehatan & biosecurity', - }, - { - id: 5, - tanggal: '27-Sep-2025', - no_referensi: 'PO-OVK-364', - qty_masuk: 7, - qty_keluar: 0, - qty_pakai: 7, - uraian: 'EGG STIMULANT', - kategori_produk: 'OVK VITAMIN', - harga_beli_per_qty: 115024, - total_harga: 805168, - keterangan: 'Program kesehatan & biosecurity', - }, - { - id: 6, - tanggal: '16-Sep-2025', - no_referensi: 'PO-OVK-982', - qty_masuk: 57, - qty_keluar: 0, - qty_pakai: 57, - uraian: 'MULTIVIT-AMINO', - kategori_produk: 'OVK VITAMIN', - harga_beli_per_qty: 65123, - total_harga: 3712011, - keterangan: 'Program kesehatan & biosecurity', - }, - { - id: 7, - tanggal: '04-Okt-2025', - no_referensi: 'PO-OVK-876', - qty_masuk: 4, - qty_keluar: 0, - qty_pakai: 4, - uraian: 'BKC DESINFEKTAN', - kategori_produk: 'OVK KIMIA', - harga_beli_per_qty: 105677, - total_harga: 422708, - keterangan: 'Program kesehatan & biosecurity', - }, - ], - total: { - label: 'TOTAL OVK', - qty_masuk: 222, - qty_keluar: 0, - qty_pakai: 222, - harga_beli_per_qty: 172965.92, - total_harga: 38481094, - }, - }, - pakan: { - rows: [ - { - id: 1, - tanggal: '13-Ags-2025', - no_referensi: 'PO-FEED-730', - qty_masuk: 4833, - qty_keluar: 0, - qty_pakai: 4833, - uraian: 'FEED PRE-LAY', - kategori_produk: 'PAKAN PRE-LAY', - harga_beli_per_qty: 7578, - total_harga: 36625874, - keterangan: 'Konsumsi pakan kandang layer', - }, - { - id: 2, - tanggal: '28-Jul-2025', - no_referensi: 'PO-FEED-555', - qty_masuk: 6500, - qty_keluar: 0, - qty_pakai: 6500, - uraian: 'FEED LAYER PHASE 1', - kategori_produk: 'PAKAN LAYER', - harga_beli_per_qty: 8116, - total_harga: 52754000, - keterangan: 'Konsumsi pakan kandang layer', - }, - { - id: 3, - tanggal: '24-Agu-2025', - no_referensi: 'PO-FEED-683', - qty_masuk: 8802, - qty_keluar: 0, - qty_pakai: 8802, - uraian: 'FEED LAYER PHASE 2', - kategori_produk: 'PAKAN LAYER', - harga_beli_per_qty: 8801, - total_harga: 77465402, - keterangan: 'Konsumsi pakan kandang layer', - }, - { - id: 4, - tanggal: '02-Sep-2025', - no_referensi: 'PO-FEED-448', - qty_masuk: 2185, - qty_keluar: 0, - qty_pakai: 2185, - uraian: 'JAGUNG GILING', - kategori_produk: 'PAKAN MIX', - harga_beli_per_qty: 5573, - total_harga: 12187705, - keterangan: 'Konsumsi pakan kandang layer', - }, - ], - total: { - label: 'TOTAL PAKAN', - qty_masuk: 22320, - qty_keluar: 0, - qty_pakai: 22320, - harga_beli_per_qty: 8092.39, - total_harga: 179032981, - }, - }, -}; - -export class ClosingService extends BaseApiService { - 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 deleted file mode 100644 index dea01068..00000000 --- a/src/components/pages/us-284/SapronakCalculationTable.tsx +++ /dev/null @@ -1,204 +0,0 @@ -'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;