feat(customers): add customer-level and device-level update/upgrade buttons with automatic license date calculation for update discount
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user