feat: Initial Mediusa Clinic OS practice management platform ('Jane App But Better')
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
import jsPDF from 'jspdf';
|
||||
import { Superbill } from '@/types/clinical';
|
||||
|
||||
export function generateSuperbillPdf(superbill: Superbill) {
|
||||
const doc = new jsPDF({
|
||||
orientation: 'portrait',
|
||||
unit: 'pt',
|
||||
format: 'letter',
|
||||
});
|
||||
|
||||
const margin = 40;
|
||||
let y = margin;
|
||||
|
||||
// Header Banner
|
||||
doc.setFillColor(15, 23, 42); // Slate 900
|
||||
doc.rect(0, 0, doc.internal.pageSize.getWidth(), 80, 'F');
|
||||
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.setTextColor(255, 255, 255);
|
||||
doc.setFontSize(20);
|
||||
doc.text('MEDICAL SUPERBILL & STATEMENT', margin, 42);
|
||||
|
||||
doc.setFont('helvetica', 'normal');
|
||||
doc.setFontSize(10);
|
||||
doc.setTextColor(148, 163, 184); // Slate 400
|
||||
doc.text('Comprehensive Out-of-Network Insurance Reimbursement Form', margin, 60);
|
||||
|
||||
doc.setTextColor(255, 255, 255);
|
||||
doc.text(`Invoice #: ${superbill.invoiceNumber}`, doc.internal.pageSize.getWidth() - margin - 150, 42);
|
||||
doc.text(`Date of Service: ${superbill.dateOfService}`, doc.internal.pageSize.getWidth() - margin - 150, 60);
|
||||
|
||||
y = 110;
|
||||
|
||||
// Two columns: Clinic (Billing Provider) & Patient Details
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.setFontSize(11);
|
||||
doc.setTextColor(15, 23, 42);
|
||||
doc.text('BILLING PROVIDER & CLINIC', margin, y);
|
||||
doc.text('PATIENT INFORMATION', 320, y);
|
||||
|
||||
doc.setDrawColor(226, 232, 240);
|
||||
doc.line(margin, y + 6, 280, y + 6);
|
||||
doc.line(320, y + 6, doc.internal.pageSize.getWidth() - margin, y + 6);
|
||||
|
||||
y += 22;
|
||||
doc.setFont('helvetica', 'normal');
|
||||
doc.setFontSize(9);
|
||||
doc.setTextColor(51, 65, 85);
|
||||
|
||||
// Clinic Info
|
||||
doc.text(superbill.clinicName, margin, y);
|
||||
doc.text(superbill.clinicAddress, margin, y + 14);
|
||||
doc.text(`Billing Provider: ${superbill.providerName}`, margin, y + 28);
|
||||
doc.text(`Provider NPI: ${superbill.providerNpi} | Tax ID: ${superbill.clinicTaxId}`, margin, y + 42);
|
||||
doc.text(`Place of Service (POS): ${superbill.posCode}`, margin, y + 56);
|
||||
|
||||
// Patient Info
|
||||
doc.text(`Name: ${superbill.patientName}`, 320, y);
|
||||
doc.text(`DOB: ${superbill.patientDob}`, 320, y + 14);
|
||||
doc.text(`Address: ${superbill.patientAddress}`, 320, y + 28);
|
||||
doc.text(`Payment Status: ${superbill.paymentMethod} (PAID IN FULL)`, 320, y + 42);
|
||||
|
||||
y += 85;
|
||||
|
||||
// Diagnosis (ICD-10) Section
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.setFontSize(11);
|
||||
doc.setTextColor(15, 23, 42);
|
||||
doc.text('DIAGNOSIS CODES (ICD-10-CM)', margin, y);
|
||||
doc.line(margin, y + 6, doc.internal.pageSize.getWidth() - margin, y + 6);
|
||||
|
||||
y += 20;
|
||||
doc.setFont('helvetica', 'normal');
|
||||
doc.setFontSize(9);
|
||||
doc.setTextColor(51, 65, 85);
|
||||
|
||||
superbill.icd10Codes.forEach((icd, idx) => {
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.text(`(${idx + 1}) ${icd.code}`, margin, y);
|
||||
doc.setFont('helvetica', 'normal');
|
||||
doc.text(` - ${icd.description}`, margin + 65, y);
|
||||
y += 15;
|
||||
});
|
||||
|
||||
y += 15;
|
||||
|
||||
// Procedure Line Items Table
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.setFontSize(11);
|
||||
doc.setTextColor(15, 23, 42);
|
||||
doc.text('PROCEDURES & SERVICES (CPT CODES)', margin, y);
|
||||
doc.line(margin, y + 6, doc.internal.pageSize.getWidth() - margin, y + 6);
|
||||
|
||||
y += 18;
|
||||
|
||||
// Table Header
|
||||
doc.setFillColor(241, 245, 249);
|
||||
doc.rect(margin, y, doc.internal.pageSize.getWidth() - (margin * 2), 22, 'F');
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.setFontSize(9);
|
||||
doc.setTextColor(71, 85, 105);
|
||||
doc.text('CPT CODE', margin + 8, y + 15);
|
||||
doc.text('DESCRIPTION', margin + 80, y + 15);
|
||||
doc.text('UNITS', 400, y + 15);
|
||||
doc.text('RATE', 450, y + 15);
|
||||
doc.text('TOTAL', 505, y + 15);
|
||||
|
||||
y += 24;
|
||||
|
||||
doc.setFont('helvetica', 'normal');
|
||||
doc.setFontSize(9);
|
||||
doc.setTextColor(30, 41, 59);
|
||||
|
||||
superbill.items.forEach((item) => {
|
||||
doc.text(item.cptCode, margin + 8, y + 14);
|
||||
doc.text(item.description, margin + 80, y + 14);
|
||||
doc.text(String(item.units), 405, y + 14);
|
||||
doc.text(`$${item.rate.toFixed(2)}`, 450, y + 14);
|
||||
doc.text(`$${item.total.toFixed(2)}`, 505, y + 14);
|
||||
|
||||
doc.setDrawColor(241, 245, 249);
|
||||
doc.line(margin, y + 20, doc.internal.pageSize.getWidth() - margin, y + 20);
|
||||
y += 22;
|
||||
});
|
||||
|
||||
y += 20;
|
||||
|
||||
// Summary Totals Box
|
||||
const summaryX = 350;
|
||||
doc.setFillColor(248, 250, 252);
|
||||
doc.rect(summaryX, y, doc.internal.pageSize.getWidth() - margin - summaryX, 70, 'F');
|
||||
doc.rect(summaryX, y, doc.internal.pageSize.getWidth() - margin - summaryX, 70, 'S');
|
||||
|
||||
doc.setFont('helvetica', 'normal');
|
||||
doc.text('Total Charges:', summaryX + 15, y + 20);
|
||||
doc.text(`$${superbill.totalAmount.toFixed(2)}`, 505, y + 20);
|
||||
|
||||
doc.text('Patient Amount Paid:', summaryX + 15, y + 38);
|
||||
doc.text(`$${superbill.patientPaid.toFixed(2)}`, 505, y + 38);
|
||||
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.text('Balance Due:', summaryX + 15, y + 56);
|
||||
doc.text(`$${superbill.balanceDue.toFixed(2)}`, 505, y + 56);
|
||||
|
||||
y += 95;
|
||||
|
||||
// Practitioner Attestation & Signature
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.setFontSize(9);
|
||||
doc.setTextColor(15, 23, 42);
|
||||
doc.text('PRACTITIONER ATTESTATION & SIGNATURE', margin, y);
|
||||
doc.line(margin, y + 4, doc.internal.pageSize.getWidth() - margin, y + 4);
|
||||
|
||||
y += 16;
|
||||
doc.setFont('helvetica', 'normal');
|
||||
doc.setFontSize(8);
|
||||
doc.setTextColor(100, 116, 139);
|
||||
doc.text(
|
||||
'I certify that the services listed above were medically necessary and personally rendered by me or under my direct supervision on the date indicated.',
|
||||
margin,
|
||||
y
|
||||
);
|
||||
|
||||
y += 25;
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.setTextColor(15, 23, 42);
|
||||
doc.text(`Electronically Signed by: ${superbill.providerName}`, margin, y);
|
||||
doc.setFont('helvetica', 'normal');
|
||||
doc.text(`Timestamp: ${superbill.generatedAt}`, margin, y + 12);
|
||||
doc.text(`Verification ID: MED-${superbill.id.toUpperCase()}`, margin, y + 24);
|
||||
|
||||
// Footer Branding
|
||||
doc.setFontSize(8);
|
||||
doc.setTextColor(148, 163, 184);
|
||||
doc.text('Generated via Mediusa Clinic OS • Clean Claim Direct Superbill Standard', margin, 760);
|
||||
|
||||
doc.save(`Superbill_${superbill.invoiceNumber}_${superbill.patientName.replace(/\s+/g, '_')}.pdf`);
|
||||
}
|
||||
Reference in New Issue
Block a user