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">
|
<script lang="ts">
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import type { WorkoutEntry } from "$lib/types";
|
|
||||||
import { getWorkouts, saveWorkouts } from "$lib/storage";
|
|
||||||
import { Save, Trash2 } from "@lucide/svelte";
|
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 date = $state("");
|
||||||
let workout_type = $state("");
|
let workout_type = $state("");
|
||||||
@ -15,32 +14,22 @@
|
|||||||
onMount(() => {
|
onMount(() => {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
date = today.toISOString().split("T")[0];
|
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) {
|
function updateRow(index: number) {
|
||||||
alert(`Update row #${index + 1}`);
|
alert(`Update row #${index + 1}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function on_save() {
|
function on_save() {
|
||||||
const workout: WorkoutEntry = {
|
log.add_workout({
|
||||||
date: date,
|
date: date,
|
||||||
workout_type: workout_type,
|
type: workout_type,
|
||||||
duration_minutes: duration_minutes,
|
duration_minutes: duration_minutes,
|
||||||
};
|
});
|
||||||
|
|
||||||
workouts.push(workout);
|
|
||||||
|
|
||||||
saveWorkouts(workouts);
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h1>FitLog <i>(0.0.3)</i></h1>
|
<h1>FitLog <i>(0.0.4)</i></h1>
|
||||||
|
|
||||||
<form onsubmit={on_save}>
|
<form onsubmit={on_save}>
|
||||||
<table>
|
<table>
|
||||||
@ -64,12 +53,20 @@
|
|||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
><input
|
><input
|
||||||
|
id="workout_type"
|
||||||
|
list="workout_types"
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={workout_type}
|
bind:value={workout_type}
|
||||||
placeholder="Enter workout type"
|
placeholder="Enter workout type"
|
||||||
required
|
required
|
||||||
/></td
|
/>
|
||||||
>
|
|
||||||
|
<datalist id="workout_types">
|
||||||
|
{#each log.types as value}
|
||||||
|
<option {value}></option>
|
||||||
|
{/each}
|
||||||
|
</datalist>
|
||||||
|
</td>
|
||||||
<td
|
<td
|
||||||
><input
|
><input
|
||||||
type="number"
|
type="number"
|
||||||
@ -86,27 +83,28 @@
|
|||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{#if workouts.length < 1}
|
{#if log.workouts.length < 1}
|
||||||
<tr
|
<tr
|
||||||
><td colspan="4" style="text-align: center;"
|
><td colspan="4" style="text-align: center;"
|
||||||
><p>No entries.. yet!</p></td
|
><p>No entries.. yet!</p></td
|
||||||
></tr
|
></tr
|
||||||
>
|
>
|
||||||
{:else}
|
{:else}
|
||||||
{#each workouts as wk, i}
|
{#each log.workouts as wk, i}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{wk.date}</td>
|
<td>{wk.date}</td>
|
||||||
<td>{wk.workout_type}</td>
|
<td>{wk.type}</td>
|
||||||
<td>{wk.duration_minutes}</td>
|
<td>{wk.duration_minutes}</td>
|
||||||
<td>
|
<td>
|
||||||
<a
|
<a
|
||||||
|
href="/#"
|
||||||
class="button button-delete"
|
class="button button-delete"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex={i}
|
tabindex={i}
|
||||||
onclick={(e) => {
|
onclick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
deleteRow(i);
|
log.remove_workout(wk);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Trash2 color="red" />
|
<Trash2 color="red" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user