"use client"; import { ReactFlow, Background, type Node, type Edge, type NodeProps, Handle, Position, MarkerType, } from "@xyflow/react"; import "@xyflow/react/dist/style.css"; import { CheckCircle2, Circle, Flag, Rocket, Settings, ShieldCheck, Database, Layout, Activity, TestTube, } from "lucide-react"; type PhaseNodeData = { label: string; status: "todo" | "doing" | "done"; icon: React.ElementType; color: string; items: { text: string; completed: boolean }[]; }; function PhaseNode({ data }: NodeProps>) { const Icon = data.icon; return (
{data.label}
{data.status}
    {data.items.map((item, i) => (
  • {item.completed ? ( ) : ( )} {item.text}
  • ))}
); } const nodeTypes = { phase: PhaseNode }; const nodes: Node[] = [ { id: "p1", type: "phase", position: { x: 0, y: 0 }, data: { label: "Phase 1 — Foundation", status: "todo", icon: Database, color: "#6366f1", items: [ { text: "TypeScript types", completed: true }, { text: "Supabase schema & migrations", completed: false }, { text: "Supabase client setup (@supabase/ssr)", completed: false }, { text: "Project config & env setup", completed: false }, ], }, }, { id: "p2", type: "phase", position: { x: 400, y: 0 }, data: { label: "Phase 2 — Core Services", status: "todo", icon: Settings, color: "#8b5cf6", items: [ { text: "DNS service (tangerine)", completed: false }, { text: "WHOIS service (whoiser)", completed: false }, { text: "Availability service (IANA RDAP)", completed: false }, { text: "Public lookup APIs", completed: false }, { text: "Integration tests", completed: false }, ], }, }, { id: "p3", type: "phase", position: { x: 800, y: 0 }, data: { label: "Phase 3 — Authentication", status: "todo", icon: ShieldCheck, color: "#ec4899", items: [ { text: "Supabase Auth (GitHub, Google, Email)", completed: false }, { text: "Auth server actions", completed: false }, { text: "OAuth callback route", completed: false }, { text: "Middleware protection", completed: false }, { text: "Login/signup pages", completed: false }, ], }, }, { id: "p4", type: "phase", position: { x: 0, y: 450 }, data: { label: "Phase 4 — Public UI", status: "doing", icon: Layout, color: "#3b82f6", items: [ { text: "App shell layout", completed: false }, { text: "Homepage Hero & Search", completed: true }, { text: "DNS results page", completed: false }, { text: "Save to Dashboard button", completed: false }, ], }, }, { id: "p5", type: "phase", position: { x: 400, y: 450 }, data: { label: "Phase 5 — Dashboard", status: "todo", icon: Rocket, color: "#06b6d4", items: [ { text: "Dashboard layout & stats", completed: false }, { text: "Saved domains CRUD", completed: false }, { text: "Domain detail page & history", completed: false }, { text: "Notes & tags (auto-save)", completed: false }, { text: "Manual re-check triggers", completed: false }, ], }, }, { id: "p6", type: "phase", position: { x: 800, y: 450 }, data: { label: "Phase 6 — Monitoring & Alerts", status: "todo", icon: Activity, color: "#10b981", items: [ { text: "Change detection logic", completed: false }, { text: "Vercel Daily Cron job", completed: false }, { text: "In-app notification system", completed: false }, { text: "Email alerts via Resend", completed: false }, ], }, }, { id: "p7", type: "phase", position: { x: 200, y: 900 }, data: { label: "Phase 7 — Settings & Polish", status: "todo", icon: Flag, color: "#f59e0b", items: [ { text: "User profile & preferences", completed: false }, { text: "Error boundaries & 404s", completed: false }, { text: "Toast notifications (sonner)", completed: false }, { text: "SEO & OG image generation", completed: false }, ], }, }, { id: "p8", type: "phase", position: { x: 600, y: 900 }, data: { label: "Phase 8 — Testing & QA", status: "todo", icon: TestTube, color: "#64748b", items: [ { text: "End-to-end integration tests", completed: false }, { text: "Build verification (zero TS errors)", completed: false }, { text: "Manual QA pass (Light/Dark mode)", completed: false }, ], }, }, ]; const edges: Edge[] = [ { id: "e1-2", source: "p1", target: "p2", markerEnd: { type: MarkerType.ArrowClosed, color: "#94a3b8" }, style: { stroke: "#94a3b8" }, }, { id: "e2-3", source: "p2", target: "p3", markerEnd: { type: MarkerType.ArrowClosed, color: "#94a3b8" }, style: { stroke: "#94a3b8" }, }, { id: "e3-4", source: "p3", target: "p4", markerEnd: { type: MarkerType.ArrowClosed, color: "#94a3b8" }, style: { stroke: "#94a3b8", strokeWidth: 2 }, }, { id: "e4-5", source: "p4", target: "p5", markerEnd: { type: MarkerType.ArrowClosed, color: "#94a3b8" }, style: { stroke: "#94a3b8" }, }, { id: "e5-6", source: "p5", target: "p6", markerEnd: { type: MarkerType.ArrowClosed, color: "#94a3b8" }, style: { stroke: "#94a3b8" }, }, { id: "e6-7", source: "p6", target: "p7", markerEnd: { type: MarkerType.ArrowClosed, color: "#94a3b8" }, style: { stroke: "#94a3b8", strokeWidth: 2 }, }, { id: "e7-8", source: "p7", target: "p8", markerEnd: { type: MarkerType.ArrowClosed, color: "#94a3b8" }, style: { stroke: "#94a3b8" }, }, ]; export function RoadmapFlowchart() { return (
); }