import React from 'react'; import * as fs from 'fs'; import { Document, Page, Text, View, StyleSheet, Font, Image, Svg, Path, G, Rect, ClipPath, Circle, } from '@react-pdf/renderer'; import * as path from 'path'; export interface PersonData { name: string; role: string; phone: string; email: string; } export interface PDFBusinessCardProps { person: PersonData; qrCodeDataUrl: string; isWhiteVariant?: boolean; } // Mintel Aesthetics Colors - EXACT PROD COLORS const COLORS = { primary: '#011dff', // Brand Royal Blue green: '#82ed20', // Brand Accent Green white: '#ffffff', grayText: '#6c757d', black: '#0a0a0a', neutralDark: '#263336', lightGray: '#f8f9fa', }; const styles = StyleSheet.create({ pageBleed: { width: '91mm', height: '61mm', backgroundColor: COLORS.primary, position: 'relative', fontFamily: 'Helvetica', overflow: 'hidden', }, pageBleedBack: { width: '91mm', height: '61mm', backgroundColor: COLORS.white, position: 'relative', fontFamily: 'Helvetica', overflow: 'hidden', }, // -- BLUE PAGE (Rückseite) -- truckWrapper: { position: 'absolute', top: 0, left: 0, right: 0, bottom: '16mm', // Leave space for the bar below zIndex: 1, }, frontBackgroundImage: { width: '100%', height: '100%', objectFit: 'contain', objectPositionX: 'center', objectPositionY: 'center', opacity: 0.2, // Much more transparent }, frontContainer: { flex: 1, paddingBottom: '16mm', // Push the logo up to center it in the area above the bar justifyContent: 'center', alignItems: 'center', }, frontLogo: { width: 140, zIndex: 100, }, frontTagline: { color: COLORS.white, fontSize: 6, marginTop: 10, letterSpacing: 1.5, fontWeight: 'bold', textTransform: 'uppercase', zIndex: 100, }, frontGreenBarBottom: { position: 'absolute', bottom: 0, left: 0, right: 0, height: '16mm', borderTop: `2pt solid ${COLORS.green}`, backgroundColor: '#000a66', zIndex: 50, flexDirection: 'column', justifyContent: 'center', alignItems: 'center', gap: 6, // Increased gap for more spacing under tagline }, frontIconsGroup: { flexDirection: 'row', gap: 12, }, frontBrandIconWrapper: { alignItems: 'center', gap: 2, }, frontBrandIcon: { width: 14, height: 14, opacity: 0.9, }, frontBrandText: { fontSize: 4, color: COLORS.white, textTransform: 'uppercase', letterSpacing: 0.5, opacity: 0.9, }, frontTaglineBar: { color: COLORS.green, fontSize: 5.5, letterSpacing: 1.5, fontWeight: 'bold', textTransform: 'uppercase', }, // -- WHITE PAGE (Vorderseite) -- backContainer: { flex: 1, padding: '8mm', flexDirection: 'column', justifyContent: 'space-between', }, backHeader: { marginBottom: 'auto', flexDirection: 'row', alignItems: 'center', width: '100%', }, backLogo: { width: 70, }, accentLineHorizontal: { flex: 1, height: 1.5, backgroundColor: COLORS.primary, // Brand blue line marginLeft: 15, marginRight: 0, }, accentDot: { width: 4, height: 4, borderRadius: 2, backgroundColor: COLORS.green, marginRight: 20, // Keep away from the edge! }, accentBoxEdge: { width: 3, height: 25, // Sleek vertical bar on the edge backgroundColor: COLORS.green, position: 'absolute', right: '-8mm', // Bleed edge top: -5, }, backBody: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-end', width: '100%', }, leftColumn: { flex: 1, flexDirection: 'column', paddingRight: '4mm', paddingBottom: '2mm', }, nameSection: { marginBottom: '5mm', }, nameText: { fontSize: 14, fontWeight: 'bold', color: COLORS.neutralDark, marginBottom: 2, letterSpacing: -0.2, }, roleText: { fontSize: 7.5, fontWeight: 'bold', color: COLORS.primary, letterSpacing: 0.5, textTransform: 'uppercase', }, contactSection: { flexDirection: 'column', gap: 5, }, contactRow: { flexDirection: 'row', alignItems: 'center', }, iconWrapper: { width: 10, justifyContent: 'center', alignItems: 'flex-start', }, contactText: { fontSize: 7.5, color: COLORS.neutralDark, fontWeight: 'normal', paddingTop: 1, }, rightColumn: { flexDirection: 'column', alignItems: 'flex-end', justifyContent: 'flex-end', }, // Ultra Minimalist QR Area qrContainer: { flexDirection: 'column', alignItems: 'center', gap: 4, }, qrCodeWrapper: { width: '15mm', height: '15mm', }, qrCode: { width: '100%', height: '100%', }, qrLabel: { fontSize: 3.5, color: COLORS.neutralDark, // Subtle grey instead of loud blue fontWeight: 'bold', letterSpacing: 1.2, }, }); // SVG Icons const PhoneIcon = () => ( ); const EmailIcon = () => ( ); const GlobeIcon = () => ( ); const ScanIcon = () => ( ); const parseSvgPaths = (filePath: string) => { try { const raw = fs.readFileSync(filePath, 'utf8'); const paths = []; const pathRegex = /]+)>/g; let match; while ((match = pathRegex.exec(raw)) !== null) { const attrs = match[1]; const dMatch = attrs.match(/d="([^"]+)"/); if (!dMatch) continue; let fill = 'white'; const fillMatch = attrs.match(/fill(?:[:=])"?([^;"\s>]+)/); if (fillMatch) { fill = fillMatch[1].replace(/"$/, ''); if (fill === 'none') continue; } paths.push({ d: dMatch[1], fill }); } return paths; } catch (e) { console.error('Could not parse SVG:', filePath); return []; } }; const VectorLogo = ({ paths, style }: { paths: { d: string; fill: string }[]; style: any }) => ( {paths.map((p, i) => ( ))} ); export const IconSolar = ({ style, color = 'white' }: { style: any; color?: string }) => ( ); export const AbstractCable = ({ size = 10, color = COLORS.green, }: { size?: number; color?: string; }) => ( ); export const IconLowVoltage = ({ style, color = 'white' }: { style: any; color?: string }) => ( ); export const IconMediumVoltage = ({ style, color = 'white' }: { style: any; color?: string }) => ( ); export const IconHighVoltage = ({ style, color = 'white' }: { style: any; color?: string }) => ( ); export const PDFBusinessCard: React.FC = ({ person, qrCodeDataUrl, isWhiteVariant = false, }) => { const logoWhitePath = path.join(process.cwd(), 'public', 'logo-green-text.svg'); const logoBluePath = path.join(process.cwd(), 'public', 'logo-green-text-blue.svg'); const logoBlueWithTaglinePath = path.join( process.cwd(), 'public', 'logo-green-text-blue-with-tagline.svg', ); const logoWhitePaths = parseSvgPaths(logoWhitePath); const logoBluePaths = parseSvgPaths(logoBluePath); const logoBlueWithTaglinePaths = parseSvgPaths(logoBlueWithTaglinePath); const bgImagePath = isWhiteVariant ? path.join(process.cwd(), 'public', 'truck_original_rasterized.png') : path.join(process.cwd(), 'public', 'cable_drums_bg.png'); return ( {/* VORDERSEITE (Blue page with logo, truck and tagline) */} VON 0,6 KV BIS 110 KV Niederspannung Mittelspannung Hochspannung Solar {/* RÜCKSEITE (White page with contact info) */} {person.name} {person.role} {person.phone} {person.email} klz-cables.com ABSPEICHERN ); };