85 lines
2.6 KiB
JavaScript
85 lines
2.6 KiB
JavaScript
import { Link } from 'react-router-dom'
|
|
import { RECURRING_STATUS_LABELS } from '../constants/status.js'
|
|
import { EmptyState } from './EmptyState.jsx'
|
|
import { scopedPath } from '../utils/routes.js'
|
|
|
|
function formatDueAt(iso) {
|
|
if (!iso) return null
|
|
try {
|
|
return new Date(iso).toLocaleString('de-DE')
|
|
} catch {
|
|
return iso
|
|
}
|
|
}
|
|
|
|
export function RecurringRhythmPanel({
|
|
initiativeId,
|
|
recurringItems = [],
|
|
embedded = true,
|
|
}) {
|
|
const sorted = [...recurringItems].sort((a, b) => {
|
|
const statusOrder = { active: 0, paused: 1, archived: 2 }
|
|
const diff = (statusOrder[a.status] ?? 9) - (statusOrder[b.status] ?? 9)
|
|
if (diff !== 0) return diff
|
|
return (a.title || '').localeCompare(b.title || '', 'de')
|
|
})
|
|
|
|
const active = sorted.filter((item) => item.status === 'active')
|
|
|
|
const body =
|
|
sorted.length === 0 ? (
|
|
<EmptyState message="Noch keine Rhythmen — Starter-Kit oder Journey legt Übungen an." />
|
|
) : (
|
|
<>
|
|
{active.length > 0 && (
|
|
<p className="recurring-rhythm-summary muted">
|
|
{active.length} aktive Routine{active.length === 1 ? '' : 'n'} — fällige Übung steuert
|
|
Next Action.
|
|
</p>
|
|
)}
|
|
<ul className="item-list recurring-rhythm-list">
|
|
{sorted.map((item) => (
|
|
<li
|
|
key={item.id}
|
|
className={
|
|
'list-item card-list-item recurring-rhythm-item' +
|
|
(item.status === 'active' ? ' recurring-rhythm-item--active' : '')
|
|
}
|
|
>
|
|
<div className="list-item-main">
|
|
<strong>{item.title}</strong>
|
|
<span className="muted list-item-sub">
|
|
{RECURRING_STATUS_LABELS[item.status] || item.status}
|
|
{item.next_due_at ? ` · Fällig: ${formatDueAt(item.next_due_at)}` : ''}
|
|
</span>
|
|
</div>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
<p className="muted recurring-rhythm-hint">
|
|
Rhythmen pflegen unter{' '}
|
|
<Link to={scopedPath('/control/journey', { initiativeId })} className="link-inline">
|
|
Kontrolle → Journey
|
|
</Link>
|
|
.
|
|
</p>
|
|
</>
|
|
)
|
|
|
|
if (!embedded) return body
|
|
|
|
return (
|
|
<section className="card recurring-rhythm-panel">
|
|
<div className="section-header">
|
|
<div>
|
|
<h2>Rhythmen & Übungen</h2>
|
|
<p className="section-lead muted">
|
|
Aktive Routinen am Reifegrad-Pfad — Leading Next aus fälliger Übung (A1).
|
|
</p>
|
|
</div>
|
|
</div>
|
|
{body}
|
|
</section>
|
|
)
|
|
}
|