{
  "$schema": "https://shadcn-vue.com/schema/registry-item.json",
  "name": "metrics-grid",
  "title": "Metrics Grid",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-vue/blocks/metrics-grid/MetricsGrid.vue",
      "content": "<script setup lang=\"ts\">\n// Six-tile KPI grid. Each tile renders a labeled KPI header (title +\n// big number / percentage / count) above a small chart -- pie or\n// horizontal bar -- that gives the breakdown.\n//\n// Per the registry's primitive-vs-block rule: tile shapes are spelled\n// out inline as siblings. Different tiles use different chart types\n// (donut, full pie, horizontal bar) -- those differences are the whole\n// point of the layout, so they don't hide behind a wrapper.\nimport { computed } from 'vue'\nimport { PieChart, BarChart } from '@/components/ui/charts'\n\n// --- KPI 1: status pie (e.g. successful / partially / error) ---\nconst totalRuns = 770\nconst runsByStatus = [\n  { name: 'Successful', value: 638 },\n  { name: 'Partial', value: 0 },\n  { name: 'Error / Skipped', value: 132 },\n]\n\n// --- KPI 2: disposition split ---\nconst totalProcessed = 638\nconst dispositionSplit = [\n  { name: 'Non-disputable', value: 168 },\n  { name: 'Disputable', value: 470 },\n]\n\n// --- KPI 3: classification breakdown ---\nconst totalClassified = 638\nconst classification = [\n  { name: 'Type A', value: 525 },\n  { name: 'Type B', value: 113 },\n]\n\n// --- KPI 4: top reasons (horizontal bar) ---\nconst skipReasons = [\n  { reason: 'CREDIT_NOTE', count: 11 },\n  { reason: 'CUSTOMS_INSPECT', count: 5 },\n  { reason: 'NEGATIVE_COST', count: 8 },\n]\nconst totalSkipped = computed(() => skipReasons.reduce((a, r) => a + r.count, 0))\n\n// --- KPI 5: error reasons (horizontal bar) ---\nconst errorReasons = [\n  { reason: 'INVALID_CUTOFF', count: 3 },\n  { reason: 'NO_SHIPMENT_DATA', count: 20 },\n  { reason: 'SELF_BILLING', count: 42 },\n  { reason: 'MISSING_OBLIGATORY_FIELD', count: 2 },\n  { reason: 'MISSING_OBLIGATORY_TIME', count: 4 },\n  { reason: 'UNABLE_TO_CLASSIFY', count: 40 },\n]\nconst totalErrors = computed(() => errorReasons.reduce((a, r) => a + r.count, 0))\n\n// --- KPI 6: workflow status ---\nconst totalProcessed2 = 638\nconst openShare = 0.7602\nconst workflowStatus = [\n  { name: 'Open', value: 485 },\n  { name: 'Pending', value: 151 },\n  { name: 'Closed', value: 2 },\n]\n\nconst pieOption = {\n  legend: { show: false },\n  series: [\n    {\n      radius: ['0%', '70%'],\n      label: {\n        show: true,\n        formatter: (p: any) => `${p.value}\\n(${p.percent}%)`,\n        fontSize: 11,\n        color: '#fff',\n        fontWeight: 600,\n      },\n      labelLine: { show: false },\n    },\n  ],\n}\n\nconst donutOption = {\n  legend: { show: false },\n  series: [\n    {\n      radius: ['40%', '70%'],\n      label: {\n        show: true,\n        formatter: (p: any) => `${p.value}\\n(${p.percent}%)`,\n        fontSize: 11,\n        color: '#fff',\n        fontWeight: 600,\n      },\n      labelLine: { show: false },\n    },\n  ],\n}\n\nconst horizontalBarOption = {\n  legend: { show: false },\n  xAxis: { type: 'value' as const, axisLabel: { fontSize: 10 } },\n  yAxis: { type: 'category' as const, axisLabel: { fontSize: 10 } },\n  grid: { left: 16, right: 16, top: 8, bottom: 24, containLabel: true },\n  series: [\n    {\n      type: 'bar' as const,\n      barMaxWidth: 18,\n      itemStyle: { borderRadius: [0, 3, 3, 0] },\n    },\n  ],\n}\n\ninterface TileShape {\n  title: string\n  big: string\n  legend?: { label: string; color: string }[]\n}\n\nconst tiles: TileShape[] = [\n  {\n    title: 'Runs by status',\n    big: `${totalRuns} runs`,\n    legend: [\n      { label: 'Successful', color: 'var(--chart-1)' },\n      { label: 'Error / Skipped', color: 'var(--chart-4)' },\n    ],\n  },\n  {\n    title: 'Disposition split',\n    big: `${totalProcessed} processed`,\n    legend: [\n      { label: 'Non-disputable', color: 'var(--chart-1)' },\n      { label: 'Disputable', color: 'var(--chart-3)' },\n    ],\n  },\n  {\n    title: 'Classification',\n    big: `${totalClassified} classified`,\n    legend: [\n      { label: 'Type A', color: 'var(--chart-1)' },\n      { label: 'Type B', color: 'var(--chart-3)' },\n    ],\n  },\n]\n</script>\n\n<template>\n  <div class=\"space-y-4\">\n    <h2 class=\"text-primary text-[15px] font-semibold tracking-tight\">Results Overview</h2>\n\n    <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n      <!-- Tile 1: Runs by status (pie) -->\n      <article class=\"bg-card border-border rounded-lg border p-4\">\n        <h3 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Runs by status</h3>\n        <div class=\"text-primary mt-1 mb-2 text-2xl font-semibold\">{{ totalRuns }} runs</div>\n        <div class=\"text-muted-foreground mb-3 flex items-center gap-3 text-[11px]\">\n          <span class=\"inline-flex items-center gap-1.5\"\n            ><span class=\"size-2 rounded-full\" style=\"background: var(--chart-1)\"></span>Successful</span\n          >\n          <span class=\"inline-flex items-center gap-1.5\"\n            ><span class=\"size-2 rounded-full\" style=\"background: var(--chart-4)\"></span>Error / Skipped</span\n          >\n        </div>\n        <PieChart :data=\"runsByStatus\" :option=\"pieOption\" height=\"220\" />\n      </article>\n\n      <!-- Tile 2: Disposition split (pie) -->\n      <article class=\"bg-card border-border rounded-lg border p-4\">\n        <h3 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Disposition split</h3>\n        <div class=\"text-primary mt-1 mb-2 text-2xl font-semibold\">{{ totalProcessed }} processed</div>\n        <div class=\"text-muted-foreground mb-3 flex items-center gap-3 text-[11px]\">\n          <span class=\"inline-flex items-center gap-1.5\"\n            ><span class=\"size-2 rounded-full\" style=\"background: var(--chart-1)\"></span>Non-disputable</span\n          >\n          <span class=\"inline-flex items-center gap-1.5\"\n            ><span class=\"size-2 rounded-full\" style=\"background: var(--chart-3)\"></span>Disputable</span\n          >\n        </div>\n        <PieChart :data=\"dispositionSplit\" :option=\"pieOption\" height=\"220\" />\n      </article>\n\n      <!-- Tile 3: Classification (pie) -->\n      <article class=\"bg-card border-border rounded-lg border p-4\">\n        <h3 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Classification</h3>\n        <div class=\"text-primary mt-1 mb-2 text-2xl font-semibold\">{{ totalClassified }} classified</div>\n        <div class=\"text-muted-foreground mb-3 flex items-center gap-3 text-[11px]\">\n          <span class=\"inline-flex items-center gap-1.5\"\n            ><span class=\"size-2 rounded-full\" style=\"background: var(--chart-1)\"></span>Type A</span\n          >\n          <span class=\"inline-flex items-center gap-1.5\"\n            ><span class=\"size-2 rounded-full\" style=\"background: var(--chart-3)\"></span>Type B</span\n          >\n        </div>\n        <PieChart :data=\"classification\" :option=\"pieOption\" height=\"220\" />\n      </article>\n\n      <!-- Tile 4: Skip reasons (horizontal bar) -->\n      <article class=\"bg-card border-border rounded-lg border p-4\">\n        <h3 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Top skip reasons</h3>\n        <div class=\"text-primary mt-1 mb-2 text-2xl font-semibold\">{{ totalSkipped }} skipped</div>\n        <div class=\"text-muted-foreground mb-3 text-[11px]\">By trigger</div>\n        <BarChart :data=\"skipReasons\" x-field=\"reason\" y-field=\"count\" :option=\"horizontalBarOption\" height=\"220\" />\n      </article>\n\n      <!-- Tile 5: Error reasons (horizontal bar) -->\n      <article class=\"bg-card border-border rounded-lg border p-4\">\n        <h3 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Top error reasons</h3>\n        <div class=\"text-primary mt-1 mb-2 text-2xl font-semibold\">{{ totalErrors }} errors</div>\n        <div class=\"text-muted-foreground mb-3 text-[11px]\">By failure mode</div>\n        <BarChart :data=\"errorReasons\" x-field=\"reason\" y-field=\"count\" :option=\"horizontalBarOption\" height=\"220\" />\n      </article>\n\n      <!-- Tile 6: Workflow status (donut + highlight) -->\n      <article class=\"bg-card border-border rounded-lg border p-4\">\n        <h3 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Workflow status</h3>\n        <div class=\"text-primary mt-1 mb-2 text-2xl font-semibold\">{{ (openShare * 100).toFixed(2) }}% open</div>\n        <div class=\"text-muted-foreground mb-3 flex items-center gap-3 text-[11px]\">\n          <span class=\"inline-flex items-center gap-1.5\"\n            ><span class=\"size-2 rounded-full\" style=\"background: var(--chart-1)\"></span>Open</span\n          >\n          <span class=\"inline-flex items-center gap-1.5\"\n            ><span class=\"size-2 rounded-full\" style=\"background: var(--chart-5)\"></span>Pending</span\n          >\n          <span class=\"inline-flex items-center gap-1.5\"\n            ><span class=\"size-2 rounded-full\" style=\"background: var(--chart-3)\"></span>Closed</span\n          >\n        </div>\n        <PieChart :data=\"workflowStatus\" :option=\"donutOption\" :donut=\"true\" height=\"220\" />\n      </article>\n    </div>\n  </div>\n</template>\n",
      "type": "registry:block",
      "target": "~/app/components/blocks/MetricsGrid.vue"
    }
  ],
  "dependencies": [
    "echarts",
    "vue-echarts"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/vue/pie-chart.json",
    "https://uipkge.dev/r/vue/bar-chart.json"
  ],
  "description": "Six-tile KPI status grid. Each tile pairs a stat header (count / percentage) with a small pie or horizontal bar chart that breaks the metric down. Different tiles use different chart types so each KPI reads at a glance.",
  "categories": [
    "dashboard",
    "analytics"
  ]
}