use global state and add code for toggling task completeness

This commit is contained in:
D. Scott Boggs 2023-06-17 13:20:34 -04:00
parent c85af82eb7
commit 3553743a9a
4 changed files with 53 additions and 12 deletions

View file

@ -2,13 +2,13 @@
<table class="table">
<thead>
<th>Date</th>
<th v-for="track in tracks" :key="track.id">{{ track.icon }}</th>
<th v-for="track in state.tracks" :key="track.id">{{ track.icon }}</th>
</thead>
<tbody>
<tr v-for="date in dates" :key="date.valueOf()">
<th>{{ dateString(date) }}</th>
<td v-for="track in tracks" :key="track.id">
<TickComponent :isSet="track.isSetOn(date)" />
<td v-for="track in state.tracks" :key="track.id">
<TickComponent :isSet="track.isSetOn(date)" :trackID="track.id" />
</td>
</tr>
</tbody>
@ -16,11 +16,8 @@
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Track } from '../track'
import TickComponent from "./TickComponent.vue";
const tracks = ref(new Array<Track>())
import { state } from "../state";
const today = new Date()
const ONE_DAY_MS = 86_400_000
@ -33,6 +30,4 @@ function dateString(date: Date) {
return date.toISOString().substring(0, 10)
}
Track.fetchAll().then(result => tracks.value = result)
</script>

View file

@ -1,9 +1,23 @@
<template>
<button :class="className()"></button>
<button :class="className()" @click="toggle"></button>
</template>
<script setup lang="ts">
const props = defineProps<{ isSet: boolean }>()
import { Ref, ref } from 'vue';
import { state } from '../state';
import { Track } from '../track';
const tick: Ref<Tick | undefined> = ref()
const props = defineProps<{ isSet: boolean, track: Track }>()
const className = () => props.isSet ? "button is-rounded is-info" : "button is-rounded"
async function toggle() {
const $tick = tick.value
if ($tick) {
await state.taskMarkedIncomplete($tick)
tick.value = undefined
} else
tick.value = await state.taskCompleted(props.track)
}
</script>

33
client/src/state.ts Normal file
View file

@ -0,0 +1,33 @@
import { reactive } from "vue"
import { Track } from "./track"
import { error } from "./error"
export const state = reactive({
tracks: new Array<Track>,
isPopulating: false,
async populate() {
if (this.isPopulating) return
this.isPopulating = true
this.tracks = await Track.fetchAll()
this.isPopulating = false
},
async taskCompleted(track: Track): Promise<Tick> {
const result = await fetch(`/api/v1/tracks/${track.id}/ticked`, { method: "PATCH" })
const body = await result.text()
if (!result.ok) {
error(body)
throw new Error(`error setting tick for track ${track.id} ("${track.name}"): ${result.status} ${result.statusText}`)
}
const tick: Tick = JSON.parse(body)
track.ticks = track.ticks ?? []
track.ticks.push(tick)
const tracks = this.tracks.map($track => track.id === $track.id ? track : $track)
this.tracks = tracks
return tick
},
async taskMarkedIncomplete(tick: Tick) {
const { ok, status, statusText } = await fetch(`/api/v1/ticks/${tick.id}`, { method: 'DELETE' })
if (!ok)
error(`error deleting tick ${tick.id}: ${statusText} (${status})`)
}
})

View file

@ -85,7 +85,6 @@ export class Track implements ITrack {
console.error(e)
console.debug(body)
}
} catch (err) {
console.error(err)
result.text()