Each page.tsx was >1000 LOC; extract components to _components/ and hooks to _hooks/ so page files stay under 500 LOC (164 / 255 / 243 respectively). Zero behavior changes — logic relocated verbatim. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
61 lines
2.3 KiB
TypeScript
61 lines
2.3 KiB
TypeScript
'use client'
|
|
|
|
import type { RoadmapData } from './types'
|
|
import { BUCKET_LABELS, DOMAIN_LABELS } from './types'
|
|
|
|
interface RoadmapTabProps {
|
|
roadmap: RoadmapData | null
|
|
}
|
|
|
|
export function RoadmapTab({ roadmap }: RoadmapTabProps) {
|
|
if (!roadmap) {
|
|
return (
|
|
<div className="flex items-center justify-center h-48">
|
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-purple-600" />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4">
|
|
{(['quick_wins', 'must_have', 'should_have', 'nice_to_have'] as const).map(bucketKey => {
|
|
const meta = BUCKET_LABELS[bucketKey]
|
|
const items = roadmap.buckets[bucketKey] || []
|
|
|
|
return (
|
|
<div key={bucketKey} className={`rounded-xl border p-4 ${meta.bg}`}>
|
|
<div className="flex items-center justify-between mb-3">
|
|
<h3 className={`font-semibold ${meta.color}`}>{meta.label}</h3>
|
|
<span className={`text-xs font-medium px-2 py-0.5 rounded-full bg-white ${meta.color}`}>
|
|
{items.length}
|
|
</span>
|
|
</div>
|
|
<div className="space-y-2 max-h-96 overflow-y-auto">
|
|
{items.length === 0 ? (
|
|
<p className="text-sm text-slate-400 text-center py-4">Keine Eintraege</p>
|
|
) : (
|
|
items.map(item => (
|
|
<div key={item.id} className="bg-white rounded-lg p-3 shadow-sm">
|
|
<p className="text-sm font-medium text-slate-900 truncate">{item.title}</p>
|
|
<div className="mt-1 flex items-center gap-2 text-xs text-slate-500">
|
|
<span className="font-mono">{item.control_id}</span>
|
|
<span>·</span>
|
|
<span>{DOMAIN_LABELS[item.domain] || item.domain}</span>
|
|
</div>
|
|
{item.days_overdue > 0 && (
|
|
<p className="mt-1 text-xs text-red-600">{item.days_overdue}d ueberfaellig</p>
|
|
)}
|
|
{item.owner && (
|
|
<p className="mt-1 text-xs text-slate-400">{item.owner}</p>
|
|
)}
|
|
</div>
|
|
))
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
)
|
|
}
|