[] => [
+ {
+ id: 'expand',
+ header: '',
+ cell: ({ row }) => {
+ const hasFlocks = (row.original.flocks?.length ?? 0) > 0;
+ if (!hasFlocks) return null;
+ const isExpanded = expandedLocations.has(row.original.location.id);
+ return (
+
+ );
+ },
+ footer: () => null,
+ },
+ {
+ id: 'no',
+ header: 'No',
+ cell: (props) => props.row.index + 1,
+ footer: () => TOTAL
,
+ },
+ {
+ id: 'farm',
+ header: 'Farm',
+ cell: ({ row }) => (
+ {row.original.location.name}
+ ),
+ footer: () => ALL
,
+ },
+ {
+ id: 'total_cost_rp',
+ header: 'Total Biaya (RP)',
+ cell: ({ row }) => (
+
+ {formatCurrency(row.original.total_cost_rp)}
+
+ ),
+ footer: () => (
+
+ {formatCurrency(summary?.total_cost_rp ?? 0)}
+
+ ),
+ },
+ {
+ id: 'feed_cost_rp',
+ header: 'Biaya Pakan (RP)',
+ cell: ({ row }) => (
+
+ {formatCurrency(row.original.feed_cost_rp)}
+
+ ),
+ footer: () => (
+ -
+ ),
+ },
+ {
+ id: 'ovk_cost_rp',
+ header: 'Biaya OVK (RP)',
+ cell: ({ row }) => (
+
+ {formatCurrency(row.original.ovk_cost_rp)}
+
+ ),
+ footer: () => (
+ -
+ ),
+ },
+ {
+ id: 'bop_cost_rp',
+ header: 'BOP (RP)',
+ cell: ({ row }) => (
+
+ {formatCurrency(row.original.bop_cost_rp)}
+
+ ),
+ footer: () => (
+ -
+ ),
+ },
+ {
+ id: 'depreciation_rp',
+ header: 'Penyusutan (RP)',
+ cell: ({ row }) => (
+
+ {formatCurrency(row.original.depreciation_rp)}
+
+ ),
+ footer: () => (
+ -
+ ),
+ },
+ {
+ id: 'other_cost_rp',
+ header: 'Biaya Lain (RP)',
+ cell: ({ row }) => (
+
+ {formatCurrency(row.original.other_cost_rp)}
+
+ ),
+ footer: () => (
+ -
+ ),
+ },
+ {
+ id: 'egg_weight_recording_kg',
+ header: 'Bobot Telur Recording (KG)',
+ cell: ({ row }) => (
+
+ {formatNumber(row.original.egg_weight_recording_kg)}
+
+ ),
+ footer: () => (
+
+ {formatNumber(summary?.total_egg_weight_recording_kg ?? 0)}
+
+ ),
+ },
+ {
+ id: 'egg_weight_do_kg',
+ header: 'Bobot Telur DO (KG)',
+ cell: ({ row }) => (
+
+ {formatNumber(row.original.egg_weight_do_kg)}
+
+ ),
+ footer: () => (
+
+ {formatNumber(summary?.total_egg_weight_do_kg ?? 0)}
+
+ ),
+ },
+ {
+ id: 'hpp_per_kg_production',
+ header: 'HPP/KG Produksi (RP/KG)',
+ cell: ({ row }) => (
+
+ {formatCurrency(row.original.hpp_per_kg_production)}
+
+ ),
+ footer: () => (
+
+ {formatCurrency(summary?.average_hpp_per_kg_production ?? 0)}
+
+ ),
+ },
+ {
+ id: 'hpp_per_kg_sales',
+ header: 'HPP/KG Penjualan (RP/KG)',
+ cell: ({ row }) => (
+
+ {formatCurrency(row.original.hpp_per_kg_sales)}
+
+ ),
+ footer: () => (
+
+ {formatCurrency(summary?.average_hpp_per_kg_sales ?? 0)}
+
+ ),
+ },
+ {
+ id: 'average_doc_price_rp',
+ header: 'Rata-rata Harga DOC (RP)',
+ cell: ({ row }) => (
+
+ {formatCurrency(row.original.average_doc_price_rp)}
+
+ ),
+ footer: () => (
+ -
+ ),
+ },
+ ],
+ [expandedLocations, toggleLocation, summary]
+ );
+
+ const renderCustomRow = useCallback(
+ (row: Row): React.ReactNode => {
+ const isExpanded = expandedLocations.has(row.original.location.id);
+ const flocks = row.original.flocks ?? [];
+
+ const locationRow = (
+
+ {row.getVisibleCells().map((cell) => (
+ |
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
+ |
+ ))}
+
+ );
+
+ if (!isExpanded || flocks.length === 0) {
+ return locationRow;
+ }
+
+ const flockRows = flocks.map((flock: HppPerFarmFlock, i: number) => (
+
+ |
+ {i + 1} |
+ {flock.flock_name} |
+ {formatCurrency(flock.total_cost_rp)} |
+ {formatCurrency(flock.feed_cost_rp)} |
+ {formatCurrency(flock.ovk_cost_rp)} |
+ {formatCurrency(flock.bop_cost_rp)} |
+
+ {formatCurrency(flock.depreciation_rp)}
+ |
+ {formatCurrency(flock.other_cost_rp)} |
+
+ {formatNumber(flock.egg_weight_recording_kg)}
+ |
+ {formatNumber(flock.egg_weight_do_kg)} |
+
+ {formatCurrency(flock.hpp_per_kg_production)}
+ |
+
+ {formatCurrency(flock.hpp_per_kg_sales)}
+ |
+
+ {formatCurrency(flock.average_doc_price_rp)}
+ |
+
+ ));
+
+ return [locationRow, ...flockRows];
+ },
+ [expandedLocations]
+ );
+
+ return (
+ <>
+
+ {!isSubmitted ? (
+
[]
+ }
+ icon={
+
+ }
+ title='No Filters Selected'
+ subtitle='Please choose filters to narrow down your results and make your search easier.'
+ />
+ ) : isLoading ? (
+ []
+ }
+ icon={
+
+ }
+ title='Memuat Data HPP Per Farm'
+ subtitle='Silakan tunggu sebentar...'
+ />
+ ) : data.length === 0 ? (
+ []
+ }
+ icon={
+
+ }
+ title='Data Not Yet Available'
+ subtitle='Please change your filters to get the data.'
+ />
+ ) : (
+ 0}
+ renderCustomRow={renderCustomRow}
+ className={{
+ containerClassName: 'w-full mb-0!',
+ tableWrapperClassName: 'overflow-x-auto',
+ tableClassName: 'w-full table-auto text-sm',
+ headerRowClassName: 'border-b border-b-gray-200 bg-gray-50',
+ headerColumnClassName:
+ 'px-4 py-3 text-xs font-semibold text-gray-700 text-left border border-gray-200',
+ bodyRowClassName:
+ 'hover:bg-gray-50 transition-colors border-b border-l border-r border-b-gray-200 border-l-gray-200 border-r-gray-200',
+ bodyColumnClassName:
+ 'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
+ tableFooterClassName:
+ 'bg-gray-100 font-semibold border border-gray-200',
+ footerRowClassName: 'border-t-2 border-gray-300',
+ footerColumnClassName:
+ 'px-4 py-3 text-xs text-gray-900 whitespace-nowrap',
+ }}
+ />
+ )}
+
+
+ {/* Filter Modal */}
+
+ {/* Modal Header */}
+
+
+
+
Filter Data
+
+
+
+
+
+
+ >
+ );
+};
+
+export default HppPerFarmTab;
diff --git a/src/services/http/client.ts b/src/services/http/client.ts
index 64bf9680..4ab9820c 100644
--- a/src/services/http/client.ts
+++ b/src/services/http/client.ts
@@ -5,7 +5,7 @@ import { RequestOptions } from '@/services/http/base';
import { redirectToSSO } from '@/lib/auth-helper';
const BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL ?? '';
-const axiosClient = axios.create({ baseURL: BASE_URL, timeout: 60_000 });
+const axiosClient = axios.create({ baseURL: BASE_URL, timeout: 300_000 });
axiosClient.interceptors.response.use(
(response) => response,
@@ -38,7 +38,7 @@ export async function httpClient(
method: opts.method ?? 'GET',
params: opts.query,
data: opts.body,
- timeout: opts.timeoutMs ?? 60_000,
+ timeout: opts.timeoutMs ?? 300_000,
withCredentials: isCookieAuth && !isBearerAuth,
responseType: opts.responseType,
headers: {
diff --git a/src/types/api/report/hpp-per-farm.d.ts b/src/types/api/report/hpp-per-farm.d.ts
new file mode 100644
index 00000000..df02eccc
--- /dev/null
+++ b/src/types/api/report/hpp-per-farm.d.ts
@@ -0,0 +1,46 @@
+export type HppPerFarmFlock = {
+ project_flock_id: number;
+ flock_name: string;
+ total_cost_rp: number;
+ feed_cost_rp: number;
+ ovk_cost_rp: number;
+ bop_cost_rp: number;
+ depreciation_rp: number;
+ other_cost_rp: number;
+ egg_weight_recording_kg: number;
+ egg_weight_do_kg: number;
+ hpp_per_kg_production: number;
+ hpp_per_kg_sales: number;
+ average_doc_price_rp: number;
+};
+
+export type HppPerFarmRow = {
+ location: { id: number; name: string };
+ total_cost_rp: number;
+ feed_cost_rp: number;
+ ovk_cost_rp: number;
+ bop_cost_rp: number;
+ depreciation_rp: number;
+ other_cost_rp: number;
+ egg_weight_recording_kg: number;
+ egg_weight_do_kg: number;
+ hpp_per_kg_production: number;
+ hpp_per_kg_sales: number;
+ average_doc_price_rp: number;
+ flocks: HppPerFarmFlock[];
+};
+
+export type HppPerFarmSummary = {
+ total_cost_rp: number;
+ total_egg_weight_recording_kg: number;
+ total_egg_weight_do_kg: number;
+ average_hpp_per_kg_production: number;
+ average_hpp_per_kg_sales: number;
+};
+
+export type HppPerFarmReport = {
+ start_date: string;
+ end_date: string;
+ rows: HppPerFarmRow[];
+ summary: HppPerFarmSummary;
+};