feat(customers): add customer-level and device-level update/upgrade buttons with automatic license date calculation for update discount

This commit is contained in:
DanielS
2026-08-11 23:34:35 +02:00
parent 9bde60553e
commit b2a5f7cc64
4 changed files with 43 additions and 16 deletions

View File

@@ -104,6 +104,13 @@ export default function CustomerDetailPage({ params }: { params: Promise<{ id: s
Kunden-ID: <span className="font-mono">{customer.id.slice(0, 8)}</span> Kunden-ID: <span className="font-mono">{customer.id.slice(0, 8)}</span>
</p> </p>
</div> </div>
{!customer.is_anonymized && (
<Link href={`/order?customer_id=${customer.id}`} className="ml-auto">
<Button size="sm" className="bg-primary hover:bg-primary/90 text-white font-bold gap-2 shadow-[0_0_15px_rgba(59,130,246,0.3)] text-xs">
<ShoppingBag className="w-4 h-4" /> Kunde updaten / bestellen
</Button>
</Link>
)}
{customer.is_anonymized && ( {customer.is_anonymized && (
<Badge className="bg-red-500/10 text-red-400 border-red-500/20 gap-1 ml-auto"> <Badge className="bg-red-500/10 text-red-400 border-red-500/20 gap-1 ml-auto">
<AlertTriangle className="w-3 h-3" /> Anonymisiert <AlertTriangle className="w-3 h-3" /> Anonymisiert

View File

@@ -138,6 +138,10 @@ async function OrderDataWrapper({
companies = await getCompanies().catch(() => []) companies = await getCompanies().catch(() => [])
} }
const initialLastLicenseDate = initialOrder
? (initialOrder.order_data?.last_license_date || (initialOrder.created_at ? new Date(initialOrder.created_at).toISOString().split('T')[0] : ''))
: ''
return ( return (
<OrderWizard <OrderWizard
products={products} products={products}
@@ -150,6 +154,7 @@ async function OrderDataWrapper({
upgradeMode={mode === 'upgrade'} upgradeMode={mode === 'upgrade'}
initialEndCustomerId={customerId || null} initialEndCustomerId={customerId || null}
lockedDeviceId={deviceId ? decodeURIComponent(deviceId) : null} lockedDeviceId={deviceId ? decodeURIComponent(deviceId) : null}
initialLastLicenseDate={initialLastLicenseDate}
/> />
) )
} }

View File

@@ -120,14 +120,15 @@ function DeviceCard({
</p> </p>
</div> </div>
{/* Upgrade / Abo Button */} {/* Update / Upgrade Button für Kasse */}
<Link href={upgradeUrl}> <Link href={upgradeUrl}>
<Button <Button
size="sm" size="sm"
className="bg-primary/20 hover:bg-primary/30 text-primary border border-primary/30 text-xs font-semibold gap-1.5" className="bg-sky-500/20 hover:bg-sky-500/30 text-sky-300 border border-sky-500/40 text-xs font-bold gap-1.5 shadow-[0_0_12px_rgba(56,189,248,0.2)]"
title="Kasse updaten oder upgraden (Erstelldatum wird für den Update-Rabatt genutzt)"
> >
<Sparkles className="w-3.5 h-3.5" /> <Sparkles className="w-3.5 h-3.5 text-sky-400" />
Upgrade / Abo Update / Upgrade
</Button> </Button>
</Link> </Link>
@@ -272,18 +273,31 @@ export function CustomerAccordionList({ customers }: CustomerAccordionListProps)
</Badge> </Badge>
{!customer.is_anonymized && ( {!customer.is_anonymized && (
<Link <>
href={`/my-customers/${customer.id}`} <Link
onClick={(e) => e.stopPropagation()} href={`/order?customer_id=${customer.id}`}
> onClick={(e) => e.stopPropagation()}
<Button
variant="ghost"
size="sm"
className="text-slate-400 hover:text-white hover:bg-white/10 gap-1 text-xs"
> >
<Edit2 className="w-3.5 h-3.5" /> Bearbeiten <Button
</Button> size="sm"
</Link> className="bg-primary/20 hover:bg-primary/30 text-primary border border-primary/40 gap-1.5 text-xs font-bold shadow-[0_0_10px_rgba(59,130,246,0.2)]"
>
<Sparkles className="w-3.5 h-3.5" /> Kunde updaten / bestellen
</Button>
</Link>
<Link
href={`/my-customers/${customer.id}`}
onClick={(e) => e.stopPropagation()}
>
<Button
variant="ghost"
size="sm"
className="text-slate-400 hover:text-white hover:bg-white/10 gap-1 text-xs"
>
<Edit2 className="w-3.5 h-3.5" /> Bearbeiten
</Button>
</Link>
</>
)} )}
<Button <Button

View File

@@ -90,6 +90,7 @@ export function OrderWizard({
upgradeMode?: boolean upgradeMode?: boolean
initialEndCustomerId?: string | null initialEndCustomerId?: string | null
lockedDeviceId?: string | null lockedDeviceId?: string | null
initialLastLicenseDate?: string
}) { }) {
const router = useRouter() const router = useRouter()
// Upgrade-Mode: starte direkt bei Schritt 3 (Software) // Upgrade-Mode: starte direkt bei Schritt 3 (Software)
@@ -214,7 +215,7 @@ export function OrderWizard({
// Falls "one_time" (Kauf) gewählt: optionales Datum der letzten CASPOS-Lizenzierung // Falls "one_time" (Kauf) gewählt: optionales Datum der letzten CASPOS-Lizenzierung
const [lastLicenseDate, setLastLicenseDate] = useState<string>( const [lastLicenseDate, setLastLicenseDate] = useState<string>(
initialOrder?.order_data?.last_license_date || '' initialLastLicenseDate || initialOrder?.order_data?.last_license_date || ''
) )
// Aktive Auswahllisten initialisieren // Aktive Auswahllisten initialisieren