jrrade commited on
Commit
ffd507a
·
verified ·
1 Parent(s): 84f47ed

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +852 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Myworkouts
3
- emoji: 🏢
4
- colorFrom: red
5
- colorTo: pink
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: myworkouts
3
+ emoji: 🐳
4
+ colorFrom: pink
5
+ colorTo: yellow
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,852 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Workout Logger - Push Legs Pull Split</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .fade-in {
11
+ animation: fadeIn 0.3s ease-in-out;
12
+ }
13
+ @keyframes fadeIn {
14
+ from { opacity: 0; transform: translateY(10px); }
15
+ to { opacity: 1; transform: translateY(0); }
16
+ }
17
+ .workout-day.active {
18
+ box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.5);
19
+ }
20
+ .progress-bar {
21
+ transition: width 0.5s ease-in-out;
22
+ }
23
+ .history-item {
24
+ transition: all 0.2s ease;
25
+ cursor: pointer;
26
+ }
27
+ .history-item:hover {
28
+ transform: translateY(-2px);
29
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
30
+ }
31
+ .history-item.active {
32
+ border-left: 4px solid #3b82f6;
33
+ }
34
+ .history-exercises {
35
+ max-height: 0;
36
+ overflow: hidden;
37
+ transition: max-height 0.3s ease;
38
+ }
39
+ .history-exercises.show {
40
+ max-height: 1000px;
41
+ }
42
+ .edit-history-form {
43
+ background-color: rgba(243, 244, 246, 0.8);
44
+ backdrop-filter: blur(5px);
45
+ }
46
+ </style>
47
+ </head>
48
+ <body class="bg-gray-100 min-h-screen">
49
+ <div class="container mx-auto px-4 py-8 max-w-4xl">
50
+ <!-- Header -->
51
+ <header class="mb-8 text-center">
52
+ <h1 class="text-4xl font-bold text-blue-600 mb-2">Workout Logger</h1>
53
+ <p class="text-gray-600">Track your Push, Legs, Pull split progress</p>
54
+ </header>
55
+
56
+ <!-- Week Navigation -->
57
+ <div class="bg-white rounded-xl shadow-md p-4 mb-6">
58
+ <div class="flex justify-between items-center mb-4">
59
+ <h2 class="text-xl font-semibold text-gray-800">This Week</h2>
60
+ <div class="flex space-x-2">
61
+ <button id="prev-week" class="p-2 rounded-full bg-gray-200 hover:bg-gray-300">
62
+ <i class="fas fa-chevron-left"></i>
63
+ </button>
64
+ <button id="next-week" class="p-2 rounded-full bg-gray-200 hover:bg-gray-300">
65
+ <i class="fas fa-chevron-right"></i>
66
+ </button>
67
+ </div>
68
+ </div>
69
+
70
+ <div class="grid grid-cols-6 gap-2">
71
+ <div class="workout-day rounded-lg p-3 text-center cursor-pointer transition-all" data-day="monday" data-type="push">
72
+ <div class="font-medium">Monday</div>
73
+ <div class="text-xs text-blue-500">Push</div>
74
+ </div>
75
+ <div class="workout-day rounded-lg p-3 text-center cursor-pointer transition-all" data-day="tuesday" data-type="pull">
76
+ <div class="font-medium">Tuesday</div>
77
+ <div class="text-xs text-green-500">Pull</div>
78
+ </div>
79
+ <div class="workout-day rounded-lg p-3 text-center cursor-pointer transition-all" data-day="wednesday" data-type="legs">
80
+ <div class="font-medium">Wednesday</div>
81
+ <div class="text-xs text-purple-500">Legs</div>
82
+ </div>
83
+ <div class="workout-day rounded-lg p-3 text-center cursor-pointer transition-all" data-day="thursday" data-type="push">
84
+ <div class="font-medium">Thursday</div>
85
+ <div class="text-xs text-blue-500">Push</div>
86
+ </div>
87
+ <div class="workout-day rounded-lg p-3 text-center cursor-pointer transition-all" data-day="friday" data-type="pull">
88
+ <div class="font-medium">Friday</div>
89
+ <div class="text-xs text-green-500">Pull</div>
90
+ </div>
91
+ <div class="workout-day rounded-lg p-3 text-center cursor-pointer transition-all" data-day="saturday" data-type="legs">
92
+ <div class="font-medium">Saturday</div>
93
+ <div class="text-xs text-purple-500">Legs</div>
94
+ </div>
95
+ </div>
96
+ </div>
97
+
98
+ <!-- Current Workout -->
99
+ <div id="current-workout" class="bg-white rounded-xl shadow-md p-6 mb-6 fade-in">
100
+ <div class="flex justify-between items-center mb-4">
101
+ <h2 class="text-xl font-semibold text-gray-800">
102
+ <span id="current-day">Monday</span> -
103
+ <span id="workout-type" class="text-blue-500">Push</span>
104
+ </h2>
105
+ <div class="text-sm text-gray-500" id="workout-date">June 12, 2023</div>
106
+ </div>
107
+
108
+ <!-- Progress -->
109
+ <div class="mb-6">
110
+ <div class="flex justify-between text-sm mb-1">
111
+ <span>Workout Progress</span>
112
+ <span id="progress-percent">0%</span>
113
+ </div>
114
+ <div class="w-full bg-gray-200 rounded-full h-2.5">
115
+ <div id="progress-bar" class="progress-bar h-2.5 rounded-full bg-blue-500" style="width: 0%"></div>
116
+ </div>
117
+ </div>
118
+
119
+ <!-- Exercises List -->
120
+ <div id="exercises-container" class="mb-6">
121
+ <!-- Exercises will be added here -->
122
+ </div>
123
+
124
+ <!-- Add Exercise Form -->
125
+ <div class="bg-gray-50 p-4 rounded-lg">
126
+ <h3 class="font-medium mb-3">Add New Exercise</h3>
127
+ <div class="grid grid-cols-1 md:grid-cols-4 gap-3">
128
+ <div>
129
+ <label class="block text-sm font-medium text-gray-700 mb-1">Exercise</label>
130
+ <input type="text" id="exercise-name" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Bench Press">
131
+ </div>
132
+ <div>
133
+ <label class="block text-sm font-medium text-gray-700 mb-1">Weight (lbs)</label>
134
+ <input type="number" id="exercise-weight" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="45">
135
+ </div>
136
+ <div>
137
+ <label class="block text-sm font-medium text-gray-700 mb-1">Sets</label>
138
+ <input type="number" id="exercise-sets" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="3" value="3">
139
+ </div>
140
+ <div>
141
+ <label class="block text-sm font-medium text-gray-700 mb-1">Reps</label>
142
+ <input type="number" id="exercise-reps" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="10" value="10">
143
+ </div>
144
+ </div>
145
+ <button id="add-exercise" class="mt-4 w-full bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-md transition-colors">
146
+ <i class="fas fa-plus mr-2"></i> Add Exercise
147
+ </button>
148
+ </div>
149
+ </div>
150
+
151
+ <!-- Workout History -->
152
+ <div class="bg-white rounded-xl shadow-md p-6">
153
+ <div class="flex justify-between items-center mb-4">
154
+ <h2 class="text-xl font-semibold text-gray-800">Workout History</h2>
155
+ <button id="toggle-history-view" class="text-sm text-blue-600 hover:text-blue-800">
156
+ <i class="fas fa-list mr-1"></i> Toggle View
157
+ </button>
158
+ </div>
159
+ <div id="history-container">
160
+ <!-- History items will be added here -->
161
+ <div class="text-center py-8 text-gray-400">
162
+ <i class="fas fa-dumbbell text-4xl mb-2"></i>
163
+ <p>Your workout history will appear here</p>
164
+ </div>
165
+ </div>
166
+ </div>
167
+ </div>
168
+
169
+ <!-- Edit History Modal -->
170
+ <div id="edit-history-modal" class="fixed inset-0 z-50 flex items-center justify-center hidden">
171
+ <div class="absolute inset-0 bg-black bg-opacity-50"></div>
172
+ <div class="edit-history-form relative bg-white rounded-xl shadow-xl p-6 w-full max-w-2xl max-h-[90vh] overflow-y-auto">
173
+ <div class="flex justify-between items-center mb-4">
174
+ <h3 class="text-xl font-semibold">Edit Workout</h3>
175
+ <button id="close-edit-modal" class="text-gray-500 hover:text-gray-700">
176
+ <i class="fas fa-times"></i>
177
+ </button>
178
+ </div>
179
+ <div id="edit-history-content">
180
+ <!-- Content will be added here -->
181
+ </div>
182
+ </div>
183
+ </div>
184
+
185
+ <script>
186
+ document.addEventListener('DOMContentLoaded', function() {
187
+ // DOM Elements
188
+ const workoutDays = document.querySelectorAll('.workout-day');
189
+ const currentDayElement = document.getElementById('current-day');
190
+ const workoutTypeElement = document.getElementById('workout-type');
191
+ const workoutDateElement = document.getElementById('workout-date');
192
+ const exercisesContainer = document.getElementById('exercises-container');
193
+ const historyContainer = document.getElementById('history-container');
194
+ const progressBar = document.getElementById('progress-bar');
195
+ const progressPercent = document.getElementById('progress-percent');
196
+ const toggleHistoryViewBtn = document.getElementById('toggle-history-view');
197
+ const editHistoryModal = document.getElementById('edit-history-modal');
198
+ const editHistoryContent = document.getElementById('edit-history-content');
199
+ const closeEditModalBtn = document.getElementById('close-edit-modal');
200
+
201
+ // Form elements
202
+ const exerciseNameInput = document.getElementById('exercise-name');
203
+ const exerciseWeightInput = document.getElementById('exercise-weight');
204
+ const exerciseSetsInput = document.getElementById('exercise-sets');
205
+ const exerciseRepsInput = document.getElementById('exercise-reps');
206
+ const addExerciseBtn = document.getElementById('add-exercise');
207
+
208
+ // Data
209
+ let currentDay = 'monday';
210
+ let currentWorkoutType = 'push';
211
+ let workouts = {
212
+ monday: { exercises: [], completed: false, date: new Date().toISOString() },
213
+ tuesday: { exercises: [], completed: false, date: new Date().toISOString() },
214
+ wednesday: { exercises: [], completed: false, date: new Date().toISOString() },
215
+ thursday: { exercises: [], completed: false, date: new Date().toISOString() },
216
+ friday: { exercises: [], completed: false, date: new Date().toISOString() },
217
+ saturday: { exercises: [], completed: false, date: new Date().toISOString() }
218
+ };
219
+
220
+ // View state
221
+ let historyViewMode = 'detailed'; // 'detailed' or 'compact'
222
+
223
+ // Initialize the app
224
+ initApp();
225
+
226
+ // Event Listeners
227
+ workoutDays.forEach(day => {
228
+ day.addEventListener('click', function() {
229
+ currentDay = this.dataset.day;
230
+ currentWorkoutType = this.dataset.type;
231
+ updateUI();
232
+ });
233
+ });
234
+
235
+ addExerciseBtn.addEventListener('click', addExercise);
236
+ toggleHistoryViewBtn.addEventListener('click', toggleHistoryView);
237
+ closeEditModalBtn.addEventListener('click', () => editHistoryModal.classList.add('hidden'));
238
+
239
+ // Functions
240
+ function initApp() {
241
+ // Load data from localStorage if available
242
+ const savedWorkouts = localStorage.getItem('workoutLoggerData');
243
+ if (savedWorkouts) {
244
+ workouts = JSON.parse(savedWorkouts);
245
+
246
+ // Ensure all dates are properly formatted
247
+ Object.keys(workouts).forEach(day => {
248
+ if (workouts[day].date) {
249
+ // If date is already in ISO format, keep it
250
+ if (typeof workouts[day].date === 'string' && workouts[day].date.includes('T')) {
251
+ return;
252
+ }
253
+ // Otherwise, convert to ISO format
254
+ workouts[day].date = new Date(workouts[day].date).toISOString();
255
+ } else {
256
+ workouts[day].date = new Date().toISOString();
257
+ }
258
+
259
+ // Ensure each exercise has a date
260
+ workouts[day].exercises.forEach(exercise => {
261
+ if (!exercise.date) {
262
+ exercise.date = workouts[day].date;
263
+ } else if (!exercise.date.includes('T')) {
264
+ exercise.date = new Date(exercise.date).toISOString();
265
+ }
266
+ });
267
+ });
268
+ }
269
+
270
+ // Set current date
271
+ updateDate();
272
+
273
+ // Initialize UI
274
+ updateUI();
275
+ loadHistory();
276
+ }
277
+
278
+ function updateDate() {
279
+ const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
280
+ const today = new Date();
281
+ workoutDateElement.textContent = today.toLocaleDateString('en-US', options);
282
+ }
283
+
284
+ function updateUI() {
285
+ // Update active day
286
+ workoutDays.forEach(day => {
287
+ day.classList.remove('active', 'bg-blue-50', 'bg-green-50', 'bg-purple-50');
288
+ if (day.dataset.day === currentDay) {
289
+ day.classList.add('active');
290
+ if (day.dataset.type === 'push') day.classList.add('bg-blue-50');
291
+ if (day.dataset.type === 'pull') day.classList.add('bg-green-50');
292
+ if (day.dataset.type === 'legs') day.classList.add('bg-purple-50');
293
+ }
294
+ });
295
+
296
+ // Update header
297
+ currentDayElement.textContent = currentDay.charAt(0).toUpperCase() + currentDay.slice(1);
298
+ workoutTypeElement.textContent = currentWorkoutType.charAt(0).toUpperCase() + currentWorkoutType.slice(1);
299
+
300
+ // Update color based on workout type
301
+ workoutTypeElement.className = '';
302
+ if (currentWorkoutType === 'push') workoutTypeElement.classList.add('text-blue-500');
303
+ if (currentWorkoutType === 'pull') workoutTypeElement.classList.add('text-green-500');
304
+ if (currentWorkoutType === 'legs') workoutTypeElement.classList.add('text-purple-500');
305
+
306
+ // Update exercises list
307
+ renderExercises();
308
+
309
+ // Update progress
310
+ updateProgress();
311
+ }
312
+
313
+ function renderExercises() {
314
+ exercisesContainer.innerHTML = '';
315
+
316
+ const dayExercises = workouts[currentDay].exercises;
317
+
318
+ if (dayExercises.length === 0) {
319
+ exercisesContainer.innerHTML = `
320
+ <div class="text-center py-8 text-gray-400">
321
+ <i class="fas fa-plus-circle text-4xl mb-2"></i>
322
+ <p>Add your first exercise to get started</p>
323
+ </div>
324
+ `;
325
+ return;
326
+ }
327
+
328
+ dayExercises.forEach((exercise, index) => {
329
+ const exerciseElement = document.createElement('div');
330
+ exerciseElement.className = 'exercise-item bg-gray-50 rounded-lg p-4 mb-3 fade-in';
331
+ exerciseElement.innerHTML = `
332
+ <div class="flex justify-between items-start mb-2">
333
+ <h3 class="font-medium">${exercise.name}</h3>
334
+ <div class="flex space-x-2">
335
+ <button class="edit-exercise p-1 text-blue-500 hover:text-blue-700" data-index="${index}">
336
+ <i class="fas fa-edit"></i>
337
+ </button>
338
+ <button class="delete-exercise p-1 text-red-500 hover:text-red-700" data-index="${index}">
339
+ <i class="fas fa-trash"></i>
340
+ </button>
341
+ </div>
342
+ </div>
343
+ <div class="grid grid-cols-3 gap-2 text-sm">
344
+ <div class="bg-white p-2 rounded">
345
+ <div class="text-gray-500">Weight</div>
346
+ <div>${exercise.weight} lbs</div>
347
+ </div>
348
+ <div class="bg-white p-2 rounded">
349
+ <div class="text-gray-500">Sets</div>
350
+ <div>${exercise.sets}</div>
351
+ </div>
352
+ <div class="bg-white p-2 rounded">
353
+ <div class="text-gray-500">Reps</div>
354
+ <div>${exercise.reps}</div>
355
+ </div>
356
+ </div>
357
+ <div class="text-xs text-gray-400 mt-1">${formatShortDate(exercise.date)}</div>
358
+ `;
359
+ exercisesContainer.appendChild(exerciseElement);
360
+ });
361
+
362
+ // Add event listeners to delete buttons
363
+ document.querySelectorAll('.delete-exercise').forEach(btn => {
364
+ btn.addEventListener('click', function() {
365
+ const index = parseInt(this.dataset.index);
366
+ deleteExercise(index);
367
+ });
368
+ });
369
+
370
+ // Add event listeners to edit buttons
371
+ document.querySelectorAll('.edit-exercise').forEach(btn => {
372
+ btn.addEventListener('click', function() {
373
+ const index = parseInt(this.dataset.index);
374
+ editExercise(index);
375
+ });
376
+ });
377
+ }
378
+
379
+ function addExercise() {
380
+ const name = exerciseNameInput.value.trim();
381
+ const weight = parseFloat(exerciseWeightInput.value);
382
+ const sets = parseInt(exerciseSetsInput.value);
383
+ const reps = parseInt(exerciseRepsInput.value);
384
+
385
+ if (!name || isNaN(weight) || isNaN(sets) || isNaN(reps)) {
386
+ alert('Please fill in all fields with valid values');
387
+ return;
388
+ }
389
+
390
+ const newExercise = {
391
+ name,
392
+ weight,
393
+ sets,
394
+ reps,
395
+ date: new Date().toISOString()
396
+ };
397
+
398
+ workouts[currentDay].exercises.push(newExercise);
399
+ workouts[currentDay].completed = workouts[currentDay].exercises.length > 0;
400
+ workouts[currentDay].date = new Date().toISOString();
401
+ saveData();
402
+ updateUI();
403
+ loadHistory();
404
+
405
+ // Reset form
406
+ exerciseNameInput.value = '';
407
+ exerciseWeightInput.value = '';
408
+ exerciseSetsInput.value = '3';
409
+ exerciseRepsInput.value = '10';
410
+ exerciseNameInput.focus();
411
+ }
412
+
413
+ function deleteExercise(index) {
414
+ if (confirm('Are you sure you want to delete this exercise?')) {
415
+ workouts[currentDay].exercises.splice(index, 1);
416
+ workouts[currentDay].completed = workouts[currentDay].exercises.length > 0;
417
+ saveData();
418
+ updateUI();
419
+ loadHistory();
420
+ }
421
+ }
422
+
423
+ function editExercise(index) {
424
+ const exercise = workouts[currentDay].exercises[index];
425
+
426
+ // Fill the form with exercise data
427
+ exerciseNameInput.value = exercise.name;
428
+ exerciseWeightInput.value = exercise.weight;
429
+ exerciseSetsInput.value = exercise.sets;
430
+ exerciseRepsInput.value = exercise.reps;
431
+
432
+ // Delete the exercise (we'll add it again when saved)
433
+ workouts[currentDay].exercises.splice(index, 1);
434
+ updateUI();
435
+ loadHistory();
436
+
437
+ // Focus on the name field
438
+ exerciseNameInput.focus();
439
+ }
440
+
441
+ function updateProgress() {
442
+ const dayExercises = workouts[currentDay].exercises;
443
+ const totalExercises = dayExercises.length;
444
+
445
+ // Simple progress calculation (could be enhanced)
446
+ const progress = totalExercises > 0 ? Math.min(100, totalExercises * 20) : 0;
447
+
448
+ progressBar.style.width = `${progress}%`;
449
+ progressPercent.textContent = `${progress}%`;
450
+
451
+ // Change color based on progress
452
+ progressBar.className = 'progress-bar h-2.5 rounded-full';
453
+ if (progress < 30) progressBar.classList.add('bg-red-500');
454
+ else if (progress < 70) progressBar.classList.add('bg-yellow-500');
455
+ else progressBar.classList.add('bg-green-500');
456
+ }
457
+
458
+ function saveData() {
459
+ localStorage.setItem('workoutLoggerData', JSON.stringify(workouts));
460
+ }
461
+
462
+ function loadHistory() {
463
+ historyContainer.innerHTML = '';
464
+
465
+ // Get all workout days that have exercises
466
+ const workoutDaysWithData = Object.entries(workouts)
467
+ .filter(([day, data]) => data.exercises.length > 0)
468
+ .sort((a, b) => new Date(b[1].date) - new Date(a[1].date));
469
+
470
+ if (workoutDaysWithData.length === 0) {
471
+ historyContainer.innerHTML = `
472
+ <div class="text-center py-8 text-gray-400">
473
+ <i class="fas fa-dumbbell text-4xl mb-2"></i>
474
+ <p>Your workout history will appear here</p>
475
+ </div>
476
+ `;
477
+ return;
478
+ }
479
+
480
+ workoutDaysWithData.forEach(([day, workoutData]) => {
481
+ const historyItem = document.createElement('div');
482
+ historyItem.className = 'history-item bg-gray-50 rounded-lg p-4 mb-3';
483
+
484
+ if (historyViewMode === 'detailed') {
485
+ historyItem.innerHTML = `
486
+ <div class="flex justify-between items-center mb-2">
487
+ <div>
488
+ <h3 class="font-medium">${day.charAt(0).toUpperCase() + day.slice(1)} -
489
+ <span class="${getWorkoutTypeColorClass(day)}">
490
+ ${getWorkoutType(day)}
491
+ </span></h3>
492
+ <div class="text-xs text-gray-500">${formatDate(workoutData.date)}</div>
493
+ </div>
494
+ <div class="flex space-x-2">
495
+ <button class="edit-history p-1 text-blue-500 hover:text-blue-700" data-day="${day}">
496
+ <i class="fas fa-edit"></i>
497
+ </button>
498
+ <span class="text-sm text-gray-500">${workoutData.exercises.length} ex.</span>
499
+ </div>
500
+ </div>
501
+ <div class="flex space-x-2 text-sm mb-2">
502
+ <span class="bg-blue-100 text-blue-800 px-2 py-1 rounded">${workoutData.completed ? 'Completed' : 'In Progress'}</span>
503
+ <span class="bg-green-100 text-green-800 px-2 py-1 rounded">${formatShortDate(workoutData.date)}</span>
504
+ </div>
505
+ <div class="history-exercises">
506
+ ${renderHistoryExercises(workoutData.exercises)}
507
+ </div>
508
+ `;
509
+ } else {
510
+ historyItem.innerHTML = `
511
+ <div class="flex justify-between items-center">
512
+ <div>
513
+ <h3 class="font-medium">${day.charAt(0).toUpperCase() + day.slice(1)} -
514
+ <span class="${getWorkoutTypeColorClass(day)}">
515
+ ${getWorkoutType(day)}
516
+ </span></h3>
517
+ <div class="text-xs text-gray-500">${formatDate(workoutData.date)}</div>
518
+ </div>
519
+ <div class="flex space-x-2 items-center">
520
+ <button class="edit-history p-1 text-blue-500 hover:text-blue-700" data-day="${day}">
521
+ <i class="fas fa-edit"></i>
522
+ </button>
523
+ <span class="text-sm bg-blue-100 text-blue-800 px-2 py-1 rounded">${workoutData.exercises.length} ex.</span>
524
+ </div>
525
+ </div>
526
+ `;
527
+ }
528
+
529
+ historyContainer.appendChild(historyItem);
530
+
531
+ // Add click event to toggle exercises visibility (detailed view only)
532
+ if (historyViewMode === 'detailed') {
533
+ const header = historyItem.querySelector('.flex.justify-between.items-center');
534
+ const exercisesSection = historyItem.querySelector('.history-exercises');
535
+
536
+ header.addEventListener('click', function(e) {
537
+ // Don't toggle if clicking the edit button
538
+ if (!e.target.closest('.edit-history')) {
539
+ historyItem.classList.toggle('active');
540
+ exercisesSection.classList.toggle('show');
541
+ }
542
+ });
543
+ }
544
+
545
+ // Add event listener to edit button
546
+ historyItem.querySelector('.edit-history').addEventListener('click', function() {
547
+ const day = this.dataset.day;
548
+ openEditHistoryModal(day);
549
+ });
550
+ });
551
+ }
552
+
553
+ function renderHistoryExercises(exercises) {
554
+ if (exercises.length === 0) return '';
555
+
556
+ let html = '<div class="space-y-2">';
557
+ exercises.forEach((exercise, index) => {
558
+ html += `
559
+ <div class="bg-white p-3 rounded-lg border border-gray-200">
560
+ <div class="flex justify-between items-start">
561
+ <div class="font-medium">${exercise.name}</div>
562
+ <div class="flex space-x-2">
563
+ <button class="edit-history-exercise p-1 text-blue-500 hover:text-blue-700" data-index="${index}">
564
+ <i class="fas fa-edit"></i>
565
+ </button>
566
+ <button class="delete-history-exercise p-1 text-red-500 hover:text-red-700" data-index="${index}">
567
+ <i class="fas fa-trash"></i>
568
+ </button>
569
+ </div>
570
+ </div>
571
+ <div class="grid grid-cols-3 gap-2 text-sm mt-2">
572
+ <div>
573
+ <div class="text-gray-500">Weight</div>
574
+ <div>${exercise.weight} lbs</div>
575
+ </div>
576
+ <div>
577
+ <div class="text-gray-500">Sets</div>
578
+ <div>${exercise.sets}</div>
579
+ </div>
580
+ <div>
581
+ <div class="text-gray-500">Reps</div>
582
+ <div>${exercise.reps}</div>
583
+ </div>
584
+ </div>
585
+ <div class="text-xs text-gray-400 mt-1">${formatShortDate(exercise.date)}</div>
586
+ </div>
587
+ `;
588
+ });
589
+ html += '</div>';
590
+ return html;
591
+ }
592
+
593
+ function openEditHistoryModal(day) {
594
+ const workoutData = workouts[day];
595
+
596
+ editHistoryContent.innerHTML = `
597
+ <div class="mb-4">
598
+ <h4 class="font-medium text-lg mb-2">${day.charAt(0).toUpperCase() + day.slice(1)} Workout</h4>
599
+ <div class="text-sm text-gray-600 mb-4">${formatDate(workoutData.date)}</div>
600
+
601
+ <div class="flex items-center mb-4">
602
+ <label class="block text-sm font-medium text-gray-700 mr-2">Completed:</label>
603
+ <input type="checkbox" id="edit-completed" ${workoutData.completed ? 'checked' : ''} class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
604
+ </div>
605
+
606
+ <div class="mb-2">
607
+ <label class="block text-sm font-medium text-gray-700 mb-1">Workout Date</label>
608
+ <input type="datetime-local" id="edit-workout-date" value="${formatDateTimeLocal(workoutData.date)}" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
609
+ </div>
610
+ </div>
611
+
612
+ <div class="border-t border-gray-200 pt-4">
613
+ <h5 class="font-medium mb-3">Exercises</h5>
614
+ <div id="edit-exercises-list" class="space-y-3 mb-4">
615
+ ${renderEditExercisesList(workoutData.exercises)}
616
+ </div>
617
+
618
+ <div class="bg-gray-50 p-3 rounded-lg">
619
+ <h6 class="font-medium mb-2">Add New Exercise</h6>
620
+ <div class="grid grid-cols-1 md:grid-cols-4 gap-2">
621
+ <div>
622
+ <input type="text" id="new-exercise-name" placeholder="Exercise" class="w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
623
+ </div>
624
+ <div>
625
+ <input type="number" id="new-exercise-weight" placeholder="Weight" class="w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
626
+ </div>
627
+ <div>
628
+ <input type="number" id="new-exercise-sets" placeholder="Sets" class="w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
629
+ </div>
630
+ <div>
631
+ <input type="number" id="new-exercise-reps" placeholder="Reps" class="w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
632
+ </div>
633
+ </div>
634
+ <button id="add-new-exercise" class="mt-2 w-full bg-blue-600 hover:bg-blue-700 text-white py-1 px-3 rounded-md text-sm transition-colors">
635
+ <i class="fas fa-plus mr-1"></i> Add Exercise
636
+ </button>
637
+ </div>
638
+ </div>
639
+
640
+ <div class="flex justify-end space-x-3 mt-6">
641
+ <button id="cancel-edit" class="px-4 py-2 border border-gray-300 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-50">
642
+ Cancel
643
+ </button>
644
+ <button id="save-edit" data-day="${day}" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-md text-sm font-medium">
645
+ Save Changes
646
+ </button>
647
+ </div>
648
+ `;
649
+
650
+ // Add event listeners to delete buttons
651
+ editHistoryContent.querySelectorAll('.delete-history-exercise').forEach(btn => {
652
+ btn.addEventListener('click', function() {
653
+ const index = parseInt(this.dataset.index);
654
+ if (confirm('Are you sure you want to delete this exercise?')) {
655
+ workoutData.exercises.splice(index, 1);
656
+ openEditHistoryModal(day); // Refresh the modal
657
+ }
658
+ });
659
+ });
660
+
661
+ // Add event listener to add new exercise button
662
+ editHistoryContent.querySelector('#add-new-exercise').addEventListener('click', function() {
663
+ const name = editHistoryContent.querySelector('#new-exercise-name').value.trim();
664
+ const weight = parseFloat(editHistoryContent.querySelector('#new-exercise-weight').value);
665
+ const sets = parseInt(editHistoryContent.querySelector('#new-exercise-sets').value);
666
+ const reps = parseInt(editHistoryContent.querySelector('#new-exercise-reps').value);
667
+
668
+ if (!name || isNaN(weight) || isNaN(sets) || isNaN(reps)) {
669
+ alert('Please fill in all fields with valid values');
670
+ return;
671
+ }
672
+
673
+ workoutData.exercises.push({
674
+ name,
675
+ weight,
676
+ sets,
677
+ reps,
678
+ date: new Date().toISOString()
679
+ });
680
+
681
+ openEditHistoryModal(day); // Refresh the modal
682
+ });
683
+
684
+ // Add event listener to save button
685
+ editHistoryContent.querySelector('#save-edit').addEventListener('click', function() {
686
+ const day = this.dataset.day;
687
+ const completed = editHistoryContent.querySelector('#edit-completed').checked;
688
+ const date = new Date(editHistoryContent.querySelector('#edit-workout-date').value).toISOString();
689
+
690
+ workouts[day].completed = completed;
691
+ workouts[day].date = date;
692
+
693
+ // Update all exercises dates if workout date changed
694
+ if (workouts[day].date !== workoutData.date) {
695
+ workouts[day].exercises.forEach(exercise => {
696
+ exercise.date = workouts[day].date;
697
+ });
698
+ }
699
+
700
+ saveData();
701
+ updateUI();
702
+ loadHistory();
703
+ editHistoryModal.classList.add('hidden');
704
+ });
705
+
706
+ // Add event listener to cancel button
707
+ editHistoryContent.querySelector('#cancel-edit').addEventListener('click', function() {
708
+ editHistoryModal.classList.add('hidden');
709
+ });
710
+
711
+ editHistoryModal.classList.remove('hidden');
712
+ }
713
+
714
+ function renderEditExercisesList(exercises) {
715
+ if (exercises.length === 0) return '<div class="text-center py-4 text-gray-400">No exercises</div>';
716
+
717
+ let html = '';
718
+ exercises.forEach((exercise, index) => {
719
+ html += `
720
+ <div class="bg-white p-3 rounded-lg border border-gray-200">
721
+ <div class="grid grid-cols-1 md:grid-cols-5 gap-2">
722
+ <div>
723
+ <label class="text-xs text-gray-500">Exercise</label>
724
+ <input type="text" value="${exercise.name}" data-index="${index}" data-field="name" class="w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
725
+ </div>
726
+ <div>
727
+ <label class="text-xs text-gray-500">Weight</label>
728
+ <input type="number" value="${exercise.weight}" data-index="${index}" data-field="weight" class="w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
729
+ </div>
730
+ <div>
731
+ <label class="text-xs text-gray-500">Sets</label>
732
+ <input type="number" value="${exercise.sets}" data-index="${index}" data-field="sets" class="w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
733
+ </div>
734
+ <div>
735
+ <label class="text-xs text-gray-500">Reps</label>
736
+ <input type="number" value="${exercise.reps}" data-index="${index}" data-field="reps" class="w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
737
+ </div>
738
+ <div>
739
+ <label class="text-xs text-gray-500">Actions</label>
740
+ <button class="delete-history-exercise w-full px-2 py-1 bg-red-500 hover:bg-red-600 text-white rounded-md text-sm" data-index="${index}">
741
+ <i class="fas fa-trash mr-1"></i> Delete
742
+ </button>
743
+ </div>
744
+ </div>
745
+ <div class="mt-2">
746
+ <label class="text-xs text-gray-500">Date</label>
747
+ <input type="datetime-local" value="${formatDateTimeLocal(exercise.date)}" data-index="${index}" data-field="date" class="w-full px-2 py-1 border border-gray-300 rounded-md text-sm">
748
+ </div>
749
+ </div>
750
+ `;
751
+ });
752
+
753
+ // Add input change listeners
754
+ setTimeout(() => {
755
+ editHistoryContent.querySelectorAll('input[data-index]').forEach(input => {
756
+ input.addEventListener('change', function() {
757
+ const index = parseInt(this.dataset.index);
758
+ const field = this.dataset.field;
759
+ const value = field === 'name' ? this.value :
760
+ field === 'date' ? new Date(this.value).toISOString() :
761
+ parseFloat(this.value);
762
+
763
+ workouts[currentDay].exercises[index][field] = value;
764
+ });
765
+ });
766
+ }, 0);
767
+
768
+ return html;
769
+ }
770
+
771
+ function toggleHistoryView() {
772
+ historyViewMode = historyViewMode === 'detailed' ? 'compact' : 'detailed';
773
+ toggleHistoryViewBtn.innerHTML = historyViewMode === 'detailed' ?
774
+ '<i class="fas fa-list mr-1"></i> Compact View' :
775
+ '<i class="fas fa-list mr-1"></i> Detailed View';
776
+ loadHistory();
777
+ }
778
+
779
+ function getWorkoutType(day) {
780
+ if (day === 'monday' || day === 'thursday') return 'Push';
781
+ if (day === 'tuesday' || day === 'friday') return 'Pull';
782
+ if (day === 'wednesday' || day === 'saturday') return 'Legs';
783
+ return '';
784
+ }
785
+
786
+ function getWorkoutTypeColorClass(day) {
787
+ if (day === 'monday' || day === 'thursday') return 'text-blue-500';
788
+ if (day === 'tuesday' || day === 'friday') return 'text-green-500';
789
+ if (day === 'wednesday' || day === 'saturday') return 'text-purple-500';
790
+ return '';
791
+ }
792
+
793
+ function formatDate(dateString) {
794
+ try {
795
+ const date = new Date(dateString);
796
+ if (isNaN(date.getTime())) {
797
+ return 'Date not available';
798
+ }
799
+ return date.toLocaleDateString('en-US', {
800
+ weekday: 'long',
801
+ month: 'short',
802
+ day: 'numeric',
803
+ year: 'numeric',
804
+ hour: '2-digit',
805
+ minute: '2-digit'
806
+ });
807
+ } catch (e) {
808
+ console.error('Error formatting date:', e);
809
+ return 'Date not available';
810
+ }
811
+ }
812
+
813
+ function formatShortDate(dateString) {
814
+ try {
815
+ const date = new Date(dateString);
816
+ if (isNaN(date.getTime())) {
817
+ return '';
818
+ }
819
+ return date.toLocaleDateString('en-US', {
820
+ month: 'short',
821
+ day: 'numeric',
822
+ hour: '2-digit',
823
+ minute: '2-digit'
824
+ });
825
+ } catch (e) {
826
+ console.error('Error formatting short date:', e);
827
+ return '';
828
+ }
829
+ }
830
+
831
+ function formatDateTimeLocal(dateString) {
832
+ try {
833
+ const date = new Date(dateString);
834
+ if (isNaN(date.getTime())) {
835
+ return '';
836
+ }
837
+ const year = date.getFullYear();
838
+ const month = String(date.getMonth() + 1).padStart(2, '0');
839
+ const day = String(date.getDate()).padStart(2, '0');
840
+ const hours = String(date.getHours()).padStart(2, '0');
841
+ const minutes = String(date.getMinutes()).padStart(2, '0');
842
+
843
+ return `${year}-${month}-${day}T${hours}:${minutes}`;
844
+ } catch (e) {
845
+ console.error('Error formatting datetime-local:', e);
846
+ return '';
847
+ }
848
+ }
849
+ });
850
+ </script>
851
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - <a href="https://enzostvs-deepsite.hf.space?remix=jrrade/myworkouts" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body>
852
+ </html>