2026-07-05 15:11:15 +02:00
|
|
|
import { useState } from 'react'
|
|
|
|
|
import { StatusBadge } from './StatusBadge.jsx'
|
|
|
|
|
import { PriorityBadge } from './PriorityBadge.jsx'
|
|
|
|
|
import { EmptyState } from './EmptyState.jsx'
|
2026-07-09 11:26:48 +02:00
|
|
|
import { Modal } from './Modal.jsx'
|
|
|
|
|
import { BacklogItemForm } from './BacklogItemForm.jsx'
|
|
|
|
|
import { gateTitleById } from './GateSelect.jsx'
|
2026-07-06 08:43:11 +02:00
|
|
|
|
2026-07-05 15:11:15 +02:00
|
|
|
export function BacklogSection({
|
|
|
|
|
items,
|
2026-07-06 08:43:11 +02:00
|
|
|
roadmapItems = [],
|
2026-07-05 15:11:15 +02:00
|
|
|
canManage,
|
|
|
|
|
onCreate,
|
2026-07-09 11:26:48 +02:00
|
|
|
onUpdate,
|
2026-07-05 15:11:15 +02:00
|
|
|
onConvert,
|
|
|
|
|
onDelete,
|
|
|
|
|
busy,
|
|
|
|
|
}) {
|
2026-07-09 11:26:48 +02:00
|
|
|
const [modalMode, setModalMode] = useState(null)
|
|
|
|
|
|
|
|
|
|
function closeModal() {
|
|
|
|
|
setModalMode(null)
|
|
|
|
|
}
|
2026-07-05 15:11:15 +02:00
|
|
|
|
2026-07-09 11:26:48 +02:00
|
|
|
async function handleCreateSubmit(payload) {
|
2026-07-06 08:43:11 +02:00
|
|
|
await onCreate({
|
2026-07-09 11:26:48 +02:00
|
|
|
title: payload.title,
|
|
|
|
|
description: payload.description,
|
|
|
|
|
priority: payload.priority,
|
|
|
|
|
roadmap_item_id: payload.roadmap_item_id,
|
|
|
|
|
status: payload.status || 'new',
|
|
|
|
|
})
|
|
|
|
|
closeModal()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleEditSubmit(payload) {
|
|
|
|
|
if (!modalMode?.item) return
|
|
|
|
|
const ok = await onUpdate(modalMode.item.id, {
|
|
|
|
|
title: payload.title,
|
|
|
|
|
description: payload.description,
|
|
|
|
|
status: payload.status,
|
|
|
|
|
priority: payload.priority,
|
|
|
|
|
roadmap_item_id: payload.roadmap_item_id,
|
|
|
|
|
clear_roadmap_item: payload.clear_roadmap_item,
|
2026-07-06 08:43:11 +02:00
|
|
|
})
|
2026-07-09 11:26:48 +02:00
|
|
|
if (ok !== false) closeModal()
|
2026-07-05 15:11:15 +02:00
|
|
|
}
|
|
|
|
|
|
2026-07-09 11:26:48 +02:00
|
|
|
const modalTitle =
|
|
|
|
|
modalMode?.kind === 'create' ? 'Backlog-Item anlegen' : 'Backlog-Item bearbeiten'
|
|
|
|
|
|
2026-07-05 15:11:15 +02:00
|
|
|
return (
|
|
|
|
|
<section className="card">
|
|
|
|
|
<div className="section-header">
|
|
|
|
|
<h2>Backlog</h2>
|
|
|
|
|
{canManage && (
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
className="btn btn-primary btn-block-mobile"
|
2026-07-09 11:26:48 +02:00
|
|
|
onClick={() => setModalMode({ kind: 'create' })}
|
2026-07-05 15:11:15 +02:00
|
|
|
>
|
2026-07-09 11:26:48 +02:00
|
|
|
Backlog-Item
|
2026-07-05 15:11:15 +02:00
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{items.length === 0 && <EmptyState message="Backlog ist leer." />}
|
|
|
|
|
|
|
|
|
|
<ul className="item-list">
|
|
|
|
|
{items.map((item) => (
|
|
|
|
|
<li key={item.id} className="list-item card-list-item">
|
2026-07-09 11:26:48 +02:00
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
className="list-item-main list-item-main--clickable"
|
|
|
|
|
onClick={() => canManage && setModalMode({ kind: 'edit', item })}
|
|
|
|
|
disabled={!canManage}
|
|
|
|
|
>
|
2026-07-05 15:11:15 +02:00
|
|
|
<strong>{item.title}</strong>
|
|
|
|
|
{item.description && (
|
|
|
|
|
<p className="list-item-desc">{item.description}</p>
|
|
|
|
|
)}
|
2026-07-06 08:43:11 +02:00
|
|
|
{item.roadmap_item_id && (
|
|
|
|
|
<p className="list-item-sub muted">
|
|
|
|
|
Gate: {gateTitleById(roadmapItems, item.roadmap_item_id) || item.roadmap_item_id}
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
2026-07-09 11:26:48 +02:00
|
|
|
</button>
|
2026-07-05 15:11:15 +02:00
|
|
|
<div className="list-item-meta action-controls">
|
|
|
|
|
<StatusBadge kind="backlog" status={item.status} />
|
|
|
|
|
<PriorityBadge priority={item.priority} />
|
|
|
|
|
{canManage && item.status !== 'converted' && (
|
|
|
|
|
<>
|
|
|
|
|
{item.status === 'accepted' && (
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
2026-07-09 11:26:48 +02:00
|
|
|
className="btn btn-primary btn-sm"
|
2026-07-05 15:11:15 +02:00
|
|
|
onClick={() => onConvert(item.id)}
|
|
|
|
|
disabled={busy}
|
|
|
|
|
>
|
|
|
|
|
In Maßnahme umwandeln
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
2026-07-09 11:26:48 +02:00
|
|
|
className="btn btn-secondary btn-sm"
|
|
|
|
|
onClick={() => setModalMode({ kind: 'edit', item })}
|
|
|
|
|
disabled={busy}
|
|
|
|
|
>
|
|
|
|
|
Bearbeiten
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
className="btn btn-secondary btn-sm"
|
2026-07-05 15:11:15 +02:00
|
|
|
onClick={() => onDelete(item.id)}
|
|
|
|
|
>
|
|
|
|
|
Löschen
|
|
|
|
|
</button>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</li>
|
|
|
|
|
))}
|
|
|
|
|
</ul>
|
2026-07-09 11:26:48 +02:00
|
|
|
|
|
|
|
|
<Modal open={Boolean(modalMode)} title={modalTitle} onClose={closeModal}>
|
|
|
|
|
{modalMode?.kind === 'create' && (
|
|
|
|
|
<BacklogItemForm
|
|
|
|
|
roadmapItems={roadmapItems}
|
|
|
|
|
onSubmit={handleCreateSubmit}
|
|
|
|
|
onCancel={closeModal}
|
|
|
|
|
busy={busy}
|
|
|
|
|
submitLabel="Anlegen"
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
{modalMode?.kind === 'edit' && modalMode.item && (
|
|
|
|
|
<BacklogItemForm
|
|
|
|
|
initial={modalMode.item}
|
|
|
|
|
roadmapItems={roadmapItems}
|
|
|
|
|
onSubmit={handleEditSubmit}
|
|
|
|
|
onCancel={closeModal}
|
|
|
|
|
busy={busy}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</Modal>
|
2026-07-05 15:11:15 +02:00
|
|
|
</section>
|
|
|
|
|
)
|
|
|
|
|
}
|