Add routes for daily weekly and the rest
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
<script lang="ts">
|
||||
import type { AggregatedFood } from '$lib/database/food'
|
||||
|
||||
export let item: AggregatedFood
|
||||
</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>
|
||||
<td class="px-6 py-4 bg-gray-50 dark:bg-gray-800">
|
||||
{item.avgPer100}
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
{item.energy}
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
@@ -0,0 +1,118 @@
|
||||
<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'
|
||||
|
||||
ChartJS.register(
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend,
|
||||
LineElement,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
CategoryScale
|
||||
)
|
||||
|
||||
export let items: AggregatedFood[] = []
|
||||
export let energyTarget: number = 2000
|
||||
export let energyLimit: number = 2500
|
||||
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',
|
||||
},
|
||||
{
|
||||
...defaultOptions,
|
||||
label: 'AvgPer100',
|
||||
data: reversedItems.map(f => f.avgPer100),
|
||||
borderColor: '#ffb84d',
|
||||
pointBorderColor: '#ffb84d',
|
||||
},
|
||||
{
|
||||
...defaultOptions,
|
||||
label: 'Energy',
|
||||
data: reversedItems.map(f => f.energy),
|
||||
borderColor: '#b8ff4d',
|
||||
pointBorderColor: '#b8ff4d',
|
||||
},
|
||||
{
|
||||
...defaultOptions,
|
||||
label: 'Target',
|
||||
data: reversedItems.map(f => energyTarget),
|
||||
borderColor: '#00ff00',
|
||||
pointBorderColor: '#00ff00',
|
||||
},
|
||||
{
|
||||
...defaultOptions,
|
||||
label: 'Limit',
|
||||
data: reversedItems.map(f => energyLimit),
|
||||
borderColor: '#ff0000',
|
||||
pointBorderColor: '#ff0000',
|
||||
}
|
||||
]
|
||||
}
|
||||
</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>
|
||||
<th class="px-6 py-3 bg-gray-50 dark:bg-gray-800" scope="col">
|
||||
AvgPer100
|
||||
</th>
|
||||
<th class="px-6 py-3" scope="col">
|
||||
Energy
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each items as f}
|
||||
<AggregatedFoodComp item="{f}" />
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
@@ -2,7 +2,7 @@
|
||||
import { toast } from "svelte-sonner";
|
||||
import { main } from "$wails/models";
|
||||
import { CreateFood, GetLastPer100 } from "$wails/main/App";
|
||||
import { foodStore } from "$lib/store/FoodStore";
|
||||
import { foodStore } from "$lib/store/Energy/foodStore";
|
||||
|
||||
let item: main.Food = {
|
||||
food: "",
|
||||
|
@@ -1,9 +1,17 @@
|
||||
<script lang="ts">
|
||||
import Router from 'svelte-spa-router'
|
||||
import Energy from '$lib/components/Energy/Energy.svelte'
|
||||
import Energy from './routes/Energy.svelte'
|
||||
import Daily from './routes/Daily.svelte'
|
||||
import Weekly from './routes/Weekly.svelte'
|
||||
import Monthly from './routes/Monthly.svelte'
|
||||
import Yearly from './routes/Yearly.svelte'
|
||||
|
||||
const routes = {
|
||||
'/': Energy,
|
||||
'/Energy/daily': Daily,
|
||||
'/Energy/weekly': Weekly,
|
||||
'/Energy/monthly': Monthly,
|
||||
'/Energy/yearly': Yearly,
|
||||
}
|
||||
</script>
|
||||
|
||||
|
8
frontend/src/lib/router/routes/Daily.svelte
Normal file
8
frontend/src/lib/router/routes/Daily.svelte
Normal file
@@ -0,0 +1,8 @@
|
||||
<script lang="ts">
|
||||
import AggregatedFoodTable from '$components/Energy/AggregatedFood/AggregatedFoodTable.svelte'
|
||||
import { dailyFoodStore } from '$lib/store/Energy/dailyFoodStore'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AggregatedFoodTable items="{$dailyFoodStore}" />
|
||||
</template>
|
@@ -1,24 +1,24 @@
|
||||
<script lang="ts">
|
||||
import { foodStore } from "$lib/store/FoodStore";
|
||||
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>
|
||||
|
||||
<template>
|
||||
{#if forceUpdate}
|
||||
<FoodTable items={$foodStore} />
|
||||
{:else}
|
||||
<FoodTable items={$foodStore} />
|
||||
{/if}
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { foodStore } from "$lib/store/Energy/foodStore";
|
||||
import FoodTable from "$lib/components/Energy/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>
|
||||
|
||||
<template>
|
||||
{#if forceUpdate}
|
||||
<FoodTable items={$foodStore} />
|
||||
{:else}
|
||||
<FoodTable items={$foodStore} />
|
||||
{/if}
|
||||
</template>
|
8
frontend/src/lib/router/routes/Monthly.svelte
Normal file
8
frontend/src/lib/router/routes/Monthly.svelte
Normal file
@@ -0,0 +1,8 @@
|
||||
<script lang="ts">
|
||||
import AggregatedFoodTable from '$components/Energy/AggregatedFood/AggregatedFoodTable.svelte'
|
||||
import { monthlyFoodStore } from '$lib/store/Energy/monthlyFoodStore'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AggregatedFoodTable items="{$monthlyFoodStore}" />
|
||||
</template>
|
8
frontend/src/lib/router/routes/Weekly.svelte
Normal file
8
frontend/src/lib/router/routes/Weekly.svelte
Normal file
@@ -0,0 +1,8 @@
|
||||
<script lang="ts">
|
||||
import AggregatedFoodTable from '$components/Energy/AggregatedFood/AggregatedFoodTable.svelte'
|
||||
import { weeklyFoodStore } from '$lib/store/Energy/weeklyFoodStore'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AggregatedFoodTable items="{$weeklyFoodStore}" />
|
||||
</template>
|
8
frontend/src/lib/router/routes/Yearly.svelte
Normal file
8
frontend/src/lib/router/routes/Yearly.svelte
Normal file
@@ -0,0 +1,8 @@
|
||||
<script lang="ts">
|
||||
import AggregatedFoodTable from '$components/Energy/AggregatedFood/AggregatedFoodTable.svelte'
|
||||
import { yearlyFoodStore } from '$lib/store/Energy/yearlyFoodStore'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AggregatedFoodTable items="{$yearlyFoodStore}" />
|
||||
</template>
|
39
frontend/src/lib/store/Energy/dailyFoodStore.ts
Normal file
39
frontend/src/lib/store/Energy/dailyFoodStore.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { type Writable, writable } from "svelte/store";
|
||||
import { main } from "$wails/models";
|
||||
import { GetDailyFood } from "$wails/main/App";
|
||||
import { toast } from "svelte-sonner";
|
||||
import { settingsStore } from "../SettingsStore";
|
||||
|
||||
async function createStore(): Promise<Writable<main.AggregatedFood[]>> {
|
||||
let foods: main.AggregatedFood[] = [];
|
||||
let res: main.WailsAggregateFood = await GetDailyFood();
|
||||
if (!res.success) {
|
||||
toast.error(`Failed to get foods with error: ${res.error}`);
|
||||
} else {
|
||||
foods = res.data;
|
||||
}
|
||||
|
||||
const { subscribe, update, set } = writable(foods);
|
||||
return {
|
||||
subscribe,
|
||||
update,
|
||||
set,
|
||||
// @ts-ignore
|
||||
refresh: async () => {
|
||||
const res = await GetDailyFood();
|
||||
if (!res.success) {
|
||||
toast.error(`Failed to get foods with error: ${res.error}`);
|
||||
return;
|
||||
}
|
||||
set(res.data);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const dailyFoodStore = await createStore();
|
||||
settingsStore.subscribe((settings) => {
|
||||
// @ts-ignore
|
||||
dailyFoodStore.refresh();
|
||||
});
|
||||
|
||||
export { dailyFoodStore };
|
@@ -2,7 +2,7 @@ import { type Writable, writable } from "svelte/store";
|
||||
import { main } from "$wails/models";
|
||||
import { GetFood } from "$wails/main/App";
|
||||
import { toast } from "svelte-sonner";
|
||||
import { settingsStore } from "./SettingsStore";
|
||||
import { settingsStore } from "../SettingsStore";
|
||||
|
||||
async function createStore(): Promise<Writable<main.Food[]>> {
|
||||
let foods: main.Food[] = [];
|
39
frontend/src/lib/store/Energy/monthlyFoodStore.ts
Normal file
39
frontend/src/lib/store/Energy/monthlyFoodStore.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { type Writable, writable } from "svelte/store";
|
||||
import { main } from "$wails/models";
|
||||
import { GetMonthlyFood } from "$wails/main/App";
|
||||
import { toast } from "svelte-sonner";
|
||||
import { settingsStore } from "../SettingsStore";
|
||||
|
||||
async function createStore(): Promise<Writable<main.AggregatedFood[]>> {
|
||||
let foods: main.AggregatedFood[] = [];
|
||||
let res: main.WailsAggregateFood = await GetMonthlyFood();
|
||||
if (!res.success) {
|
||||
toast.error(`Failed to get foods with error: ${res.error}`);
|
||||
} else {
|
||||
foods = res.data;
|
||||
}
|
||||
|
||||
const { subscribe, update, set } = writable(foods);
|
||||
return {
|
||||
subscribe,
|
||||
update,
|
||||
set,
|
||||
// @ts-ignore
|
||||
refresh: async () => {
|
||||
const res = await GetMonthlyFood();
|
||||
if (!res.success) {
|
||||
toast.error(`Failed to get foods with error: ${res.error}`);
|
||||
return;
|
||||
}
|
||||
set(res.data);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const monthlyFoodStore = await createStore();
|
||||
settingsStore.subscribe((settings) => {
|
||||
// @ts-ignore
|
||||
monthlyFoodStore.refresh();
|
||||
});
|
||||
|
||||
export { monthlyFoodStore };
|
39
frontend/src/lib/store/Energy/weeklyFoodStore.ts
Normal file
39
frontend/src/lib/store/Energy/weeklyFoodStore.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { type Writable, writable } from "svelte/store";
|
||||
import { main } from "$wails/models";
|
||||
import { GetWeeklyFood } from "$wails/main/App";
|
||||
import { toast } from "svelte-sonner";
|
||||
import { settingsStore } from "../SettingsStore";
|
||||
|
||||
async function createStore(): Promise<Writable<main.AggregatedFood[]>> {
|
||||
let foods: main.AggregatedFood[] = [];
|
||||
let res: main.WailsAggregateFood = await GetWeeklyFood();
|
||||
if (!res.success) {
|
||||
toast.error(`Failed to get foods with error: ${res.error}`);
|
||||
} else {
|
||||
foods = res.data;
|
||||
}
|
||||
|
||||
const { subscribe, update, set } = writable(foods);
|
||||
return {
|
||||
subscribe,
|
||||
update,
|
||||
set,
|
||||
// @ts-ignore
|
||||
refresh: async () => {
|
||||
const res = await GetWeeklyFood();
|
||||
if (!res.success) {
|
||||
toast.error(`Failed to get foods with error: ${res.error}`);
|
||||
return;
|
||||
}
|
||||
set(res.data);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const weeklyFoodStore = await createStore();
|
||||
settingsStore.subscribe((settings) => {
|
||||
// @ts-ignore
|
||||
weeklyFoodStore.refresh();
|
||||
});
|
||||
|
||||
export { weeklyFoodStore };
|
39
frontend/src/lib/store/Energy/yearlyFoodStore.ts
Normal file
39
frontend/src/lib/store/Energy/yearlyFoodStore.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { type Writable, writable } from "svelte/store";
|
||||
import { main } from "$wails/models";
|
||||
import { GetYearlyFood } from "$wails/main/App";
|
||||
import { toast } from "svelte-sonner";
|
||||
import { settingsStore } from "../SettingsStore";
|
||||
|
||||
async function createStore(): Promise<Writable<main.AggregatedFood[]>> {
|
||||
let foods: main.AggregatedFood[] = [];
|
||||
let res: main.WailsAggregateFood = await GetYearlyFood();
|
||||
if (!res.success) {
|
||||
toast.error(`Failed to get foods with error: ${res.error}`);
|
||||
} else {
|
||||
foods = res.data;
|
||||
}
|
||||
|
||||
const { subscribe, update, set } = writable(foods);
|
||||
return {
|
||||
subscribe,
|
||||
update,
|
||||
set,
|
||||
// @ts-ignore
|
||||
refresh: async () => {
|
||||
const res = await GetYearlyFood();
|
||||
if (!res.success) {
|
||||
toast.error(`Failed to get foods with error: ${res.error}`);
|
||||
return;
|
||||
}
|
||||
set(res.data);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const yearlyFoodStore = await createStore();
|
||||
settingsStore.subscribe((settings) => {
|
||||
// @ts-ignore
|
||||
yearlyFoodStore.refresh();
|
||||
});
|
||||
|
||||
export { yearlyFoodStore };
|
8
frontend/wailsjs/go/main/App.d.ts
vendored
8
frontend/wailsjs/go/main/App.d.ts
vendored
@@ -4,12 +4,20 @@ import {main} from '../models';
|
||||
|
||||
export function CreateFood(arg1:main.Food):Promise<main.WailsFood1>;
|
||||
|
||||
export function GetDailyFood():Promise<main.WailsAggregateFood>;
|
||||
|
||||
export function GetFood():Promise<main.WailsFood>;
|
||||
|
||||
export function GetLastPer100(arg1:string):Promise<main.WailsPer100>;
|
||||
|
||||
export function GetMonthlyFood():Promise<main.WailsAggregateFood>;
|
||||
|
||||
export function GetSettings():Promise<main.settings>;
|
||||
|
||||
export function GetWeeklyFood():Promise<main.WailsAggregateFood>;
|
||||
|
||||
export function GetYearlyFood():Promise<main.WailsAggregateFood>;
|
||||
|
||||
export function SetSetting(arg1:string,arg2:number):Promise<main.WailsGenericAck>;
|
||||
|
||||
export function UpdateFood(arg1:main.Food):Promise<main.WailsFood1>;
|
||||
|
@@ -6,6 +6,10 @@ export function CreateFood(arg1) {
|
||||
return window['go']['main']['App']['CreateFood'](arg1);
|
||||
}
|
||||
|
||||
export function GetDailyFood() {
|
||||
return window['go']['main']['App']['GetDailyFood']();
|
||||
}
|
||||
|
||||
export function GetFood() {
|
||||
return window['go']['main']['App']['GetFood']();
|
||||
}
|
||||
@@ -14,10 +18,22 @@ export function GetLastPer100(arg1) {
|
||||
return window['go']['main']['App']['GetLastPer100'](arg1);
|
||||
}
|
||||
|
||||
export function GetMonthlyFood() {
|
||||
return window['go']['main']['App']['GetMonthlyFood']();
|
||||
}
|
||||
|
||||
export function GetSettings() {
|
||||
return window['go']['main']['App']['GetSettings']();
|
||||
}
|
||||
|
||||
export function GetWeeklyFood() {
|
||||
return window['go']['main']['App']['GetWeeklyFood']();
|
||||
}
|
||||
|
||||
export function GetYearlyFood() {
|
||||
return window['go']['main']['App']['GetYearlyFood']();
|
||||
}
|
||||
|
||||
export function SetSetting(arg1, arg2) {
|
||||
return window['go']['main']['App']['SetSetting'](arg1, arg2);
|
||||
}
|
||||
|
@@ -1,5 +1,23 @@
|
||||
export namespace main {
|
||||
|
||||
export class AggregatedFood {
|
||||
period: string;
|
||||
amount: number;
|
||||
avgPer100: number;
|
||||
energy: number;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new AggregatedFood(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.period = source["period"];
|
||||
this.amount = source["amount"];
|
||||
this.avgPer100 = source["avgPer100"];
|
||||
this.energy = source["energy"];
|
||||
}
|
||||
}
|
||||
export class Food {
|
||||
rowid: number;
|
||||
date: string;
|
||||
@@ -24,6 +42,40 @@ export namespace main {
|
||||
this.energy = source["energy"];
|
||||
}
|
||||
}
|
||||
export class WailsAggregateFood {
|
||||
data: AggregatedFood[];
|
||||
success: boolean;
|
||||
error?: string;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new WailsAggregateFood(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.data = this.convertValues(source["data"], AggregatedFood);
|
||||
this.success = source["success"];
|
||||
this.error = source["error"];
|
||||
}
|
||||
|
||||
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||
if (!a) {
|
||||
return a;
|
||||
}
|
||||
if (a.slice && a.map) {
|
||||
return (a as any[]).map(elem => this.convertValues(elem, classs));
|
||||
} else if ("object" === typeof a) {
|
||||
if (asMap) {
|
||||
for (const key of Object.keys(a)) {
|
||||
a[key] = new classs(a[key]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
return new classs(a);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
}
|
||||
export class WailsFood {
|
||||
data: Food[];
|
||||
success: boolean;
|
||||
@@ -136,6 +188,7 @@ export namespace main {
|
||||
weightMonthlyLookback: number;
|
||||
weightYearlyLookback: number;
|
||||
target: number;
|
||||
limit: number;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new settings(source);
|
||||
@@ -156,6 +209,7 @@ export namespace main {
|
||||
this.weightMonthlyLookback = source["weightMonthlyLookback"];
|
||||
this.weightYearlyLookback = source["weightYearlyLookback"];
|
||||
this.target = source["target"];
|
||||
this.limit = source["limit"];
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user