56 lines
3.8 KiB
TypeScript
56 lines
3.8 KiB
TypeScript
'use client';
|
|
|
|
import * as React from 'react';
|
|
import { View as PDFView, Text as PDFText, StyleSheet } from '@react-pdf/renderer';
|
|
import { DocumentTitle } from '../SharedUI';
|
|
|
|
const styles = StyleSheet.create({
|
|
table: { marginTop: 12 },
|
|
tableHeader: { flexDirection: 'row', paddingBottom: 8, borderBottomWidth: 1, borderBottomColor: '#000000', marginBottom: 12 },
|
|
tableRow: { flexDirection: 'row', paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: '#f8fafc', alignItems: 'flex-start' },
|
|
colPos: { width: '8%' },
|
|
colDesc: { width: '62%' },
|
|
colQty: { width: '10%', textAlign: 'center' },
|
|
colPrice: { width: '20%', textAlign: 'right' },
|
|
headerText: { fontSize: 7, fontWeight: 'bold', textTransform: 'uppercase', letterSpacing: 1 },
|
|
posText: { fontSize: 8, color: '#999999' },
|
|
itemTitle: { fontSize: 10, fontWeight: 'bold', marginBottom: 4 },
|
|
itemDesc: { fontSize: 8, color: '#666666', lineHeight: 1.4 },
|
|
priceText: { fontSize: 10, fontWeight: 'bold' },
|
|
summaryContainer: { borderTopWidth: 1, borderTopColor: '#000000', paddingTop: 8 },
|
|
summaryRow: { flexDirection: 'row', justifyContent: 'flex-end', paddingVertical: 4, alignItems: 'baseline' },
|
|
summaryLabel: { fontSize: 7, color: '#64748b', textTransform: 'uppercase', letterSpacing: 1, fontWeight: 'bold', marginRight: 12 },
|
|
summaryValue: { fontSize: 9, fontWeight: 'bold', width: 100, textAlign: 'right' },
|
|
totalRow: { flexDirection: 'row', justifyContent: 'flex-end', paddingTop: 12, marginTop: 8, borderTopWidth: 2, borderTopColor: '#000000', alignItems: 'baseline' },
|
|
});
|
|
|
|
export const EstimationModule = ({ state, positions, totalPrice, date }: any) => (
|
|
<>
|
|
<DocumentTitle title="Kostenschätzung" subLines={[`Datum: ${date}`, `Projekt: ${state.projectType === 'website' ? 'Website' : 'Web App'}`]} />
|
|
<PDFView style={styles.table}>
|
|
<PDFView style={styles.tableHeader}>
|
|
<PDFText style={[styles.headerText, styles.colPos]}>Pos</PDFText>
|
|
<PDFText style={[styles.headerText, styles.colDesc]}>Beschreibung</PDFText>
|
|
<PDFText style={[styles.headerText, styles.colQty]}>Menge</PDFText>
|
|
<PDFText style={[styles.headerText, styles.colPrice]}>Betrag</PDFText>
|
|
</PDFView>
|
|
{positions.map((item: any, i: number) => (
|
|
<PDFView key={i} style={styles.tableRow} wrap={false}>
|
|
<PDFText style={[styles.posText, styles.colPos]}>{item.pos.toString().padStart(2, '0')}</PDFText>
|
|
<PDFView style={styles.colDesc}>
|
|
<PDFText style={styles.itemTitle}>{item.title}</PDFText>
|
|
<PDFText style={styles.itemDesc}>{state.positionDescriptions?.[item.title] || item.desc}</PDFText>
|
|
</PDFView>
|
|
<PDFText style={[styles.posText, styles.colQty]}>{item.qty}</PDFText>
|
|
<PDFText style={[styles.priceText, styles.colPrice]}>{item.price > 0 ? `${item.price.toLocaleString('de-DE')} €` : 'n. A.'}</PDFText>
|
|
</PDFView>
|
|
))}
|
|
</PDFView>
|
|
<PDFView style={styles.summaryContainer} wrap={false}>
|
|
<PDFView style={styles.summaryRow}><PDFText style={styles.summaryLabel}>Nettobetrag</PDFText><PDFText style={styles.summaryValue}>{totalPrice.toLocaleString('de-DE')} €</PDFText></PDFView>
|
|
<PDFView style={styles.summaryRow}><PDFText style={styles.summaryLabel}>Umsatzsteuer (19%)</PDFText><PDFText style={styles.summaryValue}>{(totalPrice * 0.19).toLocaleString('de-DE')} €</PDFText></PDFView>
|
|
<PDFView style={styles.totalRow}><PDFText style={styles.summaryLabel}>Gesamtbetrag (Brutto)</PDFText><PDFText style={[styles.summaryValue, { fontSize: 14 }]}>{(totalPrice * 1.19).toLocaleString('de-DE')} €</PDFText></PDFView>
|
|
</PDFView>
|
|
</>
|
|
);
|