{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "stats-11",
  "type": "registry:block",
  "title": "Stats Dashboard with Progress Bars",
  "description": "A stats dashboard with progress bars block.",
  "author": "ephraim duncan <https://ephraimduncan.com>",
  "registryDependencies": [
    "button",
    "card",
    "dialog",
    "input",
    "label"
  ],
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "path": "content/components/stats/stats-11.tsx",
      "type": "registry:component",
      "target": "components/stats-11.tsx",
      "content": "'use client';\n\nimport { Box, Edit } from 'lucide-react';\nimport type React from 'react';\nimport { useState } from 'react';\nimport { Button } from '@/components/ui/button';\nimport { Card, CardContent } from '@/components/ui/card';\nimport {\n  Dialog,\n  DialogContent,\n  DialogDescription,\n  DialogFooter,\n  DialogHeader,\n  DialogTitle,\n} from '@/components/ui/dialog';\nimport { Input } from '@/components/ui/input';\nimport { Label } from '@/components/ui/label';\n\ninterface MetricCardProps {\n  title: string;\n  value: string;\n  limit: string;\n  percentage: number;\n  status?: string;\n  statusColor?: string;\n  progressColor: string;\n  details?: Array<{ label: string; value: string; color: string }>;\n  actionLabel: string;\n  actionIcon: React.ReactNode;\n  warningMessage?: string;\n  onActionClick?: () => void;\n}\n\nfunction MetricCard({\n  title,\n  value,\n  limit,\n  percentage,\n  status,\n  statusColor = 'text-emerald-600 dark:text-emerald-400',\n  progressColor,\n  details,\n  actionLabel,\n  actionIcon,\n  warningMessage,\n  onActionClick,\n}: MetricCardProps) {\n  const renderProgressBar = () => {\n    if (details && title === 'Commands') {\n      const writes = Number.parseInt(details[0].value.replace(/,/g, ''));\n      const reads = Number.parseInt(details[1].value.replace(/,/g, ''));\n      const total = writes + reads;\n      const writesPercentage = (writes / total) * 100;\n      const readsPercentage = (reads / total) * 100;\n\n      return (\n        <div className=\"relative h-1 w-full overflow-hidden rounded-full bg-muted\">\n          <div\n            className=\"absolute left-0 h-full w-full origin-left bg-emerald-500 transition-transform duration-200 ease-out\"\n            style={{ transform: `scaleX(${writesPercentage / 100})` }}\n          />\n          <div\n            className=\"absolute left-0 h-full w-full origin-left bg-blue-500 transition-transform duration-200 ease-out\"\n            style={{\n              transform: `translateX(${writesPercentage}%) scaleX(${readsPercentage / 100})`,\n            }}\n          />\n        </div>\n      );\n    }\n\n    return (\n      <div className=\"relative h-1 w-full overflow-hidden rounded-full bg-muted\">\n        <div\n          className={`h-full w-full origin-left transition-transform duration-200 ease-out ${progressColor}`}\n          style={{ transform: `scaleX(${Math.min(percentage, 100) / 100})` }}\n        />\n      </div>\n    );\n  };\n\n  return (\n    <Card className=\"relative max-w-[280px] overflow-hidden shadow-2xs\">\n      <CardContent className=\"p-4 py-0\">\n        <h5 className=\"font-normal text-muted-foreground text-xs uppercase leading-none tracking-wide dark:text-foreground/80\">\n          {title}\n        </h5>\n\n        <div className=\"mt-2 flex items-baseline gap-1\">\n          <div className=\"font-medium text-[1.2rem] text-foreground tabular-nums leading-none\">\n            {value}\n          </div>\n          <div className=\"text-muted-foreground text-xs leading-none\">\n            / {limit}\n          </div>\n        </div>\n\n        <div className=\"mt-3\">\n          {renderProgressBar()}\n\n          {details && (\n            <div className=\"my-6 mb-8\">\n              <div className=\"flex flex-col gap-3\">\n                {details.map((detail, index) => (\n                  <div\n                    className=\"flex w-full items-center text-muted-foreground text-xs leading-none dark:text-foreground/70\"\n                    key={index}\n                  >\n                    <div\n                      className={`mr-[6px] h-2 w-2 rounded-full ${detail.color}`}\n                    />\n                    <div className=\"mr-1\">{detail.label}</div>\n                    <div className=\"h-[9px] flex-1 border-border border-b-2 border-dotted\" />\n                    <div className=\"ml-1 tabular-nums\">{detail.value}</div>\n                  </div>\n                ))}\n              </div>\n            </div>\n          )}\n\n          {status && (\n            <div className=\"pt-2\">\n              <div className={statusColor}>{status}</div>\n            </div>\n          )}\n\n          {warningMessage && (\n            <div className=\"pt-2\">\n              <div className=\"text-amber-700 text-sm dark:text-amber-400\">\n                {warningMessage}\n              </div>\n            </div>\n          )}\n        </div>\n\n        <div className=\"absolute right-0 bottom-0 left-0\">\n          <Button\n            className=\"h-8 w-full justify-start gap-0 rounded-none bg-muted/50 text-blue-500 hover:text-blue-600 dark:text-blue-400 dark:hover:text-blue-300\"\n            onClick={onActionClick}\n            variant=\"ghost\"\n          >\n            {actionIcon}\n            <span className=\"ml-1 text-xs\">{actionLabel}</span>\n          </Button>\n        </div>\n      </CardContent>\n    </Card>\n  );\n}\n\nfunction BudgetDialog({\n  open,\n  onOpenChange,\n}: {\n  open: boolean;\n  onOpenChange: (open: boolean) => void;\n}) {\n  const [budget, setBudget] = useState('150');\n\n  const handleUpdate = () => {\n    onOpenChange(false);\n  };\n\n  return (\n    <Dialog onOpenChange={onOpenChange} open={open}>\n      <DialogContent className=\"sm:max-w-md\">\n        <DialogHeader>\n          <DialogTitle>Update budget</DialogTitle>\n          <DialogDescription>\n            When your monthly cost reaches the max budget, we send an email and\n            throttle your database. You will not be charged beyond your set\n            budget for this database.\n          </DialogDescription>\n        </DialogHeader>\n\n        <div className=\"space-y-2\">\n          <Label htmlFor=\"budget\">Max budget per month</Label>\n          <Input\n            id=\"budget\"\n            onChange={(e) => setBudget(e.target.value)}\n            placeholder=\"150\"\n            type=\"number\"\n            value={budget}\n          />\n        </div>\n\n        <DialogFooter className=\"pt-2\">\n          <Button onClick={() => onOpenChange(false)} variant=\"outline\">\n            Cancel\n          </Button>\n          <Button onClick={handleUpdate}>Update</Button>\n        </DialogFooter>\n      </DialogContent>\n    </Dialog>\n  );\n}\n\nexport default function Stats11() {\n  const [budgetDialogOpen, setBudgetDialogOpen] = useState(false);\n\n  return (\n    <>\n      <div className=\"grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-4\">\n        <MetricCard\n          actionIcon={<Box className=\"h-4 w-4\" />}\n          actionLabel=\"Upgrade\"\n          details={[\n            { label: 'Writes', value: '11,276,493', color: 'bg-emerald-500' },\n            { label: 'Reads', value: '2,548,921', color: 'bg-blue-500' },\n          ]}\n          limit=\"Unlimited\"\n          percentage={67}\n          progressColor=\"bg-blue-500\"\n          title=\"Commands\"\n          value=\"13.8M\"\n        />\n\n        <MetricCard\n          actionIcon={<Box className=\"h-4 w-4\" />}\n          actionLabel=\"Upgrade\"\n          limit=\"150 GB\"\n          percentage={94}\n          progressColor=\"bg-orange-500\"\n          title=\"Bandwidth\"\n          value=\"141 GB\"\n          warningMessage=\"There will be a charge for the excessive bandwidth over the limit.\"\n        />\n\n        <MetricCard\n          actionIcon={<Box className=\"h-4 w-4\" />}\n          actionLabel=\"Upgrade\"\n          limit=\"500 GB\"\n          percentage={7.4}\n          progressColor=\"bg-emerald-500\"\n          status=\"It's all right.\"\n          title=\"Storage\"\n          value=\"37 GB\"\n        />\n\n        <MetricCard\n          actionIcon={<Edit className=\"h-4 w-4\" />}\n          actionLabel=\"Change Budget\"\n          limit=\"$150 Budget\"\n          onActionClick={() => setBudgetDialogOpen(true)}\n          percentage={48.95}\n          progressColor=\"bg-emerald-500\"\n          status=\"It's all right.\"\n          title=\"Cost\"\n          value=\"$73.42\"\n        />\n      </div>\n\n      <BudgetDialog\n        onOpenChange={setBudgetDialogOpen}\n        open={budgetDialogOpen}\n      />\n    </>\n  );\n}\n"
    }
  ],
  "categories": [
    "stats"
  ]
}