Implement creating food
This commit is contained in:
12
app.go
12
app.go
@@ -28,7 +28,6 @@ func (a *App) GetFood() WailsFood {
|
|||||||
}
|
}
|
||||||
return WailsFood{Data: data, Success: true}
|
return WailsFood{Data: data, Success: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) CreateFood(food Food) WailsFood1 {
|
func (a *App) CreateFood(food Food) WailsFood1 {
|
||||||
data, err := foodService.Create(food)
|
data, err := foodService.Create(food)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -36,7 +35,6 @@ func (a *App) CreateFood(food Food) WailsFood1 {
|
|||||||
}
|
}
|
||||||
return WailsFood1{Data: data, Success: true}
|
return WailsFood1{Data: data, Success: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) UpdateFood(food Food) WailsFood1 {
|
func (a *App) UpdateFood(food Food) WailsFood1 {
|
||||||
data, err := foodService.Update(food)
|
data, err := foodService.Update(food)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -45,10 +43,18 @@ func (a *App) UpdateFood(food Food) WailsFood1 {
|
|||||||
return WailsFood1{Data: data, Success: true}
|
return WailsFood1{Data: data, Success: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) GetLastPer100(name string) WailsPer100 {
|
||||||
|
data, err := foodService.GetLastPer100(name)
|
||||||
|
if err != nil {
|
||||||
|
return WailsPer100{Success: false, Error: err.Error()}
|
||||||
|
}
|
||||||
|
return WailsPer100{Data: data, Success: true}
|
||||||
|
}
|
||||||
|
|
||||||
// region settings
|
// region settings
|
||||||
func (a *App) GetSettings() settings {
|
func (a *App) GetSettings() settings {
|
||||||
return Settings
|
return Settings
|
||||||
}
|
}
|
||||||
func (a *App) SetSetting(key string, value any) settings {
|
func (a *App) SetSetting(key string, value any) settings {
|
||||||
return settingsService.Set(key, value)
|
return settingsService.Set(key, value)
|
||||||
}
|
}
|
||||||
|
@@ -56,6 +56,21 @@ func (s *FoodService) GetRecent() ([]Food, error) {
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *FoodService) GetLastPer100(name string) (float32, error) {
|
||||||
|
if s.db == nil || !s.db.Ready {
|
||||||
|
return 0, fmt.Errorf("cannot get last per100, db is nil or is not ready")
|
||||||
|
}
|
||||||
|
|
||||||
|
row := s.db.readConn.QueryRow("SELECT per100 FROM food WHERE food like ? ORDER BY rowid DESC LIMIT 1", name+"%")
|
||||||
|
var per100 float32
|
||||||
|
err := row.Scan(&per100)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("error scanning row: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return per100, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *FoodService) Create(food Food) (Food, error) {
|
func (s *FoodService) Create(food Food) (Food, error) {
|
||||||
if s.db == nil || !s.db.Ready {
|
if s.db == nil || !s.db.Ready {
|
||||||
return food, fmt.Errorf("cannot create food, db is nil or is not ready")
|
return food, fmt.Errorf("cannot create food, db is nil or is not ready")
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Header from "$lib/components/Header.svelte";
|
import Header from "$lib/components/Header.svelte";
|
||||||
import Router from "$lib/router/Router.svelte";
|
import Router from "$lib/router/Router.svelte";
|
||||||
|
import { Toaster } from 'svelte-sonner'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<Toaster />
|
||||||
<template>
|
<template>
|
||||||
<Header />
|
<Header />
|
||||||
<main class="flex-1">
|
<main class="flex-1">
|
||||||
|
@@ -1,8 +1,24 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { foodStore } from "$lib/store/FoodStore";
|
import { foodStore } from "$lib/store/FoodStore";
|
||||||
import FoodTable from "./Food/FoodTable.svelte";
|
import FoodTable from "./Food/FoodTable.svelte";
|
||||||
|
|
||||||
|
// Fuck this hacky shit
|
||||||
|
// Svelte won't re-render FoodTable when using the store directly
|
||||||
|
// It won't do it when using a variable and subscribing to the store
|
||||||
|
// It won't do it when reassigning the store
|
||||||
|
// Not when pushing unshifting the store
|
||||||
|
// This is the only thing that works
|
||||||
|
// Hacky ass shit
|
||||||
|
let forceUpdate = false;
|
||||||
|
foodStore.subscribe(() => {
|
||||||
|
forceUpdate = !forceUpdate;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FoodTable items={$foodStore} />
|
{#if forceUpdate}
|
||||||
</template>
|
<FoodTable items={$foodStore} />
|
||||||
|
{:else}
|
||||||
|
<FoodTable items={$foodStore} />
|
||||||
|
{/if}
|
||||||
|
</template>
|
||||||
|
@@ -1,95 +1,110 @@
|
|||||||
<!-- <script lang="ts">
|
<script lang="ts">
|
||||||
import { type Food, FoodService } from '$lib/database/food'
|
import { toast } from "svelte-sonner";
|
||||||
import { toast } from 'svelte-sonner'
|
import { main } from "$wails/models";
|
||||||
import type { Err } from '$lib/types'
|
import { CreateFood, GetLastPer100 } from "$wails/main/App";
|
||||||
import { foodStore } from '$lib/store/energy/foodStore'
|
import { foodStore } from "$lib/store/FoodStore";
|
||||||
import { RefreshStores } from '$lib/utils'
|
|
||||||
|
|
||||||
let item: Food = {
|
let item: main.Food = {
|
||||||
food: '',
|
food: "",
|
||||||
amount: 0,
|
amount: 0,
|
||||||
description: ''
|
description: "",
|
||||||
}
|
rowid: 0,
|
||||||
let name: string = ''
|
date: "",
|
||||||
let amount: string = ''
|
per100: 0,
|
||||||
let description: string = ''
|
energy: 0,
|
||||||
let per100: string = ''
|
};
|
||||||
let per100Edited: boolean = false
|
let name: string = "";
|
||||||
let per100Element: HTMLTableCellElement
|
let amount: string = "";
|
||||||
|
let description: string = "";
|
||||||
|
let per100: string = "";
|
||||||
|
let per100Edited: boolean = false;
|
||||||
|
let per100Element: HTMLTableCellElement;
|
||||||
|
|
||||||
async function update(event: KeyboardEvent & { currentTarget: (EventTarget & HTMLTableCellElement) }) {
|
async function update(event: KeyboardEvent & { currentTarget: EventTarget & HTMLTableCellElement }) {
|
||||||
name = name.trim()
|
name = name.trim();
|
||||||
amount = amount.trim()
|
amount = amount.trim();
|
||||||
description = description.trim()
|
description = description.trim();
|
||||||
per100 = per100.trim()
|
per100 = per100.trim();
|
||||||
|
|
||||||
if (!per100Edited && event.currentTarget === per100Element)
|
if (!per100Edited && event.currentTarget === per100Element) per100Edited = true;
|
||||||
per100Edited = true
|
|
||||||
|
|
||||||
if (event.key == 'Enter') {
|
if (event.key == "Enter") {
|
||||||
event.preventDefault()
|
event.preventDefault();
|
||||||
item.food = name
|
item.food = name;
|
||||||
item.description = description
|
item.description = description;
|
||||||
item.amount = parseInt(amount)
|
item.amount = parseInt(amount);
|
||||||
item.per100 = parseInt(per100)
|
item.per100 = parseInt(per100);
|
||||||
|
|
||||||
const [dbFood, err]: [Food, Err] = await FoodService.Create(item)
|
const res = await CreateFood(item);
|
||||||
name = ''
|
name = "";
|
||||||
amount = ''
|
amount = "";
|
||||||
// description = ''
|
// description = ''
|
||||||
per100 = ''
|
per100 = "";
|
||||||
per100Edited = false
|
per100Edited = false;
|
||||||
|
|
||||||
if (err) {
|
if (!res.success) {
|
||||||
toast.error(err)
|
toast.error(`failed to create item with error ${res.error}`);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
RefreshStores()
|
|
||||||
|
foodStore.update((value) => {
|
||||||
|
const updatedValue = [res.data, ...value];
|
||||||
|
console.log("Updated items:", updatedValue.length);
|
||||||
|
return updatedValue;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!per100Edited)
|
if (!per100Edited)
|
||||||
FoodService.GetLatestPer100(name.trim()).then((res) => {
|
GetLastPer100(name.trim()).then((res) => {
|
||||||
if (res[1])
|
if (res.success) {
|
||||||
// toast.error(res[1])
|
per100 = res.data.toString();
|
||||||
return
|
}
|
||||||
|
});
|
||||||
per100 = res[0].toString()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<tr class="border-b border-gray-200 dark:border-gray-700 text-lg font-bold">
|
<tr class="border-b border-gray-200 dark:border-gray-700 text-lg font-bold">
|
||||||
<th class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap bg-gray-50 dark:text-white dark:bg-gray-800"
|
<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"
|
||||||
|
scope="row"
|
||||||
|
>
|
||||||
</th>
|
</th>
|
||||||
<td bind:innerText={name}
|
<td
|
||||||
class:border-[3px]={!name}
|
bind:innerText={name}
|
||||||
class:border-red-600={!name}
|
class:border-[3px]={!name}
|
||||||
class="px-6 py-4 overflow-hidden"
|
class:border-red-600={!name}
|
||||||
contenteditable="true"
|
class="px-6 py-4 overflow-hidden"
|
||||||
autofocus
|
contenteditable="true"
|
||||||
on:keydown={update}>
|
autofocus
|
||||||
|
on:keydown={update}
|
||||||
|
>
|
||||||
</td>
|
</td>
|
||||||
<td bind:innerText={description}
|
<td
|
||||||
class="px-6 py-4 bg-gray-50 dark:bg-gray-800 overflow-hidden"
|
bind:innerText={description}
|
||||||
contenteditable="true"
|
class="px-6 py-4 bg-gray-50 dark:bg-gray-800 overflow-hidden"
|
||||||
on:keydown={update}>
|
contenteditable="true"
|
||||||
|
on:keydown={update}
|
||||||
|
>
|
||||||
</td>
|
</td>
|
||||||
<td bind:innerText={amount}
|
<td
|
||||||
class:border-[3px]={!amount}
|
bind:innerText={amount}
|
||||||
class:border-red-600={!amount}
|
class:border-[3px]={!amount}
|
||||||
class="px-6 py-4 overflow-hidden"
|
class:border-red-600={!amount}
|
||||||
contenteditable="true"
|
class="px-6 py-4 overflow-hidden"
|
||||||
on:keydown={update}>
|
contenteditable="true"
|
||||||
|
on:keydown={update}
|
||||||
|
>
|
||||||
</td>
|
</td>
|
||||||
<td bind:this={per100Element}
|
<td
|
||||||
bind:innerText={per100}
|
bind:this={per100Element}
|
||||||
class="px-6 py-4 bg-gray-50 dark:bg-gray-800 overflow-hidden"
|
bind:innerText={per100}
|
||||||
class:border-[3px]={!per100}
|
class="px-6 py-4 bg-gray-50 dark:bg-gray-800 overflow-hidden"
|
||||||
class:border-orange-600={!per100}
|
class:border-[3px]={!per100}
|
||||||
contenteditable="true"
|
class:border-orange-600={!per100}
|
||||||
on:keydown={update}>
|
contenteditable="true"
|
||||||
|
on:keydown={update}
|
||||||
|
>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template> -->
|
</template>
|
||||||
|
@@ -8,10 +8,12 @@
|
|||||||
|
|
||||||
let minCal = 1e5;
|
let minCal = 1e5;
|
||||||
let maxCal = 0;
|
let maxCal = 0;
|
||||||
for (let item of items) {
|
$: {
|
||||||
if (!item.energy) continue;
|
for (let item of items) {
|
||||||
if (item.energy > maxCal) maxCal = item.energy;
|
if (!item.energy) continue;
|
||||||
if (item.energy < minCal) minCal = item.energy;
|
if (item.energy > maxCal) maxCal = item.energy;
|
||||||
|
if (item.energy < minCal) minCal = item.energy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const start = "#99ff99";
|
const start = "#99ff99";
|
||||||
@@ -72,7 +74,12 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<EmptyFoodComp />
|
<EmptyFoodComp />
|
||||||
{#each items as f}
|
{#each items as f}
|
||||||
<FoodComp item="{f}" energyColor="{lerp(f)}" nameColor="{getNameColor(f)}" dateColor="{getDateColor(f)}" />
|
<FoodComp
|
||||||
|
item={f}
|
||||||
|
energyColor={lerp(f)}
|
||||||
|
nameColor={getNameColor(f)}
|
||||||
|
dateColor={getDateColor(f)}
|
||||||
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
2
frontend/wailsjs/go/main/App.d.ts
vendored
2
frontend/wailsjs/go/main/App.d.ts
vendored
@@ -6,6 +6,8 @@ export function CreateFood(arg1:main.Food):Promise<main.WailsFood1>;
|
|||||||
|
|
||||||
export function GetFood():Promise<main.WailsFood>;
|
export function GetFood():Promise<main.WailsFood>;
|
||||||
|
|
||||||
|
export function GetLastPer100(arg1:string):Promise<main.WailsPer100>;
|
||||||
|
|
||||||
export function GetSettings():Promise<main.settings>;
|
export function GetSettings():Promise<main.settings>;
|
||||||
|
|
||||||
export function SetSetting(arg1:string,arg2:any):Promise<main.settings>;
|
export function SetSetting(arg1:string,arg2:any):Promise<main.settings>;
|
||||||
|
@@ -10,6 +10,10 @@ export function GetFood() {
|
|||||||
return window['go']['main']['App']['GetFood']();
|
return window['go']['main']['App']['GetFood']();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function GetLastPer100(arg1) {
|
||||||
|
return window['go']['main']['App']['GetLastPer100'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
export function GetSettings() {
|
export function GetSettings() {
|
||||||
return window['go']['main']['App']['GetSettings']();
|
return window['go']['main']['App']['GetSettings']();
|
||||||
}
|
}
|
||||||
|
@@ -92,6 +92,22 @@ export namespace main {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export class WailsPer100 {
|
||||||
|
data: number;
|
||||||
|
success: boolean;
|
||||||
|
error?: string;
|
||||||
|
|
||||||
|
static createFrom(source: any = {}) {
|
||||||
|
return new WailsPer100(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(source: any = {}) {
|
||||||
|
if ('string' === typeof source) source = JSON.parse(source);
|
||||||
|
this.data = source["data"];
|
||||||
|
this.success = source["success"];
|
||||||
|
this.error = source["error"];
|
||||||
|
}
|
||||||
|
}
|
||||||
export class settings {
|
export class settings {
|
||||||
foodDaysLookback: number;
|
foodDaysLookback: number;
|
||||||
foodAggregatedDaysLookback: number;
|
foodAggregatedDaysLookback: number;
|
||||||
|
@@ -16,11 +16,15 @@ type (
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
WailsFood1 struct {
|
WailsFood1 struct {
|
||||||
Data Food `json:"data"`
|
Data Food `json:"data"`
|
||||||
Success bool `json:"success"`
|
Success bool `json:"success"`
|
||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
}
|
}
|
||||||
|
WailsPer100 struct {
|
||||||
|
Data float32 `json:"data"`
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Error string `json:"error,omitempty"`
|
||||||
|
}
|
||||||
WailsAggregateFood struct {
|
WailsAggregateFood struct {
|
||||||
Data []AggregatedFood `json:"data"`
|
Data []AggregatedFood `json:"data"`
|
||||||
Success bool `json:"success"`
|
Success bool `json:"success"`
|
||||||
|
Reference in New Issue
Block a user