Heftig rekatorering
This commit is contained in:
parent
e5e68a7764
commit
201280dc54
16 changed files with 700 additions and 534 deletions
152
src/routes/WorkoutLogger.svelte
Normal file
152
src/routes/WorkoutLogger.svelte
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { saveWorkout, getTodaysWorkout, type WorkOutData } from './workout.remote';
|
||||
import ExerciseField from './ExerciseField.svelte';
|
||||
import { exerciseConfigs } from './workoutData';
|
||||
import { getTodayDateString, exampleWorkout } from './workoutUtils';
|
||||
|
||||
let todayDate = getTodayDateString();
|
||||
|
||||
// Form state
|
||||
let form: WorkOutData = {
|
||||
pushups: 0,
|
||||
situps: 0,
|
||||
plankSeconds: 0,
|
||||
hangups: 0,
|
||||
runKm: 0
|
||||
};
|
||||
|
||||
onMount(async () => {
|
||||
const result = await getTodaysWorkout();
|
||||
form = result.data ?? form;
|
||||
});
|
||||
|
||||
function loadExample() {
|
||||
form = { ...exampleWorkout };
|
||||
}
|
||||
|
||||
function handleFieldChange(field: keyof WorkOutData, value: number) {
|
||||
form[field] = value;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="mx-auto max-w-md rounded-lg bg-white p-6 shadow-lg">
|
||||
<!-- Header -->
|
||||
<header class="mb-6 text-center">
|
||||
<h2 class="text-2xl font-bold text-gray-800">Log Today's Workout</h2>
|
||||
<div class="mt-2 text-gray-600">📅 {todayDate}</div>
|
||||
</header>
|
||||
|
||||
<!-- Main Form -->
|
||||
<form {...saveWorkout}>
|
||||
<!-- Push-ups Field -->
|
||||
<ExerciseField
|
||||
label={exerciseConfigs.pushups.name}
|
||||
icon={exerciseConfigs.pushups.icon}
|
||||
name="pushups"
|
||||
bind:value={form.pushups}
|
||||
defaultValue={form.pushups}
|
||||
onchange={(value) => handleFieldChange('pushups', value)}
|
||||
quickAddOptions={exerciseConfigs.pushups.quickAddOptions}
|
||||
color={exerciseConfigs.pushups.color}
|
||||
max={exerciseConfigs.pushups.max}
|
||||
step={exerciseConfigs.pushups.step}
|
||||
/>
|
||||
|
||||
<!-- Sit-ups Field -->
|
||||
<ExerciseField
|
||||
label={exerciseConfigs.situps.name}
|
||||
icon={exerciseConfigs.situps.icon}
|
||||
name="situps"
|
||||
bind:value={form.situps}
|
||||
onchange={(value) => handleFieldChange('situps', value)}
|
||||
defaultValue={form.situps}
|
||||
quickAddOptions={exerciseConfigs.situps.quickAddOptions}
|
||||
color={exerciseConfigs.situps.color}
|
||||
max={exerciseConfigs.situps.max}
|
||||
step={exerciseConfigs.situps.step}
|
||||
/>
|
||||
|
||||
<!-- Plank Field -->
|
||||
<ExerciseField
|
||||
label="{exerciseConfigs.plankSeconds.name} (seconds)"
|
||||
icon={exerciseConfigs.plankSeconds.icon}
|
||||
name="plankSeconds"
|
||||
bind:value={form.plankSeconds}
|
||||
onchange={(value) => handleFieldChange('plankSeconds', value)}
|
||||
defaultValue={form.plankSeconds}
|
||||
quickAddOptions={exerciseConfigs.plankSeconds.quickAddOptions}
|
||||
color={exerciseConfigs.plankSeconds.color}
|
||||
max={exerciseConfigs.plankSeconds.max}
|
||||
step={exerciseConfigs.plankSeconds.step}
|
||||
/>
|
||||
|
||||
<!-- Running Field -->
|
||||
<ExerciseField
|
||||
label={exerciseConfigs.hangups.name}
|
||||
icon={exerciseConfigs.hangups.icon}
|
||||
name="hangups"
|
||||
bind:value={form.hangups}
|
||||
onchange={(value) => handleFieldChange('hangups', value)}
|
||||
defaultValue={form.hangups}
|
||||
quickAddOptions={exerciseConfigs.hangups.quickAddOptions}
|
||||
color={exerciseConfigs.hangups.color}
|
||||
max={exerciseConfigs.hangups.max}
|
||||
step={exerciseConfigs.hangups.step}
|
||||
/>
|
||||
|
||||
<ExerciseField
|
||||
label="{exerciseConfigs.runKm.name} (km)"
|
||||
icon={exerciseConfigs.runKm.icon}
|
||||
name="runKm"
|
||||
bind:value={form.runKm}
|
||||
onchange={(value) => handleFieldChange('runKm', value)}
|
||||
defaultValue={form.runKm}
|
||||
quickAddOptions={exerciseConfigs.runKm.quickAddOptions}
|
||||
color={exerciseConfigs.runKm.color}
|
||||
max={exerciseConfigs.runKm.max}
|
||||
step={exerciseConfigs.runKm.step}
|
||||
/>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<div class="mb-4 flex space-x-3">
|
||||
<button
|
||||
type="submit"
|
||||
class="flex-1 rounded-md bg-blue-600 px-4 py-2 font-medium text-white hover:bg-blue-700 focus:ring-2 focus:ring-blue-500 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50"
|
||||
>
|
||||
💾 Save Workout
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Message Display -->
|
||||
{#if saveWorkout.result?.success}
|
||||
<div
|
||||
class="mb-4 rounded-md border border-green-200 bg-green-100 p-3 text-sm font-medium text-green-800"
|
||||
role="alert"
|
||||
>
|
||||
{saveWorkout.result.message}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#snippet pending()}{/snippet}
|
||||
|
||||
<!-- Example Section -->
|
||||
<section class="rounded-md bg-gray-50 p-4">
|
||||
<h3 class="mb-2 text-sm font-medium text-gray-700">Quick Example:</h3>
|
||||
<div class="space-y-1 text-sm text-gray-600">
|
||||
<div>💪 Push-ups: {exampleWorkout.pushups}</div>
|
||||
<div>🏋️ Sit-ups: {exampleWorkout.situps}</div>
|
||||
<div>🧘 Plank: {exampleWorkout.plankSeconds} seconds</div>
|
||||
<div>🏃 Running: {exampleWorkout.runKm} km</div>
|
||||
<div>☕ Hangups: {exampleWorkout.hangups}</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onclick={loadExample}
|
||||
class="mt-2 rounded bg-gray-200 px-2 py-1 text-xs text-gray-700 hover:bg-gray-300 focus:ring-2 focus:ring-gray-500 focus:outline-none"
|
||||
>
|
||||
Load Example
|
||||
</button>
|
||||
</section>
|
||||
</div>
|
||||
Loading…
Add table
Add a link
Reference in a new issue