import { PDFDocument, StandardFonts, rgb } from 'pdf-lib' export type JkkpIncident = { reference_no: string | null incident_type: string description: string reported_at: string severity: number | null is_fatality: boolean is_serious_bodily_injury: boolean is_dangerous_occurrence: boolean lost_days: number | null site_name: string reporter_name: string } type EmbeddedFont = Awaited> type Page = ReturnType async function createBaseDoc(title: string): Promise<{ doc: PDFDocument page: Page font: EmbeddedFont boldFont: EmbeddedFont y: { value: number } }> { const doc = await PDFDocument.create() const page = doc.addPage([595, 842]) // A4 const font = await doc.embedFont(StandardFonts.Helvetica) const boldFont = await doc.embedFont(StandardFonts.HelveticaBold) const y = { value: 800 } page.drawText(title, { x: 50, y: y.value, size: 14, font: boldFont, color: rgb(0, 0, 0) }) y.value -= 8 page.drawLine({ start: { x: 50, y: y.value }, end: { x: 545, y: y.value }, thickness: 1, color: rgb(0, 0, 0) }) y.value -= 20 return { doc, page, font, boldFont, y } } function drawField( page: Page, label: string, value: string, font: EmbeddedFont, boldFont: EmbeddedFont, y: { value: number } ) { page.drawText(label + ':', { x: 50, y: y.value, size: 9, font: boldFont, color: rgb(0.3, 0.3, 0.3) }) const lines = value.length > 80 ? [value.slice(0, 80), value.slice(80, 160)] : [value] for (const line of lines) { y.value -= 14 page.drawText(line || '—', { x: 50, y: y.value, size: 10, font, color: rgb(0, 0, 0) }) } y.value -= 8 } export async function buildJkkp6Pdf(incident: JkkpIncident): Promise { const { doc, page, font, boldFont, y } = await createBaseDoc('BORANG JKKP 6 — Notis Kemalangan / Kejadian Berbahaya') const reportedDate = new Date(incident.reported_at).toLocaleDateString('en-MY', { timeZone: 'Asia/Kuala_Lumpur' }) drawField(page, 'Rujukan / Reference', incident.reference_no ?? '—', font, boldFont, y) drawField(page, 'Tapak / Site', incident.site_name, font, boldFont, y) drawField(page, 'Tarikh Laporan / Date Reported', reportedDate, font, boldFont, y) drawField(page, 'Jenis Insiden / Incident Type', incident.incident_type.replace(/_/g, ' '), font, boldFont, y) drawField(page, 'Dilaporkan Oleh / Reported By', incident.reporter_name, font, boldFont, y) drawField(page, 'Penerangan / Description', incident.description, font, boldFont, y) drawField(page, 'Kematian / Fatality', incident.is_fatality ? 'Yes' : 'No', font, boldFont, y) drawField(page, 'Kecederaan Serius / Serious Bodily Injury', incident.is_serious_bodily_injury ? 'Yes' : 'No', font, boldFont, y) drawField(page, 'Kejadian Berbahaya / Dangerous Occurrence', incident.is_dangerous_occurrence ? 'Yes' : 'No', font, boldFont, y) drawField(page, 'Hari Hilang Kerja / Lost Days', incident.lost_days !== null ? String(incident.lost_days) : '—', font, boldFont, y) y.value -= 20 page.drawText('Nota: Borang ini adalah draf yang dijana secara automatik. Sila semak sebelum dikemukakan ke DOSH.', { x: 50, y: y.value, size: 8, font, color: rgb(0.5, 0.5, 0.5) }) return doc.save() } export async function buildJkkp7Pdf(incident: JkkpIncident): Promise { const { doc, page, font, boldFont, y } = await createBaseDoc('BORANG JKKP 7 — Laporan Siasatan Kemalangan') const reportedDate = new Date(incident.reported_at).toLocaleDateString('en-MY', { timeZone: 'Asia/Kuala_Lumpur' }) drawField(page, 'Rujukan / Reference', incident.reference_no ?? '—', font, boldFont, y) drawField(page, 'Tapak / Site', incident.site_name, font, boldFont, y) drawField(page, 'Tarikh Kemalangan / Incident Date', reportedDate, font, boldFont, y) drawField(page, 'Jenis Insiden / Incident Type', incident.incident_type.replace(/_/g, ' '), font, boldFont, y) drawField(page, 'Penerangan Kemalangan / Incident Description', incident.description, font, boldFont, y) drawField(page, 'Keterukan / Severity', incident.severity !== null ? String(incident.severity) + ' / 5' : '—', font, boldFont, y) drawField(page, 'Hari Hilang Kerja / Lost Days', incident.lost_days !== null ? String(incident.lost_days) : '—', font, boldFont, y) y.value -= 20 page.drawText('Rumusan Punca Asas / Root Cause Summary:', { x: 50, y: y.value, size: 9, font: boldFont, color: rgb(0.3, 0.3, 0.3) }) y.value -= 14 page.drawText('[To be completed by HSE investigator]', { x: 50, y: y.value, size: 10, font, color: rgb(0.6, 0.6, 0.6) }) y.value -= 30 page.drawText('Nota: Borang ini adalah draf yang dijana secara automatik. Sila semak sebelum dikemukakan ke DOSH.', { x: 50, y: y.value, size: 8, font, color: rgb(0.5, 0.5, 0.5) }) return doc.save() }