feat(combo-planning): enhance modal UI and styling for combination planning editing
All checks were successful
Deploy Development / deploy (push) Successful in 44s
Test Suite / pytest-backend (push) Successful in 35s
Test Suite / lint-backend (push) Successful in 1s
Test Suite / build-frontend (push) Successful in 12s
Test Suite / playwright-tests (push) Successful in 58s
All checks were successful
Deploy Development / deploy (push) Successful in 44s
Test Suite / pytest-backend (push) Successful in 35s
Test Suite / lint-backend (push) Successful in 1s
Test Suite / build-frontend (push) Successful in 12s
Test Suite / playwright-tests (push) Successful in 58s
- Updated the TrainingUnitSectionsEditor to integrate new CSS classes for the combo planning modal, improving the visual consistency with the exercise preview. - Added responsive design features to the modal, including max-width and max-height adjustments for better usability on different screen sizes. - Introduced new toolbar and hint elements to enhance user interaction and provide clearer guidance within the combo planning context. - Refactored existing modal structure for improved accessibility and user experience. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a8942a9e4e
commit
ed15f73727
|
|
@ -6382,6 +6382,47 @@ a.analysis-split__nav-item {
|
|||
margin-top: 0.65rem;
|
||||
}
|
||||
|
||||
/* Kombi-Planung bearbeiten (Planungseditor): gleiches Modal-Chrome wie Übungs-Vorschau */
|
||||
.combo-planning-edit-backdrop.admin-modal-backdrop {
|
||||
z-index: 10060;
|
||||
}
|
||||
.combo-planning-edit-sheet.admin-modal-sheet {
|
||||
max-width: min(880px, calc(100vw - 24px));
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.combo-planning-edit-sheet.admin-modal-sheet {
|
||||
max-height: min(88vh, 860px);
|
||||
}
|
||||
}
|
||||
.combo-planning-edit-toolbar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.combo-planning-edit-hint {
|
||||
margin: 0 0 14px;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text2);
|
||||
line-height: 1.45;
|
||||
}
|
||||
.combo-planning-edit-card {
|
||||
margin-top: 4px;
|
||||
padding: 14px 16px 16px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--surface2);
|
||||
border-left: 4px solid var(--accent);
|
||||
}
|
||||
.combo-planning-edit-card__title {
|
||||
margin: 0 0 12px;
|
||||
font-size: 0.72rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
color: var(--text3);
|
||||
}
|
||||
|
||||
@media print {
|
||||
.desktop-sidebar,
|
||||
.bottom-nav,
|
||||
|
|
|
|||
|
|
@ -1537,134 +1537,106 @@ export default function TrainingUnitSectionsEditor({
|
|||
comboPlanningModalSX != null &&
|
||||
comboPlanningModalIX != null ? (
|
||||
<div
|
||||
className="tu-textedit-backdrop"
|
||||
className="admin-modal-backdrop combo-planning-edit-backdrop"
|
||||
role="presentation"
|
||||
onMouseDown={(e) => {
|
||||
if (e.target === e.currentTarget) setComboPlanningModal(null)
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="tu-textedit-panel tu-textedit-panel--combo-planning"
|
||||
className="admin-modal-sheet combo-planning-edit-sheet"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-labelledby="tu-combo-planning-title"
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
style={{
|
||||
maxWidth: 'min(920px, 96vw)',
|
||||
maxHeight: 'min(800px, 88vh)',
|
||||
overflow: 'auto',
|
||||
}}
|
||||
>
|
||||
<h4 id="tu-combo-planning-title" className="tu-textedit-title">
|
||||
Ablaufprofil dieser Kombination für diese Planung
|
||||
</h4>
|
||||
<p
|
||||
style={{
|
||||
margin: '0 0 0.85rem',
|
||||
fontSize: '0.82rem',
|
||||
color: 'var(--text2)',
|
||||
lineHeight: 1.45,
|
||||
}}
|
||||
>
|
||||
<strong style={{ fontWeight: 600, color: 'var(--text1)' }}>
|
||||
{(comboPlanningModalItem.exercise_title || '').trim() ||
|
||||
`Kombination #${comboPlanningModalItem.exercise_id}`}
|
||||
</strong>
|
||||
<span style={{ marginLeft: 8 }}>
|
||||
({compactComboPlanningCaption(comboPlanningModalItem)})
|
||||
</span>
|
||||
</p>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 12 }}>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary framework-ctrl framework-ctrl--xs"
|
||||
onClick={() =>
|
||||
updateItem(comboPlanningModalSX, comboPlanningModalIX, 'planning_method_profile', null)
|
||||
}
|
||||
>
|
||||
Planung wie Katalog
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary framework-ctrl framework-ctrl--xs"
|
||||
title="Bearbeitbare Kopie der Katalog-Vorgaben setzen"
|
||||
onClick={() =>
|
||||
updateItem(comboPlanningModalSX, comboPlanningModalIX, 'planning_method_profile', {
|
||||
...(comboPlanningModalItem.catalog_method_profile || {}),
|
||||
})
|
||||
}
|
||||
>
|
||||
Aus Katalog kopieren …
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
style={{
|
||||
margin: '0 0 12px',
|
||||
fontSize: '0.8rem',
|
||||
color: 'var(--text2)',
|
||||
lineHeight: 1.45,
|
||||
}}
|
||||
>
|
||||
Stationen und Einzelübungen entsprechen der Kombination im Katalog. Einzelübungen hier auszutauschen ist
|
||||
derzeit nicht vorgesehen (würde die Katalog-Übung ändern). Die Bereiche unten überschreiben nur diesen
|
||||
Termin, sofern du von den Katalogvorgaben abweichst.
|
||||
</p>
|
||||
{comboPlanningResolvedSlots.length > 0 ? (
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<CombinationPlanBracket
|
||||
methodArchetype={(comboPlanningModalItem.catalog_method_archetype || '').trim()}
|
||||
methodProfile={comboPlanningEffectiveProfile}
|
||||
combinationSlots={comboPlanningResolvedSlots}
|
||||
planningAdjusted={
|
||||
comboPlanningModalItem.planning_method_profile != null &&
|
||||
typeof comboPlanningModalItem.planning_method_profile === 'object' &&
|
||||
!Array.isArray(comboPlanningModalItem.planning_method_profile)
|
||||
}
|
||||
/>
|
||||
<div className="admin-modal-sheet__header">
|
||||
<div style={{ minWidth: 0 }}>
|
||||
<h3 id="tu-combo-planning-title" className="admin-modal-sheet__title">
|
||||
{(comboPlanningModalItem.exercise_title || '').trim() ||
|
||||
`Kombination #${comboPlanningModalItem.exercise_id}`}
|
||||
</h3>
|
||||
<p style={{ margin: '6px 0 0', fontSize: '0.82rem', color: 'var(--text2)', lineHeight: 1.4 }}>
|
||||
Planung für diesen Termin · {compactComboPlanningCaption(comboPlanningModalItem)}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<p style={{ margin: '0 0 14px', fontSize: '0.82rem', color: 'var(--text3)', lineHeight: 1.45 }}>
|
||||
Stationen werden geladen … oder die Kombination hat im Katalog keine Stationsliste.
|
||||
</p>
|
||||
)}
|
||||
<h5
|
||||
style={{
|
||||
margin: '0 0 10px',
|
||||
fontSize: '0.95rem',
|
||||
fontWeight: 700,
|
||||
color: 'var(--text1)',
|
||||
}}
|
||||
>
|
||||
Zeiten und Steuerung für diesen Termin
|
||||
</h5>
|
||||
<CombinationMethodProfileEditor
|
||||
plannerMode
|
||||
methodArchetype={(comboPlanningModalItem.catalog_method_archetype || '').trim()}
|
||||
methodProfileJson={comboPlanningProfileJsonForEditor(
|
||||
comboPlanningModalItem.catalog_method_profile || {},
|
||||
comboPlanningModalItem.planning_method_profile
|
||||
)}
|
||||
onChangeMethodProfileJson={(json) => {
|
||||
try {
|
||||
const obj = JSON.parse(json || '{}')
|
||||
if (obj && typeof obj === 'object' && !Array.isArray(obj)) {
|
||||
updateItem(comboPlanningModalSX, comboPlanningModalIX, 'planning_method_profile', obj)
|
||||
}
|
||||
} catch {
|
||||
/* Ungültiges JSON — Hinweis im Editor */
|
||||
}
|
||||
}}
|
||||
comboSlotsOutline={comboPlanningSlotsOutline}
|
||||
/>
|
||||
<div className="tu-textedit-actions" style={{ marginTop: '0.95rem', paddingTop: '0.25rem' }}>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
className="btn btn-secondary admin-modal-sheet__close"
|
||||
onClick={() => setComboPlanningModal(null)}
|
||||
>
|
||||
Schließen
|
||||
</button>
|
||||
</div>
|
||||
<div className="admin-modal-sheet__body">
|
||||
<div className="combo-planning-edit-toolbar">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary framework-ctrl framework-ctrl--xs"
|
||||
onClick={() =>
|
||||
updateItem(comboPlanningModalSX, comboPlanningModalIX, 'planning_method_profile', null)
|
||||
}
|
||||
>
|
||||
Planung wie Katalog
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-secondary framework-ctrl framework-ctrl--xs"
|
||||
title="Bearbeitbare Kopie der Katalog-Vorgaben für diese Einheit setzen"
|
||||
onClick={() =>
|
||||
updateItem(comboPlanningModalSX, comboPlanningModalIX, 'planning_method_profile', {
|
||||
...(comboPlanningModalItem.catalog_method_profile || {}),
|
||||
})
|
||||
}
|
||||
>
|
||||
Aus Katalog kopieren …
|
||||
</button>
|
||||
</div>
|
||||
<p className="combo-planning-edit-hint">
|
||||
Vorschau unten entspricht der effektiven Planung (Katalog oder Anpassung). Stationen und Einzelübungen
|
||||
kommen aus dem Katalog; hier änderst du nur Zeiten, Runden und Steuerung für diese Einheit.
|
||||
</p>
|
||||
{comboPlanningResolvedSlots.length > 0 ? (
|
||||
<div style={{ marginBottom: 18 }}>
|
||||
<CombinationPlanBracket
|
||||
methodArchetype={(comboPlanningModalItem.catalog_method_archetype || '').trim()}
|
||||
methodProfile={comboPlanningEffectiveProfile}
|
||||
combinationSlots={comboPlanningResolvedSlots}
|
||||
planningAdjusted={
|
||||
comboPlanningModalItem.planning_method_profile != null &&
|
||||
typeof comboPlanningModalItem.planning_method_profile === 'object' &&
|
||||
!Array.isArray(comboPlanningModalItem.planning_method_profile)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p style={{ margin: '0 0 18px', fontSize: '0.82rem', color: 'var(--text3)', lineHeight: 1.45 }}>
|
||||
Stationen werden geladen … oder die Kombination hat im Katalog keine Stationsliste.
|
||||
</p>
|
||||
)}
|
||||
<div className="combo-planning-edit-card">
|
||||
<h4 className="combo-planning-edit-card__title">Globale und stationsbezogene Anpassungen</h4>
|
||||
<CombinationMethodProfileEditor
|
||||
plannerMode
|
||||
methodArchetype={(comboPlanningModalItem.catalog_method_archetype || '').trim()}
|
||||
methodProfileJson={comboPlanningProfileJsonForEditor(
|
||||
comboPlanningModalItem.catalog_method_profile || {},
|
||||
comboPlanningModalItem.planning_method_profile
|
||||
)}
|
||||
onChangeMethodProfileJson={(json) => {
|
||||
try {
|
||||
const obj = JSON.parse(json || '{}')
|
||||
if (obj && typeof obj === 'object' && !Array.isArray(obj)) {
|
||||
updateItem(comboPlanningModalSX, comboPlanningModalIX, 'planning_method_profile', obj)
|
||||
}
|
||||
} catch {
|
||||
/* Ungültiges JSON — Hinweis im Editor */
|
||||
}
|
||||
}}
|
||||
comboSlotsOutline={comboPlanningSlotsOutline}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user