sp/src/lib/InvoicePDF_V1.jsx

219 lines
6.2 KiB
JavaScript

import React from 'react';
import { Page, Text, View, Document, StyleSheet, Image, Font } from '@react-pdf/renderer';
import {localizeTime} from "../lib/localizeTime";
import { IndianRupee } from "lucide-react";
import NotoSans from "../lib/fonts/static/NotoSans_Condensed-Bold.ttf";
Font.register({
family: "NotoSans",
src: NotoSans,
});
// console.log('Fonts', Font)
// Create styles
const styles = StyleSheet.create({
page: {
display: "flex",
flexDirection: 'column',
backgroundColor: '#FFFFFF',
padding: 40,
},
currencyValue: {
fontSize: 12,
fontWeight: 'bold'
},
header: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 20,
borderBottomWidth: 2,
borderBottomColor: '#6d9e37',
paddingBottom: 10
},
logoContainer: {
flexDirection: 'row',
alignItems: 'center',
gap: 10,
marginBottom: 5
},
logoImage: {
width: 30,
height: 30
},
title: {
fontSize: 24,
fontWeight: 'bold',
color: '#6d9e37'
},
section: {
marginBottom: 20
},
row: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 5
},
label: {
fontSize: 12,
fontWeight: 'bold'
},
value: {
fontSize: 12
},
divider: {
borderBottomWidth: 1,
borderBottomColor: '#EEEEEE',
marginVertical: 10
},
tableHeader: {
flexDirection: 'row',
backgroundColor: '#F5F5F5',
padding: 5,
marginBottom: 5
},
tableRow: {
flexDirection: 'row',
padding: 5,
borderBottomWidth: 1,
borderBottomColor: '#EEEEEE'
},
col1: {
width: '40%'
},
col2: {
width: '30%',
textAlign: 'right'
},
col3: {
width: '30%',
textAlign: 'right'
},
total: {
flexDirection: 'row',
justifyContent: 'flex-end',
marginTop: 10
},
totalText: {
fontSize: 14,
fontWeight: 'bold'
},
footer: {
position: 'absolute',
bottom: 30,
left: 40,
right: 40,
textAlign: 'center',
fontSize: 10,
color: '#999999'
},
status: {
padding: 3,
borderRadius: 3,
fontSize: 10,
fontWeight: 'bold'
}
});
// Base64 encoded SVG logo (replace with your actual logo)
const SILICONPIN_LOGO = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABgElEQVR4nO3bsW0UURRA0TfYLThEDreatUSGC7BdBi4D0QAiWiQ3g0OTQgvsONiICv4J7pF+PE//jmaiN/vMDpzHWWyfedhnzqvv4sPqi8j/CoIpCKYgmIJgCoIpCKYgmIJgCoIpCKYgmIJgCoIpCKYgmIJgCoIpCKYgmIJgCoIpCKYgmIJgCoIpCKYgmIJgCoIpCKYgmE1Ylvn0eT7+PMzNyhmOv+bv6cf8vlo5xMxsi59/8WW+zjZPi6f4Ns/LZ+iTpSkIpiCYgmAKgikIpiCYgmAKgikIpiCYgmAKgikIpiCYgmAKgikIpiCYgmAKgikIpiCYgmAKgikIpiCYgmAKgikIpiCYbWZ/WD3E3N/dzuFl6cLOvB7/zPfT28zqlZ3Zz8BZvsV1eTH3f6vv4nqULSrDNovvo38IpiCYgmAKgikIpiCYgmAKgikIpiCYgmAKgikIpiCYgmAKgikIpiCYgmAKgikIpiCYgmAKgikIpiCYgmAKgikIpiCYgmDeAd5vHuV+dwDGAAAAAElFTkSuQmCC';
const InvoicePDF = ({ data }) => {
const statusColor = data.status === 'completed' ? '#10B981' : '#EF4444';
return (
<Document>
<Page size="A4" style={styles.page}>
{/* Header */}
<View style={styles.header}>
<View>
<Text style={styles.title}>INVOICE</Text>
<Text style={styles.label}>Invoice #: {data.billing_id}</Text>
<Text style={styles.label}>Date: {localizeTime(data.created_at)}</Text>
</View>
<View>
<View style={styles.logoContainer}>
<Image
style={styles.logoImage}
src={SILICONPIN_LOGO}
/>
<Text style={styles.title}>SiliconPin</Text>
</View>
<Text style={styles.value}>121 Lalbari, GourBongo Road</Text>
<Text style={styles.value}>Habra, W.B. 743271, India</Text>
<Text style={styles.value}>contact@siliconpin.com</Text>
</View>
</View>
{/* Bill To */}
<View style={styles.section}>
<View style={styles.row}>
<View>
<Text style={styles.label}>BILL TO:</Text>
<Text style={styles.value}>{data.name}</Text>
</View>
<View>
<Text style={styles.label}>STATUS:</Text>
<Text style={[styles.value, { color: statusColor }]}>
{data.status.toUpperCase()}
</Text>
</View>
</View>
</View>
<View style={styles.divider} />
{/* Items Table */}
<View style={styles.section}>
<View style={styles.tableHeader}>
<Text style={styles.col1}>DESCRIPTION</Text>
<Text style={styles.col2}>cycle</Text>
<Text style={styles.col3}>AMOUNT</Text>
</View>
<View style={styles.tableRow}>
<Text style={styles.col1}>{data.service}</Text>
<Text style={styles.col2}>{data.cycle}</Text>
<Text style={{fontFamily: 'NotoSans', ...styles.col3}}>
{new Intl.NumberFormat('en-IN', {
style: 'currency',
currency: 'INR',
}).format(parseFloat(data.amount))}
</Text>
</View>
</View>
<View style={styles.divider} />
{/* Total */}
<View style={styles.total}>
<View style={{width: '30%'}}>
<View style={styles.row}>
<Text style={styles.label}>SUBTOTAL:</Text>
<Text style={{fontFamily: 'NotoSans', ...styles.value}}>
{new Intl.NumberFormat('en-IN', {
style: 'currency',
currency: 'INR',
}).format(parseFloat(data.amount))}
</Text>
</View>
<View style={styles.row}>
<Text style={styles.label}>TOTAL:</Text>
<Text style={{fontFamily: 'NotoSans', ...styles.totalText}}>
{new Intl.NumberFormat('en-IN', {
style: 'currency',
currency: 'INR',
}).format(parseFloat(data.amount))}
</Text>
</View>
</View>
</View>
{/* Footer */}
<View style={styles.footer}>
<Text>Thank you for your business!</Text>
<Text>Please make payments payable to SiliconPin</Text>
</View>
</Page>
</Document>
);
};
export default InvoicePDF;