Kairo-Jinkendo/frontend/src/components/RoadmapPlanSection.jsx

125 lines
3.7 KiB
React
Raw Normal View History

import { useState } from 'react'
import { Link } from 'react-router-dom'
import { gatePath } from '../utils/routes.js'
import {
ROADMAP_ITEM_TYPE_LABELS,
SEQUENCING_MODE_LABELS,
} from '../constants/status.js'
import { StatusBadge } from './StatusBadge.jsx'
import { EmptyState } from './EmptyState.jsx'
import { Modal } from './Modal.jsx'
import { RoadmapItemForm } from './RoadmapItemForm.jsx'
function formatDate(value) {
if (!value) return null
try {
return new Date(value.includes('T') ? value : `${value}T12:00:00`).toLocaleDateString(
'de-DE',
)
} catch {
return value
}
}
export function RoadmapPlanSection({
initiativeId,
items,
canManage,
onCreate,
onDelete,
busy,
}) {
const [showCreate, setShowCreate] = useState(false)
async function handleCreateSubmit(payload) {
await onCreate(payload)
setShowCreate(false)
}
return (
<section className="card roadmap-plan-section">
<div className="section-header">
<div>
<h2>Zielzustände (Gates)</h2>
<p className="section-lead muted">
Überprüfbare Zielpunkte — optional. Bearbeitung und Verify auf der Gate-Detailseite,
nicht inline in der Liste.
</p>
</div>
{canManage && (
<button
type="button"
className="btn btn-primary btn-block-mobile"
onClick={() => setShowCreate(true)}
>
Plan-Element
</button>
)}
</div>
{items.length === 0 && (
<EmptyState message="Noch kein Plan — strukturiere das Vorhaben in überprüfbare Roadmap-Elemente." />
)}
<ul className="item-list milestone-list">
{items.map((item) => (
<li key={item.id} className="list-item card-list-item milestone-list-item">
<div className="list-item-main">
<strong>
{initiativeId ? (
<Link to={gatePath(item.id)} className="roadmap-plan-section__title-link">
{item.title}
</Link>
) : (
item.title
)}
</strong>
<p className="muted list-item-sub">
{ROADMAP_ITEM_TYPE_LABELS[item.item_type] || item.item_type}
{' · '}
{SEQUENCING_MODE_LABELS[item.sequencing_mode] || item.sequencing_mode}
</p>
{item.goal_description && (
<p className="list-item-desc">{item.goal_description}</p>
)}
{item.target_date && (
<p className="muted list-item-sub">
Zieltermin: {formatDate(item.target_date)}
</p>
)}
</div>
<div className="list-item-meta action-controls">
<StatusBadge kind="milestone" status={item.status} />
{initiativeId && (
<Link to={gatePath(item.id)} className="btn btn-secondary btn-sm">
Öffnen
</Link>
)}
{canManage && item.status !== 'reached' && (
<button
type="button"
className="btn btn-secondary btn-sm"
onClick={() => onDelete(item.id)}
disabled={busy}
>
Löschen
</button>
)}
</div>
</li>
))}
</ul>
<Modal open={showCreate} title="Plan-Element anlegen" onClose={() => setShowCreate(false)}>
<RoadmapItemForm
onSubmit={handleCreateSubmit}
onCancel={() => setShowCreate(false)}
busy={busy}
submitLabel="Anlegen"
mode="create"
/>
</Modal>
</section>
)
}