import { CanvasElement, Content, TDocumentDefinitions } from 'pdfmake/interfaces' import { useEffect, useState } from 'react' import pdfMake from 'pdfmake/build/pdfmake' export interface DataToPrint { configs: { title?: string logoUrl?: string headline?: string columnsHeader: Array } data: { header: any items: any[] summary: any footer?: Array } } const isInvoiceMasterRow = (i: number) => { return i % 2 === 0 && i === 0 } pdfMake.fonts = { Khmer: { normal: 'kh-battambang.ttf', bold: 'kh-battambang.ttf', italics: 'kh-battambang.ttf', bolditalics: 'kh-battambang.ttf' }, Roboto: { normal: 'https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.66/fonts/Roboto/Roboto-Regular.ttf', bold: 'https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.66/fonts/Roboto/Roboto-Medium.ttf', italics: 'https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.66/fonts/Roboto/Roboto-Italic.ttf', bolditalics: 'https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.66/fonts/Roboto/Roboto-MediumItalic.ttf' } } pdfMake.tableLayouts = { invoiceMasterReport: { paddingTop: function (i: number) { return isInvoiceMasterRow(i) ? 1 : 0 }, paddingBottom: function (i: number) { return isInvoiceMasterRow(i) ? 5 : 0 }, paddingLeft: function () { return 2 }, paddingRight: function () { return 2 }, fillColor: function (i: number) { return i === 1 ? 'black' : '#e4e4e4' }, vLineWidth: function () { return 1 }, defaultBorder: false }, invoiceNestedDetailReport: { paddingLeft: function () { return 1 }, paddingRight: function () { return 0 }, paddingBottom: function () { return 5 }, defaultBorder: false }, invoiceLayout: { paddingLeft: function () { return 0 }, paddingRight: function () { return 0 }, paddingTop: function () { return 0.5 }, paddingBottom: function () { return 0.5 }, hLineWidth: function (i: number, node: any) { return i === 1 || i === node.table.body.length ? 0.2 : 0 }, vLineWidth: function () { return 0 } }, summaryInvoice: { paddingLeft: function () { return 0 }, paddingRight: function () { return 0 }, paddingTop: function () { return 5 }, paddingBottom: function () { return 5 }, hLineColor: function (i) { return i === 1 ? 'black' : '#e4e4e4' }, vLineWidth: function () { return 1 }, defaultBorder: false } } const drawLine: (length?: number) => CanvasElement = (length = 292.26) => { return { type: 'line', x1: 0, y1: 0, x2: length, y2: 0, lineWidth: 0.2 } } export const useDoc = (mockData: DataToPrint) => { const [columns, setColumns] = useState>([]) const [body, setBody] = useState>([]) const [title, setTitle] = useState>([]) const [summary, setSummary] = useState>([]) useEffect(() => { setColumns(mockData.configs.columnsHeader) }, []) useEffect(() => { let temp: Array = [] // eslint-disable-next-line array-callback-return mockData.data.items.map((it: any) => { let current: Array = [] // eslint-disable-next-line array-callback-return Object.values(it).map(function (key, index) { const data = { text: key, fontSize: 9, alignment: columns[index]?.alignment } current.push(data) }) temp.push(current) }) setBody([...temp]) }, [columns]) useEffect(() => { let temp: Array = [] // eslint-disable-next-line array-callback-return Object.keys(mockData.data.header).map(function (key) { const keyLabel = { text: key + ' :', fontSize: 9, alignment: 'left' } const value = { // @ts-ignore text: mockData.data?.header[key], fontSize: 9, alignment: 'right' } temp.push([keyLabel, value]) }) setTitle([...temp]) }, []) useEffect(() => { const data = mockData.data.items.map((it: any) => { return { columns: [ Object.values(it).map(function (value, index) { return { text: value, fontSize: 9, width: '*', alignment: columns[index]?.alignment } }) ] } }) setBody([...data]) }, []) useEffect(() => { let temp: Array = [] // eslint-disable-next-line array-callback-return Object.keys(mockData.data.summary).map(function (key) { const keyLabel = { text: key + ' :', fontSize: 9, alignment: 'right' } const value = { // @ts-ignore text: mockData.data?.summary[key], fontSize: 9, alignment: 'center' } temp.push([keyLabel, value]) }) setSummary([...temp]) }, []) const data: TDocumentDefinitions | any = { content: [ mockData.configs.logoUrl && { alignment: 'center', image: mockData.configs.logoUrl, width: 100, height: 75, style: 'header', fontSize: 23, bold: true, margin: [0, 10] }, mockData.configs.title && { alignment: 'center', text: mockData.configs.title, style: 'header', fontSize: 8, bold: true, margin: [0, 10] }, mockData.configs.headline && { alignment: 'center', text: mockData.configs.headline, fontSize: 18, bold: true }, { layout: 'noBorders', fontSize: 9, table: { widths: '*', body: [...title] } }, { layout: 'invoiceMasterReport', table: { widths: '*', body: [mockData.configs.columnsHeader] } }, { layout: 'invoiceNestedDetailReport', table: { widths: '*', body: [...body] } }, { columns: [ { canvas: [drawLine()] } ] }, { layout: 'summaryInvoice', table: { widths: ['*', '*'], body: [...summary] } }, { columns: [ { canvas: [drawLine()] } ] }, mockData.data.footer?.map((it) => { return it }) ], pageSize: { width: 302.26, height: 'auto' }, pageOrientation: 'portrait', pageMargins: [5, 5, 5, 5], styles: { header: { color: '#2ac4e6' } } } return pdfMake.createPdf(data) }