Some checks failed
Test Suite / pytest-backend (push) Failing after 2s
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 3s
Test Suite / compose-smoke (push) Has been skipped
Deploy Development / deploy (push) Failing after 50s
Method-Profiles-API und Auswahl beim Anlegen/Profil; Steuerungs-Meta in Listen und Plan; Projekt-Archetyp-Spiegel, Next-Action-Links und Umlaut-Fix fuer testbare Guidance. Co-authored-by: Cursor <cursoragent@cursor.com>
88 lines
2.9 KiB
JavaScript
88 lines
2.9 KiB
JavaScript
import { useNavigate } from 'react-router-dom'
|
|
import { useState } from 'react'
|
|
import { useCapabilities } from '../hooks/useCapabilities.js'
|
|
import { getWidgetsForArea } from '../registry/widgetRegistry.js'
|
|
import { useSession } from '../context/SessionContext.jsx'
|
|
import { InitiativeForm } from '../components/InitiativeForm.jsx'
|
|
import { createInitiative } from '../api/initiatives.js'
|
|
import { saveInitiativeDynamicFields, splitInitiativeFormPayload } from '../api/entityFields.js'
|
|
import { scopedPath } from '../utils/routes.js'
|
|
import { Link } from 'react-router-dom'
|
|
|
|
export function WorkspacePage() {
|
|
const navigate = useNavigate()
|
|
const { context } = useSession()
|
|
const { capabilities, hasCapability } = useCapabilities()
|
|
const widgets = getWidgetsForArea('workspace', capabilities)
|
|
const [showForm, setShowForm] = useState(false)
|
|
const [formBusy, setFormBusy] = useState(false)
|
|
const [formError, setFormError] = useState(null)
|
|
|
|
async function handleCreateInitiative(payload) {
|
|
setFormBusy(true)
|
|
setFormError(null)
|
|
const { core, dynamicFields } = splitInitiativeFormPayload(payload)
|
|
try {
|
|
const created = await createInitiative({
|
|
...core,
|
|
owner_actor_id: context?.actor?.id,
|
|
})
|
|
await saveInitiativeDynamicFields(created.id, dynamicFields)
|
|
setShowForm(false)
|
|
navigate(scopedPath('/plan/profile', { initiativeId: created.id }))
|
|
} catch (err) {
|
|
setFormError(err.message)
|
|
} finally {
|
|
setFormBusy(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="app-page">
|
|
<header className="page-header">
|
|
<div>
|
|
<h1>Workspace</h1>
|
|
<p className="page-lead">Portfolio-Überblick und nächste Schritte über alle Vorhaben.</p>
|
|
</div>
|
|
{hasCapability('kairo.initiative.manage') && (
|
|
<button
|
|
type="button"
|
|
className="btn btn-primary btn-block-mobile"
|
|
onClick={() => setShowForm((v) => !v)}
|
|
>
|
|
{showForm ? 'Abbrechen' : 'Vorhaben anlegen'}
|
|
</button>
|
|
)}
|
|
</header>
|
|
|
|
{showForm && (
|
|
<section className="card inline-form-card">
|
|
<h2 className="card-title card-title--lg">Neues Vorhaben</h2>
|
|
{formError && <p className="error">{formError}</p>}
|
|
<InitiativeForm
|
|
onSubmit={handleCreateInitiative}
|
|
onCancel={() => setShowForm(false)}
|
|
busy={formBusy}
|
|
submitLabel="Vorhaben anlegen"
|
|
/>
|
|
</section>
|
|
)}
|
|
|
|
<div className="widget-grid">
|
|
{widgets.map((widget) => {
|
|
const Component = widget.component
|
|
return <Component key={widget.key} />
|
|
})}
|
|
</div>
|
|
|
|
{hasCapability('kairo.initiative.read') && (
|
|
<p className="page-footer-link">
|
|
<Link to="/initiatives" className="link-inline">
|
|
Zur Vorhabenliste →
|
|
</Link>
|
|
</p>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|