"use client"; import React, { FC } from "react"; import { Page, Text, View, Document, StyleSheet, Font, Image, } from "@react-pdf/renderer"; import { Style } from "@react-pdf/types"; import { getNumber } from "@/lib/utils/getNumber"; Font.register({ family: "Noto Sans SC", src: `${process.env.NEXT_PUBLIC_BASE_URL}/NotoSerifSC-Regular.ttf`, }); Font.register({ family: "roboto", src: `${process.env.NEXT_PUBLIC_BASE_URL}/Roboto-Medium.ttf`, }); Font.register({ family: "roboto-light", src: `${process.env.NEXT_PUBLIC_BASE_URL}/Roboto-Light.ttf`, }); // Create styles const styles = StyleSheet.create({ chinese: { fontFamily: "Noto Sans SC", // Font Chinese fontSize: 10, }, page: { padding: 20, fontFamily: "roboto", fontSize: 10, display: "flex", flexDirection: "column", }, title: { fontSize: 14, textAlign: "center", fontWeight: "bold", }, thead: { fontSize: 12, textAlign: "center", fontWeight: "bold", display: "flex", flexDirection: "row", alignItems: "center", }, section: { marginBottom: 10, }, table: { width: "auto", borderStyle: "solid", borderWidth: 1, marginBottom: 10, }, tableRow: { flexDirection: "row", }, tableCol: { borderStyle: "solid", borderWidth: 1, padding: 5, flex: 1, }, bold: { fontWeight: "bold", }, image: { height: 40, // Atur tinggi gambar marginBottom: 10, alignSelf: "center", }, }); const Row: FC<{ col1?: string; col2?: string; col3?: string; col4?: string; col5?: string; style?: Style; styleText?: Style; footer?: boolean; hideBorder?: boolean; }> = ({ col1, col2, col3, col4, col5, style, styleText, footer, hideBorder, }) => { return ( {col1 && {col1}} {col2 && {col2}} {col3 && {col3}} {col4 && {col4}} {col5 && {col5}} ); }; // Create Document Component const convertRawData = (data: any): any[] => { const formatGradeData = (grade: any): any[] => { const exec = grade?.executive || []; const non = grade?.non_executive || []; const calculateSubTotal = (items: any[]): any => { return { existing: items.reduce((sum, item) => sum + (item?.existing || 0), 0), promote: items.reduce((sum, item) => sum + (item?.promote || 0), 0), recruit: items.reduce((sum, item) => sum + (item?.recruit || 0), 0), total: items.reduce((sum, item) => sum + (item?.total || 0), 0), }; }; const subTotalExecutive = calculateSubTotal(exec); const subTotalNon = calculateSubTotal(non); const rows: any[] = []; const addRowData = (label: string, data: any[], subTotal: any): void => { rows.push({ col1: label }); data.forEach((e) => { rows.push({ col1: e?.job_level_name, col2: e?.existing, col3: e?.promote, col4: e?.recruit, col5: e?.total, }); }); rows.push({ col1: "Sub - Total =", col2: subTotal?.existing, col3: subTotal?.promote, col4: subTotal?.recruit, col5: subTotal?.total, }); }; if (exec.length) { addRowData("Executives", exec, subTotalExecutive); } if (non.length) { addRowData("Non-Executives", non, subTotalNon); } const totalRow = grade?.total?.[0] || {}; rows.push({ col1: "Total =", col2: totalRow.existing || 0, col3: totalRow.promote || 0, col4: totalRow.recruit || 0, col5: totalRow.total || 0, }); return rows; }; const processOverall = (overall: any, type: string, label: string): any => { return { type, label, operatingUnit: overall.operating_unit, budgetYear: overall.budget_year, rows: formatGradeData(overall.grade), budgetRange: overall.budget_range, existingDate: overall.existing_date, }; }; const result: any[] = []; if (data.overall) { result.push(processOverall(data.overall, "overall", "Overall")); } if (data.organization_overall) { data.organization_overall.forEach((org: any, index: number) => { result.push( processOverall(org.overall, "organization", `Organization ${index + 1}`) ); org.location_overall.forEach((loc: any, locIndex: number) => { result.push( processOverall( loc, "location", `Location ${index + 1}.${locIndex + 1}` ) ); }); }); } return result; }; const MyDocument: FC = ({ data }) => { const page = convertRawData(data); return ( {page.map((page, pageIndex) => { return ( JULONG GROUP (INDONESIA) 聚龙集团印尼区 STAFF REQUIREMENT OPERATING UNIT : {page?.operatingUnit} BUDGET YEAR : {page?.budgetYear} Grade Existing {page?.existingDate} {page?.budgetRange} Promote Recruit TOTAL {page?.budgetYear} {/* ROW */} {page.rows.map((row: any, rowIndex: any) => (