import React, { useState, useEffect } from 'react';
import { Plus, Trash2, PlayCircle, Dumbbell, Save, X, ChevronRight, List, ArrowUp, ArrowDown, Scale, Edit2, User, Flame, Timer as TimerIcon, Ruler, Footprints, Activity, Percent, CheckCircle, GripVertical } from 'lucide-react';
import { WorkoutPlan, ExerciseDef, PlannedSet, Language, ExerciseType } from '../types';
import { getPlans, savePlan, deletePlan, getExercises, saveExercise } from '../services/storage';
import { t } from '../services/i18n';
interface PlansProps {
userId: string;
onStartPlan: (plan: WorkoutPlan) => void;
lang: Language;
}
const FilledInput = ({ label, value, onChange, type = "number", icon, autoFocus, step }: any) => (
);
const Plans: React.FC = ({ userId, onStartPlan, lang }) => {
const [plans, setPlans] = useState([]);
const [isEditing, setIsEditing] = useState(false);
const [editId, setEditId] = useState(null);
const [name, setName] = useState('');
const [description, setDescription] = useState('');
const [steps, setSteps] = useState([]);
const [availableExercises, setAvailableExercises] = useState([]);
const [showExerciseSelector, setShowExerciseSelector] = useState(false);
// Drag and Drop Refs
const dragItem = React.useRef(null);
const [draggingIndex, setDraggingIndex] = useState(null);
// Create Exercise State
const [isCreatingExercise, setIsCreatingExercise] = useState(false);
const [newExName, setNewExName] = useState('');
const [newExType, setNewExType] = useState(ExerciseType.STRENGTH);
const [newExBwPercentage, setNewExBwPercentage] = useState('100');
useEffect(() => {
const loadData = async () => {
const fetchedPlans = await getPlans(userId);
setPlans(fetchedPlans);
const fetchedExercises = await getExercises(userId);
// Filter out archived exercises
if (Array.isArray(fetchedExercises)) {
setAvailableExercises(fetchedExercises.filter(e => !e.isArchived));
} else {
setAvailableExercises([]);
}
};
loadData();
}, [userId]);
const handleCreateNew = () => {
setEditId(crypto.randomUUID());
setName('');
setDescription('');
setSteps([]);
setIsEditing(true);
};
const handleEdit = (plan: WorkoutPlan) => {
setEditId(plan.id);
setName(plan.name);
setDescription(plan.description || '');
setSteps(plan.steps);
setIsEditing(true);
};
const handleSave = async () => {
if (!name.trim() || !editId) return;
const newPlan: WorkoutPlan = { id: editId, name, description, steps };
await savePlan(userId, newPlan);
const updated = await getPlans(userId);
setPlans(updated);
setIsEditing(false);
};
const handleDelete = async (id: string, e: React.MouseEvent) => {
e.stopPropagation();
if (confirm(t('delete_confirm', lang))) {
await deletePlan(userId, id);
const updated = await getPlans(userId);
setPlans(updated);
}
};
const addStep = (ex: ExerciseDef) => {
const newStep: PlannedSet = {
id: crypto.randomUUID(),
exerciseId: ex.id,
exerciseName: ex.name,
exerciseType: ex.type,
isWeighted: false
};
setSteps([...steps, newStep]);
setShowExerciseSelector(false);
};
const handleCreateExercise = async () => {
if (!newExName.trim()) return;
const newEx: ExerciseDef = {
id: crypto.randomUUID(),
name: newExName.trim(),
type: newExType,
...(newExType === ExerciseType.BODYWEIGHT && { bodyWeightPercentage: parseFloat(newExBwPercentage) || 100 })
};
await saveExercise(userId, newEx);
const exList = await getExercises(userId);
setAvailableExercises(exList.filter(e => !e.isArchived));
// Automatically add the new exercise to the plan
addStep(newEx);
setNewExName('');
setNewExType(ExerciseType.STRENGTH);
setNewExBwPercentage('100');
setIsCreatingExercise(false);
};
const exerciseTypeLabels: Record = {
[ExerciseType.STRENGTH]: t('type_strength', lang),
[ExerciseType.BODYWEIGHT]: t('type_bodyweight', lang),
[ExerciseType.CARDIO]: t('type_cardio', lang),
[ExerciseType.STATIC]: t('type_static', lang),
[ExerciseType.HIGH_JUMP]: t('type_height', lang),
[ExerciseType.LONG_JUMP]: t('type_dist', lang),
[ExerciseType.PLYOMETRIC]: t('type_jump', lang),
};
const toggleWeighted = (stepId: string) => {
setSteps(steps.map(s => s.id === stepId ? { ...s, isWeighted: !s.isWeighted } : s));
};
const removeStep = (stepId: string) => {
setSteps(steps.filter(s => s.id !== stepId));
};
const onDragStart = (index: number) => {
dragItem.current = index;
setDraggingIndex(index);
};
const onDragEnter = (index: number) => {
if (dragItem.current === null) return;
if (dragItem.current === index) return;
const newSteps = [...steps];
const draggedItemContent = newSteps.splice(dragItem.current, 1)[0];
newSteps.splice(index, 0, draggedItemContent);
setSteps(newSteps);
dragItem.current = index;
setDraggingIndex(index);
};
const onDragEnd = () => {
dragItem.current = null;
setDraggingIndex(null);
};
if (isEditing) {
return (
{t('plan_editor', lang)}
setName(e.target.value)}
/>
{steps.map((step, idx) => (
onDragStart(idx)}
onDragEnter={() => onDragEnter(idx)}
onDragOver={(e) => e.preventDefault()}
onDragEnd={onDragEnd}
>
{idx + 1}
))}
{showExerciseSelector && (
{t('select_exercise', lang)}
{availableExercises
.slice()
.sort((a, b) => a.name.localeCompare(b.name))
.map(ex => (
))}
{isCreatingExercise && (
{t('create_exercise', lang)}
setNewExName(e.target.value)}
type="text"
autoFocus
/>
{[
{ id: ExerciseType.STRENGTH, label: exerciseTypeLabels[ExerciseType.STRENGTH], icon: Dumbbell },
{ id: ExerciseType.BODYWEIGHT, label: exerciseTypeLabels[ExerciseType.BODYWEIGHT], icon: User },
{ id: ExerciseType.CARDIO, label: exerciseTypeLabels[ExerciseType.CARDIO], icon: Flame },
{ id: ExerciseType.STATIC, label: exerciseTypeLabels[ExerciseType.STATIC], icon: TimerIcon },
{ id: ExerciseType.HIGH_JUMP, label: exerciseTypeLabels[ExerciseType.HIGH_JUMP], icon: ArrowUp },
{ id: ExerciseType.LONG_JUMP, label: exerciseTypeLabels[ExerciseType.LONG_JUMP], icon: Ruler },
{ id: ExerciseType.PLYOMETRIC, label: exerciseTypeLabels[ExerciseType.PLYOMETRIC], icon: Footprints },
].map((type) => (
))}
{newExType === ExerciseType.BODYWEIGHT && (
setNewExBwPercentage(e.target.value)}
icon={}
/>
)}
)}
)}
);
}
return (
{t('my_plans', lang)}
{plans.length === 0 ? (
) : (
plans.map(plan => (
{plan.name}
{plan.description || t('prep_no_instructions', lang)}
{plan.steps.length} {t('exercises_count', lang)}
))
)}
{/* FAB */}
);
};
export default Plans;