Implement food creation, such as it is

This commit is contained in:
2024-06-12 00:56:52 +02:00
parent c1c821d703
commit 5ee56a98d0
8 changed files with 201 additions and 50 deletions

View File

@@ -64,8 +64,8 @@
"windows": [
{
"title": "Svelte-Tauri",
"width": 900,
"height": 600,
"width": 1920,
"height": 1080,
"fullscreen": false,
"transparent": true,
"decorations": false

View File

@@ -1,29 +1,16 @@
<script lang="ts">
import { mode, ModeWatcher } from 'mode-watcher'
import { Toaster } from 'svelte-sonner'
import { onMount } from 'svelte'
import { type Food, FoodService } from '$lib/database/food'
let food: Food[] = []
onMount(async () => {
food = await FoodService.GetAll()
})
import Header from '$components/Header.svelte'
import Router from '$router/Router.svelte'
</script>
<ModeWatcher defaultMode="dark" />
<Toaster theme={$mode} />
<div class="relative flex flex-col h-screen" data-vaul-drawer-wrapper id="page">
<div>
<pre>
{#each food as f}
{f.amount}
{/each}
</pre>
</div>
<!-- <Header />-->
<!-- <main class="flex-1">-->
<!-- <Router />-->
<!-- </main>-->
</div>
<template>
<Header />
<main class="flex-1">
<Router />
</main>
</template>

View File

@@ -0,0 +1,61 @@
<script lang="ts">
import { type Food, FoodService } from '$lib/database/food'
import { toast } from 'svelte-sonner'
import { createEventDispatcher } from 'svelte'
const dispatch = createEventDispatcher()
let item: Food = {
food: '',
amount: 0,
description: ''
}
let name: string = ''
let amount: string = ''
let description: string = ''
async function update(event: KeyboardEvent & { currentTarget: (EventTarget & HTMLTableCellElement) }) {
if (event.key == 'Enter') {
item.food = name.trim()
item.amount = parseInt(amount.trim())
item.description = description.trim()
const [food, err] = await FoodService.Create(item)
name = ''
amount = ''
description = ''
if (err) {
toast.error(err)
return
}
dispatch('created', food)
}
}
</script>
<template>
<tr class="border-b border-gray-200 dark:border-gray-700">
<th class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap bg-gray-50 dark:text-white dark:bg-gray-800"
scope="row">
</th>
<td class="px-6 py-4"
bind:innerText={name}
contenteditable="true"
on:keyup={update}>
</td>
<td class="px-6 py-4 bg-gray-50 dark:bg-gray-800"
bind:innerText={description}
contenteditable="true"
on:keyup={update}>
</td>
<td class="px-6 py-4"
bind:innerText={amount}
contenteditable="true"
on:keyup={update}>
</td>
<td class="px-6 py-4 bg-gray-50 dark:bg-gray-800">
</td>
<td class="px-6 py-4">
</td>
</tr>
</template>

View File

@@ -0,0 +1,31 @@
<script lang="ts">
import type { Food } from '$lib/database/food'
export let item: Food
console.log(item)
</script>
<template>
<tr class="border-b border-gray-200 dark:border-gray-700">
<th scope="row"
class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap bg-gray-50 dark:text-white dark:bg-gray-800">
{item.date}
</th>
<td class="px-6 py-4">
{item.food}
</td>
<td class="px-6 py-4 bg-gray-50 dark:bg-gray-800">
{item.description}
</td>
<td class="px-6 py-4">
{item.amount}
</td>
<td class="px-6 py-4 bg-gray-50 dark:bg-gray-800">
{item.per100}
</td>
<td class="px-6 py-4">
{item.energy}
</td>
</tr>
</template>

View File

@@ -1,18 +1,44 @@
import { db } from '$lib/database'
import type { Err } from '$lib/types'
export type Food = {
rowid: number,
rowid?: number,
date?: Date,
food: string,
description?: string,
amount: number,
per100: number,
energy: number,
per100?: number,
energy?: number,
}
const columns = ['rowid', 'date', 'food', 'description', 'amount', 'per100', 'energy']
const FoodService = {
async GetAll() {
return await db.select<Food[]>('SELECT rowid, food, amount, per100, energy FROM food ORDER BY date DESC')
return await db.select<Food[]>(`
select ${columns.join(', ')}
from food
order by date desc
`)
},
async SetAll(data: Food[]) {
async GetAllForDate(date: Date) {
return await db.select<Food[]>(`
select ${columns.join(', ')}
from food
where strftime('%Y-%m-%d', date) = strftime('%Y-%m-%d', '2024-06-12')
or strftime('%Y-%m-%d', date) = strftime('%Y-%m-%d', date('2024-06-12', '-1 day'))
order by date DESC;
`, [date])
},
// TODO: Rework this to use Err in Go style
async Create(food: Food): Promise<[Food, Err]> {
if (!food.food) return [food, 'food.food is required']
if (!food.amount) throw [food, 'food.amount is required']
const res = await db.execute(`insert into food (food, description, amount) values ($1, $2, $3)`, [food.food, food.description, food.amount])
const row = await db.select<Food>(`select ${columns.join(', ')} from food where rowid = $1`, [res.lastInsertId])
return [row, null]
}
}

View File

@@ -2,26 +2,28 @@
// This file was generated by [tauri-specta](https://github.com/oscartbeaumont/tauri-specta). Do not edit this file manually.
declare global {
interface Window {
__TAURI_INVOKE__<T>(cmd: string, args?: Record<string, unknown>): Promise<T>;
}
interface Window {
__TAURI_INVOKE__<T>(cmd: string, args?: Record<string, unknown>): Promise<T>;
}
}
// Function avoids 'window not defined' in SSR
const invoke = () => window.__TAURI_INVOKE__
const invoke = () => window.__TAURI_INVOKE__;
export function helloTauri() {
return invoke()<string>('hello_tauri')
return invoke()<string>("hello_tauri")
}
export function hash256sum(hashInput: string) {
return invoke()<string>('hash256sum', { hashInput })
return invoke()<string>("hash256sum", { hashInput })
}
export function storeSetKey(key: string, value: string) {
return invoke()<null>('store_set_key', { key, value })
return invoke()<null>("store_set_key", { key,value })
}
export function storeReadKey(key: string) {
return invoke()<string | null>('store_read_key', { key })
return invoke()<string | null>("store_read_key", { key })
}

View File

@@ -1,14 +1,56 @@
<section class="h-full flex-col flex items-center justify-center gap-y-8">
<h1 class="text-6xl">Welcome</h1>
<h2 class="flex items-center text-3xl [&_img]:h-12">
This is a &#160
<span>
<img alt="svelte logo" src="/svelte_logo.svg" />
</span>
&#160-&#160
<span>
<img alt="svelte logo" src="/tauri_logo.svg" />
</span>
&#160 Template
</h2>
</section>
<script lang="ts">
import { onMount } from 'svelte'
import { type Food, FoodService } from '$lib/database/food'
import FoodComp from '$components/FoodComp.svelte'
import EmptyFoodComp from '$components/EmptyFoodComp.svelte'
let food: Food[] = []
onMount(async () => {
food = await FoodService.GetAllForDate(new Date());
})
function newFood(event: CustomEvent<Food>) {
console.log(event)
food.push(event.detail)
food = food
}
</script>
<template>
<div class="relative flex flex-col h-screen" data-vaul-drawer-wrapper id="page">
<div class="relative overflow-x-auto shadow-md sm:rounded-lg">
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
<thead class="text-xs text-gray-700 uppercase dark:text-gray-400">
<tr>
<th scope="col" class="px-6 py-3 bg-gray-50 dark:bg-gray-800">
Date
</th>
<th scope="col" class="px-6 py-3">
Food
</th>
<th scope="col" class="px-6 py-3 bg-gray-50 dark:bg-gray-800">
Description
</th>
<th scope="col" class="px-6 py-3">
Amount
</th>
<th scope="col" class="px-6 py-3 bg-gray-50 dark:bg-gray-800">
Cal Per 100
</th>
<th scope="col" class="px-6 py-3">
Energy
</th>
</tr>
</thead>
<tbody>
<EmptyFoodComp on:created={newFood}/>
{#each food as f}
<FoodComp item="{f}" />
{/each}
</tbody>
</table>
</div>
<div>
</div>
</div>
</template>

View File

@@ -1,2 +1,4 @@
export const themes = ['dark', 'light'] as const
export type Theme = (typeof themes)[number]
export type Err = string | null