revert: move scan counts back above the tabs + fix tab centering
Reverts 1aeea23 and folds in the actual fix the relocation was
chasing: the Scanner / Scanned tab labels were rendering with
their icons and text mis-aligned because TabsTrigger wraps its
slot in an inline `<span class="truncate">`. A `gap-1.5` on
TabsTrigger never reached the icon/label children. Wrap each
trigger's content in an `inline-flex items-center gap-1.5` span
so the icon and label share a real flex container.
This commit is contained in:
parent
1aeea23296
commit
e3f665ceea
1 changed files with 53 additions and 47 deletions
|
|
@ -115,15 +115,62 @@ function fmtTime(iso: string) {
|
|||
{{ activity.title }}
|
||||
</p>
|
||||
|
||||
<!-- Counts strip — backend-authoritative. Source: the
|
||||
`events_list_event_tickets` RPC, refreshed after every scan.
|
||||
Stays consistent across organizer devices unlike a
|
||||
per-device localStorage count. -->
|
||||
<div class="grid grid-cols-3 gap-2 mb-4">
|
||||
<div class="rounded-lg border border-border bg-muted/30 p-3 text-center">
|
||||
<p class="text-2xl font-bold text-foreground">{{ registeredCount }}</p>
|
||||
<p class="text-[10px] uppercase tracking-wide text-muted-foreground mt-1">Scanned</p>
|
||||
</div>
|
||||
<div class="rounded-lg border border-border bg-muted/30 p-3 text-center">
|
||||
<p class="text-2xl font-bold text-foreground">
|
||||
{{ soldCount ?? '—' }}
|
||||
</p>
|
||||
<p class="text-[10px] uppercase tracking-wide text-muted-foreground mt-1">Sold</p>
|
||||
</div>
|
||||
<div class="rounded-lg border border-border bg-muted/30 p-3 text-center">
|
||||
<p class="text-2xl font-bold text-foreground">
|
||||
{{ remainingCount ?? '—' }}
|
||||
</p>
|
||||
<p class="text-[10px] uppercase tracking-wide text-muted-foreground mt-1">Remaining</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Surface stats fetch failures (e.g. backend missing the /stats
|
||||
endpoint, or wallet ownership rejected). Without this the
|
||||
counts strip silently freezes on the last good value while
|
||||
scans keep landing on the backend. -->
|
||||
<div
|
||||
v-if="statsError"
|
||||
class="mb-4 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 p-3 text-xs text-destructive"
|
||||
role="alert"
|
||||
>
|
||||
<AlertCircle class="w-4 h-4 mt-0.5 shrink-0" />
|
||||
<div class="min-w-0">
|
||||
<p class="font-medium">Counts may be out of date</p>
|
||||
<p class="text-destructive/80 mt-0.5 break-words">{{ statsError }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Tabs v-model="activeTab" class="w-full">
|
||||
<TabsList class="grid w-full grid-cols-2 mb-4">
|
||||
<TabsTrigger value="scanner" class="gap-1.5">
|
||||
<ScanLine class="w-4 h-4" />
|
||||
Scanner
|
||||
<!-- Icon + label wrapped in a real flex container so they
|
||||
share a gap and items-center alignment. TabsTrigger's
|
||||
internal slot lives in an inline span, so a `gap-1.5`
|
||||
on the trigger itself never reaches these two children. -->
|
||||
<TabsTrigger value="scanner">
|
||||
<span class="inline-flex items-center justify-center gap-1.5">
|
||||
<ScanLine class="w-4 h-4" />
|
||||
Scanner
|
||||
</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="list" class="gap-1.5">
|
||||
<Ticket class="w-4 h-4" />
|
||||
Scanned ({{ registeredCount }})
|
||||
<TabsTrigger value="list">
|
||||
<span class="inline-flex items-center justify-center gap-1.5">
|
||||
<Ticket class="w-4 h-4" />
|
||||
Scanned ({{ registeredCount }})
|
||||
</span>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
|
|
@ -189,47 +236,6 @@ function fmtTime(iso: string) {
|
|||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
<!-- Counts strip — backend-authoritative. Source: the
|
||||
`events_list_event_tickets` RPC, refreshed after every scan.
|
||||
Stays consistent across organizer devices unlike a
|
||||
per-device localStorage count. Lives below the scanner so
|
||||
the camera view stays prominent and the counts read as a
|
||||
summary footer rather than a header. -->
|
||||
<div class="grid grid-cols-3 gap-2 mt-4">
|
||||
<div class="rounded-lg border border-border bg-muted/30 p-3 text-center">
|
||||
<p class="text-2xl font-bold text-foreground">{{ registeredCount }}</p>
|
||||
<p class="text-[10px] uppercase tracking-wide text-muted-foreground mt-1">Scanned</p>
|
||||
</div>
|
||||
<div class="rounded-lg border border-border bg-muted/30 p-3 text-center">
|
||||
<p class="text-2xl font-bold text-foreground">
|
||||
{{ soldCount ?? '—' }}
|
||||
</p>
|
||||
<p class="text-[10px] uppercase tracking-wide text-muted-foreground mt-1">Sold</p>
|
||||
</div>
|
||||
<div class="rounded-lg border border-border bg-muted/30 p-3 text-center">
|
||||
<p class="text-2xl font-bold text-foreground">
|
||||
{{ remainingCount ?? '—' }}
|
||||
</p>
|
||||
<p class="text-[10px] uppercase tracking-wide text-muted-foreground mt-1">Remaining</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Surface stats fetch failures (e.g. backend missing the /stats
|
||||
endpoint, or wallet ownership rejected). Without this the
|
||||
counts strip silently freezes on the last good value while
|
||||
scans keep landing on the backend. -->
|
||||
<div
|
||||
v-if="statsError"
|
||||
class="mt-3 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 p-3 text-xs text-destructive"
|
||||
role="alert"
|
||||
>
|
||||
<AlertCircle class="w-4 h-4 mt-0.5 shrink-0" />
|
||||
<div class="min-w-0">
|
||||
<p class="font-medium">Counts may be out of date</p>
|
||||
<p class="text-destructive/80 mt-0.5 break-words">{{ statsError }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Full-screen result overlay. Tap anywhere to dismiss and
|
||||
resume the decode loop. Replaces the inline banner so the
|
||||
door operator can't miss the outcome — a busy entry meant
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue