Add delete functionality for training plan templates
All checks were successful
Deploy Development / deploy (push) Successful in 39s
Test Suite / pytest-backend (push) Successful in 36s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 12s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Successful in 1m22s

This commit is contained in:
Lars 2026-05-16 07:45:53 +02:00
parent c3eb5a62c4
commit e441f59bff
2 changed files with 89 additions and 0 deletions

View File

@ -658,6 +658,29 @@ function TrainingPlanningPageRoot() {
}
}
const handleDeletePlanTemplate = useCallback(
async (tpl) => {
if (!tpl?.id) return
const label = (tpl.name || '').trim() || `Vorlage #${tpl.id}`
if (
!window.confirm(
`Trainingsvorlage „${label}“ wirklich löschen? Die Aktion kann nicht rückgängig gemacht werden.`
)
) {
return
}
try {
await api.deleteTrainingPlanTemplate(tpl.id)
setDraftPlanTemplateId((prev) => (String(prev) === String(tpl.id) ? '' : prev))
await loadPlanTemplates()
toast.success('Vorlage gelöscht.')
} catch (err) {
toast.error(err.message || 'Löschen fehlgeschlagen')
}
},
[loadPlanTemplates, toast]
)
const openModuleApplyModal = useCallback(async (placement) => {
setModuleApplyErr('')
setModuleApplySearchQuery('')
@ -1924,6 +1947,7 @@ function TrainingPlanningPageRoot() {
draftPlanTemplateId={draftPlanTemplateId}
onDraftTemplateSelect={applyTemplateFromSelect}
planTemplates={planTemplates}
onDeletePlanTemplate={handleDeletePlanTemplate}
clubDirectory={clubDirectory}
clubDirectoryForCo={clubDirectoryForCo}
planningModalClubId={planningModalClubId}

View File

@ -18,6 +18,7 @@ export default function TrainingPlanningUnitFormModal({
draftPlanTemplateId,
onDraftTemplateSelect,
planTemplates,
onDeletePlanTemplate,
clubDirectory,
clubDirectoryForCo,
planningModalClubId,
@ -129,6 +130,70 @@ export default function TrainingPlanningUnitFormModal({
</div>
)}
{planTemplates.length > 0 && typeof onDeletePlanTemplate === 'function' ? (
<details
className="card"
style={{
marginBottom: '1.35rem',
padding: '12px 14px',
background: 'var(--surface2)',
border: '1px solid var(--border)',
}}
>
<summary style={{ cursor: 'pointer', fontWeight: 600, color: 'var(--text1)' }}>
Gespeicherte Vorlagen löschen
</summary>
<p style={{ margin: '0.65rem 0 0.75rem', fontSize: '0.82rem', color: 'var(--text2)', lineHeight: 1.45 }}>
Du kannst eigene Vorlagen entfernen. Plattform-Admins dürfen auch fremde Vorlagen löschen. Einheiten, die
noch auf eine Vorlage verweisen, behalten ihren Ablauf; die Verknüpfung zur Vorlage wird vom Server
entfernt.
</p>
<ul style={{ listStyle: 'none', margin: 0, padding: 0 }}>
{planTemplates.map((t, ti) => {
const roleLc = String(user?.role || '').toLowerCase()
const isPlatformAdmin = roleLc === 'admin' || roleLc === 'superadmin'
const canDel =
user &&
(isPlatformAdmin || Number(t.created_by) === Number(user.id))
return (
<li
key={t.id}
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
gap: '10px',
padding: '8px 0',
borderTop: ti === 0 ? 'none' : '1px solid var(--border)',
}}
>
<span style={{ minWidth: 0, flex: 1, fontSize: '0.9rem' }}>
<strong style={{ color: 'var(--text1)' }}>{t.name}</strong>
{typeof t.sections_count === 'number' ? (
<span style={{ fontSize: '0.82rem', color: 'var(--text2)', marginLeft: '6px' }}>
· {t.sections_count} Abschn.
</span>
) : null}
</span>
{canDel ? (
<button
type="button"
className="btn btn-danger"
style={{ flexShrink: 0, padding: '6px 12px', fontSize: '0.82rem' }}
onClick={() => onDeletePlanTemplate(t)}
>
Löschen
</button>
) : (
<span style={{ fontSize: '0.78rem', color: 'var(--text3)', flexShrink: 0 }}>nur Lesen</span>
)}
</li>
)
})}
</ul>
</details>
) : null}
<form onSubmit={onSubmit}>
<h3 style={{ marginBottom: '1rem' }}>Planung</h3>