egentrening/src/routes/ExerciseField.svelte
2025-09-03 19:18:29 +02:00

70 lines
1.9 KiB
Svelte

<script lang="ts">
import type { ExerciseConfig, ColorExercise } from '$lib/workout';
interface Props extends ExerciseConfig {
value: number;
}
let {
value = $bindable(),
min = 0,
max = 9999,
step = 1,
color = 'blue',
...restProps
}: Props = $props();
// Destructure the remaining props for easier access
const { icon, name, quickAddOptions, unit } = restProps;
const label = unit ? `${icon} ${name} (${unit})` : `${icon} ${name}`;
function quickAdd(amount: number) {
const newValue = Math.max(min, value + amount);
value = step < 1 ? Number(newValue.toFixed(2)) : newValue;
}
const colorClasses = {
blue: 'bg-blue-100 text-blue-700 hover:bg-blue-200 focus:ring-blue-500',
green: 'bg-green-100 text-green-700 hover:bg-green-200 focus:ring-green-500',
orange: 'bg-orange-100 text-orange-700 hover:bg-orange-200 focus:ring-orange-500',
red: 'bg-red-100 text-red-700 hover:bg-red-200 focus:ring-red-500',
purple: 'bg-purple-100 text-purple-700 hover:bg-purple-200 focus:ring-purple-500'
};
</script>
<div class="mb-6">
<label for={name} class="mb-2 block text-sm font-medium text-gray-700">
{label}
</label>
<div class="flex items-center space-x-2">
<input
id={name}
{name}
type="number"
bind:value
defaultValue={value}
{min}
{max}
{step}
required={true}
class="flex-1 rounded-md border border-gray-300 px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:outline-none"
/>
{#each quickAddOptions as option}
{@render quickAddButton(option.label, () => quickAdd(option.value), color)}
{/each}
</div>
</div>
{#snippet quickAddButton(label: string, onclick: () => void, color: ColorExercise)}
<button
type="button"
{onclick}
class="rounded px-3 py-1 text-xs focus:ring-2 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 {colorClasses[
color
]}"
>
{label}
</button>
{/snippet}