refactor: rename orders to inquiries and update PDF and email text
This commit is contained in:
@@ -13,7 +13,7 @@ const defaultUrl = process.env.VERCEL_URL
|
||||
export const metadata: Metadata = {
|
||||
metadataBase: new URL(defaultUrl),
|
||||
title: "CASPOS-Shop | Die Kasse",
|
||||
description: "Konfigurieren und bestellen Sie Ihre maßgeschneiderte Business-Software in Minuten.",
|
||||
description: "Konfigurieren Sie Ihre maßgeschneiderte Business-Software in Minuten und fragen Sie sie an.",
|
||||
};
|
||||
|
||||
const geistSans = Geist({
|
||||
|
||||
@@ -44,10 +44,10 @@ export default async function MyOrdersPage() {
|
||||
<div>
|
||||
<h1 className="text-3xl font-extrabold tracking-tight flex items-center gap-3">
|
||||
<ShoppingBag className="w-8 h-8 text-primary" />
|
||||
Meine Bestellungen
|
||||
Meine Anfragen
|
||||
</h1>
|
||||
<p className="text-slate-400 text-sm mt-1">
|
||||
Alle Ihre Bestellungen auf einen Blick – inkl. aktuellem Status.
|
||||
Alle Ihre Anfragen auf einen Blick – inkl. aktuellem Status.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -55,16 +55,16 @@ export default async function MyOrdersPage() {
|
||||
{/* Fehler */}
|
||||
{error && (
|
||||
<div className="bg-red-500/10 border border-red-500/20 text-red-400 rounded-xl p-4 text-sm">
|
||||
Fehler beim Laden der Bestellungen: {error.message}
|
||||
Fehler beim Laden der Anfragen: {error.message}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Keine Bestellungen */}
|
||||
{/* Keine Anfragen */}
|
||||
{!error && (!orders || orders.length === 0) && (
|
||||
<Card className="glass-dark border-white/10">
|
||||
<CardContent className="flex flex-col items-center justify-center py-16 gap-4">
|
||||
<Package className="w-12 h-12 text-slate-600" />
|
||||
<p className="text-slate-400 text-lg">Sie haben noch keine Bestellungen aufgegeben.</p>
|
||||
<p className="text-slate-400 text-lg">Sie haben noch keine Anfragen aufgegeben.</p>
|
||||
<Link href="/order">
|
||||
<Button>Jetzt konfigurieren</Button>
|
||||
</Link>
|
||||
@@ -72,7 +72,7 @@ export default async function MyOrdersPage() {
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Bestellliste */}
|
||||
{/* Anfragenliste */}
|
||||
<div className="space-y-4">
|
||||
{(orders ?? []).map((order) => {
|
||||
const o = order as Order
|
||||
@@ -83,7 +83,7 @@ export default async function MyOrdersPage() {
|
||||
{/* Kopfzeile */}
|
||||
<div className="flex items-start justify-between gap-4 flex-wrap">
|
||||
<div className="space-y-1">
|
||||
<p className="text-xs text-slate-500 uppercase tracking-wider">Bestellnummer</p>
|
||||
<p className="text-xs text-slate-500 uppercase tracking-wider">Anfragenummer</p>
|
||||
<p className="font-mono font-bold text-primary text-lg">#{o.order_number}</p>
|
||||
</div>
|
||||
<div className="space-y-1 text-right">
|
||||
@@ -136,7 +136,7 @@ export default async function MyOrdersPage() {
|
||||
<>
|
||||
<Button variant="ghost" size="sm" asChild className="text-xs text-slate-400 hover:text-white">
|
||||
<a href={o.pdf_url} target="_blank" rel="noopener noreferrer">
|
||||
<ExternalLink className="w-3 h-3 mr-1" /> Angebotsbestätigung ansehen
|
||||
<ExternalLink className="w-3 h-3 mr-1" /> Anfrage ansehen
|
||||
</a>
|
||||
</Button>
|
||||
<Button variant="ghost" size="sm" asChild className="text-xs text-slate-400 hover:text-white">
|
||||
|
||||
@@ -50,27 +50,27 @@ export default async function OrderSuccessPage({
|
||||
<CheckCircle2 className="w-12 h-12 text-green-400" />
|
||||
</div>
|
||||
<h1 className="text-4xl font-extrabold tracking-tight text-white">
|
||||
Bestellung eingegangen!
|
||||
Anfrage eingegangen!
|
||||
</h1>
|
||||
<p className="text-slate-400 text-lg">
|
||||
Ihre Bestellung wurde erfolgreich gespeichert.
|
||||
Ihre Anfrage wurde erfolgreich gespeichert.
|
||||
</p>
|
||||
<div className="inline-flex items-center gap-2 bg-white/5 border border-white/10 rounded-full px-5 py-2 font-mono text-lg font-bold text-primary">
|
||||
#{o.order_number}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bestell-Details */}
|
||||
{/* Anfrage-Details */}
|
||||
<Card className="glass-dark border-white/10">
|
||||
<CardHeader className="flex flex-row items-center justify-between">
|
||||
<CardTitle className="text-white">Bestellübersicht</CardTitle>
|
||||
<CardTitle className="text-white">Anfrageübersicht</CardTitle>
|
||||
<Badge
|
||||
className={
|
||||
o.status === 'active'
|
||||
? 'bg-green-500/20 text-green-400 border-green-500/30'
|
||||
: o.status === 'cancelled'
|
||||
? 'bg-red-500/20 text-red-400 border-red-500/30'
|
||||
: 'bg-amber-500/20 text-amber-400 border-amber-500/30'
|
||||
? 'bg-red-500/20 text-red-400 border-red-500/30'
|
||||
: 'bg-amber-500/20 text-amber-400 border-amber-500/30'
|
||||
}
|
||||
>
|
||||
{statusLabel[o.status] ?? o.status}
|
||||
@@ -117,16 +117,16 @@ export default async function OrderSuccessPage({
|
||||
{o.order_data.price_multiplier === 0
|
||||
? "Update (0-12 Monate): 100% Rabatt (inklusive)"
|
||||
: o.order_data.price_multiplier === 0.15
|
||||
? "Update (13-14 Monate): 15% vom Listenpreis"
|
||||
: o.order_data.price_multiplier === 0.30
|
||||
? "Update (15-25 Monate): 30% vom Listenpreis"
|
||||
: o.order_data.price_multiplier === 0.45
|
||||
? "Update (26-37 Monate): 45% vom Listenpreis"
|
||||
: o.order_data.price_multiplier === 0.60
|
||||
? "Update (38-49 Monate): 60% vom Listenpreis"
|
||||
: o.order_data.price_multiplier === 0.90
|
||||
? "Neukauf (>= 50 Monate): 10% Rabatt"
|
||||
: `Gebühr: ${o.order_data.price_multiplier * 100}%`}
|
||||
? "Update (13-14 Monate): 15% vom Listenpreis"
|
||||
: o.order_data.price_multiplier === 0.30
|
||||
? "Update (15-25 Monate): 30% vom Listenpreis"
|
||||
: o.order_data.price_multiplier === 0.45
|
||||
? "Update (26-37 Monate): 45% vom Listenpreis"
|
||||
: o.order_data.price_multiplier === 0.60
|
||||
? "Update (38-49 Monate): 60% vom Listenpreis"
|
||||
: o.order_data.price_multiplier === 0.90
|
||||
? "Neukauf (>= 50 Monate): 10% Rabatt"
|
||||
: `Gebühr: ${o.order_data.price_multiplier * 100}%`}
|
||||
</p>
|
||||
{o.order_data.last_license_date && (
|
||||
<p className="text-xs font-normal text-slate-400 flex items-center gap-1">
|
||||
|
||||
@@ -110,17 +110,17 @@ export const InvoicePDF = ({ order, orderSnapshot, customer }: any) => {
|
||||
<Text>Software Solutions</Text>
|
||||
</View>
|
||||
<View style={styles.companyInfo}>
|
||||
<Text>CASPOS GmbH</Text>
|
||||
<Text>Musterstraße 1</Text>
|
||||
<Text>12345 Musterstadt</Text>
|
||||
<Text>CASPOS Computerabrechnungssysteme GmbH</Text>
|
||||
<Text>Alte Bundesstraße 16</Text>
|
||||
<Text>76846 Hauenstein</Text>
|
||||
<Text>Deutschland</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<Text style={styles.title}>Angebotsbestätigung</Text>
|
||||
<Text style={styles.title}>Anfragebestätigung</Text>
|
||||
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.label}>Besteller / Kunde</Text>
|
||||
<Text style={styles.label}>Anfragender Kunde</Text>
|
||||
<Text>{customer.company_name}</Text>
|
||||
<Text>{customer.first_name} {customer.last_name}</Text>
|
||||
<Text>{customer.address}</Text>
|
||||
@@ -129,8 +129,8 @@ export const InvoicePDF = ({ order, orderSnapshot, customer }: any) => {
|
||||
</View>
|
||||
|
||||
<View style={styles.section}>
|
||||
<Text style={styles.label}>Bestelldetails</Text>
|
||||
<Text>Bestellnummer: {order.order_number || order.id}</Text>
|
||||
<Text style={styles.label}>Anfragedetails</Text>
|
||||
<Text>Anfrage-Nummer: {order.order_number || order.id}</Text>
|
||||
<Text>Datum: {new Date(order.created_at || Date.now()).toLocaleDateString('de-DE')}</Text>
|
||||
</View>
|
||||
|
||||
@@ -141,16 +141,16 @@ export const InvoicePDF = ({ order, orderSnapshot, customer }: any) => {
|
||||
{orderSnapshot.price_multiplier === 0
|
||||
? "Update (0-12 Monate): 100% Rabatt (inklusive)"
|
||||
: orderSnapshot.price_multiplier === 0.15
|
||||
? "Update (13-14 Monate): 15% vom Listenpreis"
|
||||
: orderSnapshot.price_multiplier === 0.30
|
||||
? "Update (15-25 Monate): 30% vom Listenpreis"
|
||||
: orderSnapshot.price_multiplier === 0.45
|
||||
? "Update (26-37 Monate): 45% vom Listenpreis"
|
||||
: orderSnapshot.price_multiplier === 0.60
|
||||
? "Update (38-49 Monate): 60% vom Listenpreis"
|
||||
: orderSnapshot.price_multiplier === 0.90
|
||||
? "Neukauf (>= 50 Monate): 10% Rabatt auf Neukauf"
|
||||
: `Gebühr: ${orderSnapshot.price_multiplier * 100}%`}
|
||||
? "Update (13-14 Monate): 15% vom Listenpreis"
|
||||
: orderSnapshot.price_multiplier === 0.30
|
||||
? "Update (15-25 Monate): 30% vom Listenpreis"
|
||||
: orderSnapshot.price_multiplier === 0.45
|
||||
? "Update (26-37 Monate): 45% vom Listenpreis"
|
||||
: orderSnapshot.price_multiplier === 0.60
|
||||
? "Update (38-49 Monate): 60% vom Listenpreis"
|
||||
: orderSnapshot.price_multiplier === 0.90
|
||||
? "Neukauf (>= 50 Monate): 10% Rabatt auf Neukauf"
|
||||
: `Gebühr: ${orderSnapshot.price_multiplier * 100}%`}
|
||||
</Text>
|
||||
{orderSnapshot.last_license_date && (
|
||||
<Text style={{ marginTop: 2, color: '#666' }}>
|
||||
@@ -165,7 +165,7 @@ export const InvoicePDF = ({ order, orderSnapshot, customer }: any) => {
|
||||
<View style={styles.tableCol}><Text style={{ fontWeight: 'bold' }}>Beschreibung</Text></View>
|
||||
<View style={styles.tableColPrice}><Text style={{ fontWeight: 'bold' }}>Preis (netto)</Text></View>
|
||||
</View>
|
||||
|
||||
|
||||
{items.map((item: any, idx: number) => (
|
||||
<View key={idx}>
|
||||
<View style={styles.tableRow}>
|
||||
@@ -213,7 +213,10 @@ export const InvoicePDF = ({ order, orderSnapshot, customer }: any) => {
|
||||
<Text>{new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(taxAmount)}</Text>
|
||||
</View>
|
||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between', marginTop: 5, borderTopWidth: 1, borderTopColor: '#000', paddingTop: 5 }}>
|
||||
<Text style={styles.totalLabel}>Gesamtbetrag (netto):</Text>
|
||||
<Text style={styles.totalLabel}>MwSt.Betrag:</Text>
|
||||
<Text style={styles.totalLabel}>Gesamtbetrag (brutto):</Text>
|
||||
|
||||
<Text style={styles.totalLabel}>{new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(total)}</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -81,7 +81,7 @@ export async function submitOrder(params: {
|
||||
if (!prod) {
|
||||
throw new Error(`Das ausgewählte Produkt für Kategorie "${cat.name}" wurde nicht gefunden.`)
|
||||
}
|
||||
|
||||
|
||||
// Validate selected modules
|
||||
for (const mId of sel.moduleIds) {
|
||||
const mod = prod.modules?.find(m => m.id === mId)
|
||||
@@ -205,7 +205,7 @@ export async function submitOrder(params: {
|
||||
)
|
||||
|
||||
// 6. PDF in Supabase Storage hochladen
|
||||
const fileName = `angebotsbestaetigung_${order.id}.pdf`
|
||||
const fileName = `ab_${order.id}.pdf`
|
||||
const { error: uploadError } = await supabase
|
||||
.storage
|
||||
.from('invoices')
|
||||
@@ -224,21 +224,21 @@ export async function submitOrder(params: {
|
||||
try {
|
||||
const formattedDate = new Date(order.created_at).toLocaleDateString('de-DE')
|
||||
const formattedTotal = order.total_price.toLocaleString('de-DE', { style: 'currency', currency: 'EUR' })
|
||||
|
||||
|
||||
await sendMail({
|
||||
to: user.email,
|
||||
subject: `Angebotsbestätigung ${orderNumber}`,
|
||||
text: `Hallo,\n\nvielen Dank für Ihre Bestellung bei CASPOS Shop!\n\nBestelldetails:\n- Bestellnummer: ${orderNumber}\n- Datum: ${formattedDate}\n- Endkunde: ${customerSnapshot.company_name}\n- Gesamtsumme: ${formattedTotal}\n\nIm Anhang dieser E-Mail finden Sie Ihre Angebotsbestätigung als PDF-Dokument.\n\nViele Grüße,\nIhr CASPOS Shop-Team`,
|
||||
subject: `Anfragebestätigung ${orderNumber}`,
|
||||
text: `Hallo,\n\nvielen Dank für Ihre Anfrage bei CASPOS Shop!\n\nAngebotsdetails:\n- Anfrage-Nummer: ${orderNumber}\n- Datum: ${formattedDate}\n- Endkunde: ${customerSnapshot.company_name}\n- Gesamtsumme: ${formattedTotal}\n\nIm Anhang dieser E-Mail finden Sie Ihre Anfragebestätigung als PDF-Dokument.\n\nViele Grüße,\nIhr CASPOS Shop-Team`,
|
||||
html: `
|
||||
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e2e8f0; border-radius: 8px;">
|
||||
<h2 style="color: #0f172a; margin-bottom: 16px;">Vielen Dank für Ihre Bestellung!</h2>
|
||||
<h2 style="color: #0f172a; margin-bottom: 16px;">Vielen Dank für Ihre Anfrage!</h2>
|
||||
<p style="color: #475569; font-size: 16px; line-height: 1.5;">Hallo,</p>
|
||||
<p style="color: #475569; font-size: 16px; line-height: 1.5;">wir freuen uns sehr über Ihre Bestellung bei CASPOS Shop. Ihre Bestellung wurde erfolgreich entgegengenommen und wird nun verarbeitet.</p>
|
||||
<p style="color: #475569; font-size: 16px; line-height: 1.5;">wir freuen uns sehr über Ihre Anfrage bei CASPOS Shop. Ihre Anfrage wurde erfolgreich entgegengenommen und wird nun verarbeitet.</p>
|
||||
<div style="background-color: #f8fafc; border: 1px solid #e2e8f0; border-radius: 6px; padding: 16px; margin: 24px 0;">
|
||||
<h3 style="color: #0f172a; margin-top: 0; margin-bottom: 12px;">Bestelldetails</h3>
|
||||
<h3 style="color: #0f172a; margin-top: 0; margin-bottom: 12px;">Anfrage-Details</h3>
|
||||
<table style="width: 100%; border-collapse: collapse; font-size: 14px; color: #475569;">
|
||||
<tr>
|
||||
<td style="padding: 4px 0; font-weight: bold; width: 140px;">Bestellnummer:</td>
|
||||
<td style="padding: 4px 0; font-weight: bold; width: 140px;">Anfrage-Nummer:</td>
|
||||
<td style="padding: 4px 0;">${orderNumber}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -255,7 +255,7 @@ export async function submitOrder(params: {
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<p style="color: #475569; font-size: 16px; line-height: 1.5;">Im Anhang dieser E-Mail finden Sie Ihre Angebotsbestätigung als PDF-Dokument.</p>
|
||||
<p style="color: #475569; font-size: 16px; line-height: 1.5;">Im Anhang dieser E-Mail finden Sie Ihre Anfragebestätigung als PDF-Dokument.</p>
|
||||
<p style="color: #475569; font-size: 16px; line-height: 1.5; margin-top: 24px;">Mit freundlichen Grüßen,<br>Ihr CASPOS Shop-Team</p>
|
||||
<hr style="border: 0; border-top: 1px solid #e2e8f0; margin: 24px 0;">
|
||||
<p style="color: #94a3b8; font-size: 12px; text-align: center;">Diese E-Mail wurde automatisch generiert. Bitte antworten Sie nicht darauf.</p>
|
||||
@@ -321,7 +321,7 @@ export async function updateOrderStatus(
|
||||
if (order.user_id) {
|
||||
try {
|
||||
const { data: { user }, error: userError } = await admin.auth.admin.getUserById(order.user_id)
|
||||
|
||||
|
||||
if (!userError && user && user.email) {
|
||||
const orderNumber = order.order_number || order.id.slice(0, 8)
|
||||
const statusLabelMap: Record<string, string> = {
|
||||
|
||||
Reference in New Issue
Block a user