219 lines
6.2 KiB
JavaScript
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; |