Files
breakpilot-lehrer/website/app/admin/backlog/page.tsx
Benjamin Admin 0b37c5e692 [split-required] Split website + studio-v2 monoliths (Phase 3 continued)
Website (14 monoliths split):
- compliance/page.tsx (1,519 → 9), docs/audit (1,262 → 20)
- quality (1,231 → 16), alerts (1,203 → 10), docs (1,202 → 11)
- i18n.ts (1,173 → 8 language files)
- unity-bridge (1,094 → 12), backlog (1,087 → 6)
- training (1,066 → 8), rag (1,063 → 8)
- Deleted index_original.ts (4,899 LOC dead backup)

Studio-v2 (5 monoliths split):
- meet/page.tsx (1,481 → 9), messages (1,166 → 9)
- AlertsB2BContext.tsx (1,165 → 5 modules)
- alerts-b2b/page.tsx (1,019 → 6), korrektur/archiv (1,001 → 6)

All existing imports preserved. Zero new TypeScript errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 17:52:36 +02:00

148 lines
5.6 KiB
TypeScript

'use client'
import AdminLayout from '@/components/admin/AdminLayout'
import { useBacklog } from './_components/useBacklog'
import { BacklogItemCard } from './_components/BacklogItemCard'
export default function BacklogPage() {
const backlog = useBacklog()
const progress = backlog.getProgress()
return (
<AdminLayout
title="Production Readiness Backlog"
description="Alle Aufgaben vor dem Go-Live"
>
{/* Overall Progress */}
<div className="bg-white rounded-xl border border-slate-200 p-6 mb-6">
<div className="flex items-center justify-between mb-4">
<div>
<h2 className="text-lg font-semibold text-slate-900">Gesamtfortschritt</h2>
<p className="text-sm text-slate-500">
{progress.completed} von {progress.total} Aufgaben abgeschlossen
</p>
</div>
<div className="text-3xl font-bold text-primary-600">{progress.percentage}%</div>
</div>
<div className="w-full bg-slate-200 rounded-full h-3">
<div
className="bg-primary-600 h-3 rounded-full transition-all duration-500"
style={{ width: `${progress.percentage}%` }}
/>
</div>
</div>
{/* Category Cards */}
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 mb-6">
{backlog.categories.map((cat) => {
const catProgress = backlog.getCategoryProgress(cat.id)
return (
<button
key={cat.id}
onClick={() => backlog.setSelectedCategory(backlog.selectedCategory === cat.id ? null : cat.id)}
className={`p-4 rounded-xl border-2 text-left transition-all ${
backlog.selectedCategory === cat.id
? `${cat.color} ring-2 ring-offset-2`
: 'bg-white border-slate-200 hover:border-slate-300'
}`}
>
<div className="flex items-center gap-3 mb-2">
<span className={backlog.selectedCategory === cat.id ? '' : 'text-slate-600'}>
{cat.icon}
</span>
<span className="font-medium text-sm">{cat.name}</span>
</div>
<div className="text-xs text-slate-500">
{catProgress.completed}/{catProgress.total} erledigt
</div>
</button>
)
})}
</div>
{/* Filters & Search */}
<div className="flex flex-wrap gap-4 mb-6">
<div className="flex-1 min-w-[200px]">
<input
type="text"
placeholder="Suchen..."
value={backlog.searchQuery}
onChange={(e) => backlog.setSearchQuery(e.target.value)}
className="w-full px-4 py-2 border border-slate-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500"
/>
</div>
<select
value={backlog.selectedPriority || ''}
onChange={(e) => backlog.setSelectedPriority(e.target.value || null)}
className="px-4 py-2 border border-slate-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500"
>
<option value="">Alle Prioritaeten</option>
<option value="critical">Kritisch</option>
<option value="high">Hoch</option>
<option value="medium">Mittel</option>
<option value="low">Niedrig</option>
</select>
{(backlog.selectedCategory || backlog.selectedPriority || backlog.searchQuery) && (
<button
onClick={backlog.clearFilters}
className="px-4 py-2 text-sm text-slate-600 hover:text-slate-900"
>
Filter zuruecksetzen
</button>
)}
</div>
{/* Backlog Items */}
<div className="space-y-4">
{backlog.filteredItems.map((item) => {
const category = backlog.categories.find((c) => c.id === item.category)
return (
<BacklogItemCard
key={item.id}
item={item}
category={category}
isExpanded={backlog.expandedItems.has(item.id)}
onToggleExpand={() => backlog.toggleExpand(item.id)}
onUpdateStatus={(status) => backlog.updateItemStatus(item.id, status)}
onToggleSubtask={(subtaskId) => backlog.toggleSubtask(item.id, subtaskId)}
/>
)
})}
</div>
{backlog.filteredItems.length === 0 && (
<div className="text-center py-12 text-slate-500">
Keine Aufgaben gefunden. Versuche einen anderen Filter.
</div>
)}
{/* Info Box */}
<div className="mt-8 bg-amber-50 border border-amber-200 rounded-xl p-6">
<div className="flex items-start gap-4">
<svg
className="w-6 h-6 text-amber-600 flex-shrink-0 mt-0.5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
/>
</svg>
<div>
<h3 className="font-semibold text-amber-900">Wichtiger Hinweis</h3>
<p className="text-sm text-amber-800 mt-1">
Diese Backlog-Liste muss vollstaendig abgearbeitet sein, bevor BreakPilot in den
Produktivbetrieb gehen kann. Alle kritischen Items muessen abgeschlossen sein.
Der Fortschritt wird lokal im Browser gespeichert.
</p>
</div>
</div>
</div>
</AdminLayout>
)
}