Plain-text paid badge, uniform item rows, show B2B recipient fields
Validate e-invoices / mustang (push) Successful in 22s
Validate e-invoices / mustang (push) Successful in 22s
- The "Bereits beglichen" confirmation is now plain green Text, not a tinted pill/box — read as too heavy for a status note. - Item table rows no longer alternate white/tinted (zebra striping); every row now shares the same tinted background for a more uniform table, on both the invoice and its Storno/Gutschrift corrections. - InvoiceOrder/CorrectionInvoiceOrder gained optional companyName/ vatId, rendered in the "An" recipient block when present — the buyer-side counterpart to the sellers' own fields already shown in the footer. Both consuming repos need their own commit to actually pass these through from Orders.companyName/vatId. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -63,8 +63,9 @@ const styles = StyleSheet.create({
|
||||
metaValue: { fontSize: 10, fontFamily: "Helvetica-Bold" },
|
||||
table: { borderRadius: 6, overflow: "hidden", borderWidth: 1, borderColor: BORDER, marginBottom: 16 },
|
||||
tableHeader: { flexDirection: "row", backgroundColor: BG_MUTED, paddingVertical: 8, paddingHorizontal: 10 },
|
||||
tableRow: { flexDirection: "row", paddingVertical: 8, paddingHorizontal: 10, borderTopWidth: 1, borderTopColor: BORDER },
|
||||
tableRowAlt: { backgroundColor: BG_MUTED },
|
||||
// Same uniform tinted-row background as invoicePdf.tsx now — no more
|
||||
// zebra striping, kept identical between the two documents.
|
||||
tableRow: { flexDirection: "row", paddingVertical: 8, paddingHorizontal: 10, borderTopWidth: 1, borderTopColor: BORDER, backgroundColor: BG_MUTED },
|
||||
// marginRight (not a tableRow `gap`) — see invoicePdf.tsx's own comment
|
||||
// on this same style, kept identical between the two documents.
|
||||
colImage: { width: 28, marginRight: 10 },
|
||||
@@ -126,6 +127,11 @@ export type CorrectionInvoiceOrder = {
|
||||
correctionInvoiceIssuedAt: string;
|
||||
customerFirstName: string;
|
||||
customerLastName: string;
|
||||
// Same optional B2B recipient fields as invoicePdf.tsx's InvoiceOrder —
|
||||
// a Storno/Gutschrift for a B2B order should show the same buyer
|
||||
// identification as the original invoice it corrects.
|
||||
companyName?: string | null;
|
||||
vatId?: string | null;
|
||||
deliveryMethod: "address" | "packstation";
|
||||
street?: string | null;
|
||||
packstationNumber?: string | null;
|
||||
@@ -229,6 +235,7 @@ function CorrectionInvoiceDocument({ kind, order, seller }: { kind: CorrectionIn
|
||||
</View>
|
||||
<View style={styles.addressBlock}>
|
||||
<Text style={styles.addressLabel}>An</Text>
|
||||
{order.companyName && <Text style={styles.addressLine}>{order.companyName}</Text>}
|
||||
<Text style={styles.addressLine}>
|
||||
{order.customerFirstName} {order.customerLastName}
|
||||
</Text>
|
||||
@@ -237,6 +244,7 @@ function CorrectionInvoiceDocument({ kind, order, seller }: { kind: CorrectionIn
|
||||
{order.zip} {order.city}
|
||||
</Text>
|
||||
<Text style={styles.addressLine}>{order.country}</Text>
|
||||
{order.vatId && <Text style={styles.addressLine}>USt-IdNr. {order.vatId}</Text>}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -260,7 +268,7 @@ function CorrectionInvoiceDocument({ kind, order, seller }: { kind: CorrectionIn
|
||||
<Text style={[styles.colTotal, styles.headerCell]}>Betrag</Text>
|
||||
</View>
|
||||
{lines.map(({ item, effectiveQuantity }, i) => (
|
||||
<View style={[styles.tableRow, i % 2 === 1 ? styles.tableRowAlt : {}]} key={i}>
|
||||
<View style={styles.tableRow} key={i}>
|
||||
<View style={styles.colImage}>
|
||||
{item.imageUrl && <Image src={item.imageUrl} style={styles.itemImage} />}
|
||||
</View>
|
||||
|
||||
+20
-13
@@ -19,7 +19,6 @@ const TEXT_MUTED = "#6b6b69";
|
||||
const BORDER = "#e5e0d8";
|
||||
const BG_MUTED = "#f8f5f1";
|
||||
const SUCCESS = "#2f8f4e";
|
||||
const SUCCESS_TINT = "#e7f5eb";
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
page: { padding: 0, fontSize: 10, fontFamily: "Helvetica", color: "#1a1a18" },
|
||||
@@ -50,12 +49,13 @@ const styles = StyleSheet.create({
|
||||
metaBox: { borderWidth: 1, borderColor: BORDER, borderRadius: 6, paddingVertical: 8, paddingHorizontal: 12 },
|
||||
metaLabel: { fontSize: 7, color: TEXT_MUTED, textTransform: "uppercase", marginBottom: 2 },
|
||||
metaValue: { fontSize: 10, fontFamily: "Helvetica-Bold" },
|
||||
paidBadge: { backgroundColor: SUCCESS_TINT, borderRadius: 6, paddingVertical: 8, paddingHorizontal: 12, justifyContent: "center" },
|
||||
paidBadgeText: { fontSize: 10, fontFamily: "Helvetica-Bold", color: SUCCESS },
|
||||
table: { borderRadius: 6, overflow: "hidden", borderWidth: 1, borderColor: BORDER, marginTop: 8, marginBottom: 16 },
|
||||
tableHeader: { flexDirection: "row", backgroundColor: BG_MUTED, paddingVertical: 8, paddingHorizontal: 10 },
|
||||
tableRow: { flexDirection: "row", paddingVertical: 8, paddingHorizontal: 10, borderTopWidth: 1, borderTopColor: BORDER },
|
||||
tableRowAlt: { backgroundColor: BG_MUTED },
|
||||
// Every item row shares this same tinted background now — no more
|
||||
// odd/even zebra striping that left alternating rows plain white; the
|
||||
// borderTop is what separates rows visually instead.
|
||||
tableRow: { flexDirection: "row", paddingVertical: 8, paddingHorizontal: 10, borderTopWidth: 1, borderTopColor: BORDER, backgroundColor: BG_MUTED },
|
||||
// marginRight (not a tableRow `gap`) — explicit and unambiguous across
|
||||
// react-pdf's flexbox implementation for a mixed Image/Text row, rather
|
||||
// than relying on a row-level `gap` to apply consistently between an
|
||||
@@ -85,11 +85,12 @@ const styles = StyleSheet.create({
|
||||
// Moved here (below the summary card) from the top meta row — reads more
|
||||
// naturally right next to the amount it's confirming was paid, and keeps
|
||||
// the meta row itself to just the three reference numbers. Deliberately
|
||||
// a *sibling* of summaryBox, not a row inside it — the badge confirms
|
||||
// the whole card's total, so it sits visually outside/below the card
|
||||
// rather than being absorbed as one more line inside it (a correction
|
||||
// made after initially placing it inside the card — see this package's
|
||||
// README/the e-invoicing memory notes if this needs revisiting again).
|
||||
// a *sibling* of summaryBox, not a row inside it — the confirmation
|
||||
// applies to the whole card's total, so it sits visually outside/below
|
||||
// the card rather than being absorbed as one more line inside it (a
|
||||
// correction made after initially placing it inside the card). Plain
|
||||
// green text, not a pill/badge box — a colored background here read as
|
||||
// too heavy/attention-grabbing for what's just a status note.
|
||||
paidBadgeRow: { alignItems: "flex-end", marginTop: 10 },
|
||||
// `fixed` (below, on the element) + absolute positioning — always pinned
|
||||
// to the bottom of the page regardless of how much content is above it,
|
||||
@@ -128,6 +129,12 @@ export type InvoiceOrder = {
|
||||
invoiceIssuedAt: string;
|
||||
customerFirstName: string;
|
||||
customerLastName: string;
|
||||
// Optional B2B recipient fields (Orders.companyName/vatId in the Payload
|
||||
// backend) — when present, shown in the "An" block: companyName as its
|
||||
// own line above the contact person's name, vatId as its own line below
|
||||
// the address. Neither implies the other (see Orders.ts's own comment).
|
||||
companyName?: string | null;
|
||||
vatId?: string | null;
|
||||
deliveryMethod: "address" | "packstation";
|
||||
street?: string | null;
|
||||
packstationNumber?: string | null;
|
||||
@@ -258,6 +265,7 @@ export function InvoiceDocument({ order, seller }: { order: InvoiceOrder; seller
|
||||
</View>
|
||||
<View style={addressBlockStyle}>
|
||||
<Text style={styles.addressLabel}>An</Text>
|
||||
{order.companyName && <Text style={styles.addressLine}>{order.companyName}</Text>}
|
||||
<Text style={styles.addressLine}>
|
||||
{order.customerFirstName} {order.customerLastName}
|
||||
</Text>
|
||||
@@ -266,6 +274,7 @@ export function InvoiceDocument({ order, seller }: { order: InvoiceOrder; seller
|
||||
{order.zip} {order.city}
|
||||
</Text>
|
||||
<Text style={styles.addressLine}>{order.country}</Text>
|
||||
{order.vatId && <Text style={styles.addressLine}>USt-IdNr. {order.vatId}</Text>}
|
||||
</View>
|
||||
{order.hasDifferentShippingAddress && (
|
||||
<View style={addressBlockStyle}>
|
||||
@@ -311,7 +320,7 @@ export function InvoiceDocument({ order, seller }: { order: InvoiceOrder; seller
|
||||
<Text style={[styles.colTotal, styles.headerCell]}>Betrag</Text>
|
||||
</View>
|
||||
{order.items.map((item, i) => (
|
||||
<View style={[styles.tableRow, i % 2 === 1 ? styles.tableRowAlt : {}]} key={i}>
|
||||
<View style={styles.tableRow} key={i}>
|
||||
<View style={styles.colImage}>
|
||||
{item.imageUrl && <Image src={item.imageUrl} style={styles.itemImage} />}
|
||||
</View>
|
||||
@@ -362,9 +371,7 @@ export function InvoiceDocument({ order, seller }: { order: InvoiceOrder; seller
|
||||
</View>
|
||||
{paid && (
|
||||
<View style={styles.paidBadgeRow}>
|
||||
<View style={styles.paidBadge}>
|
||||
<Text style={styles.paidBadgeText}>✓ Bereits beglichen ({order.paymentMethodTitle})</Text>
|
||||
</View>
|
||||
<Text style={styles.paidBadgeText}>✓ Bereits beglichen ({order.paymentMethodTitle})</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user