Responsive Gui - partially Workflow #61

Merged
Lars merged 47 commits from develop into main 2026-04-05 11:27:44 +02:00
14 changed files with 45 additions and 18 deletions
Showing only changes of commit a639d08037 - Show all commits

View File

@ -3,7 +3,7 @@
> **Gitea:** [#30 Responsive UI](http://192.168.2.144:3000/Lars/mitai-jinkendo/issues/30) > **Gitea:** [#30 Responsive UI](http://192.168.2.144:3000/Lars/mitai-jinkendo/issues/30)
> **Spec:** `.claude/docs/functional/RESPONSIVE_UI.md` > **Spec:** `.claude/docs/functional/RESPONSIVE_UI.md`
> **Breakpoint:** `<1024px` = Mobile (Bottom-Nav, bestehendes Verhalten), `≥1024px` = Desktop (Sidebar 220px) > **Breakpoint:** `<1024px` = Mobile (Bottom-Nav, bestehendes Verhalten), `≥1024px` = Desktop (Sidebar 220px)
> **Letzte Plan-Aktualisierung:** 2026-04-04 (P5) > **Letzte Plan-Aktualisierung:** 2026-04-04 (P6; P7 Admin bewusst offen)
--- ---
@ -17,8 +17,8 @@
| P3 | Dashboard (Desktop-Grid) | ☑ erledigt | 4-spaltige Kennzahlen; Begrüßung; Ernährung/Aktivität 2-spaltig | | P3 | Dashboard (Desktop-Grid) | ☑ erledigt | 4-spaltige Kennzahlen; Begrüßung; Ernährung/Aktivität 2-spaltig |
| P4 | Verlauf (Tabs links / Content rechts) | ☑ erledigt | `History.jsx` + `.history-*` in `app.css`; Tab-State bei `location.state.tab` | | P4 | Verlauf (Tabs links / Content rechts) | ☑ erledigt | `History.jsx` + `.history-*` in `app.css`; Tab-State bei `location.state.tab` |
| P5 | Analyse (Prompts links / Ergebnis rechts) | ☑ erledigt | `Analysis.jsx` + `.analysis-split*` in `app.css` | | P5 | Analyse (Prompts links / Ergebnis rechts) | ☑ erledigt | `Analysis.jsx` + `.analysis-split*` in `app.css` |
| P6 | Erfassung / Capture & Formularseiten | ☐ pending | | | P6 | Erfassung / Capture & Formularseiten | ☑ erledigt | `.capture-page` / `.capture-page--wide` in `app.css`; CaptureHub, Wizard, GewichtZiele, Guide, Ernährung/Aktivität/Vital/Schlaf breiter |
| P7 | Admin & restliche Vollbreiten-Seiten | ☐ pending | | | P7 | Admin & restliche Vollbreiten-Seiten | ⏸ Konzeption | Layout nach Abstimmung; nicht mit P6 mitgezogen |
| P8 | Abschluss, Regression, Spec-Pflege | ☐ pending | | | P8 | Abschluss, Regression, Spec-Pflege | ☐ pending | |
**Status-Legende:** `☐ pending` · `◐ in Arbeit` · `☑ erledigt` · `⏸ blockiert` **Status-Legende:** `☐ pending` · `◐ in Arbeit` · `☑ erledigt` · `⏸ blockiert`

View File

@ -344,6 +344,25 @@ body { font-family: var(--font); background: var(--bg); color: var(--text1); -we
} }
} }
/* P6 / RESPONSIVE_UI §5.4 Erfassung: Desktop zentriert; data-lastige Seiten etwas breiter */
.capture-page {
width: 100%;
max-width: 100%;
box-sizing: border-box;
}
@media (min-width: 1024px) {
.capture-page {
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
.capture-page--wide {
max-width: 900px;
}
}
.muted { color: var(--text3); font-size: 13px; } .muted { color: var(--text3); font-size: 13px; }
.empty-state { text-align: center; padding: 48px 16px; color: var(--text3); } .empty-state { text-align: center; padding: 48px 16px; color: var(--text3); }
.empty-state h3 { font-size: 16px; color: var(--text2); margin-bottom: 6px; } .empty-state h3 { font-size: 16px; color: var(--text2); margin-bottom: 6px; }

View File

@ -254,7 +254,7 @@ export default function ActivityPage() {
} }
return ( return (
<div> <div className="capture-page capture-page--wide">
<h1 className="page-title">Aktivität</h1> <h1 className="page-title">Aktivität</h1>
<div className="tabs" style={{overflowX:'auto',flexWrap:'nowrap'}}> <div className="tabs" style={{overflowX:'auto',flexWrap:'nowrap'}}>

View File

@ -160,7 +160,7 @@ export default function CaliperScreen() {
} }
return ( return (
<div> <div className="capture-page">
<div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:16}}> <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:16}}>
<h1 className="page-title" style={{margin:0}}>Caliper</h1> <h1 className="page-title" style={{margin:0}}>Caliper</h1>
<button className="btn btn-secondary" style={{fontSize:12,padding:'6px 10px'}} onClick={()=>nav('/guide')}> <button className="btn btn-secondary" style={{fontSize:12,padding:'6px 10px'}} onClick={()=>nav('/guide')}>

View File

@ -85,7 +85,7 @@ const ENTRIES = [
export default function CaptureHub() { export default function CaptureHub() {
const nav = useNavigate() const nav = useNavigate()
return ( return (
<div> <div className="capture-page">
<h1 className="page-title">Erfassen</h1> <h1 className="page-title">Erfassen</h1>
<div style={{display:'flex',flexDirection:'column',gap:10}}> <div style={{display:'flex',flexDirection:'column',gap:10}}>
{ENTRIES.map(e => ( {ENTRIES.map(e => (

View File

@ -85,7 +85,7 @@ export default function CircumScreen() {
} }
return ( return (
<div> <div className="capture-page">
<div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:16}}> <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:16}}>
<h1 className="page-title" style={{margin:0}}>Umfänge</h1> <h1 className="page-title" style={{margin:0}}>Umfänge</h1>
<button className="btn btn-secondary" style={{fontSize:12,padding:'6px 10px'}} onClick={()=>nav('/guide')}> <button className="btn btn-secondary" style={{fontSize:12,padding:'6px 10px'}} onClick={()=>nav('/guide')}>

View File

@ -117,7 +117,7 @@ export default function CustomGoalsPage() {
} }
return ( return (
<div style={{ paddingBottom: 80 }}> <div className="capture-page" style={{ paddingBottom: 80 }}>
{/* Header */} {/* Header */}
<div style={{ <div style={{
background: 'linear-gradient(135deg, var(--accent) 0%, var(--accent-dark) 100%)', background: 'linear-gradient(135deg, var(--accent) 0%, var(--accent-dark) 100%)',

View File

@ -36,7 +36,7 @@ export default function GuidePage() {
const methodPoints = CALIPER_METHODS[caliperMethod]?.points_m || [] const methodPoints = CALIPER_METHODS[caliperMethod]?.points_m || []
return ( return (
<div> <div className="capture-page">
<h1 className="page-title">Messanleitung</h1> <h1 className="page-title">Messanleitung</h1>
<div className="tabs"> <div className="tabs">

View File

@ -344,7 +344,7 @@ export default function MeasureWizard() {
if (done) { if (done) {
return ( return (
<div style={{display:'flex',flexDirection:'column',alignItems:'center',justifyContent:'center', <div className="capture-page" style={{display:'flex',flexDirection:'column',alignItems:'center',justifyContent:'center',
minHeight:'60vh',gap:16,textAlign:'center'}}> minHeight:'60vh',gap:16,textAlign:'center'}}>
<div style={{fontSize:48}}></div> <div style={{fontSize:48}}></div>
<h2 style={{fontSize:20,fontWeight:700}}>Gespeichert!</h2> <h2 style={{fontSize:20,fontWeight:700}}>Gespeichert!</h2>
@ -361,11 +361,19 @@ export default function MeasureWizard() {
) )
} }
if (mode === 'circum') return <CircumWizard onDone={()=>setDone(true)} onCancel={()=>setMode(null)}/> if (mode === 'circum') return (
if (mode === 'caliper') return <CaliperWizard onDone={()=>setDone(true)} onCancel={()=>setMode(null)} profile={profile}/> <div className="capture-page">
<CircumWizard onDone={()=>setDone(true)} onCancel={()=>setMode(null)}/>
</div>
)
if (mode === 'caliper') return (
<div className="capture-page">
<CaliperWizard onDone={()=>setDone(true)} onCancel={()=>setMode(null)} profile={profile}/>
</div>
)
return ( return (
<div> <div className="capture-page">
<h1 className="page-title">Assistent</h1> <h1 className="page-title">Assistent</h1>
<p style={{fontSize:13,color:'var(--text2)',marginBottom:20,lineHeight:1.6}}> <p style={{fontSize:13,color:'var(--text2)',marginBottom:20,lineHeight:1.6}}>
Der Assistent führt dich Schritt für Schritt durch die Messung mit Anleitung für jeden Messpunkt. Der Assistent führt dich Schritt für Schritt durch die Messung mit Anleitung für jeden Messpunkt.

View File

@ -802,7 +802,7 @@ export default function NutritionPage() {
useEffect(() => { load() }, []) useEffect(() => { load() }, [])
return ( return (
<div> <div className="capture-page capture-page--wide">
<h1 className="page-title">Ernährung</h1> <h1 className="page-title">Ernährung</h1>
{/* Input Method Tabs */} {/* Input Method Tabs */}

View File

@ -177,7 +177,7 @@ export default function RestDaysPage() {
} }
return ( return (
<div> <div className="capture-page">
<h1 className="page-title">Ruhetage</h1> <h1 className="page-title">Ruhetage</h1>
{/* Toast Notification */} {/* Toast Notification */}

View File

@ -142,7 +142,7 @@ export default function SleepPage() {
} }
return ( return (
<div style={{ padding: '16px 16px 80px' }}> <div className="capture-page capture-page--wide" style={{ padding: '16px 16px 80px' }}>
{/* Toast Notification */} {/* Toast Notification */}
{toast && ( {toast && (
<div style={{ <div style={{

View File

@ -1064,7 +1064,7 @@ export default function VitalsPage() {
} }
return ( return (
<div> <div className="capture-page capture-page--wide">
<h1 className="page-title">Vitalwerte</h1> <h1 className="page-title">Vitalwerte</h1>
<div className="tabs" style={{ overflowX: 'auto', flexWrap: 'nowrap' }}> <div className="tabs" style={{ overflowX: 'auto', flexWrap: 'nowrap' }}>

View File

@ -78,7 +78,7 @@ export default function WeightScreen() {
const avgAll = weights.length ? Math.round(weights.reduce((a,b)=>a+b,0)/weights.length*10)/10 : null const avgAll = weights.length ? Math.round(weights.reduce((a,b)=>a+b,0)/weights.length*10)/10 : null
return ( return (
<div> <div className="capture-page">
<h1 className="page-title">Gewicht</h1> <h1 className="page-title">Gewicht</h1>
{/* Eingabe */} {/* Eingabe */}