workout-builder.store.ts 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import { create } from "zustand";
  2. import { ExerciseAttributeValueEnum } from "@prisma/client";
  3. import { WorkoutBuilderStep } from "../types";
  4. import { getExercisesAction } from "./get-exercises.action";
  5. interface WorkoutBuilderState {
  6. currentStep: WorkoutBuilderStep;
  7. selectedEquipment: ExerciseAttributeValueEnum[];
  8. selectedMuscles: ExerciseAttributeValueEnum[];
  9. // Exercices (groupés par muscle)
  10. exercisesByMuscle: any[];
  11. isLoadingExercises: boolean;
  12. exercisesError: any;
  13. exercisesOrder: string[];
  14. // Actions
  15. setStep: (step: WorkoutBuilderStep) => void;
  16. nextStep: () => void;
  17. prevStep: () => void;
  18. toggleEquipment: (equipment: ExerciseAttributeValueEnum) => void;
  19. clearEquipment: () => void;
  20. toggleMuscle: (muscle: ExerciseAttributeValueEnum) => void;
  21. clearMuscles: () => void;
  22. fetchExercises: () => Promise<void>;
  23. setExercisesOrder: (order: string[]) => void;
  24. loadFromSession: (params: {
  25. equipment: ExerciseAttributeValueEnum[];
  26. muscles: ExerciseAttributeValueEnum[];
  27. exercisesByMuscle: any[];
  28. exercisesOrder: string[];
  29. }) => void;
  30. }
  31. export const useWorkoutBuilderStore = create<WorkoutBuilderState>((set, get) => ({
  32. currentStep: 1 as WorkoutBuilderStep,
  33. selectedEquipment: [],
  34. selectedMuscles: [],
  35. exercisesByMuscle: [],
  36. isLoadingExercises: false,
  37. exercisesError: null,
  38. exercisesOrder: [],
  39. setStep: (step) => set({ currentStep: step }),
  40. nextStep: () => set((state) => ({ currentStep: Math.min(state.currentStep + 1, 3) as WorkoutBuilderStep })),
  41. prevStep: () => set((state) => ({ currentStep: Math.max(state.currentStep - 1, 1) as WorkoutBuilderStep })),
  42. toggleEquipment: (equipment) =>
  43. set((state) => ({
  44. selectedEquipment: state.selectedEquipment.includes(equipment)
  45. ? state.selectedEquipment.filter((e) => e !== equipment)
  46. : [...state.selectedEquipment, equipment],
  47. })),
  48. clearEquipment: () => set({ selectedEquipment: [] }),
  49. toggleMuscle: (muscle) =>
  50. set((state) => ({
  51. selectedMuscles: state.selectedMuscles.includes(muscle)
  52. ? state.selectedMuscles.filter((m) => m !== muscle)
  53. : [...state.selectedMuscles, muscle],
  54. })),
  55. clearMuscles: () => set({ selectedMuscles: [] }),
  56. fetchExercises: async () => {
  57. set({ isLoadingExercises: true, exercisesError: null });
  58. try {
  59. const { selectedEquipment, selectedMuscles } = get();
  60. const result = await getExercisesAction({
  61. equipment: selectedEquipment,
  62. muscles: selectedMuscles,
  63. limit: 3,
  64. });
  65. if (result?.serverError) {
  66. throw new Error(result.serverError);
  67. }
  68. set({ exercisesByMuscle: result?.data || [], isLoadingExercises: false });
  69. } catch (error) {
  70. set({ exercisesError: error, isLoadingExercises: false });
  71. }
  72. },
  73. setExercisesOrder: (order) => set({ exercisesOrder: order }),
  74. loadFromSession: ({ equipment, muscles, exercisesByMuscle, exercisesOrder }) => {
  75. set({
  76. selectedEquipment: equipment,
  77. selectedMuscles: muscles,
  78. exercisesByMuscle,
  79. exercisesOrder,
  80. currentStep: 3,
  81. isLoadingExercises: false,
  82. exercisesError: null,
  83. });
  84. },
  85. }));