{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "delivery-board",
  "title": "Delivery board",
  "description": "A project delivery board in Tiles: client progress, a day strip that opens on today, roadmap lanes with initials avatars and a small assistant tile.",
  "registryDependencies": [
    "utils",
    "@manniche/data-tile"
  ],
  "files": [
    {
      "path": "registry/manniche/delivery-board/delivery-board.tsx",
      "content": "// A delivery board: client progress, a date strip (opens on `now` when it is in the strip), roadmap lanes with initials avatars and a small assistant tile.\nimport { useState } from 'react'\nimport { cn } from '@/lib/utils'\nimport { DataTile } from '@/registry/manniche/data-tile/data-tile'\n\nexport type BoardClient = { id: string; name: string; progress: number }\nexport type BoardItem = { id: string; title: string; owners: string[] }\nexport type BoardLane = { id: string; title: string; items: BoardItem[] }\n\nexport type DeliveryBoardData = {\n  clients: { title: string; items: BoardClient[] }\n  /** ISO dates \"YYYY-MM-DD\", one per chip. */\n  days: string[]\n  roadmap: { title: string; lanes: BoardLane[] }\n  assistant: { title: string; text: string; action: string }\n}\n\nexport type DeliveryBoardLabels = { note?: string; daysLabel?: string }\n\nexport type DeliveryBoardProps = {\n  data: DeliveryBoardData\n  labels?: DeliveryBoardLabels\n  now?: Date\n  onAssistant?: () => void\n  className?: string\n}\n\n/** Local calendar date as \"YYYY-MM-DD\". */\nconst isoDay = (d: Date) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`\n\nconst initials = (n: string) => n.split(' ').map((w) => w[0]).join('').slice(0, 2).toUpperCase()\n\nexport function DeliveryBoard({ data, labels, now, onAssistant, className }: DeliveryBoardProps) {\n  const note = labels?.note ?? 'Example data.'\n  const today = now && isoDay(now)\n  const [day, setDay] = useState(today && data.days.includes(today) ? today : data.days[0])\n  return (\n    <div className={cn('@container w-full rounded-2xl bg-background p-3 text-foreground', className)}>\n      <div className=\"grid grid-cols-1 gap-3 @2xl:grid-cols-6\">\n        <div className=\"@2xl:col-span-4\">\n          <DataTile className=\"h-full\" title={data.clients.title} footer={note}>\n            <ul className=\"flex flex-col gap-3\">\n              {data.clients.items.map((c) => (\n                <li key={c.id} className=\"flex flex-col gap-1.5\">\n                  <div className=\"flex justify-between text-sm\">\n                    <span className=\"font-medium\">{c.name}</span>\n                    <span className=\"tabular-nums text-muted-foreground\">{c.progress}%</span>\n                  </div>\n                  <div role=\"progressbar\" aria-label={c.name} aria-valuenow={c.progress} aria-valuemin={0} aria-valuemax={100} className=\"h-1.5 overflow-hidden rounded-full bg-muted\">\n                    <div className=\"h-full rounded-full bg-foreground\" style={{ width: `${c.progress}%` }} />\n                  </div>\n                </li>\n              ))}\n            </ul>\n          </DataTile>\n        </div>\n        <div className=\"@2xl:col-span-2\">\n          <DataTile className=\"h-full\" title={data.assistant.title} inverted>\n            <p className=\"text-sm opacity-80\">{data.assistant.text}</p>\n            <button type=\"button\" onClick={onAssistant} className=\"mt-4 rounded-full bg-foreground px-4 py-2 text-sm font-medium text-background transition-transform active:scale-[0.97] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring\">\n              {data.assistant.action}\n            </button>\n          </DataTile>\n        </div>\n        <div className=\"@2xl:col-span-6\">\n          <div role=\"group\" aria-label={labels?.daysLabel ?? 'Day'} className=\"flex gap-1 overflow-x-auto rounded-full border border-border bg-card p-1\">\n            {data.days.map((d) => {\n              const date = new Date(`${d}T12:00:00Z`)\n              return (\n                <button\n                  key={d}\n                  type=\"button\"\n                  aria-pressed={d === day}\n                  aria-current={d === today ? 'date' : undefined}\n                  onClick={() => setDay(d)}\n                  className={cn('relative flex min-w-11 flex-1 flex-col items-center rounded-full px-1 py-1 text-xs text-muted-foreground hover:text-foreground focus-visible:outline-2 focus-visible:outline-ring', d === day && 'bg-foreground text-background hover:text-background')}\n                >\n                  <span>{date.toLocaleDateString('en-GB', { weekday: 'short', timeZone: 'UTC' })}</span>\n                  <span className=\"text-sm font-medium tabular-nums\">{date.getUTCDate()}</span>\n                  {d === today && <span aria-hidden className=\"absolute bottom-0.5 size-1 rounded-full bg-current\" />}\n                </button>\n              )\n            })}\n          </div>\n        </div>\n        <div className=\"@2xl:col-span-6\">\n          <DataTile className=\"h-full\" title={data.roadmap.title} footer={note}>\n            <div className=\"grid grid-cols-1 gap-4 @xl:grid-cols-3\">\n              {data.roadmap.lanes.map((lane) => (\n                <section key={lane.id} aria-label={lane.title} className=\"flex flex-col gap-2\">\n                  <h3 className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">{lane.title}</h3>\n                  <ul className=\"flex flex-col gap-2\">\n                    {lane.items.map((it) => (\n                      <li key={it.id} className=\"flex items-center justify-between gap-2 rounded-xl border border-border bg-card px-3 py-2 text-sm\">\n                        <span className=\"min-w-0 truncate\">{it.title}</span>\n                        <span className=\"flex -space-x-1.5\">\n                          {it.owners.map((o) => (\n                            <span key={o} title={o} role=\"img\" aria-label={o} className=\"grid size-6 place-items-center rounded-full border border-card bg-muted text-[10px] font-medium\">\n                              {initials(o)}\n                            </span>\n                          ))}\n                        </span>\n                      </li>\n                    ))}\n                  </ul>\n                </section>\n              ))}\n            </div>\n          </DataTile>\n        </div>\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:component"
    }
  ],
  "categories": [
    "templates"
  ],
  "type": "registry:block"
}