Add coloring
This commit is contained in:
@@ -30,24 +30,19 @@
|
||||
item.food = name
|
||||
item.amount = parseInt(amount)
|
||||
item.description = description
|
||||
const [dbFood, err]: [Food[], Err] = await FoodService.Create(item)
|
||||
const [dbFood, err]: [Food, Err] = await FoodService.Create(item)
|
||||
name = ''
|
||||
amount = ''
|
||||
description = ''
|
||||
per100 = ''
|
||||
per100Edited = false
|
||||
|
||||
if (dbFood.length == 0) {
|
||||
toast.error('Creating food returned 0 rows')
|
||||
return
|
||||
}
|
||||
if (err) {
|
||||
toast.error(err)
|
||||
return
|
||||
}
|
||||
foodStore.update((food) => {
|
||||
// @ts-ignore
|
||||
food.unshift(dbFood[0])
|
||||
food.unshift(dbFood)
|
||||
return food
|
||||
})
|
||||
}
|
||||
@@ -64,7 +59,7 @@
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<tr class="border-b border-gray-200 dark:border-gray-700">
|
||||
<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>
|
||||
|
@@ -2,6 +2,9 @@
|
||||
import { type Food, FoodService } from '$lib/database/food'
|
||||
|
||||
export let item: Food
|
||||
export let energyColor: string
|
||||
export let nameColor: string
|
||||
|
||||
let amount: string = item.amount.toString()
|
||||
let per100: string = item.per100?.toString() ?? ''
|
||||
let description: string = item.description ?? ''
|
||||
@@ -34,12 +37,13 @@
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<tr class="border-b border-gray-200 dark:border-gray-700">
|
||||
<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"
|
||||
scope="row">
|
||||
{item.date}
|
||||
</th>
|
||||
<td class="px-6 py-4"
|
||||
style="color: {nameColor}"
|
||||
contenteditable="true"
|
||||
bind:innerText={name}
|
||||
on:keydown={update}>
|
||||
@@ -59,7 +63,7 @@
|
||||
bind:innerText={per100}
|
||||
on:keydown={update}>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<td class="px-6 py-4" style="color: {energyColor}">
|
||||
{item.energy}
|
||||
</td>
|
||||
</tr>
|
||||
|
@@ -2,8 +2,43 @@
|
||||
import EmptyFoodComp from '$components/Food/EmptyFoodComp.svelte'
|
||||
import FoodComp from '$components/Food/FoodComp.svelte'
|
||||
import type { Food } from '$lib/database/food'
|
||||
import { GenerateColor } from '$lib/utils'
|
||||
|
||||
export let items: Food[] = []
|
||||
|
||||
let minCal = 1e5
|
||||
let maxCal = 0
|
||||
for (let item of items) {
|
||||
if (!item.energy) continue
|
||||
if (item.energy > maxCal) maxCal = item.energy
|
||||
if (item.energy < minCal) minCal = item.energy
|
||||
}
|
||||
|
||||
const start = '#99ff99'
|
||||
const end = '#ff9999'
|
||||
|
||||
function lerp(item: Food) {
|
||||
if (!item) return start
|
||||
if (!item.energy) return start
|
||||
const t = (item.energy - minCal) / (maxCal - minCal)
|
||||
const r = parseInt(start.slice(1, 3), 16) * (1 - t) + parseInt(end.slice(1, 3), 16) * t
|
||||
const g = parseInt(start.slice(3, 5), 16) * (1 - t) + parseInt(end.slice(3, 5), 16) * t
|
||||
const b = parseInt(start.slice(5, 7), 16) * (1 - t) + parseInt(end.slice(5, 7), 16) * t
|
||||
return `rgb(${r}, ${g}, ${b})`
|
||||
}
|
||||
|
||||
const itemColors: Map<string, string> = new Map<string, string>()
|
||||
|
||||
function getNameColor(item: Food): string {
|
||||
if (!item) return GenerateColor()
|
||||
if (!item.food) return GenerateColor()
|
||||
if (!itemColors.has(item.food)) itemColors.set(item.food, GenerateColor())
|
||||
// THERE'S NOTHING UNDEFINED HERE
|
||||
// WE GOT RID OF UNDEFINED ON LINE 33
|
||||
// ASSHOLE
|
||||
// @ts-ignore
|
||||
return itemColors.get(item.food)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -35,7 +70,7 @@
|
||||
<tbody>
|
||||
<EmptyFoodComp />
|
||||
{#each items as f}
|
||||
<FoodComp item="{f}" />
|
||||
<FoodComp item="{f}" energyColor="{lerp(f)}" nameColor="{getNameColor(f)}" />
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
|
@@ -38,14 +38,18 @@ or strftime('%Y-%m-%d', date) = strftime('%Y-%m-%d', date('2024-06-12', '-1 day'
|
||||
order by date DESC;
|
||||
`, [date])
|
||||
},
|
||||
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']
|
||||
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 foodView where rowid = $1`, [res.lastInsertId])
|
||||
const rows = await db.select<Food[]>(`select ${columns.join(', ')} from foodView where rowid = $1`, [res.lastInsertId])
|
||||
|
||||
return [row, null]
|
||||
if (!rows) return [food, 'no data found']
|
||||
if (rows.length == 0) return [food, 'no data found']
|
||||
// Its not undefined mannnnnnnnnnnnnnnnnnnnnnnnnn............
|
||||
// @ts-ignore
|
||||
return [rows[0], null]
|
||||
},
|
||||
async GetLatestPer100(food: string): Promise<[number, Err]> {
|
||||
if (!food) return [-1, 'food is required']
|
||||
|
@@ -60,3 +60,52 @@ export const flyAndScale = (
|
||||
easing: cubicOut
|
||||
}
|
||||
}
|
||||
|
||||
type Color = {
|
||||
h: number
|
||||
s: number
|
||||
l: number
|
||||
}
|
||||
|
||||
function ColorDistance(color1: Color, color2: Color) {
|
||||
return Math.abs(color1.h - color2.h)
|
||||
}
|
||||
|
||||
function GenerateRandomHSL(): Color {
|
||||
const hue = Math.floor(Math.random() * 360)
|
||||
const saturation = 70
|
||||
const lightness = 60
|
||||
return { h: hue, s: saturation, l: lightness }
|
||||
}
|
||||
|
||||
const existingColors: Color[] = []
|
||||
|
||||
function GenerateColor(): string {
|
||||
const minDistance = 200
|
||||
|
||||
let newColor: Color
|
||||
let isDistinct = false
|
||||
let iterations = 0
|
||||
while (!isDistinct) {
|
||||
iterations++
|
||||
if (iterations > 100) {
|
||||
console.error('Failed to generate a distinct color after 100 iterations')
|
||||
break
|
||||
}
|
||||
newColor = GenerateRandomHSL()
|
||||
isDistinct = true
|
||||
|
||||
for (const color of existingColors) {
|
||||
if (ColorDistance(newColor, color) < minDistance) {
|
||||
isDistinct = false
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We can not reach this point without having a color generated
|
||||
// @ts-ignore
|
||||
return `hsl(${newColor.h}, ${newColor.s}%, ${newColor.l}%)`
|
||||
}
|
||||
|
||||
export { GenerateColor }
|
||||
|
Reference in New Issue
Block a user