Some checks failed
Deploy Development / deploy (push) Successful in 47s
Test Suite / pytest-backend (push) Failing after 1m46s
Test Suite / k6 /api/health Baseline (push) Has been skipped
Test Suite / playwright-smoke (push) Has been skipped
Test Suite / lint-backend (push) Successful in 2s
Test Suite / compose-smoke (push) Has been skipped
Ersetzt die Vorhaben-Tab-Navigation durch Cockpit/Ausführen/Planen/Kontrolle/Team, Deep Links für APs/Projekte/Gates und Programm-Scope im Header. Co-authored-by: Cursor <cursoragent@cursor.com>
63 lines
1.8 KiB
JavaScript
63 lines
1.8 KiB
JavaScript
import { Link, useLocation } from 'react-router-dom'
|
|
import { useEffect, useState } from 'react'
|
|
import { listInitiatives } from '../api/initiatives.js'
|
|
import { useProgramScope } from '../context/ProgramScopeContext.jsx'
|
|
import { LoadingState } from './LoadingState.jsx'
|
|
import { scopedPath } from '../utils/routes.js'
|
|
|
|
export function RequireInitiativeScope({ children, lead }) {
|
|
const location = useLocation()
|
|
const { initiativeId, applyFromInitiative } = useProgramScope()
|
|
const [initiatives, setInitiatives] = useState(null)
|
|
const basePath = location.pathname.replace(/\/$/, '') || location.pathname
|
|
|
|
useEffect(() => {
|
|
if (initiativeId) return
|
|
let cancelled = false
|
|
listInitiatives()
|
|
.then((data) => {
|
|
if (!cancelled) setInitiatives(data)
|
|
})
|
|
.catch(() => {
|
|
if (!cancelled) setInitiatives([])
|
|
})
|
|
return () => {
|
|
cancelled = true
|
|
}
|
|
}, [initiativeId])
|
|
|
|
if (initiativeId) {
|
|
return children
|
|
}
|
|
|
|
if (initiatives === null) {
|
|
return <LoadingState message="Lade Vorhaben …" />
|
|
}
|
|
|
|
return (
|
|
<section className="card scope-picker">
|
|
<h2 className="card-title">Vorhaben wählen</h2>
|
|
<p className="page-lead">
|
|
{lead || 'Dieser Modus braucht ein Vorhaben als Scope-Filter.'}
|
|
</p>
|
|
{initiatives.length === 0 ? (
|
|
<p className="muted">Noch keine Vorhaben angelegt.</p>
|
|
) : (
|
|
<ul className="scope-picker__list">
|
|
{initiatives.map((item) => (
|
|
<li key={item.id}>
|
|
<Link
|
|
to={scopedPath(basePath, { initiativeId: item.id })}
|
|
className="scope-picker__link"
|
|
onClick={() => applyFromInitiative(item.id)}
|
|
>
|
|
{item.title}
|
|
</Link>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
)}
|
|
</section>
|
|
)
|
|
}
|