Indvidual Dashboard V0.9 #67
|
|
@ -28,15 +28,28 @@ export default function DashboardLabPage() {
|
||||||
const [err, setErr] = useState(null)
|
const [err, setErr] = useState(null)
|
||||||
const [busy, setBusy] = useState(false)
|
const [busy, setBusy] = useState(false)
|
||||||
const [msg, setMsg] = useState(null)
|
const [msg, setMsg] = useState(null)
|
||||||
|
/** Während der Fokus im Körper-Chart-Feld: Rohstring, damit Tippen (z. B. „14“) nicht sofort geclamped wird */
|
||||||
|
const [bodyChartDaysDraft, setBodyChartDaysDraft] = useState(null)
|
||||||
|
|
||||||
const metaById = catalogMetaById(catalog)
|
const metaById = catalogMetaById(catalog)
|
||||||
|
|
||||||
|
const commitBodyChartDraftToLayout = useCallback((draftStr, baseLayout) => {
|
||||||
|
const clamped = normalizeBodyChartDays(draftStr === '' || draftStr == null ? BODY_CHART_DAYS_DEFAULT : draftStr)
|
||||||
|
return {
|
||||||
|
...baseLayout,
|
||||||
|
widgets: baseLayout.widgets.map((x) =>
|
||||||
|
x.id !== 'body_overview' ? x : { ...x, config: { ...x.config, chart_days: clamped } }
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
const load = useCallback(async () => {
|
const load = useCallback(async () => {
|
||||||
setErr(null)
|
setErr(null)
|
||||||
try {
|
try {
|
||||||
const [cat, b] = await Promise.all([api.getAppWidgetsCatalog(), api.getAppDashboardLayout()])
|
const [cat, b] = await Promise.all([api.getAppWidgetsCatalog(), api.getAppDashboardLayout()])
|
||||||
setCatalog(cat)
|
setCatalog(cat)
|
||||||
setBundle(b)
|
setBundle(b)
|
||||||
|
setBodyChartDaysDraft(null)
|
||||||
setLayout(normalizeLayoutForEditor(b.layout))
|
setLayout(normalizeLayoutForEditor(b.layout))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setErr(formatFastApiDetail(null, e.message))
|
setErr(formatFastApiDetail(null, e.message))
|
||||||
|
|
@ -49,11 +62,17 @@ export default function DashboardLabPage() {
|
||||||
|
|
||||||
const save = async () => {
|
const save = async () => {
|
||||||
if (!layout) return
|
if (!layout) return
|
||||||
|
let toSave = layout
|
||||||
|
if (bodyChartDaysDraft !== null) {
|
||||||
|
toSave = normalizeLayoutForEditor(commitBodyChartDraftToLayout(bodyChartDaysDraft, layout))
|
||||||
|
setLayout(toSave)
|
||||||
|
setBodyChartDaysDraft(null)
|
||||||
|
}
|
||||||
setBusy(true)
|
setBusy(true)
|
||||||
setMsg(null)
|
setMsg(null)
|
||||||
setErr(null)
|
setErr(null)
|
||||||
try {
|
try {
|
||||||
await api.putAppDashboardLayout(layout)
|
await api.putAppDashboardLayout(toSave)
|
||||||
setMsg('Layout gespeichert.')
|
setMsg('Layout gespeichert.')
|
||||||
await load()
|
await load()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -70,6 +89,7 @@ export default function DashboardLabPage() {
|
||||||
setErr(null)
|
setErr(null)
|
||||||
try {
|
try {
|
||||||
const r = await api.resetAppDashboardLayout()
|
const r = await api.resetAppDashboardLayout()
|
||||||
|
setBodyChartDaysDraft(null)
|
||||||
setLayout(normalizeLayoutForEditor(r.layout))
|
setLayout(normalizeLayoutForEditor(r.layout))
|
||||||
setMsg('Auf Standard zurückgesetzt.')
|
setMsg('Auf Standard zurückgesetzt.')
|
||||||
await load()
|
await load()
|
||||||
|
|
@ -82,6 +102,7 @@ export default function DashboardLabPage() {
|
||||||
|
|
||||||
const applyDefaultLocal = () => {
|
const applyDefaultLocal = () => {
|
||||||
if (bundle?.default_layout) {
|
if (bundle?.default_layout) {
|
||||||
|
setBodyChartDaysDraft(null)
|
||||||
setLayout(normalizeLayoutForEditor(structuredClone(bundle.default_layout)))
|
setLayout(normalizeLayoutForEditor(structuredClone(bundle.default_layout)))
|
||||||
setMsg('Standard geladen (noch nicht gespeichert).')
|
setMsg('Standard geladen (noch nicht gespeichert).')
|
||||||
}
|
}
|
||||||
|
|
@ -206,37 +227,29 @@ export default function DashboardLabPage() {
|
||||||
Körper-Chart Zeitraum (Tage): {BODY_CHART_DAYS_MIN}–{BODY_CHART_DAYS_MAX}
|
Körper-Chart Zeitraum (Tage): {BODY_CHART_DAYS_MIN}–{BODY_CHART_DAYS_MAX}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="text"
|
||||||
|
inputMode="numeric"
|
||||||
|
autoComplete="off"
|
||||||
className="form-input"
|
className="form-input"
|
||||||
style={{ maxWidth: 120 }}
|
style={{ maxWidth: 120 }}
|
||||||
min={BODY_CHART_DAYS_MIN}
|
aria-label="Körper-Chart Zeitraum in Tagen"
|
||||||
max={BODY_CHART_DAYS_MAX}
|
value={
|
||||||
value={chartDaysVal}
|
bodyChartDaysDraft !== null
|
||||||
onChange={(e) => {
|
? bodyChartDaysDraft
|
||||||
const v = parseInt(e.target.value, 10)
|
: String(chartDaysVal)
|
||||||
setLayout((L) => ({
|
}
|
||||||
...L,
|
onFocus={() => setBodyChartDaysDraft(String(chartDaysVal))}
|
||||||
widgets: L.widgets.map((x, j) =>
|
onChange={(e) => setBodyChartDaysDraft(e.target.value)}
|
||||||
j !== i
|
onBlur={() => {
|
||||||
? x
|
setLayout((L) =>
|
||||||
: {
|
normalizeLayoutForEditor(
|
||||||
...x,
|
commitBodyChartDraftToLayout(bodyChartDaysDraft ?? String(chartDaysVal), L)
|
||||||
config: {
|
)
|
||||||
...x.config,
|
)
|
||||||
chart_days: Number.isFinite(v) ? v : BODY_CHART_DAYS_DEFAULT,
|
setBodyChartDaysDraft(null)
|
||||||
},
|
|
||||||
}
|
|
||||||
),
|
|
||||||
}))
|
|
||||||
}}
|
}}
|
||||||
onBlur={(e) => {
|
onKeyDown={(e) => {
|
||||||
const clamped = normalizeBodyChartDays(e.target.value)
|
if (e.key === 'Enter') e.currentTarget.blur()
|
||||||
setLayout((L) => ({
|
|
||||||
...L,
|
|
||||||
widgets: L.widgets.map((x, j) =>
|
|
||||||
j !== i ? x : { ...x, config: { ...x.config, chart_days: clamped } }
|
|
||||||
),
|
|
||||||
}))
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user