"use client";
import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import Image from "next/image";
import { Check, Play, ArrowRight, Trophy as TrophyIcon, Plus, Hourglass } from "lucide-react";
import confetti from "canvas-confetti";
import { useCurrentLocale, useI18n } from "locales/client";
import TrophyImg from "@public/images/trophy.png";
import { cn } from "@/shared/lib/utils";
import { useWorkoutSession } from "@/features/workout-session/model/use-workout-session";
import { useSyncWorkoutSessions } from "@/features/workout-session/model/use-sync-workout-sessions";
import { ExerciseVideoModal } from "@/features/workout-builder/ui/exercise-video-modal";
import { Button } from "@/components/ui/button";
import { WorkoutSessionSet } from "./workout-session-set";
export function WorkoutSessionSets({
showCongrats,
onCongrats,
isWorkoutActive,
}: {
showCongrats: boolean;
onCongrats: VoidFunction;
isWorkoutActive: boolean;
}) {
const t = useI18n();
const router = useRouter();
const locale = useCurrentLocale();
const { currentExerciseIndex, session, addSet, updateSet, removeSet, finishSet, goToNextExercise, goToExercise, completeWorkout } =
useWorkoutSession();
const exerciseDetailsMap = Object.fromEntries(session?.exercises.map((ex) => [ex.id, ex]) || []);
const [videoModal, setVideoModal] = useState<{ open: boolean; exerciseId?: string }>({ open: false });
const { syncSessions } = useSyncWorkoutSessions();
// auto-scroll to current exercise when index changes
useEffect(() => {
if (session && currentExerciseIndex >= 0) {
const exerciseElement = document.getElementById(`exercise-${currentExerciseIndex}`);
if (exerciseElement) {
const scrollContainer = exerciseElement.closest(".overflow-auto");
if (scrollContainer) {
const containerRect = scrollContainer.getBoundingClientRect();
const elementRect = exerciseElement.getBoundingClientRect();
const offset = 10;
const scrollTop = scrollContainer.scrollTop + elementRect.top - containerRect.top - offset;
scrollContainer.scrollTo({
top: scrollTop,
behavior: "smooth",
});
} else {
exerciseElement.scrollIntoView({
behavior: "smooth",
block: "center",
});
}
}
}
}, [currentExerciseIndex, session]);
if (showCongrats) {
return (
{t("workout_builder.session.complete") + " ! 🎉"}
{t("workout_builder.session.workout_in_progress")}
);
}
if (!session) {
return {t("workout_builder.session.no_exercise_selected")}
;
}
const handleExerciseClick = (targetIndex: number) => {
if (targetIndex !== currentExerciseIndex) {
goToExercise(targetIndex);
}
};
const renderStepIcon = (idx: number, allSetsCompleted: boolean) => {
if (allSetsCompleted) {
return ;
}
if (idx === currentExerciseIndex) {
return (
);
}
return ;
};
const renderStepBackground = (idx: number, allSetsCompleted: boolean) => {
if (allSetsCompleted) {
return "bg-green-500 border-green-500";
}
if (idx === currentExerciseIndex) {
return "bg-gray-300 border-gray-400 dark:bg-slate-500 dark:border-slate-500";
}
return "bg-slate-200 border-slate-200";
};
const handleFinishSession = () => {
completeWorkout();
syncSessions();
onCongrats();
confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } });
};
return (
{session.exercises.map((ex, idx) => {
const allSetsCompleted = ex.sets.length > 0 && ex.sets.every((set) => set.completed);
const exerciseName = locale === "fr" ? ex.name : ex.nameEn;
const details = exerciseDetailsMap[ex.id];
return (
- handleExerciseClick(idx)}
>
{/* Cercle étape */}
{renderStepIcon(idx, allSetsCompleted)}
{/* Image + nom de l'exercice */}
{details?.fullVideoImageUrl && (
{
e.stopPropagation();
setVideoModal({ open: true, exerciseId: ex.id });
}}
>
)}
{exerciseName}
{details?.introduction && (
{
e.stopPropagation();
setVideoModal({ open: true, exerciseId: ex.id });
}}
>
{t("workout_builder.session.see_instructions")}
)}
{/* Fallback: description si pas d'introduction */}
{/* Modale vidéo */}
{details && details.fullVideoUrl && videoModal.open && videoModal.exerciseId === ex.id && (
setVideoModal({ open, exerciseId: open ? ex.id : undefined })}
open={videoModal.open}
/>
)}
{/* Si exercice courant, afficher le détail */}
{idx === currentExerciseIndex && (
{/* Liste des sets */}
{ex.sets.map((set, setIdx) => (
) => updateSet(idx, sIdx, data)}
onFinish={() => finishSet(idx, setIdx)}
onRemove={() => removeSet(idx, setIdx)}
set={set}
setIndex={setIdx}
/>
))}
{/* Actions bas de page */}
)}
);
})}
{isWorkoutActive && (
)}
);
}