diff --git a/components/ChangelogTabs.tsx b/components/ChangelogTabs.tsx index 59da8a4..d73ae00 100644 --- a/components/ChangelogTabs.tsx +++ b/components/ChangelogTabs.tsx @@ -2,7 +2,8 @@ import { useEffect, useState } from 'react' import { PortableTextRenderer } from '@/components/PortableTextRenderer' -import type { ChangelogEntry, RoadmapItemData, Tab } from '@/types/changelog' +import { RoadmapItem } from '@/components/RoadmapItem' +import type { ChangelogEntry, RoadmapItemData, Tab, VoteState } from '@/types/changelog' const TABS: { id: Tab; label: string }[] = [ { id: 'whats-new', label: "What's New" }, @@ -33,6 +34,19 @@ export function ChangelogTabs({ }) { const [activeTab, setActiveTab] = useState('whats-new') + const [voteState, setVoteState] = useState>( + () => + Object.fromEntries( + roadmapItems.map((item) => [ + item._id, + { count: 0, voted: false, loading: false }, + ]) + ) + ) + + // Filled in Task 5 — no-op for now + function handleVote(_id: string) {} + useEffect(() => { const hash = window.location.hash.replace('#', '') as Tab if (TABS.some((t) => t.id === hash)) setActiveTab(hash) @@ -117,9 +131,85 @@ export function ChangelogTabs({ )} - {/* ── What's Next — stub, filled in Task 3 ── */} + {/* ── What's Next ── */} {activeTab === 'whats-next' && ( -

Roadmap coming soon.

+
+ {roadmapItems.length === 0 ? ( +

+ No roadmap items yet — check back soon. +

+ ) : ( + <> + {roadmapItems.filter((i) => i.status === 'in-progress').length > 0 && ( +
+

+ In Progress +

+
+ {roadmapItems + .filter((i) => i.status === 'in-progress') + .map((item) => ( + + ))} +
+
+ )} + + {roadmapItems.filter((i) => i.status === 'planned').length > 0 && ( +
+

+ Planned +

+
+ {roadmapItems + .filter((i) => i.status === 'planned') + .map((item) => ( + + ))} +
+
+ )} + +

+ Don't see what you need?{' '} + +

+ + )} +
)} {/* ── Give Feedback — stub, filled in Task 6 ── */} diff --git a/components/RoadmapItem.tsx b/components/RoadmapItem.tsx new file mode 100644 index 0000000..1ed672b --- /dev/null +++ b/components/RoadmapItem.tsx @@ -0,0 +1,58 @@ +'use client' + +import { ChevronUpIcon } from '@heroicons/react/20/solid' +import type { VoteState } from '@/types/changelog' + +export function RoadmapItem({ + id, + title, + description, + status, + vote, + onVote, +}: { + id: string + title: string + description: string + status: 'planned' | 'in-progress' + vote: VoteState + onVote: (id: string) => void +}) { + const statusBadgeClass = + status === 'in-progress' + ? 'border-amber-500/25 bg-amber-500/10 text-amber-400' + : 'border-zinc-700 bg-zinc-800/40 text-zinc-500' + + return ( +
+ {/* Upvote button */} + + + {/* Content */} +
+

{title}

+

{description}

+
+ + {/* Status badge */} + + {status === 'in-progress' ? 'In Progress' : 'Planned'} + +
+ ) +}