Skip to content

Conversation

@Molokai
Copy link
Contributor

@Molokai Molokai commented Sep 15, 2025

No description provided.

@tnn3 tnn3 requested a review from Copilot September 15, 2025 10:47
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a new gym workout tracker application as a single-file HTML implementation. The app provides comprehensive workout tracking functionality including exercise management, set recording, timing, and workout history.

Key Changes

  • Added a complete single-file gym workout tracker application with modern UI styling
  • Implemented workout session management with timer, pause/resume functionality
  • Created exercise and set tracking with weight/reps input and historical data

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

<html lang="en">
<head>
<meta charset="utf-8" />
<title>Gym Workout Tracker — Single‑File App</title>
Copy link

Copilot AI Sep 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The title uses a non-standard en dash character (—) and a non-breaking hyphen (‑). For better compatibility and consistency, use standard ASCII characters: 'Gym Workout Tracker - Single-File App'.

Suggested change
<title>Gym Workout Tracker SingleFile App</title>
<title>Gym Workout Tracker - Single-File App</title>

Copilot uses AI. Check for mistakes.
Comment on lines +297 to +298
const toInt = v => Number.isFinite(+v) ? parseInt(v,10) : 0;
const toFloat = v => Number.isFinite(+v) ? parseFloat(v) : 0;
Copy link

Copilot AI Sep 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These utility functions don't handle edge cases properly. They will return 0 for empty strings, which may not be the intended behavior. Consider returning NaN or null for invalid inputs to distinguish between actual zero values and invalid inputs.

Suggested change
const toInt = v => Number.isFinite(+v) ? parseInt(v,10) : 0;
const toFloat = v => Number.isFinite(+v) ? parseFloat(v) : 0;
const toInt = v => {
if (v === '' || v === null || v === undefined || isNaN(+v)) return NaN;
return parseInt(v, 10);
};
const toFloat = v => {
if (v === '' || v === null || v === undefined || isNaN(+v)) return NaN;
return parseFloat(v);
};

Copilot uses AI. Check for mistakes.
Comment on lines +337 to +343
} catch{ state.workouts = []; }
try {
state.current = JSON.parse(localStorage.getItem(KEYS.CURRENT) || 'null');
} catch{ state.current = null; }
try {
state.catalog = JSON.parse(localStorage.getItem(KEYS.EXERCISES) || '[]');
} catch{ state.catalog = []; }
Copy link

Copilot AI Sep 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing error parameter in catch blocks. While technically valid in modern JavaScript, it's better practice to include the error parameter for debugging purposes: catch(e) { ... }.

Suggested change
} catch{ state.workouts = []; }
try {
state.current = JSON.parse(localStorage.getItem(KEYS.CURRENT) || 'null');
} catch{ state.current = null; }
try {
state.catalog = JSON.parse(localStorage.getItem(KEYS.EXERCISES) || '[]');
} catch{ state.catalog = []; }
} catch(e){ state.workouts = []; }
try {
state.current = JSON.parse(localStorage.getItem(KEYS.CURRENT) || 'null');
} catch(e){ state.current = null; }
try {
state.catalog = JSON.parse(localStorage.getItem(KEYS.EXERCISES) || '[]');
} catch(e){ state.catalog = []; }

Copilot uses AI. Check for mistakes.
Comment on lines +337 to +343
} catch{ state.workouts = []; }
try {
state.current = JSON.parse(localStorage.getItem(KEYS.CURRENT) || 'null');
} catch{ state.current = null; }
try {
state.catalog = JSON.parse(localStorage.getItem(KEYS.EXERCISES) || '[]');
} catch{ state.catalog = []; }
Copy link

Copilot AI Sep 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing error parameter in catch blocks. While technically valid in modern JavaScript, it's better practice to include the error parameter for debugging purposes: catch(e) { ... }.

Suggested change
} catch{ state.workouts = []; }
try {
state.current = JSON.parse(localStorage.getItem(KEYS.CURRENT) || 'null');
} catch{ state.current = null; }
try {
state.catalog = JSON.parse(localStorage.getItem(KEYS.EXERCISES) || '[]');
} catch{ state.catalog = []; }
} catch(e){ state.workouts = []; }
try {
state.current = JSON.parse(localStorage.getItem(KEYS.CURRENT) || 'null');
} catch(e){ state.current = null; }
try {
state.catalog = JSON.parse(localStorage.getItem(KEYS.EXERCISES) || '[]');
} catch(e){ state.catalog = []; }

Copilot uses AI. Check for mistakes.
Comment on lines +337 to +343
} catch{ state.workouts = []; }
try {
state.current = JSON.parse(localStorage.getItem(KEYS.CURRENT) || 'null');
} catch{ state.current = null; }
try {
state.catalog = JSON.parse(localStorage.getItem(KEYS.EXERCISES) || '[]');
} catch{ state.catalog = []; }
Copy link

Copilot AI Sep 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing error parameter in catch blocks. While technically valid in modern JavaScript, it's better practice to include the error parameter for debugging purposes: catch(e) { ... }.

Suggested change
} catch{ state.workouts = []; }
try {
state.current = JSON.parse(localStorage.getItem(KEYS.CURRENT) || 'null');
} catch{ state.current = null; }
try {
state.catalog = JSON.parse(localStorage.getItem(KEYS.EXERCISES) || '[]');
} catch{ state.catalog = []; }
} catch(e){ state.workouts = []; }
try {
state.current = JSON.parse(localStorage.getItem(KEYS.CURRENT) || 'null');
} catch(e){ state.current = null; }
try {
state.catalog = JSON.parse(localStorage.getItem(KEYS.EXERCISES) || '[]');
} catch(e){ state.catalog = []; }

Copilot uses AI. Check for mistakes.
Comment on lines +517 to +518
const base = now() - state.current.startTime - (state.current.pauseAccum||0) - (paused ? (now() - state.current.pausedAt) : 0);
$('#timer').textContent = fmtTime(base);
Copy link

Copilot AI Sep 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This complex timer calculation is difficult to read and understand. Consider breaking it into intermediate variables with descriptive names to improve readability and maintainability.

Suggested change
const base = now() - state.current.startTime - (state.current.pauseAccum||0) - (paused ? (now() - state.current.pausedAt) : 0);
$('#timer').textContent = fmtTime(base);
const elapsedSinceStart = now() - state.current.startTime;
const totalPauseAccum = state.current.pauseAccum || 0;
const currentPauseDuration = paused ? (now() - state.current.pausedAt) : 0;
const activeWorkoutTime = elapsedSinceStart - totalPauseAccum - currentPauseDuration;
$('#timer').textContent = fmtTime(activeWorkoutTime);

Copilot uses AI. Check for mistakes.
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `gym-workout-tracker-${new Date().toISOString().slice(0,19).replace(/[:T]/g,'-')}.json`;
Copy link

Copilot AI Sep 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The date formatting logic is complex and hard to read. Consider extracting this into a separate function or using a more readable approach to format the timestamp for the filename.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant