From 0dd2edfe01f6c9be8b2ae075b308b09428eb6bef Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Dec 2025 22:22:23 +0700 Subject: [PATCH 1/9] feat(FE-442): create Production Result Report page --- src/app/report/production-result/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/report/production-result/page.tsx diff --git a/src/app/report/production-result/page.tsx b/src/app/report/production-result/page.tsx new file mode 100644 index 00000000..691ea734 --- /dev/null +++ b/src/app/report/production-result/page.tsx @@ -0,0 +1,11 @@ +import ProductionResultContent from '@/components/pages/report/production-result/ProductionResultContent'; + +const ProductionResultReportPage = () => { + return ( +
+ +
+ ); +}; + +export default ProductionResultReportPage; From 23ee8828f0cdb369acffb0e3a44ef66d495f19bc Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Dec 2025 22:24:22 +0700 Subject: [PATCH 2/9] feat(FE-442): create ProductionResultContent component --- .../ProductionResultContent.tsx | 409 ++++++++++++++++++ 1 file changed, 409 insertions(+) create mode 100644 src/components/pages/report/production-result/ProductionResultContent.tsx diff --git a/src/components/pages/report/production-result/ProductionResultContent.tsx b/src/components/pages/report/production-result/ProductionResultContent.tsx new file mode 100644 index 00000000..6fc8f7ea --- /dev/null +++ b/src/components/pages/report/production-result/ProductionResultContent.tsx @@ -0,0 +1,409 @@ +'use client'; + +import { useState } from 'react'; +import toast from 'react-hot-toast'; + +import { Icon } from '@iconify/react'; +import Button from '@/components/Button'; +import Dropdown from '@/components/dropdown/Dropdown'; +import SelectInput, { + OptionType, + useSelect, +} from '@/components/input/SelectInput'; +import Menu from '@/components/menu/Menu'; +import MenuItem from '@/components/menu/MenuItem'; +import Card from '@/components/Card'; +import ProductionResultProjectFlockKandangTable from '@/components/pages/report/production-result/ProductionResultProjectFlockKandangTable'; + +import { BaseKandang } from '@/types/api/master-data/kandang'; +import { AreaApi, LocationApi } from '@/services/api/master-data'; +import { + ProjectFlockApi, + ProjectFlockKandangApi, +} from '@/services/api/production'; +import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang'; +import { isResponseError } from '@/lib/api-helper'; +import Pagination from '@/components/Pagination'; + +const ProductionResultContent = () => { + const [projectFlockKandangs, setProjectFlockKandangs] = useState< + ProjectFlockKandang[] | null + >(null); + const [projectFlockKandangMetadata, setProjectFlockKandangMetadata] = + useState< + | { + page: number; + limit: number; + total_pages: number; + total_results: number; + } + | undefined + >(undefined); + + const [page, setPage] = useState(1); + const [pageSize, setPageSize] = useState(10); + + const [isLoadingSearch, setIsLoadingSearch] = useState(false); + + const [isLoadingExportingToExcel, setIsLoadingExportingToExcel] = + useState(false); + + const [selectedArea, setSelectedArea] = useState(null); + const [selectedLocation, setSelectedLocation] = useState( + null + ); + const [selectedProjectFlock, setSelectedProjectFlock] = + useState(null); + const [selectedProjectFlockKandang, setSelectedProjectFlockKandang] = + useState(null); + + const { + setInputValue: setAreaInputValue, + options: areaOptions, + isLoadingOptions: isLoadingAreaOptions, + } = useSelect(AreaApi.basePath, 'id', 'name'); + + const areaChangeHandler = (val: OptionType | OptionType[] | null) => { + setSelectedArea(val as OptionType); + + setSelectedLocation(null); + + setSelectedProjectFlock(null); + + setSelectedProjectFlockKandang(null); + }; + + const { + setInputValue: setLocationInputValue, + options: locationOptions, + isLoadingOptions: isLoadingLocationOptions, + } = useSelect(LocationApi.basePath, 'id', 'name', 'search', { + area_id: selectedArea ? ((selectedArea as OptionType).value as string) : '', + }); + + const locationChangeHandler = (val: OptionType | OptionType[] | null) => { + setSelectedLocation(val as OptionType); + + setSelectedProjectFlock(null); + + setSelectedProjectFlockKandang(null); + }; + + const { + setInputValue: setProjectFlockInputValue, + options: projectFlockOptions, + isLoadingOptions: isLoadingProjectFlockOptions, + } = useSelect( + ProjectFlockApi.basePath, + 'id', + 'flock_name', + 'search', + { + area_id: selectedArea + ? ((selectedArea as OptionType).value as string) + : '', + location_id: selectedLocation + ? ((selectedLocation as OptionType).value as string) + : '', + category: 'LAYING', + } + ); + + const projectFlockChangeHandler = (val: OptionType | OptionType[] | null) => { + setSelectedProjectFlock(val as OptionType); + + setSelectedProjectFlockKandang(null); + }; + + const { + setInputValue: setProjectFlockKandangInputValue, + options: projectFlockKandangOptions, + isLoadingOptions: isLoadingProjectFlockKandangOptions, + } = useSelect( + ProjectFlockKandangApi.basePath, + 'id', + 'kandang.name', + 'search', + { + area_id: selectedArea + ? ((selectedArea as OptionType).value as string) + : '', + location_id: selectedLocation + ? ((selectedLocation as OptionType).value as string) + : '', + project_flock_id: selectedProjectFlock + ? ((selectedProjectFlock as OptionType).value as string) + : '', + } + ); + + const projectFlockKandangChangeHandler = ( + val: OptionType | OptionType[] | null + ) => { + setSelectedProjectFlockKandang(val as OptionType); + }; + + const exportToExcelHandler = async () => { + setIsLoadingExportingToExcel(true); + // TODO: Implement export functionality in API service first if needed + toast.error('Fitur export belum tersedia'); + setIsLoadingExportingToExcel(false); + }; + + const searchHandler = async () => { + setProjectFlockKandangs(null); + setIsLoadingSearch(true); + + try { + if (selectedProjectFlockKandang) { + const projectFlockKandangResponse = + await ProjectFlockKandangApi.getSingle( + selectedProjectFlockKandang?.value as number + ); + + if ( + !projectFlockKandangResponse || + isResponseError(projectFlockKandangResponse) + ) { + throw new Error(); + } + + setProjectFlockKandangs([projectFlockKandangResponse.data]); + setProjectFlockKandangMetadata(projectFlockKandangResponse.meta); + setIsLoadingSearch(false); + return; + } + + const projectFlockKandangsResponse = await ProjectFlockKandangApi.getAll({ + area_id: selectedArea?.value, + project_flock_id: selectedProjectFlock?.value, + }); + + if ( + !projectFlockKandangsResponse || + isResponseError(projectFlockKandangsResponse) + ) { + throw new Error(); + } + + setProjectFlockKandangs(projectFlockKandangsResponse.data); + setProjectFlockKandangMetadata(projectFlockKandangsResponse.meta); + setIsLoadingSearch(false); + } catch (error) { + toast.error('Gagal mencari data! Coba lagi.'); + setProjectFlockKandangs(null); + setProjectFlockKandangMetadata(undefined); + setIsLoadingSearch(false); + } + }; + + const resetHandler = () => { + setProjectFlockKandangs(null); + setSelectedArea(null); + setSelectedLocation(null); + setSelectedProjectFlock(null); + setSelectedProjectFlockKandang(null); + // resetFilter(); + }; + + return ( +
+ +
+

+ Laporan Hasil Produksi +

+
+ + {/* Filters */} +
+
+ + + + + + + +
+ +
+
+ + + + + Export{' '} + + + } + > + + + + +
+
+
+
+ +
+ {isLoadingSearch && ( + + )} + + {!isLoadingSearch && !projectFlockKandangs && ( +

+ Silakan pilih filter dan klik tombol Cari untuk menampilkan data. +

+ )} + + {!isLoadingSearch && projectFlockKandangs?.length === 0 && ( +

+ Tidak ada data kandang project flock yang dapat ditampilkan. +

+ )} + + {!isLoadingSearch && projectFlockKandangs && ( + + {projectFlockKandangs.map((projectFlockKandang) => ( + + ))} + +
+ + setPage((currPage) => + currPage > 1 ? currPage - 1 : currPage + ) + } + onNextPage={() => + setPage((currPage) => + projectFlockKandangMetadata?.total_pages && + currPage < projectFlockKandangMetadata.total_pages + ? currPage + 1 + : currPage + ) + } + onPageChange={(pageNumber) => setPage(pageNumber)} + rowOptions={[10, 20, 50, 100]} + onRowChange={setPageSize} + /> +
+
+ )} +
+
+ ); +}; + +export default ProductionResultContent; From ea5ad206846f48b549d1d70dfda2469745bd2d48 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Dec 2025 22:25:27 +0700 Subject: [PATCH 3/9] feat(FE-442): create ProductionResultProjectFlockKandangTable component --- ...oductionResultProjectFlockKandangTable.tsx | 364 ++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 src/components/pages/report/production-result/ProductionResultProjectFlockKandangTable.tsx diff --git a/src/components/pages/report/production-result/ProductionResultProjectFlockKandangTable.tsx b/src/components/pages/report/production-result/ProductionResultProjectFlockKandangTable.tsx new file mode 100644 index 00000000..80ee3e9d --- /dev/null +++ b/src/components/pages/report/production-result/ProductionResultProjectFlockKandangTable.tsx @@ -0,0 +1,364 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import useSWR from 'swr'; +import { ColumnDef, SortingState } from '@tanstack/react-table'; + +import { Icon } from '@iconify/react'; +import Table from '@/components/Table'; +import Card from '@/components/Card'; +import Collapse from '@/components/Collapse'; + +import { cn, formatNumber } from '@/lib/helper'; +import { isResponseSuccess } from '@/lib/api-helper'; +import { ProductionResult } from '@/types/api/report/production-result'; +import { useTableFilter } from '@/services/hooks/useTableFilter'; +import { ProductionResultReportApi } from '@/services/api/report/production-result'; + +interface ProductionResultProjectFlockKandangTableProps { + projectFlockKandangId?: number; + kandangName?: string; +} + +const ProductionResultProjectFlockKandangTable = ({ + projectFlockKandangId, + kandangName, +}: ProductionResultProjectFlockKandangTableProps) => { + const { + state: tableFilterState, + updateFilter, + setPage, + setPageSize, + toQueryString: getTableFilterQueryString, + reset: resetFilter, + } = useTableFilter({ + initial: { + filter_by: '', + sort_by: '', + }, + paramMap: { + pageSize: 'limit', + }, + }); + + const { data: productionResults, isLoading: isLoadingProductionResults } = + useSWR( + projectFlockKandangId + ? `/reports/production-result/${projectFlockKandangId}${getTableFilterQueryString()}` + : null, + ProductionResultReportApi.getAllProductionResultFetcher, + { + keepPreviousData: true, + } + ); + + const [open, setOpen] = useState(false); + + const [sorting, setSorting] = useState([]); + + const productionResultColumns: ColumnDef[] = [ + { + header: 'No', + cell: (props) => props.row.index + 1, + }, + { + accessorKey: 'woa', + header: 'WOA', + }, + { + accessorKey: 'bw', + header: 'BW', + cell: (props) => formatNumber(props.row.original.bw), + }, + { + accessorKey: 'std_bw', + header: 'STD BW', + cell: (props) => formatNumber(props.row.original.std_bw), + }, + { + accessorKey: 'uniformity', + header: 'Uniformity', + cell: (props) => formatNumber(props.row.original.uniformity), + }, + { + accessorKey: 'std_uniformity', + header: 'STD Uniformity', + }, + { + accessorKey: 'dep_kum', + header: 'Dep Kum', + cell: (props) => formatNumber(props.row.original.dep_kum), + }, + { + accessorKey: 'dep_std', + header: 'Dep STD', + cell: (props) => formatNumber(props.row.original.dep_std), + }, + // Butiran + { + header: 'Butiran', + columns: [ + { + accessorKey: 'butiran_utuh', + header: 'Utuh', + cell: (props) => formatNumber(props.row.original.butiran_utuh), + }, + { + accessorKey: 'butiran_putih', + header: 'Putih', + cell: (props) => formatNumber(props.row.original.butiran_putih), + }, + { + accessorKey: 'butiran_retak', + header: 'Retak', + cell: (props) => formatNumber(props.row.original.butiran_retak), + }, + { + accessorKey: 'butiran_pecah', + header: 'Pecah', + cell: (props) => formatNumber(props.row.original.butiran_pecah), + }, + { + accessorKey: 'butiran_jumlah', + header: 'Jumlah (Butir)', + cell: (props) => formatNumber(props.row.original.butiran_jumlah), + }, + { + accessorKey: 'total_butir', + header: 'Total Butir', + cell: (props) => formatNumber(props.row.original.total_butir), + }, + ], + }, + // Kg + { + header: 'Kg', + columns: [ + { + accessorKey: 'kg_utuh', + header: 'Utuh (Kg)', + cell: (props) => formatNumber(props.row.original.kg_utuh), + }, + { + accessorKey: 'kg_putih', + header: 'Putih (Kg)', + cell: (props) => formatNumber(props.row.original.kg_putih), + }, + { + accessorKey: 'kg_retak', + header: 'Retak (Kg)', + cell: (props) => formatNumber(props.row.original.kg_retak), + }, + { + accessorKey: 'kg_pecah', + header: 'Pecah (Kg)', + cell: (props) => formatNumber(props.row.original.kg_pecah), + }, + { + accessorKey: 'kg_jumlah', + header: 'Jumlah (Kg)', + cell: (props) => formatNumber(props.row.original.kg_jumlah), + }, + { + accessorKey: 'total_kg', + header: 'Total Kg', + cell: (props) => formatNumber(props.row.original.total_kg), + }, + ], + }, + // Persen + { + header: '%', + columns: [ + { + accessorKey: 'persen_utuh', + header: 'Utuh', + cell: (props) => formatNumber(props.row.original.persen_utuh), + }, + { + accessorKey: 'persen_putih', + header: 'Putih', + cell: (props) => formatNumber(props.row.original.persen_putih), + }, + { + accessorKey: 'persen_retak', + header: 'Retak', + cell: (props) => formatNumber(props.row.original.persen_retak), + }, + { + accessorKey: 'persen_pecah', + header: 'Pecah', + cell: (props) => formatNumber(props.row.original.persen_pecah), + }, + ], + }, + // Produksi + { + header: 'Produksi', + columns: [ + { + accessorKey: 'hd', + header: 'HD', + cell: (props) => formatNumber(props.row.original.hd), + }, + { + accessorKey: 'hd_std', + header: 'HD STD', + cell: (props) => formatNumber(props.row.original.hd_std), + }, + { + accessorKey: 'fi', + header: 'FI', + cell: (props) => formatNumber(props.row.original.fi), + }, + { + accessorKey: 'fi_std', + header: 'FI STD', + cell: (props) => formatNumber(props.row.original.fi_std), + }, + { + accessorKey: 'em', + header: 'EM', + cell: (props) => formatNumber(props.row.original.em), + }, + { + accessorKey: 'em_std', + header: 'EM STD', + cell: (props) => formatNumber(props.row.original.em_std), + }, + { + accessorKey: 'ew', + header: 'EW', + cell: (props) => formatNumber(props.row.original.ew), + }, + { + accessorKey: 'ew_std', + header: 'EW STD', + cell: (props) => formatNumber(props.row.original.ew_std), + }, + { + accessorKey: 'fcr', + header: 'FCR', + cell: (props) => formatNumber(props.row.original.fcr), + }, + { + accessorKey: 'fcr_std', + header: 'FCR STD', + cell: (props) => formatNumber(props.row.original.fcr_std), + }, + { + accessorKey: 'hh', + header: 'HH', + cell: (props) => formatNumber(props.row.original.hh), + }, + { + accessorKey: 'hh_std', + header: 'HH STD', + cell: (props) => formatNumber(props.row.original.hh_std), + }, + ], + }, + ]; + + useEffect(() => { + if (sorting.length === 1) { + updateFilter('filter_by', sorting[0].id); + updateFilter('sort_by', sorting[0].desc ? 'desc' : 'asc'); + } else { + updateFilter('filter_by', ''); + updateFilter('sort_by', ''); + } + }, [sorting]); + + useEffect(() => { + if (!open) { + setOpen( + isResponseSuccess(productionResults) + ? productionResults.data.length > 0 + : false + ); + } + }, [productionResults, isResponseSuccess]); + + return ( + + +
{kandangName}
+ + + + } + className='w-full!' + titleClassName='w-full p-0!' + > +
+ {/*
+
+ +
+
*/} + + + data={ + isResponseSuccess(productionResults) + ? productionResults?.data + : [] + } + columns={productionResultColumns} + pageSize={tableFilterState.pageSize} + onPageSizeChange={setPageSize} + rowOptions={[10, 20, 50, 100]} + page={ + isResponseSuccess(productionResults) + ? productionResults?.meta?.page + : 0 + } + totalItems={ + isResponseSuccess(productionResults) + ? productionResults?.meta?.total_results + : 0 + } + onPageChange={setPage} + isLoading={isLoadingProductionResults} + sorting={sorting} + setSorting={setSorting} + renderFooter={false} + className={{ + containerClassName: cn({ + 'w-full mb-20': + isResponseSuccess(productionResults) && + productionResults?.data?.length === 0, + }), + headerColumnClassName: + 'px-4 py-3 border-base-content/10 text-base-content/50', + }} + /> +
+
+
+ ); +}; + +export default ProductionResultProjectFlockKandangTable; From d66bd8c6061ba7b84018bac665231f41557d9c3a Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Dec 2025 22:25:53 +0700 Subject: [PATCH 4/9] feat(FE-442): add Laporan Hasil Produksi menu --- src/config/constant.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/config/constant.ts b/src/config/constant.ts index 047ed279..dab67bab 100644 --- a/src/config/constant.ts +++ b/src/config/constant.ts @@ -76,6 +76,10 @@ export const MAIN_DRAWER_LINKS: SidebarMenuItem[] = [ text: 'Penjualan', link: '/report/marketing', }, + { + text: 'Hasil Produksi', + link: '/report/production-result', + }, ], }, { From 5326eff293266c2562bdfc217c1914d76dde39de Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Dec 2025 22:26:29 +0700 Subject: [PATCH 5/9] feat(FE-442): add laporan hasil produksi route permission --- src/config/route-permission.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config/route-permission.ts b/src/config/route-permission.ts index 1b9df69d..74b3e46c 100644 --- a/src/config/route-permission.ts +++ b/src/config/route-permission.ts @@ -98,6 +98,7 @@ export const ROUTE_PERMISSIONS: Record = { '/report/logistic-stock/': ['lti.repport.purchasesupplier.list'], '/report/expense/': ['lti.repport.expense.list'], '/report/marketing/': ['lti.repport.delivery.list'], + '/report/production-result/': ['lti.repport.production_result.list'], // Inventory '/inventory/adjustment/': ['lti.inventory.list'], From f985c041e47f5ff10227f0cbcf250cc23f87bdf5 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Dec 2025 22:26:43 +0700 Subject: [PATCH 6/9] chore: create getAll method in BaseApiService --- src/services/api/base.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/services/api/base.ts b/src/services/api/base.ts index 2fcf3712..6a3fdfa4 100644 --- a/src/services/api/base.ts +++ b/src/services/api/base.ts @@ -15,6 +15,22 @@ export class BaseApiService { return await httpClientFetcher>(endpoint); } + async getAll(query?: Record) { + try { + const getAllPath = this.basePath; + const getAllRes = await httpClient>(getAllPath, { + query, + }); + + return getAllRes; + } catch (error) { + if (axios.isAxiosError>(error)) { + return error.response?.data; + } + return undefined; + } + } + async getSingle(id: number) { try { const getSinglePath = `${this.basePath}/${id}`; From dad169d8549d89483b34dc3c1b0b654ca55d18e3 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Dec 2025 22:27:33 +0700 Subject: [PATCH 7/9] feat(FE-443): create ProductionResultReportApiService --- src/services/api/report/production-result.ts | 166 +++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 src/services/api/report/production-result.ts diff --git a/src/services/api/report/production-result.ts b/src/services/api/report/production-result.ts new file mode 100644 index 00000000..98997e9b --- /dev/null +++ b/src/services/api/report/production-result.ts @@ -0,0 +1,166 @@ +import { sleep } from '@/lib/helper'; +import { BaseApiService } from '@/services/api/base'; +import { httpClientFetcher } from '@/services/http/client'; +import { BaseApiResponse } from '@/types/api/api-general'; +import { ProductionResult } from '@/types/api/report/production-result'; + +// TODO: delete this dummy data +const PRODUCTION_RESULT_DUMMY_DATA: BaseApiResponse = { + code: 200, + status: 'success', + message: 'Get Laporan Hasil Produksi successfully', + meta: { + page: 1, + limit: 1, + total_pages: 2, + total_results: 2, + }, + data: [ + { + created_user: { + id: 1, + id_user: 1001, + email: 'user@example.com', + name: 'John Doe', + }, + project_flock: { + id: 1, + name: 'PROJECT', + category: 'LAYING', + kandang: { + id: 1, + name: 'Cikaum', + }, + }, + created_at: '2025-01-01T08:00:00Z', + updated_at: '2025-01-02T10:30:00Z', + + woa: 25, + + bw: 62.5, + std_bw: 60, + uniformity: 88, + std_uniformity: '90% up', + + dep_kum: 3.2, + dep_std: 2.5, + + butiran_utuh: 850, + butiran_putih: 50, + butiran_retak: 70, + butiran_pecah: 30, + butiran_jumlah: 1000, + total_butir: 1000, + + kg_utuh: 52.3, + kg_putih: 3.1, + kg_retak: 4.2, + kg_pecah: 1.9, + kg_jumlah: 61.5, + total_kg: 61.5, + + persen_utuh: 85, + persen_putih: 5, + persen_retak: 7, + persen_pecah: 3, + + hd: 92, + hd_std: 90, + fi: 115, + fi_std: 667, + em: 85, + em_std: 83, + ew: 62, + ew_std: 60, + fcr: 2.1, + fcr_std: 2.0, + hh: 96, + hh_std: 95, + }, + { + created_user: { + id: 1, + id_user: 1001, + email: 'user@example.com', + name: 'John Doe', + }, + project_flock: { + id: 1, + name: 'PROJECT', + category: 'LAYING', + kandang: { + id: 1, + name: 'Cikaum', + }, + }, + created_at: '2025-01-01T08:00:00Z', + updated_at: '2025-01-02T10:30:00Z', + + woa: 25, + + bw: 62.5, + std_bw: 60, + uniformity: 88, + std_uniformity: '90% up', + + dep_kum: 3.2, + dep_std: 2.5, + + butiran_utuh: 850, + butiran_putih: 50, + butiran_retak: 70, + butiran_pecah: 30, + butiran_jumlah: 1000, + total_butir: 1000, + + kg_utuh: 52.3, + kg_putih: 3.1, + kg_retak: 4.2, + kg_pecah: 1.9, + kg_jumlah: 61.5, + total_kg: 61.5, + + persen_utuh: 85, + persen_putih: 5, + persen_retak: 7, + persen_pecah: 3, + + hd: 92, + hd_std: 90, + fi: 115, + fi_std: 110, + em: 85, + em_std: 83, + ew: 62, + ew_std: 60, + fcr: 2.1, + fcr_std: 2.0, + hh: 96, + hh_std: 95, + }, + ], +}; + +export class ProductionResultReportApiService extends BaseApiService< + ProductionResult, + unknown, + unknown +> { + constructor(basePath: string = '/reports/production-result') { + super(basePath); + } + + async getAllProductionResultFetcher( + endpoint: string + ): Promise> { + // return await httpClientFetcher>( + // endpoint + // ); + + await sleep(1000); + + return PRODUCTION_RESULT_DUMMY_DATA; + } +} + +export const ProductionResultReportApi = new ProductionResultReportApiService(); From 7b99bae197ddceef4e8b989b95c229be805e247f Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Dec 2025 22:27:59 +0700 Subject: [PATCH 8/9] feat(FE-443): create ProductionResult type --- src/types/api/report/production-result.d.ts | 59 +++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/types/api/report/production-result.d.ts diff --git a/src/types/api/report/production-result.d.ts b/src/types/api/report/production-result.d.ts new file mode 100644 index 00000000..3fa8fdb8 --- /dev/null +++ b/src/types/api/report/production-result.d.ts @@ -0,0 +1,59 @@ +import { BaseMetadata } from '@/types/api/api-general'; +import { ProjectFlock } from '@/types/api/production/project-flock'; +import { BaseKandang } from '@/types/api/master-data/kandang'; + +export type BaseProductionResult = { + project_flock: Pick & { + kandang: Pick; + }; + + woa: number; + + // BW + bw: number; + std_bw: number; + uniformity: number; + std_uniformity: string; // "90% up" - keeping as string based on "up" suffix potential + + // Dep + dep_kum: number; + dep_std: number; + + // Butiran + butiran_utuh: number; + butiran_putih: number; + butiran_retak: number; + butiran_pecah: number; + butiran_jumlah: number; + total_butir: number; + + // Kg + kg_utuh: number; + kg_putih: number; + kg_retak: number; + kg_pecah: number; + kg_jumlah: number; + total_kg: number; + + // % + persen_utuh: number; + persen_putih: number; + persen_retak: number; + persen_pecah: number; + + // Produksi + hd: number; + hd_std: number; + fi: number; + fi_std: number; + em: number; + em_std: number; + ew: number; + ew_std: number; + fcr: number; + fcr_std: number; + hh: number; + hh_std: number; +}; + +export type ProductionResult = BaseMetadata & BaseProductionResult; From f0894928302800565b11f57b774f26fae86c1298 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Tue, 30 Dec 2025 22:49:39 +0700 Subject: [PATCH 9/9] chore: adjust closing data type --- .../ClosingGeneralInformationTable.tsx | 4 ++-- .../pages/closing/ClosingsTable.tsx | 22 ------------------- src/types/api/closing.d.ts | 13 +++++------ 3 files changed, 8 insertions(+), 31 deletions(-) diff --git a/src/components/pages/closing/ClosingGeneralInformationTable.tsx b/src/components/pages/closing/ClosingGeneralInformationTable.tsx index af21497a..6d5b52b2 100644 --- a/src/components/pages/closing/ClosingGeneralInformationTable.tsx +++ b/src/components/pages/closing/ClosingGeneralInformationTable.tsx @@ -25,9 +25,9 @@ const ClosingGeneralInformationTable = ({ {initialValue?.period} - Kategori + Project Flock : - {initialValue?.project_category} + {initialValue?.project_flock?.name} Populasi diff --git a/src/components/pages/closing/ClosingsTable.tsx b/src/components/pages/closing/ClosingsTable.tsx index e6574d4f..0cacb549 100644 --- a/src/components/pages/closing/ClosingsTable.tsx +++ b/src/components/pages/closing/ClosingsTable.tsx @@ -126,28 +126,6 @@ const ClosingsTable = () => { accessorKey: 'shed_label', header: 'Jumlah Kandang', }, - { - accessorKey: 'sales_paid_amount', - header: 'Jumlah Sudah Bayar', - cell: (props) => ( - - {formatCurrency(props.row.original.sales_paid_amount)} - - ), - }, - { - accessorKey: 'sales_remaining_amount', - header: 'Jumlah Sisa Bayar', - cell: (props) => ( - - {formatCurrency(props.row.original.sales_remaining_amount)} - - ), - }, - { - accessorKey: 'sales_payment_status', - header: 'Status Pembayaran', - }, { accessorKey: 'project_status', header: 'Status', diff --git a/src/types/api/closing.d.ts b/src/types/api/closing.d.ts index c23354f8..ecdaebb9 100644 --- a/src/types/api/closing.d.ts +++ b/src/types/api/closing.d.ts @@ -6,6 +6,11 @@ import { Kandang } from '@/types/api/master-data/kandang'; import { Product } from '@type/api/master-data/product'; import { Customer } from '@type/api/master-data/customer'; import { BaseMetadata } from '@/types/api/api-general'; +import { Kandang } from '@/types/api/master-data/kandang'; +import { Product } from '@type/api/master-data/product'; +import { Customer } from '@type/api/master-data/customer'; +import { BaseMetadata } from '@/types/api/api-general'; +import { ProjectFlock } from '@/types/api/production/project-flock'; export type BaseSales = { id: number; @@ -29,10 +34,6 @@ export type BaseClosingSales = { period: number; sales: BaseSales[]; }; -import { Kandang } from '@/types/api/master-data/kandang'; -import { Product } from '@type/api/master-data/product'; -import { Customer } from '@type/api/master-data/customer'; -import { BaseMetadata } from '@/types/api/api-general'; export type BaseSales = { id: number; @@ -66,9 +67,6 @@ export type BaseClosing = { closing_date?: string; shed_label: string; shed_count: number; - sales_paid_amount: number; - sales_remaining_amount: number; - sales_payment_status: string; project_status: 'Pengajuan' | 'Aktif' | 'Selesai'; }; @@ -83,6 +81,7 @@ export type BaseClosingGeneralInformation = BaseClosing & { sales_payment_status: string; project_status: 'Pengajuan' | 'Aktif' | 'Selesai'; closing_status: string; + project_flock: ProjectFlock; }; export type ClosingGeneralInformation = BaseMetadata &