refactor: update home page UI to v2 patterns and introduce availability heatmap component

This commit is contained in:
Jose Selesan
2026-04-27 08:46:32 -03:00
parent d6e32f3e84
commit 7a3452c2d1
4 changed files with 543 additions and 465 deletions

View File

@@ -117,50 +117,73 @@
---
## Home Page Patterns
## Home Page Patterns (v2)
### Structure
- Header: Title + DatePicker chip + Action button (3-column)
- Metrics Grid: 4-column stats with semantic colors
- Next Booking: Prominent card with emerald accent
- Timeline: Grouped by date with "now" indicator
- Header + URL Card: 2-column grid (lg:)
- Main: Timeline de reservas
- Sidebar: Stats grid consolidado (sticky)
### DatePicker Chip
### URL Card (destacada)
```tsx
<div className="flex items-center gap-1 rounded-md border bg-card px-2 py-1">
<Field>
<DatePicker value={...} onChange={...} placeholder="" />
</Field>
{isToday && (
<span className="text-xs font-medium text-emerald-600">Hoy</span>
)}
</div>
```
### Metrics Grid
```tsx
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
<div className="rounded-lg border bg-card p-3">
<p className="text-xs font-medium text-muted-foreground">Total</p>
<p className="mt-1 text-2xl font-semibold tracking-tight">{value}</p>
<div className="group relative overflow-hidden rounded-2xl border border-blue-200/60 bg-blue-50/50 p-5">
<div className="absolute inset-0 bg-gradient-to-br from-blue-50/80 to-blue-100/30" />
<div className="relative flex items-center justify-between gap-4">
<div className="min-w-0 flex-1">
<p className="text-[11px] font-semibold uppercase tracking-[0.28em] text-blue-600/70">
Reserva online
</p>
<a href={url} className="mt-1 block truncate text-sm font-medium text-blue-700 underline-offset-2 hover:underline">
{url}
</a>
</div>
<button className="relative flex shrink-0 items-center gap-2 rounded-lg bg-blue-500/10 px-3 py-2 text-sm font-medium text-blue-700 transition-colors hover:bg-blue-500/20">
<Copy className="size-4" />
<span>Copiar</span>
</button>
</div>
// ... confirmed (emerald), completed (sky), no-show (orange)
</div>
```
### Timeline Item
### Stats Pills (header)
```tsx
<span className="rounded-full border border-emerald-200/60 bg-emerald-50/60 px-3 py-1 text-xs font-medium text-emerald-700">
{count} hoy
</span>
```
### Stats Sidebar (grid 2x2)
```tsx
<section className="space-y-3 rounded-2xl border border-border/70 bg-card p-4">
<h2 className="text-xs font-semibold uppercase tracking-[0.28em] text-muted-foreground">
Resumen
</h2>
<div className="grid grid-cols-2 gap-3">
<div className="rounded-xl border border-border/50 bg-background/80 p-3">
<p className="text-xs text-muted-foreground">Total</p>
<p className="mt-1 text-xl font-semibold tracking-tight">{value}</p>
</div>
<div className="rounded-xl border border-emerald-200/40 bg-emerald-50/40 p-3">
<p className="text-xs text-emerald-700/80">Hoy</p>
<p className="mt-1 text-xl font-semibold tracking-tight text-emerald-700">{value}</p>
</div>
{/* ... confirmed (blue), completed (sky) */}
</div>
</section>
```
### Timeline Item (v2 - mejorado)
```tsx
<div className={[
'group flex items-center justify-between gap-3 rounded-md border p-2.5 transition-colors hover:bg-muted/50',
isPast && 'opacity-60',
'group flex items-center justify-between gap-3 rounded-xl border border-border/70 bg-card/60 p-3.5 transition-all hover:bg-muted/50',
isPast && 'opacity-50',
isNow && 'border-l-2 border-l-emerald-500 bg-emerald-50/30',
].join(' ')}>
<div className="flex min-w-0 flex-1 items-center gap-3">
<div className="flex w-16 shrink-0 flex-col items-center">
<div className="flex w-14 flex-col items-center">
<span className="text-sm font-medium tabular-nums">{startTime}</span>
<span className="text-xs text-muted-foreground">{endTime}</span>
<span className="text-[11px] text-muted-foreground">{endTime}</span>
</div>
<ChevronRight className="size-4 shrink-0 text-muted-foreground/30" />
<div className="min-w-0 flex-1">
<p className="truncate text-sm font-medium">{courtName}</p>
<p className="truncate text-xs text-muted-foreground">{customer}</p>
@@ -169,18 +192,20 @@
<div className="flex shrink-0 items-center gap-2">
<StatusBadge status={...} />
<div className="flex gap-1 opacity-0 transition-opacity group-hover:opacity-100">
<Button size="icon-xs" variant="ghost">...</Button>
<Button size="icon-xs" variant="ghost" title="Marcar cumplida"><Check className="size-3.5" /></Button>
<Button size="icon-xs" variant="ghost" title="Cancelar">×</Button>
</div>
</div>
</div>
```
### Actions Hover Pattern
### Date Group Header
```tsx
<div className="flex gap-1 opacity-0 transition-opacity group-hover:opacity-100">
<Button size="icon-xs" variant="ghost" title="Marcar cumplida">
<Check className="size-3.5" />
</Button>
<Button size="icon-xs" variant="ghost" title="Cancelar">×</Button>
<div className="flex items-center gap-3">
<h2 className="text-sm font-semibold capitalize">{dateLabel}</h2>
<div className="h-px flex-1 border-t border-dashed border-border/40" />
<span className="shrink-0 rounded-full border border-border/70 bg-background px-2.5 py-0.5 text-[11px] font-medium text-muted-foreground">
{count}
</span>
</div>
```