Implement food creation, such as it is
This commit is contained in:
@@ -64,8 +64,8 @@
|
|||||||
"windows": [
|
"windows": [
|
||||||
{
|
{
|
||||||
"title": "Svelte-Tauri",
|
"title": "Svelte-Tauri",
|
||||||
"width": 900,
|
"width": 1920,
|
||||||
"height": 600,
|
"height": 1080,
|
||||||
"fullscreen": false,
|
"fullscreen": false,
|
||||||
"transparent": true,
|
"transparent": true,
|
||||||
"decorations": false
|
"decorations": false
|
||||||
|
@@ -1,29 +1,16 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { mode, ModeWatcher } from 'mode-watcher'
|
import { mode, ModeWatcher } from 'mode-watcher'
|
||||||
import { Toaster } from 'svelte-sonner'
|
import { Toaster } from 'svelte-sonner'
|
||||||
|
import Header from '$components/Header.svelte'
|
||||||
import { onMount } from 'svelte'
|
import Router from '$router/Router.svelte'
|
||||||
import { type Food, FoodService } from '$lib/database/food'
|
|
||||||
|
|
||||||
let food: Food[] = []
|
|
||||||
onMount(async () => {
|
|
||||||
food = await FoodService.GetAll()
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ModeWatcher defaultMode="dark" />
|
<ModeWatcher defaultMode="dark" />
|
||||||
<Toaster theme={$mode} />
|
<Toaster theme={$mode} />
|
||||||
|
|
||||||
<div class="relative flex flex-col h-screen" data-vaul-drawer-wrapper id="page">
|
<template>
|
||||||
<div>
|
<Header />
|
||||||
<pre>
|
<main class="flex-1">
|
||||||
{#each food as f}
|
<Router />
|
||||||
{f.amount}
|
</main>
|
||||||
{/each}
|
</template>
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
<!-- <Header />-->
|
|
||||||
<!-- <main class="flex-1">-->
|
|
||||||
<!-- <Router />-->
|
|
||||||
<!-- </main>-->
|
|
||||||
</div>
|
|
||||||
|
61
src/lib/components/EmptyFoodComp.svelte
Normal file
61
src/lib/components/EmptyFoodComp.svelte
Normal 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>
|
31
src/lib/components/FoodComp.svelte
Normal file
31
src/lib/components/FoodComp.svelte
Normal 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>
|
@@ -1,18 +1,44 @@
|
|||||||
import { db } from '$lib/database'
|
import { db } from '$lib/database'
|
||||||
|
import type { Err } from '$lib/types'
|
||||||
|
|
||||||
export type Food = {
|
export type Food = {
|
||||||
rowid: number,
|
rowid?: number,
|
||||||
|
date?: Date,
|
||||||
food: string,
|
food: string,
|
||||||
|
description?: string,
|
||||||
amount: number,
|
amount: number,
|
||||||
per100: number,
|
per100?: number,
|
||||||
energy: number,
|
energy?: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const columns = ['rowid', 'date', 'food', 'description', 'amount', 'per100', 'energy']
|
||||||
|
|
||||||
const FoodService = {
|
const FoodService = {
|
||||||
async GetAll() {
|
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]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -8,20 +8,22 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function avoids 'window not defined' in SSR
|
// Function avoids 'window not defined' in SSR
|
||||||
const invoke = () => window.__TAURI_INVOKE__
|
const invoke = () => window.__TAURI_INVOKE__;
|
||||||
|
|
||||||
export function helloTauri() {
|
export function helloTauri() {
|
||||||
return invoke()<string>('hello_tauri')
|
return invoke()<string>("hello_tauri")
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hash256sum(hashInput: string) {
|
export function hash256sum(hashInput: string) {
|
||||||
return invoke()<string>('hash256sum', { hashInput })
|
return invoke()<string>("hash256sum", { hashInput })
|
||||||
}
|
}
|
||||||
|
|
||||||
export function storeSetKey(key: string, value: string) {
|
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) {
|
export function storeReadKey(key: string) {
|
||||||
return invoke()<string | null>('store_read_key', { key })
|
return invoke()<string | null>("store_read_key", { key })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,14 +1,56 @@
|
|||||||
<section class="h-full flex-col flex items-center justify-center gap-y-8">
|
<script lang="ts">
|
||||||
<h1 class="text-6xl">Welcome</h1>
|
import { onMount } from 'svelte'
|
||||||
<h2 class="flex items-center text-3xl [&_img]:h-12">
|
import { type Food, FoodService } from '$lib/database/food'
|
||||||
This is a  
|
import FoodComp from '$components/FoodComp.svelte'
|
||||||
<span>
|
import EmptyFoodComp from '$components/EmptyFoodComp.svelte'
|
||||||
<img alt="svelte logo" src="/svelte_logo.svg" />
|
|
||||||
</span>
|
let food: Food[] = []
|
||||||
 - 
|
onMount(async () => {
|
||||||
<span>
|
food = await FoodService.GetAllForDate(new Date());
|
||||||
<img alt="svelte logo" src="/tauri_logo.svg" />
|
})
|
||||||
</span>
|
|
||||||
  Template
|
function newFood(event: CustomEvent<Food>) {
|
||||||
</h2>
|
console.log(event)
|
||||||
</section>
|
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>
|
||||||
|
@@ -1,2 +1,4 @@
|
|||||||
export const themes = ['dark', 'light'] as const
|
export const themes = ['dark', 'light'] as const
|
||||||
export type Theme = (typeof themes)[number]
|
export type Theme = (typeof themes)[number]
|
||||||
|
|
||||||
|
export type Err = string | null
|
||||||
|
Reference in New Issue
Block a user