feat: update layout and styles for TrainingFrameworkProgramEditPage
- Adjusted responsive design breakpoints for mobile and desktop views in app.css. - Introduced a new horizontal layout for slots in the framework editor, enhancing usability on wider screens. - Updated versioning for TrainingFrameworkProgramEditPage to 1.2.0 to reflect recent changes. - Improved tab visibility and layout management based on screen size in TrainingFrameworkProgramEditPage.jsx. - Enhanced user guidance in TrainingFrameworkProgramsListPage with additional context on layout behavior.
This commit is contained in:
parent
eade9af2fe
commit
88fc9d9ba5
|
|
@ -2713,12 +2713,12 @@ a.analysis-split__nav-item {
|
|||
accent-color: var(--accent);
|
||||
}
|
||||
|
||||
/* Rahmenprogramm bearbeiten — Mobile Tabs, Desktop Ziele | Slots nebeneinander */
|
||||
/* Rahmenprogramm bearbeiten — Mobile Tabs, Desktop Ziele | Slots nebeneinander (synchron zu FRAMEWORK_DESKTOP_MIN_PX im Editor) */
|
||||
.framework-edit {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
@media (min-width: 900px) {
|
||||
.framework-edit {
|
||||
max-width: min(1200px, 100%);
|
||||
}
|
||||
|
|
@ -2772,12 +2772,42 @@ a.analysis-split__nav-item {
|
|||
.framework-edit__goals-slots {
|
||||
display: block;
|
||||
}
|
||||
@media (max-width: 1023px) {
|
||||
@media (max-width: 899px) {
|
||||
.framework-edit .framework-edit__panel:not(.framework-edit__panel--active) {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Rahmen-Editor: Slots (= Session‑Spalten) horizontal, scrollbar */
|
||||
.framework-slots-board {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
gap: 12px;
|
||||
align-items: stretch;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
padding: 4px 2px 12px;
|
||||
margin: 0 -4px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scroll-snap-type: x proximity;
|
||||
}
|
||||
.framework-slots-board .framework-slot-card {
|
||||
flex: 0 0 min(320px, calc(100vw - 48px));
|
||||
min-width: min(320px, calc(100vw - 48px));
|
||||
max-height: min(70vh, 720px);
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
scroll-snap-align: start;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@media (min-width: 900px) {
|
||||
.framework-slots-board .framework-slot-card {
|
||||
flex-basis: 300px;
|
||||
min-width: 280px;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
.desktop-sidebar,
|
||||
.bottom-nav,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import api from '../utils/api'
|
|||
import ExercisePickerModal from '../components/ExercisePickerModal'
|
||||
import ExercisePeekModal from '../components/ExercisePeekModal'
|
||||
|
||||
/** Unter dieser Breite: Registerkarten; darüber: Ziele | Slots nebeneinander (muss zu app.css passen) */
|
||||
const FRAMEWORK_DESKTOP_MIN_PX = 900
|
||||
|
||||
function emptyGoal() {
|
||||
return { title: '', notes: '' }
|
||||
}
|
||||
|
|
@ -178,11 +181,13 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
/** Nur schmal: welcher Block sichtbar — Desktop zeigt Stammdaten + zwei Spalten Ziele|Slots */
|
||||
const [frameworkTab, setFrameworkTab] = useState('meta')
|
||||
const [desktopLayout, setDesktopLayout] = useState(
|
||||
typeof window !== 'undefined' ? window.matchMedia('(min-width: 1024px)').matches : false
|
||||
typeof window !== 'undefined'
|
||||
? window.matchMedia(`(min-width: ${FRAMEWORK_DESKTOP_MIN_PX}px)`).matches
|
||||
: false
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const mq = window.matchMedia('(min-width: 1024px)')
|
||||
const mq = window.matchMedia(`(min-width: ${FRAMEWORK_DESKTOP_MIN_PX}px)`)
|
||||
const apply = () => setDesktopLayout(!!mq.matches)
|
||||
apply()
|
||||
mq.addEventListener('change', apply)
|
||||
|
|
@ -444,6 +449,10 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
|
||||
const panelActive = (key) => desktopLayout || frameworkTab === key
|
||||
|
||||
/** Schmale Ansicht: Sichtbarkeit per Inline (falls globales CSS nicht greift / altes Bundle) */
|
||||
const panelVisibilityStyle = (key) =>
|
||||
desktopLayout ? undefined : { display: panelActive(key) ? 'block' : 'none' }
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div style={{ padding: '2rem', textAlign: 'center' }}>
|
||||
|
|
@ -467,16 +476,38 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
<div className="card" style={{ marginBottom: '1rem', background: 'var(--surface2)', borderStyle: 'dashed' }}>
|
||||
<p style={{ fontSize: '0.88rem', color: 'var(--text2)', lineHeight: 1.55, margin: 0 }}>
|
||||
<strong style={{ color: 'var(--text1)' }}>Stand dieser Funktion:</strong> Der Rahmen speichert Ziele, Slots
|
||||
und Übungslisten — noch <strong>ohne</strong> die feinere{' '}
|
||||
<strong>Trainingsplan‑Struktur pro Einheit</strong> (Abschnitte wie in der Einheitenplanung) und{' '}
|
||||
<strong>ohne Übernahme</strong> in die nächste konkrete Trainingseinheit (geplanter Schritt „Warenkorb“).
|
||||
<strong> Ziele</strong> lassen sich noch nicht einzelnen Einheiten oder Übungen zuordnen;{' '}
|
||||
<strong>Progressionsketten</strong> aus dem Übungs‑Graph sind hier noch nicht eingebunden — dafür sind
|
||||
API‑/Daten‑Erweiterungen und ein Folgerelease vorgesehen.
|
||||
und pro Slot eine <strong>Übungsliste</strong> (Stückliste). Eine <strong>volle Einheiten‑Struktur</strong> wie
|
||||
in der Trainingsplanung (Abschnitte, Notizen, Mikrovorlage pro Slot) ist im Konzept optional (
|
||||
<strong>CURR‑010</strong>: <code>training_plan_template_id</code> pro Slot) — in der DB derzeit{' '}
|
||||
<strong>noch nicht</strong> umgesetzt.{' '}
|
||||
<strong>Übernahme</strong> in konkrete Trainingseinheiten mit Referenz auf den Rahmen (Kopie, editierbar){' '}
|
||||
ist <strong>Stufe 3 / Lineage</strong> vorgesehen. Die Slot‑Spalten unten sind die geplanten
|
||||
Session‑Positionen <strong>ohne feste Termine</strong> am Rahmen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="framework-edit__tabbar" role="tablist" aria-label="Bereiche">
|
||||
<div
|
||||
className="framework-edit__tabbar"
|
||||
role="tablist"
|
||||
aria-label="Bereiche"
|
||||
style={
|
||||
desktopLayout
|
||||
? { display: 'none' }
|
||||
: {
|
||||
display: 'flex',
|
||||
gap: 6,
|
||||
marginBottom: 14,
|
||||
padding: '6px 0 12px',
|
||||
borderBottom: '2px solid var(--accent)',
|
||||
flexWrap: 'nowrap',
|
||||
overflowX: 'auto',
|
||||
position: 'sticky',
|
||||
top: 0,
|
||||
zIndex: 6,
|
||||
background: 'var(--bg)',
|
||||
}
|
||||
}
|
||||
>
|
||||
{[
|
||||
{ id: 'meta', label: 'Stammdaten' },
|
||||
{ id: 'goals', label: 'Ziele' },
|
||||
|
|
@ -500,7 +531,7 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
'framework-edit__panel framework-edit__panel--meta card' +
|
||||
(panelActive('meta') ? ' framework-edit__panel--active' : '')
|
||||
}
|
||||
style={{ marginBottom: '1rem' }}
|
||||
style={{ marginBottom: '1rem', ...(panelVisibilityStyle('meta') || {}) }}
|
||||
>
|
||||
<h3 className="card-title">Stammdaten</h3>
|
||||
<div className="form-row">
|
||||
|
|
@ -607,13 +638,25 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="framework-edit__goals-slots">
|
||||
<div
|
||||
className="framework-edit__goals-slots"
|
||||
style={
|
||||
desktopLayout
|
||||
? {
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '1fr 1fr',
|
||||
gap: 16,
|
||||
alignItems: 'start',
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<div
|
||||
className={
|
||||
'framework-edit__panel framework-edit__panel--goals card' +
|
||||
(panelActive('goals') ? ' framework-edit__panel--active' : '')
|
||||
}
|
||||
style={{ marginBottom: '1rem' }}
|
||||
style={{ marginBottom: '1rem', ...(panelVisibilityStyle('goals') || {}) }}
|
||||
>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.75rem' }}>
|
||||
<h3 className="card-title" style={{ marginBottom: 0 }}>
|
||||
|
|
@ -681,7 +724,7 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
'framework-edit__panel framework-edit__panel--slots card' +
|
||||
(panelActive('slots') ? ' framework-edit__panel--active' : '')
|
||||
}
|
||||
style={{ marginBottom: '1.5rem' }}
|
||||
style={{ marginBottom: '1.5rem', ...(panelVisibilityStyle('slots') || {}) }}
|
||||
>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.75rem' }}>
|
||||
<h3 className="card-title" style={{ marginBottom: 0 }}>
|
||||
|
|
@ -694,15 +737,21 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
|
||||
{form.slots.length === 0 ? (
|
||||
<p style={{ color: 'var(--text2)', fontSize: '0.9rem' }}>
|
||||
Noch keine Slots — mit <strong>+ Slot</strong> legst du z. B. „Woche 1 / Einheit A“ an und ordnest Übungen zu.
|
||||
Noch keine Slots — mit <strong>+ Slot</strong> legst du Einheiten‑Spalten an (z. B. „Woche 1“, „Einheit
|
||||
A“) und ordnest Übungen zu. Spalten kannst du horizontal scrollen.
|
||||
</p>
|
||||
) : null}
|
||||
) : (
|
||||
<p style={{ fontSize: '0.8rem', color: 'var(--text3)', marginBottom: '10px' }}>
|
||||
Slots = geplante Einheiten/Sessions im Überblick — nach rechts scrollen, wenn es viele sind.
|
||||
</p>
|
||||
)}
|
||||
|
||||
<div className="framework-slots-board">
|
||||
{form.slots.map((slot, si) => (
|
||||
<div
|
||||
key={si}
|
||||
className="card"
|
||||
style={{ marginBottom: '12px', background: 'var(--surface)', borderStyle: 'dashed' }}
|
||||
className="card framework-slot-card"
|
||||
style={{ marginBottom: 0, background: 'var(--surface)', borderStyle: 'dashed' }}
|
||||
>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '6px', marginBottom: '10px' }}>
|
||||
<button type="button" className="btn btn-secondary" onClick={() => moveSlot(si, -1)}>
|
||||
|
|
@ -845,6 +894,7 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '10px', alignItems: 'center' }}>
|
||||
<button type="button" className="btn btn-primary" disabled={saving} onClick={handleSave}>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,11 @@ export default function TrainingFrameworkProgramsListPage() {
|
|||
<h1 style={{ marginBottom: '0.35rem' }}>Trainingsrahmenprogramme</h1>
|
||||
<p style={{ color: 'var(--text2)', fontSize: '0.95rem', maxWidth: '36rem' }}>
|
||||
Mehrere Entwicklungsziele und Übungen über Session‑Slots verteilen — als Vorlage in der Bibliothek oder
|
||||
im Kontext einer Gruppe.
|
||||
im Kontext einer Gruppe.{' '}
|
||||
<span style={{ color: 'var(--text3)', fontSize: '0.88rem' }}>
|
||||
In der <strong>Bearbeitungsansicht</strong> gibt es auf schmalen Fenstern Registerkarten, auf breiten
|
||||
Bildschirmen zwei Spalten (Ziele | Slots).
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<Link
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export const PAGE_VERSIONS = {
|
|||
SkillsPage: "1.0.0",
|
||||
TrainingPlanningPage: "1.3.1",
|
||||
TrainingFrameworkProgramsListPage: "1.0.0",
|
||||
TrainingFrameworkProgramEditPage: "1.1.0",
|
||||
TrainingFrameworkProgramEditPage: "1.2.0",
|
||||
TrainingUnitRunPage: "1.1.0",
|
||||
TrainingCoachPage: "1.0.0",
|
||||
AdminCatalogsPage: "2.2.0", // Updated: Frontend API Calls & Field Names für renamed tables
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user