kanban-dev-webapp/src/components/roadmap/roadmap-tabs.tsx

72 lines
2.2 KiB
TypeScript

"use client";
import { useState, useTransition } from "react";
import { useRouter } from "next/navigation";
import { BandView } from "@/components/roadmap/band-view";
import { TimelineView } from "@/components/roadmap/timeline-view";
import { rescheduleCardAction } from "@/app/actions/reschedule";
import type { RoadmapCard as Card } from "@/lib/roadmap/load";
export function RoadmapTabs({
cards,
inboxCount,
canReschedule,
}: {
cards: Card[];
inboxCount: number;
canReschedule: boolean;
}) {
const router = useRouter();
const [tab, setTab] = useState<"bands" | "timeline">("bands");
const [, startTransition] = useTransition();
const [error, setError] = useState<string | null>(null);
// Bands exclude Inbox and Done; the timeline shows everything schedulable.
const banded = cards.filter((card) => card.band !== null);
return (
<div className="space-y-5">
<div className="inline-flex rounded-lg border border-border-subtle bg-surface p-0.5">
{(["bands", "timeline"] as const).map((key) => (
<button
key={key}
type="button"
aria-pressed={tab === key}
onClick={() => setTab(key)}
className={`rounded-md px-3 py-1.5 text-xs font-medium transition-colors ${
tab === key
? "bg-panel text-text-primary shadow-[var(--shadow-tile)]"
: "text-text-muted hover:text-text-secondary"
}`}
>
{key === "bands" ? "Now / Next / Later" : "Timeline"}
</button>
))}
</div>
{error && (
<p role="alert" className="text-xs text-accent">
{error}
</p>
)}
{tab === "bands" ? (
<BandView cards={banded} inboxCount={inboxCount} />
) : (
<TimelineView
cards={banded}
canReschedule={canReschedule}
onReschedule={(cardId, date) =>
startTransition(async () => {
setError(null);
const result = await rescheduleCardAction({ cardId, date });
if (!result.ok) setError(result.message ?? "Could not move that card");
else router.refresh();
})
}
/>
)}
</div>
);
}