{
  "name": "app-01",
  "type": "registry:block",
  "description": "A simple task app.",
  "dependencies": [
    "swr"
  ],
  "registryDependencies": [
    "card",
    "input",
    "button",
    "skeleton",
    "label"
  ],
  "files": [
    {
      "path": "blocks/app-01/page.tsx",
      "content": "import { AddTaskForm } from \"@/registry/new-york/blocks/app-01/components/add-task-form\"\nimport { TasksList } from \"@/registry/new-york/blocks/app-01/components/tasks-list\"\nimport {\n  Card,\n  CardContent,\n  CardFooter,\n  CardHeader,\n  CardTitle,\n} from \"@/registry/new-york/ui/card\"\n\nexport default function AppPage() {\n  return (\n    <div className=\"h-screen flex flex-col items-center justify-center\">\n      <Card className=\"w-full max-w-md\">\n        <CardHeader>\n          <CardTitle>Add Task</CardTitle>\n        </CardHeader>\n        <CardContent>\n          <TasksList />\n        </CardContent>\n        <CardFooter>\n          <AddTaskForm />\n        </CardFooter>\n      </Card>\n    </div>\n  )\n}\n",
      "type": "registry:page",
      "target": "app/page.tsx"
    },
    {
      "path": "blocks/app-01/api/tasks/route.ts",
      "content": "import { NextResponse } from \"next/server\"\n\nimport { API_URL } from \"@/registry/new-york/blocks/app-01/lib/constants\"\n\nexport async function GET() {\n  const response = await fetch(API_URL)\n  const data = await response.json()\n  return NextResponse.json(data)\n}\n",
      "type": "registry:page",
      "target": "app/api/tasks/route.ts"
    },
    {
      "path": "blocks/app-01/components/add-task-form.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { Label } from \"@/registry/default/ui/label\"\nimport { SubmitButton } from \"@/registry/new-york/blocks/app-01/components/submit-button\"\nimport { useTasks } from \"@/registry/new-york/blocks/app-01/hooks/use-tasks\"\nimport { saveTask } from \"@/registry/new-york/blocks/app-01/lib/actions\"\nimport { Input } from \"@/registry/new-york/ui/input\"\n\nexport function AddTaskForm() {\n  const { mutate } = useTasks()\n  const formRef = React.useRef<HTMLFormElement>(null)\n\n  return (\n    <form\n      action={async (formData) => {\n        await saveTask(formData)\n        void mutate()\n        formRef.current?.reset()\n      }}\n      className=\"w-full\"\n      ref={formRef}\n    >\n      <div className=\"flex flex-col gap-2\">\n        <Label htmlFor=\"name\" className=\"sr-only\">\n          Task Name\n        </Label>\n        <Input\n          type=\"text\"\n          name=\"name\"\n          required\n          autoComplete=\"off\"\n          placeholder=\"Remember the milk\"\n        />\n        <SubmitButton className=\"w-full\">Add Task</SubmitButton>\n      </div>\n    </form>\n  )\n}\n",
      "type": "registry:component",
      "target": ""
    },
    {
      "path": "blocks/app-01/components/submit-button.tsx",
      "content": "\"use client\"\n\nimport { Loader2 } from \"lucide-react\"\nimport { useFormStatus } from \"react-dom\"\n\nimport { Button } from \"@/registry/new-york/ui/button\"\n\nexport function SubmitButton({\n  children,\n  ...props\n}: React.ComponentProps<typeof Button>) {\n  const { pending } = useFormStatus()\n\n  return (\n    <Button type=\"submit\" disabled={pending} {...props}>\n      {pending && <Loader2 className=\"animate-spin\" />}\n      {children}\n    </Button>\n  )\n}\n",
      "type": "registry:component",
      "target": ""
    },
    {
      "path": "blocks/app-01/components/tasks-list.tsx",
      "content": "\"use client\"\n\nimport { useTasks } from \"@/registry/new-york/blocks/app-01/hooks/use-tasks\"\nimport { Skeleton } from \"@/registry/new-york/ui/skeleton\"\n\nexport function TasksList() {\n  const { tasks, isLoading } = useTasks()\n\n  if (isLoading)\n    return (\n      <div className=\"grid gap-2\">\n        {Array.from({ length: 5 }).map((_, index) => (\n          <Skeleton className=\"h-5 w-full\" key={index} />\n        ))}\n      </div>\n    )\n\n  return (\n    <div className=\"grid gap-2\">\n      {tasks.map((task, index) => (\n        <div key={index} className=\"h-5 text-sm\">\n          {task}\n        </div>\n      ))}\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": ""
    },
    {
      "path": "blocks/app-01/hooks/use-tasks.ts",
      "content": "\"use client\"\n\nimport useSWR from \"swr\"\n\nimport { API_URL } from \"@/registry/new-york/blocks/app-01/lib/constants\"\n\nexport function useTasks() {\n  const { data, isLoading, mutate } = useSWR<{ tasks: string[] }>(\n    \"/api/tasks\",\n    async () => {\n      const response = await fetch(API_URL)\n      return response.json()\n    }\n  )\n\n  return { tasks: data?.tasks || [], isLoading, mutate }\n}\n",
      "type": "registry:hook",
      "target": ""
    },
    {
      "path": "blocks/app-01/lib/constants.ts",
      "content": "export const API_URL = \"https://api.npoint.io/40ac2c2a67c912fa2120\"\n",
      "type": "registry:lib",
      "target": ""
    },
    {
      "path": "blocks/app-01/lib/actions.ts",
      "content": "\"use server\"\n\nimport { API_URL } from \"@/registry/new-york/blocks/app-01/lib/constants\"\n\nexport async function saveTask(formData: FormData) {\n  const name = formData.get(\"name\")\n\n  // Get current tasks\n  const response = await fetch(API_URL)\n  const data = await response.json()\n  const tasks = data.tasks || []\n\n  // Add new task to array\n  tasks.push(name)\n\n  // Save updated tasks array\n  await fetch(API_URL, {\n    method: \"POST\",\n    body: JSON.stringify({ tasks }),\n  })\n\n  return { success: true }\n}\n",
      "type": "registry:lib",
      "target": ""
    }
  ],
  "cssVars": {
    "light": {
      "primary": "224.3 76.3% 48%",
      "primary-foreground": "0 0% 100%"
    }
  },
  "categories": [
    "apps"
  ]
}