feat(cms): final restoration of extension logic and monorepo stabilization
Some checks failed
Monorepo Pipeline / ⚡ Prioritize Release (push) Successful in 1s
Monorepo Pipeline / 🧹 Lint (push) Successful in 55s
Monorepo Pipeline / 🧪 Test (push) Successful in 1m32s
Monorepo Pipeline / 🏗️ Build (push) Failing after 1m50s
Monorepo Pipeline / 🚀 Release (push) Has been skipped
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been skipped
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been skipped
🏥 Server Maintenance / 🧹 Prune & Clean (push) Failing after 4s
Some checks failed
Monorepo Pipeline / ⚡ Prioritize Release (push) Successful in 1s
Monorepo Pipeline / 🧹 Lint (push) Successful in 55s
Monorepo Pipeline / 🧪 Test (push) Successful in 1m32s
Monorepo Pipeline / 🏗️ Build (push) Failing after 1m50s
Monorepo Pipeline / 🚀 Release (push) Has been skipped
Monorepo Pipeline / 🐳 Build Directus (Base) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been skipped
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been skipped
🏥 Server Maintenance / 🧹 Prune & Clean (push) Failing after 4s
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
View as PDFView,
|
||||
Text as PDFText,
|
||||
StyleSheet,
|
||||
} from "@react-pdf/renderer";
|
||||
import { DocumentTitle, COLORS, FONT_SIZES } from "../SharedUI.js";
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
section: { marginBottom: 24 },
|
||||
sectionTitle: {
|
||||
fontSize: FONT_SIZES.LABEL,
|
||||
fontWeight: "bold",
|
||||
marginBottom: 8,
|
||||
color: COLORS.CHARCOAL,
|
||||
},
|
||||
visionText: {
|
||||
fontSize: FONT_SIZES.BODY,
|
||||
color: COLORS.TEXT_MAIN,
|
||||
lineHeight: 1.4,
|
||||
textAlign: "justify",
|
||||
},
|
||||
});
|
||||
|
||||
export const BriefingModule = ({ state }: any) => (
|
||||
<>
|
||||
<DocumentTitle title="Projektdetails" isHero={true} />
|
||||
{state.briefingSummary && (
|
||||
<PDFView style={styles.section}>
|
||||
<PDFText style={styles.sectionTitle}>Briefing Analyse</PDFText>
|
||||
<PDFText
|
||||
style={{
|
||||
fontSize: FONT_SIZES.BODY,
|
||||
color: COLORS.TEXT_MAIN,
|
||||
lineHeight: 1.6,
|
||||
textAlign: "justify",
|
||||
}}
|
||||
>
|
||||
{state.briefingSummary}
|
||||
</PDFText>
|
||||
</PDFView>
|
||||
)}
|
||||
{state.designVision && (
|
||||
<PDFView
|
||||
style={[
|
||||
styles.section,
|
||||
{
|
||||
padding: 12,
|
||||
borderLeftWidth: 2,
|
||||
borderLeftColor: COLORS.DIVIDER,
|
||||
backgroundColor: COLORS.GRID,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<PDFText
|
||||
style={[
|
||||
styles.sectionTitle,
|
||||
{ color: COLORS.CHARCOAL, marginBottom: 4 },
|
||||
]}
|
||||
>
|
||||
Strategische Vision
|
||||
</PDFText>
|
||||
<PDFText style={styles.visionText}>{state.designVision}</PDFText>
|
||||
</PDFView>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
@@ -0,0 +1,97 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
View as PDFView,
|
||||
Text as PDFText,
|
||||
StyleSheet,
|
||||
} from "@react-pdf/renderer";
|
||||
import {
|
||||
DocumentTitle,
|
||||
COLORS,
|
||||
FONT_SIZES,
|
||||
} from "../SharedUI.js";
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
section: { marginBottom: 24 },
|
||||
moduleLabel: {
|
||||
fontSize: FONT_SIZES.LABEL,
|
||||
fontWeight: "bold",
|
||||
color: COLORS.CHARCOAL,
|
||||
letterSpacing: 0.5,
|
||||
marginBottom: 4,
|
||||
},
|
||||
moduleDesc: {
|
||||
fontSize: FONT_SIZES.SMALL,
|
||||
color: COLORS.TEXT_DIM,
|
||||
lineHeight: 1.5,
|
||||
},
|
||||
ledgerRow: {
|
||||
paddingVertical: 14,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: COLORS.GRID,
|
||||
flexDirection: "row",
|
||||
alignItems: "flex-start",
|
||||
},
|
||||
ledgerPrice: {
|
||||
fontSize: FONT_SIZES.BODY,
|
||||
fontWeight: "bold",
|
||||
color: COLORS.CHARCOAL,
|
||||
},
|
||||
ledgerUnit: {
|
||||
fontSize: FONT_SIZES.TINY,
|
||||
color: COLORS.TEXT_LIGHT,
|
||||
marginLeft: 2,
|
||||
},
|
||||
});
|
||||
|
||||
export const ClosingModule = () => (
|
||||
<>
|
||||
<DocumentTitle title="Abschluss & Kontakt" isHero={true} />
|
||||
<PDFView style={styles.section}>
|
||||
<PDFText
|
||||
style={[
|
||||
styles.moduleLabel,
|
||||
{ fontSize: FONT_SIZES.HEADING, marginBottom: 12 },
|
||||
]}
|
||||
>
|
||||
Vielen Dank für Ihr Interesse!
|
||||
</PDFText>
|
||||
<PDFText style={styles.moduleDesc}>
|
||||
Die aufgeführten Positionen stellen eine detaillierte Schätzung auf
|
||||
Basis unseres aktuellen Stands dar. Sollten sich Anforderungen ändern
|
||||
oder Sie Fragen zu einzelnen Details haben, lassen Sie uns die
|
||||
Positionen gerne gemeinsam besprechen.
|
||||
</PDFText>
|
||||
<PDFView
|
||||
style={{
|
||||
marginTop: 24,
|
||||
padding: 16,
|
||||
backgroundColor: COLORS.GRID,
|
||||
borderLeftWidth: 2,
|
||||
borderLeftColor: COLORS.DIVIDER,
|
||||
}}
|
||||
>
|
||||
<PDFText style={[styles.moduleLabel, { marginBottom: 8 }]}>
|
||||
Haben Sie Fragen?
|
||||
</PDFText>
|
||||
<PDFText style={styles.moduleDesc}>
|
||||
Ich erkläre Ihnen gerne noch einmal persönlich, was die technische
|
||||
Umsetzung für Ihr Projekt bedeutet und wie wir die nächsten Schritte
|
||||
gemeinsam gehen können.
|
||||
</PDFText>
|
||||
<PDFView style={{ marginTop: 16 }}>
|
||||
<PDFText style={styles.moduleLabel}>Kontakt:</PDFText>
|
||||
<PDFText
|
||||
style={[
|
||||
styles.moduleDesc,
|
||||
{ color: COLORS.CHARCOAL, fontWeight: "bold" },
|
||||
]}
|
||||
>
|
||||
Marc Mintel – marc@mintel.me
|
||||
</PDFText>
|
||||
</PDFView>
|
||||
</PDFView>
|
||||
</PDFView>
|
||||
</>
|
||||
);
|
||||
@@ -0,0 +1,159 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
View as PDFView,
|
||||
Text as PDFText,
|
||||
StyleSheet,
|
||||
} from "@react-pdf/renderer";
|
||||
import { DocumentTitle, COLORS, FONT_SIZES } from "../SharedUI.js";
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
table: { marginTop: 12 },
|
||||
tableHeader: {
|
||||
flexDirection: "row",
|
||||
paddingBottom: 8,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: COLORS.CHARCOAL,
|
||||
marginBottom: 12,
|
||||
},
|
||||
tableRow: {
|
||||
flexDirection: "row",
|
||||
paddingVertical: 10,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: COLORS.GRID,
|
||||
alignItems: "flex-start",
|
||||
},
|
||||
colPos: { width: "8%" },
|
||||
colDesc: { width: "62%" },
|
||||
colQty: { width: "10%", textAlign: "center" },
|
||||
colPrice: { width: "20%", textAlign: "right" },
|
||||
headerText: {
|
||||
fontSize: FONT_SIZES.TINY,
|
||||
fontWeight: "bold",
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: 1,
|
||||
color: COLORS.TEXT_DIM,
|
||||
},
|
||||
posText: { fontSize: FONT_SIZES.TINY, color: COLORS.TEXT_LIGHT },
|
||||
itemTitle: {
|
||||
fontSize: FONT_SIZES.LABEL,
|
||||
fontWeight: "bold",
|
||||
color: COLORS.CHARCOAL,
|
||||
marginBottom: 4,
|
||||
},
|
||||
itemDesc: {
|
||||
fontSize: FONT_SIZES.SMALL,
|
||||
color: COLORS.TEXT_DIM,
|
||||
lineHeight: 1.4,
|
||||
},
|
||||
priceText: {
|
||||
fontSize: FONT_SIZES.BODY,
|
||||
fontWeight: "bold",
|
||||
color: COLORS.CHARCOAL,
|
||||
},
|
||||
summaryContainer: {
|
||||
borderTopWidth: 1,
|
||||
borderTopColor: COLORS.CHARCOAL,
|
||||
paddingTop: 8,
|
||||
},
|
||||
summaryRow: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "flex-end",
|
||||
paddingVertical: 4,
|
||||
alignItems: "baseline",
|
||||
},
|
||||
summaryLabel: {
|
||||
fontSize: FONT_SIZES.TINY,
|
||||
color: COLORS.TEXT_DIM,
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: 1,
|
||||
fontWeight: "bold",
|
||||
marginRight: 12,
|
||||
},
|
||||
summaryValue: {
|
||||
fontSize: FONT_SIZES.BODY,
|
||||
fontWeight: "bold",
|
||||
width: 100,
|
||||
textAlign: "right",
|
||||
color: COLORS.CHARCOAL,
|
||||
},
|
||||
totalRow: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "flex-end",
|
||||
paddingTop: 12,
|
||||
marginTop: 8,
|
||||
borderTopWidth: 2,
|
||||
borderTopColor: COLORS.CHARCOAL,
|
||||
alignItems: "baseline",
|
||||
},
|
||||
});
|
||||
|
||||
export const EstimationModule = ({
|
||||
state,
|
||||
positions,
|
||||
totalPrice,
|
||||
date,
|
||||
}: any) => (
|
||||
<>
|
||||
<DocumentTitle
|
||||
title="Kostenschätzung"
|
||||
subLines={[
|
||||
`Datum: ${date}`,
|
||||
`Projekt: ${state.projectType === "website" ? "Website" : "Web App"}`,
|
||||
]}
|
||||
isHero={true}
|
||||
/>
|
||||
<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: FONT_SIZES.HEADING }]}
|
||||
>
|
||||
{(totalPrice * 1.19).toLocaleString("de-DE")} €
|
||||
</PDFText>
|
||||
</PDFView>
|
||||
</PDFView>
|
||||
</>
|
||||
);
|
||||
@@ -0,0 +1,70 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
View as PDFView,
|
||||
Text as PDFText,
|
||||
Image as PDFImage,
|
||||
StyleSheet,
|
||||
} from "@react-pdf/renderer";
|
||||
import { COLORS, FONT_SIZES } from "../SharedUI.js";
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
titlePage: {
|
||||
flex: 1,
|
||||
padding: 60,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
backgroundColor: COLORS.WHITE,
|
||||
},
|
||||
titleBrandIcon: {
|
||||
width: 80,
|
||||
height: 80,
|
||||
backgroundColor: COLORS.CHARCOAL,
|
||||
borderRadius: 16,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
marginBottom: 40,
|
||||
},
|
||||
brandIconText: {
|
||||
fontSize: 40,
|
||||
color: COLORS.WHITE,
|
||||
fontWeight: "bold",
|
||||
},
|
||||
titleProjectName: {
|
||||
fontSize: FONT_SIZES.HERO,
|
||||
fontWeight: "bold",
|
||||
color: COLORS.CHARCOAL,
|
||||
marginBottom: 16,
|
||||
textAlign: "center",
|
||||
maxWidth: "85%",
|
||||
lineHeight: 1.2,
|
||||
},
|
||||
titleDate: {
|
||||
fontSize: FONT_SIZES.BODY,
|
||||
color: COLORS.TEXT_LIGHT,
|
||||
marginTop: 40,
|
||||
},
|
||||
});
|
||||
|
||||
export const FrontPageModule = ({ state, headerIcon, date }: any) => {
|
||||
const fullTitle = `Digitale Webpräsenz für\n${state.companyName || "Ihr Projekt"}`;
|
||||
const fontSize = fullTitle.length > 60 ? 14 : fullTitle.length > 40 ? 18 : 22;
|
||||
|
||||
return (
|
||||
<PDFView style={styles.titlePage}>
|
||||
<PDFView style={styles.titleBrandIcon}>
|
||||
{headerIcon ? (
|
||||
<PDFImage src={headerIcon} style={{ width: 40, height: 40 }} />
|
||||
) : (
|
||||
<PDFText style={styles.brandIconText}>M</PDFText>
|
||||
)}
|
||||
</PDFView>
|
||||
<PDFText style={[styles.titleProjectName, { fontSize }]}>
|
||||
{fullTitle}
|
||||
</PDFText>
|
||||
<PDFView style={{ marginBottom: 40 }} />
|
||||
<PDFText style={styles.titleDate}>{date} | Marc Mintel</PDFText>
|
||||
</PDFView>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { View as PDFView, Text as PDFText, StyleSheet } from "@react-pdf/renderer";
|
||||
import { DocumentTitle, COLORS, FONT_SIZES, IndustrialListItem } from "../SharedUI.js";
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
section: { marginBottom: 24 },
|
||||
categoryBox: {
|
||||
marginBottom: 20,
|
||||
padding: 12,
|
||||
backgroundColor: COLORS.GRID,
|
||||
borderLeftWidth: 2,
|
||||
borderLeftColor: COLORS.DIVIDER,
|
||||
},
|
||||
categoryTitle: {
|
||||
fontSize: FONT_SIZES.TINY,
|
||||
fontWeight: "bold",
|
||||
color: COLORS.TEXT_LIGHT,
|
||||
textTransform: "uppercase",
|
||||
marginBottom: 10,
|
||||
letterSpacing: 1,
|
||||
},
|
||||
pageTitle: {
|
||||
fontSize: FONT_SIZES.LABEL,
|
||||
fontWeight: "bold",
|
||||
color: COLORS.CHARCOAL,
|
||||
marginBottom: 2,
|
||||
},
|
||||
pageDesc: {
|
||||
fontSize: FONT_SIZES.TINY,
|
||||
color: COLORS.TEXT_DIM,
|
||||
lineHeight: 1.4,
|
||||
},
|
||||
});
|
||||
|
||||
export const SitemapModule = ({ state }: any) => (
|
||||
<>
|
||||
<DocumentTitle title="Informations-Architektur" isHero={true} />
|
||||
<PDFView style={styles.section}>
|
||||
{state.sitemap?.map((cat: any, i: number) => (
|
||||
<PDFView key={i} style={styles.categoryBox}>
|
||||
<PDFText style={styles.categoryTitle}>{cat.category}</PDFText>
|
||||
{cat.pages?.map((p: any, j: number) => (
|
||||
<IndustrialListItem key={j}>
|
||||
<PDFView style={{ marginBottom: 8 }}>
|
||||
<PDFText style={styles.pageTitle}>{p.title}</PDFText>
|
||||
<PDFText style={styles.pageDesc}>{p.desc}</PDFText>
|
||||
</PDFView>
|
||||
</IndustrialListItem>
|
||||
))}
|
||||
</PDFView>
|
||||
))}
|
||||
</PDFView>
|
||||
</>
|
||||
);
|
||||
@@ -0,0 +1,125 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
View as PDFView,
|
||||
Text as PDFText,
|
||||
StyleSheet,
|
||||
} from "@react-pdf/renderer";
|
||||
import { DocumentTitle, COLORS, FONT_SIZES } from "../SharedUI.js";
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
section: { marginBottom: 24 },
|
||||
ledgerRow: {
|
||||
paddingVertical: 14,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: COLORS.GRID,
|
||||
flexDirection: "row",
|
||||
alignItems: "flex-start",
|
||||
},
|
||||
moduleLabel: {
|
||||
fontSize: FONT_SIZES.LABEL,
|
||||
fontWeight: "bold",
|
||||
color: COLORS.CHARCOAL,
|
||||
letterSpacing: 0.5,
|
||||
marginBottom: 4,
|
||||
},
|
||||
moduleDesc: {
|
||||
fontSize: FONT_SIZES.SMALL,
|
||||
color: COLORS.TEXT_DIM,
|
||||
lineHeight: 1.5,
|
||||
},
|
||||
ledgerPrice: {
|
||||
fontSize: FONT_SIZES.BODY,
|
||||
fontWeight: "bold",
|
||||
color: COLORS.CHARCOAL,
|
||||
},
|
||||
ledgerUnit: {
|
||||
fontSize: FONT_SIZES.TINY,
|
||||
color: COLORS.TEXT_LIGHT,
|
||||
marginLeft: 2,
|
||||
},
|
||||
});
|
||||
|
||||
export const TransparenzModule = ({ pricing }: any) => {
|
||||
const sorglosPrice = (pricing.HOSTING_MONTHLY || 250) * 12;
|
||||
|
||||
return (
|
||||
<>
|
||||
<DocumentTitle title="Preis-Transparenz & Modell" isHero={true} />
|
||||
<PDFView style={styles.section}>
|
||||
<PDFView style={{ borderTopWidth: 1, borderTopColor: COLORS.CHARCOAL }}>
|
||||
{[
|
||||
{
|
||||
l: "Fundament",
|
||||
d: "Bereitstellung der techn. Infrastruktur & System-Umgebung.",
|
||||
p: pricing.BASE_WEBSITE,
|
||||
},
|
||||
{
|
||||
l: "Einzelseiten",
|
||||
d: "Individuelle Gestaltung, Layout & responsive Struktur.",
|
||||
p: pricing.PAGE,
|
||||
unit: "/ Stk",
|
||||
},
|
||||
{
|
||||
l: "Core Features",
|
||||
d: "Geschlossene Datensysteme mit eigener Datenstruktur.",
|
||||
p: pricing.FEATURE,
|
||||
unit: "/ Stk",
|
||||
},
|
||||
{
|
||||
l: "Logik & Funktionen",
|
||||
d: "Interaktive Funktions-Bausteine & Prozess-Logik.",
|
||||
p: pricing.FUNCTION,
|
||||
unit: "/ Stk",
|
||||
},
|
||||
{
|
||||
l: "Schnittstellen",
|
||||
d: "Synchronisation mit externen Zielsystemen.",
|
||||
p: pricing.API_INTEGRATION,
|
||||
unit: "/ Stk",
|
||||
},
|
||||
{
|
||||
l: "Sprachversionen",
|
||||
d: "Skalierung der System-Architektur auf Zweit-Sprachen.",
|
||||
p: "+20%",
|
||||
},
|
||||
{
|
||||
l: "Initial-Pflege",
|
||||
d: "Konvertierung & Aufbereitung von Bestandsdaten.",
|
||||
p: pricing.NEW_DATASET,
|
||||
unit: "/ Stk",
|
||||
},
|
||||
{
|
||||
l: "Sorglos Betrieb",
|
||||
d: "Hosting, Instandhaltung, Security & techn. Support.",
|
||||
p: sorglosPrice,
|
||||
unit: "/ Jahr",
|
||||
},
|
||||
].map((item: any, i: number) => (
|
||||
<PDFView key={i} style={styles.ledgerRow}>
|
||||
<PDFView style={{ width: "25%" }}>
|
||||
<PDFText style={styles.moduleLabel}>
|
||||
{item.l.toUpperCase()}
|
||||
</PDFText>
|
||||
</PDFView>
|
||||
<PDFView style={{ width: "50%" }}>
|
||||
<PDFText style={styles.moduleDesc}>{item.d}</PDFText>
|
||||
</PDFView>
|
||||
<PDFView style={{ width: "25%", alignItems: "flex-end" }}>
|
||||
<PDFText style={styles.ledgerPrice}>
|
||||
{typeof item.p === "number"
|
||||
? `${item.p.toLocaleString("de-DE")} €`
|
||||
: item.p}
|
||||
{item.unit && (
|
||||
<PDFText style={styles.ledgerUnit}> {item.unit}</PDFText>
|
||||
)}
|
||||
</PDFText>
|
||||
</PDFView>
|
||||
</PDFView>
|
||||
))}
|
||||
</PDFView>
|
||||
</PDFView>
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user