Compare commits

...

10 Commits

Author SHA1 Message Date
PhatPhuckDave
4aefd36c68 ..update 2024-07-21 18:19:14 +02:00
dafff6d064 Make all stores refresh on change
Since everything is calculated on db.......
2024-06-15 14:08:34 +02:00
e81ead8e41 Disable auto updater 2024-06-13 18:59:36 +02:00
3adeb4d1ab Implement weight graphs 2024-06-13 18:58:59 +02:00
84e0d2b944 Format tables properly 2024-06-13 18:23:46 +02:00
800ac867f2 Copy paste food to weight 2024-06-13 18:05:14 +02:00
c8dd478419 Add placeholder weight routes 2024-06-13 17:56:11 +02:00
8a794c8bad Refactor routing 2024-06-13 17:51:02 +02:00
2596fc96b7 Fix issue with scrolling 2024-06-13 17:48:48 +02:00
3ea4ce2767 Lil refactor 2024-06-13 15:14:31 +02:00
44 changed files with 675 additions and 156 deletions

1
.gitignore vendored
View File

@@ -11,3 +11,4 @@ target
node_modules node_modules
.vscode .vscode
.idea .idea
main.log

View File

@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Svelte-Tauri</title> <title>Svelte-Tauri</title>
</head> </head>
<body id="app"> <body id="app" class="overflow-hidden">
<script type="module" src="/src/main.ts"></script> <script type="module" src="/src/main.ts"></script>
</body> </body>
</html> </html>

21
src-tauri/Cargo.lock generated
View File

@@ -2435,12 +2435,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "minisign-verify"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881"
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.7.3" version = "0.7.3"
@@ -4475,7 +4469,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77567d2b3b74de4588d544147142d02297f3eaa171a25a065252141d8597a516" checksum = "77567d2b3b74de4588d544147142d02297f3eaa171a25a065252141d8597a516"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"base64 0.21.7",
"bytes", "bytes",
"cocoa", "cocoa",
"dirs-next", "dirs-next",
@@ -4492,7 +4485,6 @@ dependencies = [
"http", "http",
"ignore", "ignore",
"indexmap 1.9.3", "indexmap 1.9.3",
"minisign-verify",
"nix 0.26.4", "nix 0.26.4",
"notify-rust", "notify-rust",
"objc", "objc",
@@ -4521,14 +4513,12 @@ dependencies = [
"tauri-utils", "tauri-utils",
"tempfile", "tempfile",
"thiserror", "thiserror",
"time",
"tokio", "tokio",
"url", "url",
"uuid", "uuid",
"webkit2gtk", "webkit2gtk",
"webview2-com", "webview2-com",
"windows 0.39.0", "windows 0.39.0",
"zip",
] ]
[[package]] [[package]]
@@ -6289,17 +6279,6 @@ dependencies = [
"syn 2.0.66", "syn 2.0.66",
] ]
[[package]]
name = "zip"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
dependencies = [
"byteorder",
"crc32fast",
"crossbeam-utils",
]
[[package]] [[package]]
name = "zvariant" name = "zvariant"
version = "4.1.1" version = "4.1.1"

View File

@@ -25,7 +25,7 @@ features = ["derive"]
[dependencies.tauri] [dependencies.tauri]
version = "1.6.5" version = "1.6.5"
features = ["api-all", "devtools", "updater"] features = ["api-all", "devtools"]
[dependencies.tauri-specta] [dependencies.tauri-specta]
version = "1.0.2" version = "1.0.2"

View File

@@ -51,7 +51,7 @@
"csp": null "csp": null
}, },
"updater": { "updater": {
"active": true, "active": false,
"windows": { "windows": {
"installMode": "passive" "installMode": "passive"
}, },

View File

@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { Line } from 'svelte-chartjs' import { Line } from 'svelte-chartjs'
import type { AggregatedFood } from '$lib/database/food' import type { AggregatedFood } from '$lib/database/food'
import AggregatedFoodComp from '$components/AggregatedFood/AggregatedFoodComp.svelte' import AggregatedFoodComp from '$components/Energy/AggregatedFood/AggregatedFoodComp.svelte'
import type { ChartData, Point } from 'chart.js' import type { ChartData, Point } from 'chart.js'
import { import {
CategoryScale, CategoryScale,
@@ -85,13 +85,13 @@
</script> </script>
<template> <template>
<Line data="{data}" /> <Line data="{data}" class="max-h-[50vh] h-[50vh]" />
<div class="relative flex flex-col h-screen" data-vaul-drawer-wrapper id="page"> <div class="relative flex flex-col h-[43vh]" data-vaul-drawer-wrapper id="page">
<div class="relative overflow-x-auto shadow-md sm:rounded-lg"> <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"> <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"> <thead class="text-xs text-gray-700 uppercase dark:text-gray-400">
<tr> <tr>
<th class="px-6 py-3 bg-gray-50 dark:bg-gray-800" scope="col"> <th class="px-6 py-3 bg-gray-50 dark:bg-gray-800 w-2/12" scope="col">
Period Period
</th> </th>
<th class="px-6 py-3" scope="col"> <th class="px-6 py-3" scope="col">

View File

@@ -2,7 +2,8 @@
import { type Food, FoodService } from '$lib/database/food' import { type Food, FoodService } from '$lib/database/food'
import { toast } from 'svelte-sonner' import { toast } from 'svelte-sonner'
import type { Err } from '$lib/types' import type { Err } from '$lib/types'
import { foodStore } from '$lib/store/foodStore' import { foodStore } from '$lib/store/energy/foodStore'
import { RefreshStores } from '$lib/utils'
let item: Food = { let item: Food = {
food: '', food: '',
@@ -35,7 +36,7 @@
const [dbFood, err]: [Food, Err] = await FoodService.Create(item) const [dbFood, err]: [Food, Err] = await FoodService.Create(item)
name = '' name = ''
amount = '' amount = ''
description = '' // description = ''
per100 = '' per100 = ''
per100Edited = false per100Edited = false
@@ -43,10 +44,7 @@
toast.error(err) toast.error(err)
return return
} }
foodStore.update((food) => { RefreshStores()
food.unshift(dbFood)
return food
})
} }
if (!per100Edited) if (!per100Edited)
@@ -93,7 +91,5 @@
contenteditable="true" contenteditable="true"
on:keydown={update}> on:keydown={update}>
</td> </td>
<td class="px-6 py-4">
</td>
</tr> </tr>
</template> </template>

View File

@@ -12,31 +12,17 @@
let name: string = item.food let name: string = item.food
async function update(event: KeyboardEvent & { currentTarget: (EventTarget & HTMLTableCellElement) }) { async function update(event: KeyboardEvent & { currentTarget: (EventTarget & HTMLTableCellElement) }) {
amount = amount.trim()
per100 = per100.trim()
description = description.trim()
name = name.trim()
if (event.key == 'Enter') { if (event.key == 'Enter') {
event.preventDefault() event.preventDefault()
item.food = name await updateItem()
item.description = description
item.amount = parseInt(amount)
item.per100 = parseInt(per100)
const [newItem, err] = await FoodService.Update(item)
if (newItem && !err) {
item = newItem
}
name = item.food
description = item.description ?? ''
amount = item.amount.toString()
per100 = item.per100?.toString() ?? ''
} }
} }
async function focusOutUpdate() { async function focusOutUpdate() {
await updateItem()
}
async function updateItem() {
amount = amount.trim() amount = amount.trim()
per100 = per100.trim() per100 = per100.trim()
description = description.trim() description = description.trim()

View File

@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import EmptyFoodComp from '$components/Food/EmptyFoodComp.svelte' import EmptyFoodComp from '$components/Energy/Food/EmptyFoodComp.svelte'
import FoodComp from '$components/Food/FoodComp.svelte' import FoodComp from '$components/Energy/Food/FoodComp.svelte'
import type { Food } from '$lib/database/food' import type { Food } from '$lib/database/food'
import { GenerateColor } from '$lib/utils' import { GenerateColor } from '$lib/utils'
@@ -56,27 +56,27 @@
</script> </script>
<template> <template>
<div class="relative flex flex-col h-screen" data-vaul-drawer-wrapper id="page"> <div class="relative flex flex-col flex-grow h-[95vh]" data-vaul-drawer-wrapper id="page">
<div class="relative overflow-x-auto shadow-md sm:rounded-lg"> <div class="relative overflow-auto h-full shadow-md sm:rounded-lg">
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400"> <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"> <thead class="text-xs text-gray-700 uppercase dark:text-gray-400">
<tr> <tr>
<th class="px-6 py-3 bg-gray-50 dark:bg-gray-800" scope="col"> <th class="px-6 py-3 bg-gray-50 dark:bg-gray-800 w-2/12" scope="col">
Date Date
</th> </th>
<th class="px-6 py-3" scope="col"> <th class="px-6 py-3 w-3/12" scope="col">
Food Food
</th> </th>
<th class="px-6 py-3 bg-gray-50 dark:bg-gray-800" scope="col"> <th class="px-6 py-3 bg-gray-50 dark:bg-gray-800 w-4/12" scope="col">
Description Description
</th> </th>
<th class="px-6 py-3" scope="col"> <th class="px-6 py-3 w-1/12" scope="col">
Amount Amount
</th> </th>
<th class="px-6 py-3 bg-gray-50 dark:bg-gray-800" scope="col"> <th class="px-6 py-3 bg-gray-50 dark:bg-gray-800 w-1/12" scope="col">
Cal Per 100 Cal Per 100
</th> </th>
<th class="px-6 py-3" scope="col"> <th class="px-6 py-3 w-1/12" scope="col">
Energy Energy
</th> </th>
</tr> </tr>

View File

@@ -1,7 +1,6 @@
<script lang="ts"> <script lang="ts">
import { appWindow } from '@tauri-apps/api/window' import { appWindow } from '@tauri-apps/api/window'
import { faWindowMinimize, faXmark } from '@fortawesome/free-solid-svg-icons' import { faWindowMinimize, faXmark } from '@fortawesome/free-solid-svg-icons'
import { faGithub } from '@fortawesome/free-brands-svg-icons'
import Fa from 'svelte-fa' import Fa from 'svelte-fa'
import { link, location } from 'svelte-spa-router' import { link, location } from 'svelte-spa-router'
import { Button } from '$components/ui/button' import { Button } from '$components/ui/button'
@@ -10,7 +9,7 @@
import { cn } from '$lib/utils' import { cn } from '$lib/utils'
import { dbStateStore } from '$lib/store/dbState' import { dbStateStore } from '$lib/store/dbState'
import { DBService } from '$lib/database' import { DBService } from '$lib/database'
import { lookbackDaysStore } from '$lib/store/lookbackDaysStore' import { lookbackDaysStore } from '$lib/store/energy/lookbackDaysStore'
Fa Fa
@@ -18,36 +17,47 @@
type Link = { type Link = {
label: string label: string
href: string href: string
base: string?
} }
const links: Link[] = [ let sublinks: Link[] = [
{
label: 'Home',
href: '/'
},
{ {
label: 'Daily', label: 'Daily',
href: '/daily' href: '/daily',
base: '/daily'
}, },
{ {
label: 'Weekly', label: 'Weekly',
href: '/weekly' href: '/weekly',
base: '/weekly'
}, },
{ {
label: 'Monthly', label: 'Monthly',
href: '/monthly' href: '/monthly',
base: '/monthly'
}, },
{ {
label: 'Yearly', label: 'Yearly',
href: '/yearly' href: '/yearly',
base: '/yearly'
} }
] ]
let selected = 'Energy'
$: {
console.log('update')
sublinks = sublinks.map((sublink: Link) => {
return {
...sublink,
href: `/${selected}${sublink.base}`
}
})
}
</script> </script>
<header <header
class="flex h-14 items-center justify-between bg-base-100 shadow-lg sticky top-0 z-50 border-b class="flex h-22 items-center justify-between bg-base-100 shadow-lg sticky top-0 z-50 border-b
border-border/40 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60" border-border/40 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60"
data-tauri-drag-region data-tauri-drag-region>
>
<Button class="ml-2" on:click={toggleMode} size="icon" variant="outline"> <Button class="ml-2" on:click={toggleMode} size="icon" variant="outline">
<Sun <Sun
class="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" class="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0"
@@ -58,38 +68,40 @@
<span class="sr-only">Toggle theme</span> <span class="sr-only">Toggle theme</span>
</Button> </Button>
<nav <div>
class="flex space-x-4 text-xl font-bold select-none" <nav class="flex space-x-4 text-2xl font-bold select-none justify-center">
on:dragstart|preventDefault <div class="cursor-pointer" class:text-amber-500="{$dbStateStore.transacting}" on:click={DBService.Begin}>T
> </div>
<div class="cursor-pointer" class:text-amber-500="{$dbStateStore.transacting}" on:click={DBService.Begin}>T <div class="cursor-pointer" class:text-emerald-600={$dbStateStore.transacting} on:click={DBService.Commit}>C
</div> </div>
<div class="cursor-pointer" class:text-emerald-600={$dbStateStore.transacting} on:click={DBService.Commit}>C <div class="cursor-pointer" class:text-red-700={$dbStateStore.transacting} on:click={DBService.Rollback}>R
</div> </div>
<div class="cursor-pointer" class:text-red-700={$dbStateStore.transacting} on:click={DBService.Rollback}>R</div> <div contenteditable="true" bind:innerText={$lookbackDaysStore}></div>
<div contenteditable="true" bind:innerText={$lookbackDaysStore}></div> <a use:link
{#each links as { href, label }} class={cn(
<a 'transition-colors hover:text-foreground/80',
use:link "/" === $location ? '' : 'text-foreground/60')}
{href} href="/"
class={cn( on:click={e => selected = 'Energy'}>Energy</a>
'transition-colors hover:text-foreground/80', <a use:link
href === $location ? '' : 'text-foreground/60' class={cn(
)}>{label}</a 'transition-colors hover:text-foreground/80',
> "/Weight" === $location ? '' : 'text-foreground/60')}
{/each} href="/Weight"
</nav> on:click={e => selected = 'Weight'}>Weight</a>
</nav>
<nav class="flex space-x-4 text-2xl font-bold select-none justify-center">
{#each sublinks as { label, href }}
<a use:link
{href}
class={cn(
'transition-colors hover:text-foreground/80',
href === $location ? '' : 'text-foreground/60')}>{label}</a>
{/each}
</nav>
</div>
<div class="flex h-full [&>*]:px-2 [&>*]:transition-all"> <div class="flex h-full [&>*]:px-2 [&>*]:transition-all">
<a
class="flex items-center hover:text-secondary"
href="https://github.com/Fractal-Tess/Svelte-Tauri"
on:dragstart|preventDefault
rel="noreferrer noopener"
target="_blank"
>
<Fa icon={faGithub} size="lg" />
</a>
<button class="text-xl hover:text-secondary" on:click={appWindow.minimize}> <button class="text-xl hover:text-secondary" on:click={appWindow.minimize}>
<Fa icon={faWindowMinimize} /> <Fa icon={faWindowMinimize} />
</button> </button>

View File

@@ -0,0 +1,17 @@
<script lang="ts">
import type { AggregatedWeight } from '$lib/database/weight'
export let item: AggregatedWeight
</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">
{item.period}
</th>
<td class="px-6 py-4">
{item.amount}
</td>
</tr>
</template>

View File

@@ -0,0 +1,85 @@
<script lang="ts">
import { Line } from 'svelte-chartjs'
import type { AggregatedFood } from '$lib/database/food'
import AggregatedFoodComp from '$components/Energy/AggregatedFood/AggregatedFoodComp.svelte'
import type { ChartData, Point } from 'chart.js'
import {
CategoryScale,
Chart as ChartJS,
Legend,
LinearScale,
LineElement,
PointElement,
Title,
Tooltip
} from 'chart.js'
import type { AggregatedWeight } from '$lib/database/weight'
import AggregatedWeightComp from '$components/Weight/Aggregated/AggregatedWeightComp.svelte'
ChartJS.register(
Title,
Tooltip,
Legend,
LineElement,
LinearScale,
PointElement,
CategoryScale
)
export let items: AggregatedWeight[] = []
let reversedItems = items.slice().reverse()
const defaultOptions = {
backgroundColor: 'rgba(225, 204,230, .3)',
borderColor: 'rgb(205, 130, 158)',
pointBorderColor: 'rgb(205, 130, 158)',
pointBackgroundColor: 'rgb(255, 255, 255)',
pointBorderWidth: 10,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'rgb(0, 157, 123)',
pointHoverBorderColor: 'rgba(220, 220, 220, 1)',
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10
}
const data: ChartData<'line', (number | Point)[]> = {
labels: reversedItems.map(f => f.period),
datasets: [
{
...defaultOptions,
label: 'Amount',
data: reversedItems.map(f => f.amount),
borderColor: '#ff4dff',
pointBorderColor: '#ff4dff',
},
]
}
console.log('aaaaaaaaaa')
</script>
<template>
<Line data="{data}" class="max-h-[50vh] h-[50vh]" />
<div class="relative flex flex-col h-[43vh]" 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 class="px-6 py-3 bg-gray-50 dark:bg-gray-800 w-2/12" scope="col">
Period
</th>
<th class="px-6 py-3" scope="col">
Amount
</th>
</tr>
</thead>
<tbody>
{#each items as f}
<AggregatedWeightComp item="{f}" />
{/each}
</tbody>
</table>
</div>
<div>
</div>
</div>
</template>

View File

@@ -0,0 +1,47 @@
<script lang="ts">
import { toast } from 'svelte-sonner'
import type { Err } from '$lib/types'
import { type Weight, WeightService } from '$lib/database/weight'
import { weightStore } from '$lib/store/weight/weightStore'
import { RefreshStores } from '$lib/utils'
let item: Weight = {
weight: 0
}
let weight: string | null = null
async function update(event: KeyboardEvent & { currentTarget: (EventTarget & HTMLTableCellElement) }) {
if (!weight) return
weight = weight.trim()
if (event.key == 'Enter') {
event.preventDefault()
item.weight = parseFloat(weight)
const [dbRow, err]: [Weight, Err] = await WeightService.Create(item)
weight = ''
if (err) {
toast.error(err)
return
}
RefreshStores()
}
}
</script>
<template>
<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"
scope="row">
</th>
<td bind:innerText={weight}
class:border-[3px]={!weight}
class:border-red-600={!weight}
class="px-6 py-4 overflow-hidden"
contenteditable="true"
autofocus
on:keydown={update}>
</td>
</tr>
</template>

View File

@@ -0,0 +1,45 @@
<script lang="ts">
import { type Weight, WeightService } from '$lib/database/weight'
export let item: Weight
export let dateColor: string
let weight: string = item.weight.toString()
async function update(event: KeyboardEvent & { currentTarget: (EventTarget & HTMLTableCellElement) }) {
if (event.key == 'Enter') {
event.preventDefault()
await updateItem()
}
}
async function focusOutUpdate() {
await updateItem()
}
async function updateItem() {
weight = weight.trim()
item.weight = weight
const [newItem, err] = await WeightService.Update(item)
if (newItem && !err) {
item = newItem
}
weight = item.weight
}
</script>
<template>
<tr class="border-b border-gray-200 dark:border-gray-700 font-bold text-lg">
<th class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap bg-gray-50 dark:text-white dark:bg-gray-800"
style="color: {dateColor}"
scope="row">
{item.date}
</th>
<td class="px-6 py-4">
{item.weight}
</td>
</tr>
</template>

View File

@@ -0,0 +1,50 @@
<script lang="ts">
import { GenerateColor } from '$lib/utils'
import EmptyWeightComp from '$components/Weight/EmptyWeightComp.svelte'
import WeightComp from '$components/Weight/WeightComp.svelte'
import type { Weight } from '$lib/database/weight'
export let items: Weight[] = []
const dateColors: Map<string, string> = new Map<string, string>()
function getDateColor(item: Weight): string {
if (!item) return GenerateColor()
if (!item.date) return GenerateColor()
const date = item.date.toString().split(' ')[0]
if (!date) return GenerateColor()
if (!dateColors.has(date)) dateColors.set(date, GenerateColor())
// THERE'S NOTHING UNDEFINED HERE
// WE GOT RID OF UNDEFINED ON LINE 33
// ASSHOLE
// @ts-ignore
return dateColors.get(date)
}
</script>
<template>
<div class="relative flex flex-col flex-grow h-[95vh]" data-vaul-drawer-wrapper id="page">
<div class="relative overflow-auto h-full 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 class="px-6 py-3 bg-gray-50 dark:bg-gray-800 w-2/12" scope="col">
Date
</th>
<th class="px-6 py-3 w-10/12" scope="col">
Weight
</th>
</tr>
</thead>
<tbody>
<EmptyWeightComp />
{#each items as f}
<WeightComp item="{f}" dateColor="{getDateColor(f)}" />
{/each}
</tbody>
</table>
</div>
<div>
</div>
</div>
</template>

View File

@@ -1,6 +1,6 @@
import { db } from '$lib/database' import { db } from '$lib/database'
import type { Err } from '$lib/types' import type { Err } from '$lib/types'
import { lookbackDaysStore } from '$lib/store/lookbackDaysStore' import { lookbackDaysStore } from '$lib/store/energy/lookbackDaysStore'
import { get } from 'svelte/store' import { get } from 'svelte/store'
export type Food = { export type Food = {

View File

@@ -0,0 +1,77 @@
import { db } from '$lib/database'
import type { Err } from '$lib/types'
import { lookbackDaysStore } from '$lib/store/energy/lookbackDaysStore'
import { get } from 'svelte/store'
export type Weight = {
rowid?: number,
date?: Date,
weight: number,
}
export type AggregatedWeight = {
period: string,
amount: number,
}
const columns = ['rowid', 'date', 'weight']
const aggColumns = ['period', 'amount']
const WeightService = {
async GetAll() {
return await db.select<Weight[]>(`
select ${columns.join(', ')}
from food
order by date desc
`)
},
async GetRecent() {
return await db.select<Weight[]>(`
select ${columns.join(', ')}
from weightView
where date > datetime('now', "-${get(lookbackDaysStore)} days")
order by date DESC;
`)
},
async Create(entry: Weight): Promise<[Weight, Err]> {
if (!entry.weight) return [entry, 'entry.weight is required']
const res = await db.execute(`insert into weight (weight) values ($1)`, [entry.weight])
const rows = await db.select<Weight[]>(`select ${columns.join(', ')} from weightView where rowid = $1`, [res.lastInsertId])
if (!rows) return [entry, 'no data found']
if (rows.length == 0) return [entry, 'no data found']
// Its not undefined mannnnnnnnnnnnnnnnnnnnnnnnnn............
// @ts-ignore
return [rows[0], null]
},
async GetDaily(): Promise<[AggregatedWeight[], Err]> {
const rows = await db.select<AggregatedWeight[]>(`select ${aggColumns.join(', ')} from weightDaily limit 100`)
return [rows, null]
},
async GetWeekly(): Promise<[AggregatedWeight[], Err]> {
const rows = await db.select<AggregatedWeight[]>(`select ${aggColumns.join(', ')} from weightWeekly limit 100`)
return [rows, null]
},
async GetMonthly(): Promise<[AggregatedWeight[], Err]> {
const rows = await db.select<AggregatedWeight[]>(`select ${aggColumns.join(', ')} from weightMonthly limit 100`)
return [rows, null]
},
async GetYearly(): Promise<[AggregatedWeight[], Err]> {
const rows = await db.select<AggregatedWeight[]>(`select ${aggColumns.join(', ')} from weightYearly limit 100`)
return [rows, null]
},
async Update(entry: Weight): Promise<[Weight, Err]> {
await db.execute(`
update weight set
weight = $1,
where rowid = $2
`, [entry.weight, entry.rowid])
const res = await db.select<Weight[]>(`select ${columns.join(', ')} from weightView where rowid = $1`, [entry.rowid])
if (!res) return [entry, 'no data found']
if (res.length == 0) return [entry, 'no data found']
if (!res[0]) return [entry, 'no data found']
return [res[0], null]
}
}
export { WeightService }

View File

@@ -1,18 +1,27 @@
<script lang="ts"> <script lang="ts">
import Router from 'svelte-spa-router' import Router from 'svelte-spa-router'
import Daily from '$router/routes/Energy/Daily.svelte'
import Home from '$lib/router/routes/Home.svelte' import Weekly from '$router/routes/Energy/Weekly.svelte'
import Daily from '$router/routes/Daily.svelte' import Monthly from '$router/routes/Energy/Monthly.svelte'
import Weekly from '$router/routes/Weekly.svelte' import Yearly from '$router/routes/Energy/Yearly.svelte'
import Monthly from '$router/routes/Monthly.svelte' import Energy from '$router/routes/Energy/Energy.svelte'
import Yearly from '$router/routes/Yearly.svelte' import Weight from '$router/routes/Weight/Weight.svelte'
import WDaily from '$router/routes/Weight/WDaily.svelte'
import WWeekly from '$router/routes/Weight/WWeekly.svelte'
import WMonthly from '$router/routes/Weight/WMonthly.svelte'
import WYearly from '$router/routes/Weight/WYearly.svelte'
const routes = { const routes = {
'/': Home, '/': Energy,
'/daily': Daily, '/Energy/daily': Daily,
'/weekly': Weekly, '/Energy/weekly': Weekly,
'/monthly': Monthly, '/Energy/monthly': Monthly,
'/yearly': Yearly '/Energy/yearly': Yearly,
'/Weight': Weight,
'/Weight/daily': WDaily,
'/Weight/weekly': WWeekly,
'/Weight/monthly': WMonthly,
'/Weight/yearly': WYearly
} }
</script> </script>

View File

@@ -1,11 +0,0 @@
<script lang="ts">
import AggregatedFoodTable from '$components/AggregatedFood/AggregatedFoodTable.svelte'
import { dailyFoodStore } from '$lib/store/dailyFoodStore'
import { energyStore } from '$lib/store/energyStore'
</script>
<template>
<AggregatedFoodTable items="{$dailyFoodStore}"
energyLimit="{$energyStore.limit}"
energyTarget="{$energyStore.target}" />
</template>

View File

@@ -0,0 +1,11 @@
<script lang="ts">
import AggregatedFoodTable from '$components/Energy/AggregatedFood/AggregatedFoodTable.svelte'
import { dailyFoodStore } from '$lib/store/energy/dailyFoodStore'
import { energyStore } from '$lib/store/energy/energyStore'
</script>
<template>
<AggregatedFoodTable items="{$dailyFoodStore}"
energyLimit="{$energyStore.limit}"
energyTarget="{$energyStore.target}" />
</template>

View File

@@ -0,0 +1,11 @@
<script lang="ts">
import { foodStore } from '$lib/store/energy/foodStore'
import FoodTable from '$components/Energy/Food/FoodTable.svelte'
import { lookbackDaysStore } from '$lib/store/energy/lookbackDaysStore'
import { RefreshStores } from '$lib/utils'
lookbackDaysStore.subscribe((n) => RefreshStores())
</script>
<template>
<FoodTable items="{$foodStore}" />
</template>

View File

@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import AggregatedFoodTable from '$components/AggregatedFood/AggregatedFoodTable.svelte' import AggregatedFoodTable from '$components/Energy/AggregatedFood/AggregatedFoodTable.svelte'
import { monthlyFoodStore } from '$lib/store/monthlyFoodStore' import { monthlyFoodStore } from '$lib/store/energy/monthlyFoodStore'
import { energyStore } from '$lib/store/energyStore' import { energyStore } from '$lib/store/energy/energyStore'
</script> </script>
<template> <template>

View File

@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import AggregatedFoodTable from '$components/AggregatedFood/AggregatedFoodTable.svelte' import AggregatedFoodTable from '$components/Energy/AggregatedFood/AggregatedFoodTable.svelte'
import { energyStore } from '$lib/store/energyStore' import { energyStore } from '$lib/store/energy/energyStore'
import { weeklyFoodStore } from '$lib/store/weeklyFoodStore' import { weeklyFoodStore } from '$lib/store/energy/weeklyFoodStore'
</script> </script>
<template> <template>

View File

@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import AggregatedFoodTable from '$components/AggregatedFood/AggregatedFoodTable.svelte' import AggregatedFoodTable from '$components/Energy/AggregatedFood/AggregatedFoodTable.svelte'
import { yearlyFoodStore } from '$lib/store/yearlyFoodStore' import { yearlyFoodStore } from '$lib/store/energy/yearlyFoodStore'
import { energyStore } from '$lib/store/energyStore' import { energyStore } from '$lib/store/energy/energyStore'
</script> </script>
<template> <template>

View File

@@ -1,11 +0,0 @@
<script lang="ts">
import { foodStore } from '$lib/store/foodStore'
import FoodTable from '$components/Food/FoodTable.svelte'
import { lookbackDaysStore } from '$lib/store/lookbackDaysStore'
// @ts-ignore
lookbackDaysStore.subscribe((n) => foodStore.refresh())
</script>
<template>
<FoodTable items="{$foodStore}" />
</template>

View File

@@ -0,0 +1,8 @@
<script lang="ts">
import AggregatedWeightTable from '$components/Weight/Aggregated/AggregatedWeightTable.svelte'
import { dailyWeightStore } from '$lib/store/weight/dailyWeightStore'
</script>
<template>
<AggregatedWeightTable items="{$dailyWeightStore}" />
</template>

View File

@@ -0,0 +1,8 @@
<script lang="ts">
import { monthlyWeightStore } from '$lib/store/weight/monthlyWeightStore'
import AggregatedWeightTable from '$components/Weight/Aggregated/AggregatedWeightTable.svelte'
</script>
<template>
<AggregatedWeightTable items="{$monthlyWeightStore}" />
</template>

View File

@@ -0,0 +1,8 @@
<script lang="ts">
import { weeklyWeightStore } from '$lib/store/weight/weeklyWeightStore'
import AggregatedWeightTable from '$components/Weight/Aggregated/AggregatedWeightTable.svelte'
</script>
<template>
<AggregatedWeightTable items="{$weeklyWeightStore}" />
</template>

View File

@@ -0,0 +1,8 @@
<script lang="ts">
import AggregatedWeightTable from '$components/Weight/Aggregated/AggregatedWeightTable.svelte'
import { yearlyWeightStore } from '$lib/store/weight/yearlyWeightStore'
</script>
<template>
<AggregatedWeightTable items="{yearlyWeightStore}" />
</template>

View File

@@ -0,0 +1,8 @@
<script lang="ts">
import WeightTable from '$components/Weight/WeightTable.svelte'
import { weightStore } from '$lib/store/weight/weightStore'
</script>
<template>
<WeightTable items="{$weightStore}" />
</template>

View File

@@ -13,7 +13,12 @@ async function createStore(): Promise<Writable<AggregatedFood[]>> {
return { return {
subscribe, subscribe,
update, update,
set set,
// @ts-ignore
refresh: async () => {
const rows = await FoodService.GetDaily()
set(rows[0])
}
} }
} }

View File

@@ -13,7 +13,12 @@ async function createStore(): Promise<Writable<AggregatedFood[]>> {
return { return {
subscribe, subscribe,
update, update,
set set,
// @ts-ignore
refresh: async () => {
const rows = await FoodService.GetMonthly()
set(rows[0])
}
} }
} }

View File

@@ -13,7 +13,12 @@ async function createStore(): Promise<Writable<AggregatedFood[]>> {
return { return {
subscribe, subscribe,
update, update,
set set,
// @ts-ignore
refresh: async () => {
const rows = await FoodService.GetWeekly()
set(rows[0])
}
} }
} }

View File

@@ -13,7 +13,12 @@ async function createStore(): Promise<Writable<AggregatedFood[]>> {
return { return {
subscribe, subscribe,
update, update,
set set,
// @ts-ignore
refresh: async () => {
const rows = await FoodService.GetYearly()
set(rows[0])
}
} }
} }

View File

@@ -0,0 +1,26 @@
import { type Writable, writable } from 'svelte/store'
import { type AggregatedWeight, WeightService } from '$lib/database/weight'
import { FoodService } from '$lib/database/food'
async function createStore(): Promise<Writable<AggregatedWeight[]>> {
let [rows, err] = await WeightService.GetDaily()
if (err) {
rows = []
console.error(err)
}
const { subscribe, update, set } = writable(rows)
return {
subscribe,
update,
set,
// @ts-ignore
refresh: async () => {
const rows = await WeightService.GetDaily()
set(rows[0])
}
}
}
export const dailyWeightStore = await createStore()

View File

@@ -0,0 +1,25 @@
import { type Writable, writable } from 'svelte/store'
import { type AggregatedWeight, WeightService } from '$lib/database/weight'
async function createStore(): Promise<Writable<AggregatedWeight[]>> {
let [rows, err] = await WeightService.GetMonthly()
if (err) {
rows = []
console.error(err)
}
const { subscribe, update, set } = writable(rows)
return {
subscribe,
update,
set,
// @ts-ignore
refresh: async () => {
const rows = await WeightService.GetMonthly()
set(rows[0])
}
}
}
export const monthlyWeightStore = await createStore()

View File

@@ -0,0 +1,25 @@
import { type Writable, writable } from 'svelte/store'
import { type AggregatedWeight, WeightService } from '$lib/database/weight'
async function createStore(): Promise<Writable<AggregatedWeight[]>> {
let [rows, err] = await WeightService.GetWeekly()
if (err) {
rows = []
console.error(err)
}
const { subscribe, update, set } = writable(rows)
return {
subscribe,
update,
set,
// @ts-ignore
refresh: async () => {
const rows = await WeightService.GetWeekly()
set(rows[0])
}
}
}
export const weeklyWeightStore = await createStore()

View File

@@ -0,0 +1,20 @@
import { type Writable, writable } from 'svelte/store'
import { type Weight, WeightService } from '$lib/database/weight'
async function createStore(): Promise<Writable<Weight[]>> {
const rows = await WeightService.GetRecent()
const { subscribe, update, set } = writable(rows)
return {
subscribe,
update,
set,
// @ts-ignore
refresh: async () => {
const foods = await WeightService.GetRecent()
set(foods)
}
}
}
export const weightStore = await createStore()

View File

@@ -0,0 +1,25 @@
import { type Writable, writable } from 'svelte/store'
import { type AggregatedWeight, WeightService } from '$lib/database/weight'
async function createStore(): Promise<Writable<AggregatedWeight[]>> {
let [rows, err] = await WeightService.GetYearly()
if (err) {
rows = []
console.error(err)
}
const { subscribe, update, set } = writable(rows)
return {
subscribe,
update,
set,
// @ts-ignore
refresh: async () => {
const rows = await WeightService.GetYearly()
set(rows[0])
}
}
}
export const yearlyWeightStore = await createStore()

View File

@@ -2,6 +2,16 @@ import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge' import { twMerge } from 'tailwind-merge'
import { cubicOut } from 'svelte/easing' import { cubicOut } from 'svelte/easing'
import type { TransitionConfig } from 'svelte/transition' import type { TransitionConfig } from 'svelte/transition'
import { dailyFoodStore } from '$lib/store/energy/dailyFoodStore'
import { foodStore } from '$lib/store/energy/foodStore'
import { weeklyFoodStore } from '$lib/store/energy/weeklyFoodStore'
import { monthlyFoodStore } from '$lib/store/energy/monthlyFoodStore'
import { yearlyFoodStore } from '$lib/store/energy/yearlyFoodStore'
import { weightStore } from '$lib/store/weight/weightStore'
import { dailyWeightStore } from '$lib/store/weight/dailyWeightStore'
import { weeklyWeightStore } from '$lib/store/weight/weeklyWeightStore'
import { monthlyWeightStore } from '$lib/store/weight/monthlyWeightStore'
import { yearlyWeightStore } from '$lib/store/weight/yearlyWeightStore'
export function cn(...inputs: ClassValue[]) { export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs)) return twMerge(clsx(inputs))
@@ -110,3 +120,27 @@ function GenerateColor(): string {
} }
export { GenerateColor } export { GenerateColor }
export function RefreshStores() {
// @ts-ignore
foodStore.refresh()
// @ts-ignore
dailyFoodStore.refresh()
// @ts-ignore
weeklyFoodStore.refresh()
// @ts-ignore
monthlyFoodStore.refresh()
// @ts-ignore
yearlyFoodStore.refresh()
// @ts-ignore
weightStore.refresh()
// @ts-ignore
dailyWeightStore.refresh()
// @ts-ignore
weeklyWeightStore.refresh()
// @ts-ignore
monthlyWeightStore.refresh()
// @ts-ignore
yearlyWeightStore.refresh()
}