feat: extract logic into class
All checks were successful
Build and Deploy Svelte App / build-and-deploy (push) Successful in 2m5s
All checks were successful
Build and Deploy Svelte App / build-and-deploy (push) Successful in 2m5s
This commit is contained in:
parent
c13c0e3323
commit
b34e73fa46
88
src/lib/types/workouts.svelte.ts
Normal file
88
src/lib/types/workouts.svelte.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import { SvelteSet } from "svelte/reactivity";
|
||||
|
||||
export interface Workout {
|
||||
id?: number;
|
||||
date: string;
|
||||
type: string;
|
||||
duration_minutes: number;
|
||||
}
|
||||
|
||||
|
||||
export class WorkoutLog {
|
||||
#types = new SvelteSet<string>(['jogging', 'crosstrainer', 'bicycle', 'crossfit']);
|
||||
#workouts = $state<Workout[]>([]);
|
||||
|
||||
get workouts(): Workout[] {
|
||||
return Array.from(this.#workouts);
|
||||
}
|
||||
|
||||
get types() {
|
||||
return Array.from(this.#types.values());
|
||||
}
|
||||
|
||||
#load_from_storage() {
|
||||
if (typeof localStorage === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
const storage = localStorage.getItem('workout_log');
|
||||
|
||||
if (!storage) {
|
||||
return
|
||||
}
|
||||
const data: {
|
||||
types: string[],
|
||||
workouts: Workout[],
|
||||
} = JSON.parse(storage);
|
||||
|
||||
this.#types = new SvelteSet<string>([...data.types]);
|
||||
this.#workouts.length = 0;
|
||||
this.#workouts.push(...data.workouts);
|
||||
}
|
||||
|
||||
#save_to_storage() {
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
|
||||
localStorage.setItem('workout_log', this.#to_json());
|
||||
}
|
||||
}
|
||||
#to_json(): string {
|
||||
return JSON.stringify({
|
||||
types: this.types,
|
||||
workouts: this.workouts,
|
||||
});
|
||||
}
|
||||
constructor() {
|
||||
this.#load_from_storage();
|
||||
}
|
||||
|
||||
add_workout(workout: Workout) {
|
||||
|
||||
|
||||
while (this.#workouts.indexOf(workout) !== -1) {
|
||||
if (!workout.id) {
|
||||
workout.id = 1;
|
||||
continue
|
||||
}
|
||||
workout.id += 5;
|
||||
}
|
||||
this.#workouts.push(workout);
|
||||
this.#types.add(workout.type.toLowerCase())
|
||||
this.#save_to_storage();
|
||||
}
|
||||
|
||||
remove_workout(workout: Workout) {
|
||||
//this.#workouts.delete(workout);
|
||||
this.#workouts = this.#workouts.filter(i => i !== workout);
|
||||
this.#save_to_storage();
|
||||
}
|
||||
|
||||
remove_type(type: string) {
|
||||
this.#types.delete(type);
|
||||
this.#save_to_storage();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default WorkoutLog;
|
@ -1,10 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import type { WorkoutEntry } from "$lib/types";
|
||||
import { getWorkouts, saveWorkouts } from "$lib/storage";
|
||||
import { Save, Trash2 } from "@lucide/svelte";
|
||||
import { WorkoutLog } from "$lib/types/workouts.svelte";
|
||||
|
||||
let workouts: WorkoutEntry[] = $state([]);
|
||||
const log = new WorkoutLog();
|
||||
|
||||
let date = $state("");
|
||||
let workout_type = $state("");
|
||||
@ -15,32 +14,22 @@
|
||||
onMount(() => {
|
||||
const today = new Date();
|
||||
date = today.toISOString().split("T")[0];
|
||||
workouts = getWorkouts();
|
||||
});
|
||||
|
||||
function deleteRow(index: number) {
|
||||
workouts = workouts.toSpliced(index, 1); // modern way to remove immutably
|
||||
saveWorkouts(workouts);
|
||||
}
|
||||
|
||||
function updateRow(index: number) {
|
||||
alert(`Update row #${index + 1}`);
|
||||
}
|
||||
|
||||
function on_save() {
|
||||
const workout: WorkoutEntry = {
|
||||
log.add_workout({
|
||||
date: date,
|
||||
workout_type: workout_type,
|
||||
type: workout_type,
|
||||
duration_minutes: duration_minutes,
|
||||
};
|
||||
|
||||
workouts.push(workout);
|
||||
|
||||
saveWorkouts(workouts);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<h1>FitLog <i>(0.0.3)</i></h1>
|
||||
<h1>FitLog <i>(0.0.4)</i></h1>
|
||||
|
||||
<form onsubmit={on_save}>
|
||||
<table>
|
||||
@ -64,12 +53,20 @@
|
||||
</td>
|
||||
<td
|
||||
><input
|
||||
id="workout_type"
|
||||
list="workout_types"
|
||||
type="text"
|
||||
bind:value={workout_type}
|
||||
placeholder="Enter workout type"
|
||||
required
|
||||
/></td
|
||||
>
|
||||
/>
|
||||
|
||||
<datalist id="workout_types">
|
||||
{#each log.types as value}
|
||||
<option {value}></option>
|
||||
{/each}
|
||||
</datalist>
|
||||
</td>
|
||||
<td
|
||||
><input
|
||||
type="number"
|
||||
@ -86,27 +83,28 @@
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{#if workouts.length < 1}
|
||||
{#if log.workouts.length < 1}
|
||||
<tr
|
||||
><td colspan="4" style="text-align: center;"
|
||||
><p>No entries.. yet!</p></td
|
||||
></tr
|
||||
>
|
||||
{:else}
|
||||
{#each workouts as wk, i}
|
||||
{#each log.workouts as wk, i}
|
||||
<tr>
|
||||
<td>{wk.date}</td>
|
||||
<td>{wk.workout_type}</td>
|
||||
<td>{wk.type}</td>
|
||||
<td>{wk.duration_minutes}</td>
|
||||
<td>
|
||||
<a
|
||||
href="/#"
|
||||
class="button button-delete"
|
||||
role="button"
|
||||
tabindex={i}
|
||||
onclick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
deleteRow(i);
|
||||
log.remove_workout(wk);
|
||||
}}
|
||||
>
|
||||
<Trash2 color="red" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user