fix: instance detail crash — use safe accessors for events/license (null check)
Root cause: useFetch returns the full API response { instance: {...} } but
the code assigned it directly: const instance = data
This meant instance.events and instance.license were undefined (data.events
doesn't exist, data.instance.events does).
Fix:
- const events = instance?.events ?? []
- const license = instance?.license ?? null
- Replaced all instance.events → events
- Replaced all instance.license → license
- format.ts already had null-safe date functions
This commit is contained in:
1 parent
52effad4a5
commit
76f3d93873
1 file changed
+15
-11
@@ -631,6 +631,10 @@ function InstanceDetailSheet({
|
||||
const status = instance?.status ?? ''
|
||||
const fullDomain = instance ? `${instance.subdomain}.dfmpanel.eu` : ''
|
||||
|
||||
// Safe accessors — events and license may be undefined during loading
|
||||
const events = instance?.events ?? []
|
||||
const license = instance?.license ?? null
|
||||
|
||||
return (
|
||||
<Sheet open={open} onOpenChange={onOpenChange}>
|
||||
<SheetContent
|
||||
@@ -735,7 +739,7 @@ function InstanceDetailSheet({
|
||||
</section>
|
||||
|
||||
{/* License info */}
|
||||
{instance.license && (
|
||||
{license && (
|
||||
<section className="space-y-2">
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
||||
Lizenz
|
||||
@@ -745,20 +749,20 @@ function InstanceDetailSheet({
|
||||
label="Key"
|
||||
value={
|
||||
<code className="text-xs">
|
||||
{maskLicenseKey(instance.license.key)}
|
||||
{maskLicenseKey(license.key)}
|
||||
</code>
|
||||
}
|
||||
/>
|
||||
<DetailRow label="Produkt" value={instance.license.product} />
|
||||
<DetailRow label="Produkt" value={license.product} />
|
||||
<DetailRow
|
||||
label="Abrechnung"
|
||||
value={
|
||||
instance.license.billingCycle === 'yearly' ? 'Jährlich' : 'Monatlich'
|
||||
license.billingCycle === 'yearly' ? 'Jährlich' : 'Monatlich'
|
||||
}
|
||||
/>
|
||||
<DetailRow
|
||||
label="Nettopreis"
|
||||
value={`${(instance.license.netPriceCents / 100).toLocaleString('de-DE', {
|
||||
value={`${(license.netPriceCents / 100).toLocaleString('de-DE', {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2,
|
||||
})} €`}
|
||||
@@ -767,15 +771,15 @@ function InstanceDetailSheet({
|
||||
label="Lizenzstatus"
|
||||
value={
|
||||
<Badge variant="outline" className="border-foreground/20">
|
||||
{instance.license.status}
|
||||
{license.status}
|
||||
</Badge>
|
||||
}
|
||||
/>
|
||||
<DetailRow
|
||||
label="Gekündigt"
|
||||
value={
|
||||
instance.license.cancelledAt
|
||||
? formatDate(instance.license.cancelledAt)
|
||||
license.cancelledAt
|
||||
? formatDate(license.cancelledAt)
|
||||
: '—'
|
||||
}
|
||||
/>
|
||||
@@ -819,7 +823,7 @@ function InstanceDetailSheet({
|
||||
</h3>
|
||||
<div className="rounded-md border border-border bg-muted/20 p-3 text-xs">
|
||||
{(() => {
|
||||
const graphEvents = instance.events.filter(
|
||||
const graphEvents = events.filter(
|
||||
(e) => e.type.startsWith('graphify.')
|
||||
)
|
||||
const buildQueued = graphEvents.some(
|
||||
@@ -874,11 +878,11 @@ function InstanceDetailSheet({
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
||||
Ereignisverlauf
|
||||
</h3>
|
||||
{instance.events.length === 0 ? (
|
||||
{events.length === 0 ? (
|
||||
<p className="text-xs text-muted-foreground">Keine Ereignisse protokolliert.</p>
|
||||
) : (
|
||||
<ol className="space-y-2">
|
||||
{instance.events.map((ev) => (
|
||||
{events.map((ev) => (
|
||||
<EventRow key={ev.id} event={ev} />
|
||||
))}
|
||||
</ol>
|
||||
|
||||
Reference in new issue
Block a user