From e1253f410078243b9a9713d146a5ae697ea931fd Mon Sep 17 00:00:00 2001 From: AG Date: Fri, 12 Dec 2025 19:34:17 +0200 Subject: [PATCH] Exercise Creation from Plan fixed --- src/components/Plans.tsx | 94 +++----------------------------------- src/components/Profile.tsx | 75 ++++++++++++++++++++++++++---- src/services/i18n.ts | 12 +++++ 3 files changed, 84 insertions(+), 97 deletions(-) diff --git a/src/components/Plans.tsx b/src/components/Plans.tsx index 3b4b7f7..4e4dd6c 100644 --- a/src/components/Plans.tsx +++ b/src/components/Plans.tsx @@ -15,6 +15,7 @@ import { Card } from './ui/Card'; import { Modal } from './ui/Modal'; import { SideSheet } from './ui/SideSheet'; import { Checkbox } from './ui/Checkbox'; +import ExerciseModal from './ExerciseModal'; interface PlansProps { lang: Language; @@ -42,9 +43,6 @@ const Plans: React.FC = ({ lang }) => { // Create Exercise State const [isCreatingExercise, setIsCreatingExercise] = useState(false); - const [newExName, setNewExName] = useState(''); - const [newExType, setNewExType] = useState(ExerciseType.STRENGTH); - const [newExBwPercentage, setNewExBwPercentage] = useState('100'); // Preparation Modal State const [showPlanPrep, setShowPlanPrep] = useState(null); @@ -123,37 +121,16 @@ const Plans: React.FC = ({ lang }) => { setShowExerciseSelector(false); }; - const handleCreateExercise = async () => { - if (!newExName.trim()) return; - const newEx: ExerciseDef = { - id: generateId(), - name: newExName.trim(), - type: newExType, - ...(newExType === ExerciseType.BODYWEIGHT && { bodyWeightPercentage: parseFloat(newExBwPercentage) || 100 }) - }; + const handleSaveNewExercise = async (newEx: ExerciseDef) => { 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)); }; @@ -328,70 +305,13 @@ const Plans: React.FC = ({ lang }) => { - setIsCreatingExercise(false)} - title={t('create_exercise', lang)} - width="md" - > -
- setNewExName(e.target.value)} - type="text" - autoFocus - autocapitalize="words" - onBlur={() => setNewExName(toTitleCase(newExName))} - /> - -
- -
- {[ - { 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={} - /> - )} - -
- -
-
-
+ onSave={handleSaveNewExercise} + lang={lang} + existingExercises={availableExercises} + /> ); } diff --git a/src/components/Profile.tsx b/src/components/Profile.tsx index c4a35b9..9671f77 100644 --- a/src/components/Profile.tsx +++ b/src/components/Profile.tsx @@ -59,6 +59,10 @@ const Profile: React.FC = ({ user, onLogout, lang, onLanguageChang const [isCreatingEx, setIsCreatingEx] = useState(false); const [exerciseNameFilter, setExerciseNameFilter] = useState(''); + // Admin Confirmation Modal State + type AdminActionType = 'DELETE_USER' | 'BLOCK_USER' | 'UNBLOCK_USER'; + const [confirmAction, setConfirmAction] = useState<{ type: AdminActionType, userId: string, email?: string, currentBlockState?: boolean } | null>(null); + const exerciseTypeLabels: Record = { [ExerciseType.STRENGTH]: t('type_strength', lang), [ExerciseType.BODYWEIGHT]: t('type_bodyweight', lang), @@ -191,16 +195,32 @@ const Profile: React.FC = ({ user, onLogout, lang, onLanguageChang } }; - const handleAdminDeleteUser = async (uid: string) => { - if (confirm(t('delete_confirm', lang))) { - await deleteUser(uid); - await refreshUserList(); - } + const handleAdminDeleteUser = (uid: string, email: string) => { + setConfirmAction({ type: 'DELETE_USER', userId: uid, email }); }; - const handleAdminBlockUser = async (uid: string, isBlocked: boolean) => { - await toggleBlockUser(uid, isBlocked); - await refreshUserList(); + const handleAdminBlockUser = (uid: string, isBlocked: boolean, email: string) => { + setConfirmAction({ + type: isBlocked ? 'BLOCK_USER' : 'UNBLOCK_USER', + userId: uid, + email, + currentBlockState: isBlocked + }); + }; + + const handleConfirmAction = async () => { + if (!confirmAction) return; + + if (confirmAction.type === 'DELETE_USER') { + await deleteUser(confirmAction.userId); + await refreshUserList(); + } else if (confirmAction.type === 'BLOCK_USER' || confirmAction.type === 'UNBLOCK_USER') { + // If type is BLOCK_USER, we are passing true to block. If UNBLOCK, false. + // But simpler: we stored currentBlockState which is the target state (e.g. isBlocked=true passed to handler) + await toggleBlockUser(confirmAction.userId, confirmAction.currentBlockState!); + await refreshUserList(); + } + setConfirmAction(null); }; const handleAdminResetPass = async (uid: string) => { @@ -551,7 +571,7 @@ const Profile: React.FC = ({ user, onLogout, lang, onLanguageChang {u.role !== 'ADMIN' && ( <> + + + + +