diff --git a/.gitignore b/.gitignore index cb5b281..3c3bbbb 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,7 @@ node_modules dist dist-ssr *.local -server/prisma/dev.db +*.db # Editor directories and files .vscode/* diff --git a/components/History.tsx b/components/History.tsx index 112ffca..67a08aa 100644 --- a/components/History.tsx +++ b/components/History.tsx @@ -41,6 +41,23 @@ const History: React.FC = ({ sessions, onUpdateSession, onDeleteSe return new Date(value).getTime(); }; + const formatDuration = (startTime: number, endTime?: number) => { + if (!endTime || isNaN(endTime) || isNaN(startTime)) return ''; + const durationMs = endTime - startTime; + if (durationMs < 0 || isNaN(durationMs)) return ''; + + const hours = Math.floor(durationMs / 3600000); + const minutes = Math.floor((durationMs % 3600000) / 60000); + + if (hours > 0) { + return `${hours}h ${minutes}m`; + } + if (minutes < 1) { + return '<1m'; + } + return `${minutes}m`; + }; + const handleSaveEdit = () => { if (editingSession && onUpdateSession) { onUpdateSession(editingSession); @@ -91,81 +108,66 @@ const History: React.FC = ({ sessions, onUpdateSession, onDeleteSe const totalWork = calculateSessionWork(session); return ( -
-
-
-
- +
setEditingSession(JSON.parse(JSON.stringify(session)))} + > +
+
+
+ + {new Date(session.startTime).toISOString().split('T')[0]} + + + {new Date(session.startTime).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} + + {session.endTime && ( + + {formatDuration(session.startTime, session.endTime)} + + )} + + {session.planName || t('no_plan', lang)} + + {session.userBodyWeight && ( + + {session.userBodyWeight}kg + + )}
-
-
- {new Date(session.startTime).toLocaleDateString(lang === 'ru' ? 'ru-RU' : 'en-US', { weekday: 'long', day: 'numeric', month: 'long' })} -
-
- {new Date(session.startTime).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} - {session.userBodyWeight && {session.userBodyWeight}kg} -
+
+ {t('sets_count', lang)}: {session.sets.length} + {totalWork > 0 && ( + + + {(totalWork / 1000).toFixed(1)}t + + )}
- -
- {Array.from(new Set(session.sets.map(s => s.exerciseName))).slice(0, 4).map(exName => { - const sets = session.sets.filter(s => s.exerciseName === exName); - const count = sets.length; - const bestSet = sets[0]; - let detail = ""; - if (bestSet.type === ExerciseType.HIGH_JUMP) detail = `${t('max', lang)}: ${Math.max(...sets.map(s => s.height || 0))}cm`; - else if (bestSet.type === ExerciseType.LONG_JUMP) detail = `${t('max', lang)}: ${Math.max(...sets.map(s => s.distanceMeters || 0))}m`; - else if (bestSet.type === ExerciseType.STRENGTH) detail = `${t('upto', lang)} ${Math.max(...sets.map(s => s.weight || 0))}kg`; - - return ( -
- {exName} - - {detail && {detail}} - {count} - -
- ); - })} - {new Set(session.sets.map(s => s.exerciseName)).size > 4 && ( -
- + ... -
- )} -
- -
-
- {t('sets_count', lang)}: {session.sets.length} - {totalWork > 0 && ( - - - {(totalWork / 1000).toFixed(1)}t - - )} -
-
- - {t('finished', lang)} -
-
) })} @@ -251,8 +253,12 @@ const History: React.FC = ({ sessions, onUpdateSession, onDeleteSe {idx + 1} {set.exerciseName}
-
@@ -290,7 +296,39 @@ const History: React.FC = ({ sessions, onUpdateSession, onDeleteSe />
)} - {/* Add other fields similarly styled if needed */} + {(set.type === ExerciseType.CARDIO || set.type === ExerciseType.STATIC) && ( +
+ + handleUpdateSet(set.id, 'durationSeconds', parseFloat(e.target.value))} + /> +
+ )} + {(set.type === ExerciseType.CARDIO || set.type === ExerciseType.LONG_JUMP) && ( +
+ + handleUpdateSet(set.id, 'distanceMeters', parseFloat(e.target.value))} + /> +
+ )} + {(set.type === ExerciseType.HIGH_JUMP) && ( +
+ + handleUpdateSet(set.id, 'height', parseFloat(e.target.value))} + /> +
+ )}
))} diff --git a/server/prisma/dev.db b/server/prisma/dev.db index eb06540..2911abf 100644 Binary files a/server/prisma/dev.db and b/server/prisma/dev.db differ diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index 1e3235c..3fefc09 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -57,6 +57,8 @@ model WorkoutSession { endTime DateTime? userBodyWeight Float? note String? + planId String? + planName String? sets WorkoutSet[] } diff --git a/server/src/routes/sessions.ts b/server/src/routes/sessions.ts index ae4928f..80954f6 100644 --- a/server/src/routes/sessions.ts +++ b/server/src/routes/sessions.ts @@ -40,7 +40,7 @@ router.get('/', async (req: any, res) => { router.post('/', async (req: any, res) => { try { const userId = req.user.userId; - const { id, startTime, endTime, userBodyWeight, note, sets } = req.body; + const { id, startTime, endTime, userBodyWeight, note, planId, planName, sets } = req.body; // Convert timestamps to Date objects if they are numbers const start = new Date(startTime); @@ -62,6 +62,8 @@ router.post('/', async (req: any, res) => { endTime: end, userBodyWeight: weight, note, + planId, + planName, sets: { create: sets.map((s: any, idx: number) => ({ exerciseId: s.exerciseId, @@ -87,6 +89,8 @@ router.post('/', async (req: any, res) => { endTime: end, userBodyWeight: weight, note, + planId, + planName, sets: { create: sets.map((s: any, idx: number) => ({ exerciseId: s.exerciseId, diff --git a/services/i18n.ts b/services/i18n.ts index 12d1632..321b166 100644 --- a/services/i18n.ts +++ b/services/i18n.ts @@ -92,6 +92,7 @@ const translations = { end_time: 'End', max: 'Max', upto: 'Up to', + no_plan: 'No plan', // Plans plans_empty: 'No plans created', @@ -232,6 +233,7 @@ const translations = { end_time: 'Конец', max: 'Макс', upto: 'До', + no_plan: 'Без плана', // Plans plans_empty: 'Нет созданных планов', diff --git a/services/storage.ts b/services/storage.ts index ce20261..3f79ca0 100644 --- a/services/storage.ts +++ b/services/storage.ts @@ -3,7 +3,13 @@ import { api } from './api'; export const getSessions = async (userId: string): Promise => { try { - return await api.get('/sessions'); + const sessions = await api.get('/sessions'); + // Convert ISO date strings to timestamps + return sessions.map((session: any) => ({ + ...session, + startTime: new Date(session.startTime).getTime(), + endTime: session.endTime ? new Date(session.endTime).getTime() : undefined + })); } catch { return []; }