refactor: streamline exercise selection process in training pages
- Simplified the exercise selection logic in TrainingUnitSectionsEditor, TrainingFrameworkProgramEditPage, and TrainingPlanningPage by removing the multi-select option. - Updated the ExercisePickerModal to always enable multi-select, enhancing user experience when selecting exercises. - Refactored the handling of selected exercises to improve clarity and maintainability of the code.
This commit is contained in:
parent
4080088d42
commit
86192df508
|
|
@ -809,19 +809,10 @@ export default function TrainingUnitSectionsEditor({
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary framework-ctrl framework-ctrl--xs"
|
className="btn btn-secondary framework-ctrl framework-ctrl--xs"
|
||||||
onClick={() => addItem(sIdx, 'exercise')}
|
onClick={() => onRequestExercisePick?.({ sectionIndex: sIdx })}
|
||||||
>
|
>
|
||||||
+ Übung
|
+ Übung
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn btn-secondary framework-ctrl framework-ctrl--xs"
|
|
||||||
onClick={() =>
|
|
||||||
onRequestExercisePick?.({ sectionIndex: sIdx, multi: true })
|
|
||||||
}
|
|
||||||
>
|
|
||||||
+ mehrere Übungen…
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-secondary framework-ctrl framework-ctrl--xs"
|
className="btn btn-secondary framework-ctrl framework-ctrl--xs"
|
||||||
|
|
|
||||||
|
|
@ -627,12 +627,11 @@ export default function TrainingFrameworkProgramEditPage() {
|
||||||
),
|
),
|
||||||
}))
|
}))
|
||||||
}}
|
}}
|
||||||
onRequestExercisePick={({ sectionIndex, itemIndex, multi }) =>
|
onRequestExercisePick={({ sectionIndex, itemIndex }) =>
|
||||||
setSectionPickerCtx({
|
setSectionPickerCtx({
|
||||||
slotIdx: si,
|
slotIdx: si,
|
||||||
sectionIndex,
|
sectionIndex,
|
||||||
itemIndex: typeof itemIndex === 'number' ? itemIndex : undefined,
|
itemIndex: typeof itemIndex === 'number' ? itemIndex : undefined,
|
||||||
multi: !!multi,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
onPeekExercise={(id, variantId) =>
|
onPeekExercise={(id, variantId) =>
|
||||||
|
|
@ -1108,75 +1107,45 @@ export default function TrainingFrameworkProgramEditPage() {
|
||||||
|
|
||||||
<ExercisePickerModal
|
<ExercisePickerModal
|
||||||
open={sectionPickerCtx != null}
|
open={sectionPickerCtx != null}
|
||||||
multiSelect={!!sectionPickerCtx?.multi}
|
multiSelect
|
||||||
onClose={() => setSectionPickerCtx(null)}
|
onClose={() => setSectionPickerCtx(null)}
|
||||||
onSelectExercises={
|
onSelectExercises={async (picked) => {
|
||||||
sectionPickerCtx?.multi
|
if (!sectionPickerCtx || !picked?.length) return
|
||||||
? async (picked) => {
|
const rows = []
|
||||||
if (!sectionPickerCtx || !picked?.length) return
|
for (const ex of picked) {
|
||||||
const { slotIdx, sectionIndex: sIdx } = sectionPickerCtx
|
const row = await hydrateExercisePlanningRow(ex)
|
||||||
const rows = []
|
if (row) rows.push(row)
|
||||||
for (const ex of picked) {
|
}
|
||||||
const row = await hydrateExercisePlanningRow(ex)
|
if (!rows.length) return
|
||||||
if (row) rows.push(row)
|
|
||||||
}
|
|
||||||
if (!rows.length) return
|
|
||||||
setForm((prev) => ({
|
|
||||||
...prev,
|
|
||||||
slots: prev.slots.map((sl, ii) =>
|
|
||||||
ii !== slotIdx
|
|
||||||
? sl
|
|
||||||
: {
|
|
||||||
...sl,
|
|
||||||
sections: (
|
|
||||||
sl.sections && sl.sections.length ? sl.sections : [defaultSection('Ablauf')]
|
|
||||||
).map((sec, si) =>
|
|
||||||
si !== sIdx ? sec : { ...sec, items: [...(sec.items || []), ...rows] }
|
|
||||||
),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
}))
|
|
||||||
setSectionPickerCtx(null)
|
|
||||||
}
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
onSelectExercise={async (exercise) => {
|
|
||||||
if (!sectionPickerCtx) return
|
|
||||||
if (sectionPickerCtx.multi) return
|
|
||||||
if (typeof sectionPickerCtx.itemIndex !== 'number') return
|
|
||||||
const { slotIdx, sectionIndex: sIdx, itemIndex: iIdx } = sectionPickerCtx
|
const { slotIdx, sectionIndex: sIdx, itemIndex: iIdx } = sectionPickerCtx
|
||||||
const row = await hydrateExercisePlanningRow(exercise)
|
|
||||||
if (!row) return
|
|
||||||
setForm((prev) => ({
|
setForm((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
slots: prev.slots.map((sl, ii) =>
|
slots: prev.slots.map((sl, ii) => {
|
||||||
ii !== slotIdx
|
if (ii !== slotIdx) return sl
|
||||||
? sl
|
const baseSecs = sl.sections && sl.sections.length ? sl.sections : [defaultSection('Ablauf')]
|
||||||
: {
|
return {
|
||||||
...sl,
|
...sl,
|
||||||
sections: (sl.sections && sl.sections.length ? sl.sections : [defaultSection('Ablauf')]).map(
|
sections: baseSecs.map((sec, si) => {
|
||||||
(sec, si) =>
|
if (si !== sIdx) return sec
|
||||||
si !== sIdx
|
const items = [...(sec.items || [])]
|
||||||
? sec
|
if (typeof iIdx === 'number') {
|
||||||
: {
|
const cur = items[iIdx]
|
||||||
...sec,
|
if (!cur || cur.item_type !== 'exercise') return sec
|
||||||
items: (sec.items || []).map((r2, ji) =>
|
const [first, ...tail] = rows
|
||||||
ji !== iIdx
|
items[iIdx] = {
|
||||||
? r2
|
...cur,
|
||||||
: r2.item_type !== 'exercise'
|
exercise_id: first.exercise_id,
|
||||||
? r2
|
exercise_variant_id: first.exercise_variant_id,
|
||||||
: {
|
exercise_title: first.exercise_title,
|
||||||
...r2,
|
variants: first.variants,
|
||||||
exercise_id: row.exercise_id,
|
}
|
||||||
exercise_variant_id: row.exercise_variant_id,
|
if (tail.length) items.splice(iIdx + 1, 0, ...tail)
|
||||||
exercise_title: row.exercise_title,
|
return { ...sec, items }
|
||||||
variants: row.variants,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
),
|
return { ...sec, items: [...items, ...rows] }
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}),
|
||||||
}))
|
}))
|
||||||
setSectionPickerCtx(null)
|
setSectionPickerCtx(null)
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -709,11 +709,10 @@ function TrainingPlanningPage() {
|
||||||
sections: updater(prev.sections),
|
sections: updater(prev.sections),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
onRequestExercisePick={({ sectionIndex, itemIndex, multi }) => {
|
onRequestExercisePick={({ sectionIndex, itemIndex }) => {
|
||||||
setExercisePickerTarget({
|
setExercisePickerTarget({
|
||||||
sIdx: sectionIndex,
|
sIdx: sectionIndex,
|
||||||
iIdx: typeof itemIndex === 'number' ? itemIndex : undefined,
|
iIdx: typeof itemIndex === 'number' ? itemIndex : undefined,
|
||||||
multi: !!multi,
|
|
||||||
})
|
})
|
||||||
setExercisePickerOpen(true)
|
setExercisePickerOpen(true)
|
||||||
}}
|
}}
|
||||||
|
|
@ -824,61 +823,41 @@ function TrainingPlanningPage() {
|
||||||
)}
|
)}
|
||||||
<ExercisePickerModal
|
<ExercisePickerModal
|
||||||
open={exercisePickerOpen}
|
open={exercisePickerOpen}
|
||||||
multiSelect={!!exercisePickerTarget?.multi}
|
multiSelect
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setExercisePickerOpen(false)
|
setExercisePickerOpen(false)
|
||||||
setExercisePickerTarget(null)
|
setExercisePickerTarget(null)
|
||||||
}}
|
}}
|
||||||
onSelectExercises={
|
onSelectExercises={async (picked) => {
|
||||||
exercisePickerTarget?.multi
|
if (!exercisePickerTarget || !picked?.length) return
|
||||||
? async (picked) => {
|
const rows = []
|
||||||
if (!exercisePickerTarget || !picked?.length) return
|
for (const ex of picked) {
|
||||||
const { sIdx } = exercisePickerTarget
|
const row = await hydrateExercisePlanningRow(ex)
|
||||||
const rows = []
|
if (row) rows.push(row)
|
||||||
for (const ex of picked) {
|
}
|
||||||
const row = await hydrateExercisePlanningRow(ex)
|
if (!rows.length) return
|
||||||
if (row) rows.push(row)
|
|
||||||
}
|
|
||||||
if (!rows.length) return
|
|
||||||
setFormData((prev) => ({
|
|
||||||
...prev,
|
|
||||||
sections: prev.sections.map((s, si) =>
|
|
||||||
si !== sIdx ? s : { ...s, items: [...(s.items || []), ...rows] }
|
|
||||||
),
|
|
||||||
}))
|
|
||||||
setExercisePickerOpen(false)
|
|
||||||
setExercisePickerTarget(null)
|
|
||||||
}
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
onSelectExercise={async (ex) => {
|
|
||||||
if (!exercisePickerTarget || exercisePickerTarget.multi) return
|
|
||||||
const row = await hydrateExercisePlanningRow(ex)
|
|
||||||
if (!row) return
|
|
||||||
const { sIdx, iIdx } = exercisePickerTarget
|
const { sIdx, iIdx } = exercisePickerTarget
|
||||||
if (typeof iIdx !== 'number') return
|
|
||||||
setFormData((prev) => ({
|
setFormData((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
sections: prev.sections.map((s, si) =>
|
sections: prev.sections.map((s, si) => {
|
||||||
si !== sIdx
|
if (si !== sIdx) return s
|
||||||
? s
|
const items = [...(s.items || [])]
|
||||||
: {
|
if (typeof iIdx === 'number') {
|
||||||
...s,
|
const cur = items[iIdx]
|
||||||
items: s.items.map((r2, ii) =>
|
if (!cur || cur.item_type !== 'exercise') return s
|
||||||
ii !== iIdx
|
const [first, ...tail] = rows
|
||||||
? r2
|
items[iIdx] = {
|
||||||
: r2.item_type !== 'exercise'
|
...cur,
|
||||||
? r2
|
exercise_id: first.exercise_id,
|
||||||
: {
|
exercise_variant_id: first.exercise_variant_id,
|
||||||
...r2,
|
exercise_title: first.exercise_title,
|
||||||
exercise_id: row.exercise_id,
|
variants: first.variants,
|
||||||
exercise_variant_id: row.exercise_variant_id,
|
}
|
||||||
exercise_title: row.exercise_title,
|
if (tail.length) items.splice(iIdx + 1, 0, ...tail)
|
||||||
variants: row.variants,
|
return { ...s, items }
|
||||||
}
|
}
|
||||||
),
|
return { ...s, items: [...items, ...rows] }
|
||||||
}
|
}),
|
||||||
),
|
|
||||||
}))
|
}))
|
||||||
setExercisePickerOpen(false)
|
setExercisePickerOpen(false)
|
||||||
setExercisePickerTarget(null)
|
setExercisePickerTarget(null)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user