瀏覽代碼

feat(workout-builder): add loadFromSession method to store for loading workout data from session
fix(workout-stepper): prevent fetching exercises if exercisesByMuscle is not empty
refactor(workout-session-list): enhance handleRepeat function to prepare and load workout session data into the builder store

Mathias 1 月之前
父節點
當前提交
952384ee56

+ 18 - 0
src/features/workout-builder/model/workout-builder.store.ts

@@ -24,6 +24,12 @@ interface WorkoutBuilderState {
   clearMuscles: () => void;
   fetchExercises: () => Promise<void>;
   setExercisesOrder: (order: string[]) => void;
+  loadFromSession: (params: {
+    equipment: ExerciseAttributeValueEnum[];
+    muscles: ExerciseAttributeValueEnum[];
+    exercisesByMuscle: any[];
+    exercisesOrder: string[];
+  }) => void;
 }
 
 export const useWorkoutBuilderStore = create<WorkoutBuilderState>((set, get) => ({
@@ -74,4 +80,16 @@ export const useWorkoutBuilderStore = create<WorkoutBuilderState>((set, get) =>
   },
 
   setExercisesOrder: (order) => set({ exercisesOrder: order }),
+
+  loadFromSession: ({ equipment, muscles, exercisesByMuscle, exercisesOrder }) => {
+    set({
+      selectedEquipment: equipment,
+      selectedMuscles: muscles,
+      exercisesByMuscle,
+      exercisesOrder,
+      currentStep: 3,
+      isLoadingExercises: false,
+      exercisesError: null,
+    });
+  },
 }));

+ 2 - 2
src/features/workout-builder/ui/workout-stepper.tsx

@@ -66,10 +66,10 @@ export function WorkoutStepper() {
 
   // Fetch exercises quand on arrive à l'étape 3
   useEffect(() => {
-    if (currentStep === 3) {
+    if (currentStep === 3 && exercisesByMuscle.length === 0) {
       fetchExercises();
     }
-  }, [currentStep, selectedEquipment, selectedMuscles]);
+  }, [currentStep, selectedEquipment, selectedMuscles, exercisesByMuscle.length]);
 
   const {
     isWorkoutActive,

+ 41 - 23
src/features/workout-session/ui/workout-session-list.tsx

@@ -1,8 +1,10 @@
 import { useState } from "react";
+import { useRouter } from "next/navigation";
 import { Repeat2, Trash2 } from "lucide-react";
 
 import { useCurrentLocale, useI18n } from "locales/client";
 import { workoutSessionLocal } from "@/shared/lib/workout-session/workout-session.local";
+import { useWorkoutBuilderStore } from "@/features/workout-builder/model/workout-builder.store";
 import { InlineTooltip } from "@/components/ui/tooltip";
 import { Button } from "@/components/ui/button";
 
@@ -20,6 +22,8 @@ const BADGE_COLORS = [
 export function WorkoutSessionList({ onSelect }: { onSelect: (id: string) => void }) {
   const locale = useCurrentLocale();
   const t = useI18n();
+  const router = useRouter();
+  const loadFromSession = useWorkoutBuilderStore((s) => s.loadFromSession);
 
   const [sessions, setSessions] = useState<WorkoutSession[]>(() =>
     workoutSessionLocal.getAll().sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime()),
@@ -33,30 +37,44 @@ export function WorkoutSessionList({ onSelect }: { onSelect: (id: string) => voi
   const handleRepeat = (id: string) => {
     const sessionToCopy = sessions.find((s) => s.id === id);
     if (!sessionToCopy) return;
-    // Deep copy des exercices et sets, reset des champs nécessaires
-    const newExercises = sessionToCopy.exercises.map((ex, idx) => ({
-      ...ex,
-      sets: ex.sets.map((set, setIdx) => ({
-        ...set,
-        id: `${ex.id}-set-${setIdx + 1}-${Date.now()}`,
-        completed: false,
-      })),
+    // prepare data for the builder
+
+    const allEquipment = Array.from(
+      new Set(
+        sessionToCopy.exercises
+          .flatMap((ex) =>
+            ex.attributes?.filter((attr) => attr.attributeName?.name === "EQUIPMENT").map((attr) => attr.attributeValue.value),
+          )
+          .filter(Boolean),
+      ),
+    );
+
+    const allMuscles = Array.from(
+      new Set(
+        sessionToCopy.exercises
+          .flatMap((ex) =>
+            ex.attributes?.filter((attr) => attr.attributeName?.name === "PRIMARY_MUSCLE").map((attr) => attr.attributeValue.value),
+          )
+          .filter(Boolean),
+      ),
+    );
+    const exercisesByMuscle = allMuscles.map((muscle) => ({
+      muscle,
+      exercises: sessionToCopy.exercises.filter((ex) =>
+        ex.attributes?.some((attr) => attr.attributeName?.name === "PRIMARY_MUSCLE" && attr.attributeValue.value === muscle),
+      ),
     }));
-    const newSession: WorkoutSession = {
-      ...sessionToCopy,
-      id: `${Date.now()}`,
-      startedAt: new Date().toISOString(),
-      endedAt: undefined,
-      duration: 0,
-      status: "active",
-      currentExerciseIndex: 0,
-      isActive: true,
-      exercises: newExercises,
-    };
-    workoutSessionLocal.add(newSession);
-    workoutSessionLocal.setCurrent(newSession.id);
-    setSessions(workoutSessionLocal.getAll().sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime()));
-    onSelect(newSession.id);
+
+    const exercisesOrder = sessionToCopy.exercises.map((ex) => ex.id);
+
+    // 5. inject in the builder and go step 3
+    loadFromSession({
+      equipment: allEquipment,
+      muscles: allMuscles,
+      exercisesByMuscle,
+      exercisesOrder,
+    });
+    router.push("/");
   };
 
   return (