feat: implement mobile and desktop layouts for framework editing
- Added responsive design for the framework editing page, including mobile tabs and a grid layout for goals and slots on desktop. - Introduced state management for tab selection and layout detection based on screen size. - Enhanced user interface with a tabbed navigation system for better organization of content. - Updated styles in app.css to support new layout features and improve overall aesthetics.
This commit is contained in:
parent
17f0513821
commit
eade9af2fe
|
|
@ -2713,6 +2713,71 @@ a.analysis-split__nav-item {
|
|||
accent-color: var(--accent);
|
||||
}
|
||||
|
||||
/* Rahmenprogramm bearbeiten — Mobile Tabs, Desktop Ziele | Slots nebeneinander */
|
||||
.framework-edit {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.framework-edit {
|
||||
max-width: min(1200px, 100%);
|
||||
}
|
||||
.framework-edit__tabbar {
|
||||
display: none !important;
|
||||
}
|
||||
.framework-edit__goals-slots {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
}
|
||||
/* breit: alle Bereiche sichtbar */
|
||||
.framework-edit__panel {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
.framework-edit__tabbar {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
margin-bottom: 14px;
|
||||
padding: 2px 0 12px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.framework-edit__tabbar::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.framework-edit__tab {
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
padding: 10px 8px;
|
||||
border: 1px solid var(--border2);
|
||||
border-radius: 10px;
|
||||
background: var(--surface2);
|
||||
color: var(--text2);
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
font-family: var(--font);
|
||||
}
|
||||
.framework-edit__tab--active {
|
||||
background: var(--accent-light);
|
||||
color: var(--accent-dark);
|
||||
border-color: var(--accent);
|
||||
}
|
||||
.framework-edit__goals-slots {
|
||||
display: block;
|
||||
}
|
||||
@media (max-width: 1023px) {
|
||||
.framework-edit .framework-edit__panel:not(.framework-edit__panel--active) {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
.desktop-sidebar,
|
||||
.bottom-nav,
|
||||
|
|
|
|||
|
|
@ -175,6 +175,19 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
const [units, setUnits] = useState([])
|
||||
const [pickerSlotIdx, setPickerSlotIdx] = useState(null)
|
||||
const [peekId, setPeekId] = useState(null)
|
||||
/** 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
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const mq = window.matchMedia('(min-width: 1024px)')
|
||||
const apply = () => setDesktopLayout(!!mq.matches)
|
||||
apply()
|
||||
mq.addEventListener('change', apply)
|
||||
return () => mq.removeEventListener('change', apply)
|
||||
}, [])
|
||||
|
||||
const loadMeta = useCallback(async () => {
|
||||
try {
|
||||
|
|
@ -429,6 +442,8 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
}
|
||||
}
|
||||
|
||||
const panelActive = (key) => desktopLayout || frameworkTab === key
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div style={{ padding: '2rem', textAlign: 'center' }}>
|
||||
|
|
@ -440,16 +455,53 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
|
||||
return (
|
||||
<div style={{ padding: '2rem' }}>
|
||||
<div style={{ maxWidth: '800px', margin: '0 auto' }}>
|
||||
<div className="framework-edit">
|
||||
<p style={{ marginBottom: '0.75rem' }}>
|
||||
<Link to="/planning/framework-programs" style={{ color: 'var(--accent-dark)' }}>
|
||||
← Alle Rahmenprogramme
|
||||
</Link>
|
||||
</p>
|
||||
|
||||
<h1 style={{ marginBottom: '1rem' }}>{isNew ? 'Neues Rahmenprogramm' : 'Rahmenprogramm bearbeiten'}</h1>
|
||||
<h1 style={{ marginBottom: '0.75rem' }}>{isNew ? 'Neues Rahmenprogramm' : 'Rahmenprogramm bearbeiten'}</h1>
|
||||
|
||||
<div className="card" style={{ marginBottom: '1rem' }}>
|
||||
<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.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="framework-edit__tabbar" role="tablist" aria-label="Bereiche">
|
||||
{[
|
||||
{ id: 'meta', label: 'Stammdaten' },
|
||||
{ id: 'goals', label: 'Ziele' },
|
||||
{ id: 'slots', label: 'Slots & Übungen' },
|
||||
].map((t) => (
|
||||
<button
|
||||
key={t.id}
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={frameworkTab === t.id}
|
||||
className={'framework-edit__tab' + (frameworkTab === t.id ? ' framework-edit__tab--active' : '')}
|
||||
onClick={() => setFrameworkTab(t.id)}
|
||||
>
|
||||
{t.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={
|
||||
'framework-edit__panel framework-edit__panel--meta card' +
|
||||
(panelActive('meta') ? ' framework-edit__panel--active' : '')
|
||||
}
|
||||
style={{ marginBottom: '1rem' }}
|
||||
>
|
||||
<h3 className="card-title">Stammdaten</h3>
|
||||
<div className="form-row">
|
||||
<label className="form-label">Titel *</label>
|
||||
|
|
@ -555,7 +607,14 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="card" style={{ marginBottom: '1rem' }}>
|
||||
<div className="framework-edit__goals-slots">
|
||||
<div
|
||||
className={
|
||||
'framework-edit__panel framework-edit__panel--goals card' +
|
||||
(panelActive('goals') ? ' framework-edit__panel--active' : '')
|
||||
}
|
||||
style={{ marginBottom: '1rem' }}
|
||||
>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.75rem' }}>
|
||||
<h3 className="card-title" style={{ marginBottom: 0 }}>
|
||||
Entwicklungsziele
|
||||
|
|
@ -617,7 +676,13 @@ export default function TrainingFrameworkProgramEditPage() {
|
|||
))}
|
||||
</div>
|
||||
|
||||
<div className="card" style={{ marginBottom: '1.5rem' }}>
|
||||
<div
|
||||
className={
|
||||
'framework-edit__panel framework-edit__panel--slots card' +
|
||||
(panelActive('slots') ? ' framework-edit__panel--active' : '')
|
||||
}
|
||||
style={{ marginBottom: '1.5rem' }}
|
||||
>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '0.75rem' }}>
|
||||
<h3 className="card-title" style={{ marginBottom: 0 }}>
|
||||
Session‑Slots & Übungen
|
||||
|
|
@ -779,6 +844,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}>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export const PAGE_VERSIONS = {
|
|||
SkillsPage: "1.0.0",
|
||||
TrainingPlanningPage: "1.3.1",
|
||||
TrainingFrameworkProgramsListPage: "1.0.0",
|
||||
TrainingFrameworkProgramEditPage: "1.0.1",
|
||||
TrainingFrameworkProgramEditPage: "1.1.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