612ecec6d9
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 27s
CI / test-go-edu-search (push) Successful in 29s
CI / test-python-klausur (push) Failing after 3m18s
CI / test-python-agent-core (push) Successful in 20s
CI / test-nodejs-website (push) Successful in 23s
Frontend additions in studio-v2:
- types.ts adds TimetableSolution, TimetableLesson, SolutionStatus,
CreateTimetableSolution mirroring the Go models.
- lib/stundenplan/api.ts adds solutionsApi with list/get/create/remove/
lessons. Solve trigger is POST /timetable/solutions — school-service
forwards to the solver-service over the Docker network.
- _components/plan/SolutionList: table of past solves with status
badges, hard/soft score, Anzeigen + Loeschen buttons, and a
'Neuen Plan generieren' trigger. Auto-polls every 4 s while any
solution is pending/running, clears the interval otherwise.
- _components/plan/PlanView: Mo–Fr × period weekly grid. Three
perspectives (Klasse / Lehrer / Raum) toggleable via test-id'd
buttons; selector below lists every unique resource with at least
one lesson. Cells colour-coded by tt_subject.color.
- _components/plan/PlanHub orchestrates list + view; default tab in
page.tsx switches from 'klassen' to 'plan'.
Tests:
- mockSchoolApi helper extracted to e2e/_helpers.ts so the spec file
stays under 500 LOC. Helper now also mocks /solutions GET/POST/DELETE
and /solutions/:id/lessons; solutions kept in a closure so POST
appears in the next GET.
- 8 new tests across two suites: SolutionList empty state, list
render, completed-vs-failed Anzeigen visibility, solve trigger;
PlanView placeholder when no selection, grid render, perspective
switching.
- Existing Klassen CRUD tests now click the Klassen tab first
(Plan is the new default landing tab).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
41 lines
1.3 KiB
TypeScript
41 lines
1.3 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import { useTheme } from '@/lib/ThemeContext'
|
|
import { SolutionList } from './SolutionList'
|
|
import { PlanView } from './PlanView'
|
|
|
|
export function PlanHub() {
|
|
const { isDark } = useTheme()
|
|
const [selected, setSelected] = useState<string | null>(null)
|
|
|
|
return (
|
|
<div className="space-y-6" data-testid="plan-hub">
|
|
<SolutionList onView={setSelected} selectedId={selected} />
|
|
|
|
{selected ? (
|
|
<div className="space-y-3">
|
|
<div className="flex items-center justify-between">
|
|
<h3 className={`text-lg font-semibold ${isDark ? 'text-white' : 'text-slate-900'}`}>
|
|
Plan-Ansicht
|
|
</h3>
|
|
<button
|
|
onClick={() => setSelected(null)}
|
|
className={`text-sm ${isDark ? 'text-white/60 hover:text-white' : 'text-slate-500 hover:text-slate-900'}`}
|
|
>
|
|
Schliessen
|
|
</button>
|
|
</div>
|
|
<PlanView solutionId={selected} />
|
|
</div>
|
|
) : (
|
|
<div className={`rounded-2xl border backdrop-blur-xl p-6 text-center text-sm ${
|
|
isDark ? 'bg-white/5 border-white/10 text-white/60' : 'bg-white/80 border-black/10 text-slate-500'
|
|
}`}>
|
|
Waehle einen abgeschlossenen Plan oben, um die Wochenansicht zu sehen.
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|