"use client"; import { Trash2, Check, Pencil, CornerDownLeft } from "lucide-react"; import { useState, useCallback } from "react"; export type InputField = "sets" | "reps" | "weight" | "duration" | "distance" | "calories" | "notes"; export interface SetRowProps { setNumber: number; inputFields?: InputField[]; weightUnit?: string; initialReps?: number; initialWeight?: number; initialRpe?: number; initialNotes?: string; initialDuration?: number; initialDistance?: number; initialCalories?: number; initialLocked?: boolean; autoFocus?: boolean; onUpdate: (data: { reps?: number; weight?: number; rpe?: number; notes?: string; durationSeconds?: number; distance?: number; calories?: number; }) => void; onConfirm?: () => void; onNextSet?: (currentValues: { weight?: string; reps?: string; rpe?: string; notes?: string; duration?: string; distance?: string; calories?: string; }) => void; onDelete: () => void; } export default function SetRow({ setNumber, inputFields = ["sets", "reps", "weight"], weightUnit = "lbs", initialReps, initialWeight, initialRpe, initialNotes, initialDuration, initialDistance, initialCalories, initialLocked = false, autoFocus = false, onUpdate, onConfirm, onNextSet, onDelete, }: SetRowProps) { const [reps, setReps] = useState(initialReps?.toString() || ""); const [weight, setWeight] = useState(initialWeight?.toString() || ""); const [rpe, setRpe] = useState(initialRpe?.toString() || ""); const [notes, setNotes] = useState(initialNotes || ""); const [duration, setDuration] = useState(initialDuration?.toString() || ""); const [distance, setDistance] = useState(initialDistance?.toString() || ""); const [calories, setCalories] = useState(initialCalories?.toString() || ""); const [showNotes, setShowNotes] = useState(!!initialNotes); const [locked, setLocked] = useState(initialLocked); const showReps = inputFields.includes("reps"); const showWeight = inputFields.includes("weight"); const showDuration = inputFields.includes("duration"); const showDistance = inputFields.includes("distance"); const showCalories = inputFields.includes("calories"); const showNotesField = inputFields.includes("notes"); const emitUpdate = useCallback( (overrides: { reps?: string; weight?: string; rpe?: string; notes?: string; duration?: string; distance?: string; calories?: string; }) => { const r = overrides.reps ?? reps; const w = overrides.weight ?? weight; const p = overrides.rpe ?? rpe; const n = overrides.notes ?? notes; const dur = overrides.duration ?? duration; const dist = overrides.distance ?? distance; const cal = overrides.calories ?? calories; onUpdate({ reps: r ? parseInt(r) : undefined, weight: w ? parseFloat(w) : undefined, rpe: p ? parseInt(p) : undefined, notes: n || undefined, durationSeconds: dur ? parseInt(dur) : undefined, distance: dist ? parseFloat(dist) : undefined, calories: cal ? parseInt(cal) : undefined, }); }, [reps, weight, rpe, notes, duration, distance, calories, onUpdate] ); const handleConfirm = () => { emitUpdate({}); setLocked(true); onConfirm?.(); }; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Enter") { e.preventDefault(); handleConfirm(); } }; const handleUnlock = () => { setLocked(false); }; const handleNextSet = () => { emitUpdate({}); setLocked(true); onNextSet?.({ weight, reps, rpe, notes, duration, distance, calories }); }; // Build a summary string for the locked view const buildSummary = () => { const parts: string[] = []; if (showWeight && weight) parts.push(`${weight} ${weightUnit}`); if (showReps && reps) parts.push(`${reps} reps`); if (showDuration && duration) parts.push(`${duration}s`); if (showDistance && distance) parts.push(`${distance} mi`); if (showCalories && calories) parts.push(`${calories} cal`); if (rpe) parts.push(`RPE ${rpe}`); if (showNotesField && notes) parts.push(notes); return parts.length > 0 ? parts.join(" ยท ") : "No data"; }; // ---------- LOCKED VIEW ---------- if (locked) { return (
{/* Set number badge */}
{setNumber}
{/* Summary text */}

{buildSummary()}

{!showNotesField && notes && (

{notes}

)}
{/* Edit (unlock) button */} {/* Delete button */}
); } // Determine which field gets autoFocus const firstField = showWeight ? "weight" : showReps ? "reps" : showDuration ? "duration" : showDistance ? "distance" : showCalories ? "calories" : null; // ---------- EDIT VIEW ---------- return (
{/* Set number badge */}
{setNumber}
{/* Weight input */} {showWeight && (
{ const val = e.target.value; setWeight(val); emitUpdate({ weight: val }); }} placeholder="0" className="w-full px-2 py-1.5 border border-zinc-700 rounded-md text-sm bg-zinc-800 text-white focus:outline-none focus:ring-2 focus:ring-white/20 placeholder:text-zinc-600" />
)} {/* Reps input */} {showReps && (
{ const val = e.target.value; setReps(val); emitUpdate({ reps: val }); }} placeholder="0" className="w-full px-2 py-1.5 border border-zinc-700 rounded-md text-sm bg-zinc-800 text-white focus:outline-none focus:ring-2 focus:ring-white/20 placeholder:text-zinc-600" />
)} {/* Duration input (seconds) */} {showDuration && (
{ const val = e.target.value; setDuration(val); emitUpdate({ duration: val }); }} placeholder="0" className="w-full px-2 py-1.5 border border-zinc-700 rounded-md text-sm bg-zinc-800 text-white focus:outline-none focus:ring-2 focus:ring-white/20 placeholder:text-zinc-600" />
)} {/* Distance input */} {showDistance && (
{ const val = e.target.value; setDistance(val); emitUpdate({ distance: val }); }} placeholder="0" className="w-full px-2 py-1.5 border border-zinc-700 rounded-md text-sm bg-zinc-800 text-white focus:outline-none focus:ring-2 focus:ring-white/20 placeholder:text-zinc-600" />
)} {/* Calories input */} {showCalories && (
{ const val = e.target.value; setCalories(val); emitUpdate({ calories: val }); }} placeholder="0" className="w-full px-2 py-1.5 border border-zinc-700 rounded-md text-sm bg-zinc-800 text-white focus:outline-none focus:ring-2 focus:ring-white/20 placeholder:text-zinc-600" />
)} {/* RPE select โ€” always shown */}
{/* Next set button โ€” confirm + add new pre-filled set */} {onNextSet && ( )} {/* Confirm button */} {/* Delete button */}
{/* Notes โ€” always visible when configured as input field */} {showNotesField && (
{ const val = e.target.value; setNotes(val); emitUpdate({ notes: val }); }} placeholder="e.g. weighted vest, ankle weights..." className="w-full px-2 py-1 border border-zinc-700 rounded-md text-xs bg-zinc-800 text-white focus:outline-none focus:ring-2 focus:ring-white/20 placeholder:text-zinc-600" />
)} {/* Toggle notes button (fallback when notes is not a configured input field) */} {!showNotesField && showNotes && (
{ const val = e.target.value; setNotes(val); emitUpdate({ notes: val }); }} placeholder="Add notes (optional)" className="w-full px-2 py-1 border border-zinc-700 rounded-md text-xs bg-zinc-800 text-white focus:outline-none focus:ring-2 focus:ring-white/20 placeholder:text-zinc-600" />
)} {!showNotesField && !showNotes && ( )}
); }