mirror of
https://github.com/KevinMidboe/brewPi.git
synced 2025-10-29 16:50:12 +00:00
Feat: Colored brew pages (#4)
* Removed graph animation * Smoother graph by removing data point bubbles * Added relatime button which keeps reloading every 2 sec * Clear timeout when destroying/navigating away from page * Added primary & secondary colors to match label per brew * Only render graph if dataset is list of length * Also color mobile image container primary color of brew * Add white background on graphs because of low contrast secondary background color
This commit is contained in:
191
src/brews.json
191
src/brews.json
@@ -1,91 +1,110 @@
|
||||
[{
|
||||
"beer": {
|
||||
"name": "Kveldsbris",
|
||||
"brewery": "Kinn Bryggeri",
|
||||
"category": "Pilsner/Lys Lager",
|
||||
"description": ""
|
||||
[
|
||||
{
|
||||
"beer": {
|
||||
"name": "Kveldsbris",
|
||||
"brewery": "Kinn Bryggeri",
|
||||
"category": "Belgian Pale Ale",
|
||||
"description": ""
|
||||
},
|
||||
"date": "1682272800",
|
||||
"by": ["Alf", "Kevin"],
|
||||
"abv": "5.6",
|
||||
"description": "Kveldsbris - Evening Breeze - is offered as a clean, refreshing and not-too-alcoholic Belgian ale. It has a fine balance of Belgian yeastiness with the premier hop varieties from three wildly different districts: East Kent Goldings on England's south coast, Saaz from Zatec in the Czech Republic, and Amarillo from Yakima Valley in the United States of America. Kveldsbris is a most versatile table ale that can cope with more spiciness and richness than a regular wheat beer.",
|
||||
"image": "kinn_kveldsbris.png",
|
||||
"recipe": "https://docs.google.com/document/d/1FL7ibXxW1r_zFNLK338pyjfMiCCaTOi2fzuMoInA3dQ",
|
||||
"order_page": "https://oslo.bryggselv.no/finest/104923/finest-originals-utepils-allgrain-ølsett-25-liter",
|
||||
"untapped": "https://untappd.com/b/kinn-bryggeri-kveldsbris/695024",
|
||||
"color_primary": "#FCF28F",
|
||||
"color_secondary": "rgba(252, 242, 143, 0.2)"
|
||||
},
|
||||
"date": "1682272800",
|
||||
"by": ["Alf", "Kevin"],
|
||||
"abv": "5.6",
|
||||
"description": "",
|
||||
"image": "kinn_kveldsbris.png",
|
||||
"recipe": "https://docs.google.com/document/d/1FL7ibXxW1r_zFNLK338pyjfMiCCaTOi2fzuMoInA3dQ",
|
||||
"order_page": "https://oslo.bryggselv.no/finest/104923/finest-originals-utepils-allgrain-ølsett-25-liter",
|
||||
"untapped": "https://untappd.com/b/kinn-bryggeri-kveldsbris/695024"
|
||||
}, {
|
||||
"beer": {
|
||||
"name": "FUCK YEAH IPA",
|
||||
"brewery": "Finest",
|
||||
"category": "American IPA",
|
||||
"description": ""
|
||||
{
|
||||
"beer": {
|
||||
"name": "FUCK YEAH IPA",
|
||||
"brewery": "Finest",
|
||||
"category": "American IPA",
|
||||
"description": ""
|
||||
},
|
||||
"date": "1648922400",
|
||||
"by": ["Alf", "Kevin"],
|
||||
"abv": "7",
|
||||
"description": "",
|
||||
"image": "finest_fuck-yeah-IPA.jpg",
|
||||
"recipe": "https://docs.google.com/document/d/1FL7ibXxW1r_zFNLK338pyjfMiCCaTOi2fzuMoInA3dQ",
|
||||
"order_page": "https://web.archive.org/web/20210225043236/https://www.bryggselv.no/finest/105943/fuck-yeah-ipa-ultra-american-west-coast-ipa-25-liter",
|
||||
"untapped": "https://untappd.com/b/kinn-bryggeri-kveldsbris/695024",
|
||||
"color_primary": "#0169A6",
|
||||
"color_secondary": "rgba(1, 105, 166, 0.2)"
|
||||
},
|
||||
"date": "1648922400",
|
||||
"by": ["Alf", "Kevin"],
|
||||
"abv": "7",
|
||||
"description": "",
|
||||
"image": "finest_fuck-yeah-IPA.jpg",
|
||||
"recipe": "https://docs.google.com/document/d/1FL7ibXxW1r_zFNLK338pyjfMiCCaTOi2fzuMoInA3dQ",
|
||||
"order_page": "https://web.archive.org/web/20210225043236/https://www.bryggselv.no/finest/105943/fuck-yeah-ipa-ultra-american-west-coast-ipa-25-liter",
|
||||
"untapped": "https://untappd.com/b/kinn-bryggeri-kveldsbris/695024"
|
||||
}, {
|
||||
"beer": {
|
||||
"name": "Love in a canoe",
|
||||
"brewery": "Finest",
|
||||
"category": "Mexican Lager",
|
||||
"description": ""
|
||||
{
|
||||
"beer": {
|
||||
"name": "Love in a canoe",
|
||||
"brewery": "Finest",
|
||||
"category": "Mexican Lager",
|
||||
"description": ""
|
||||
},
|
||||
"date": "1646420400",
|
||||
"by": ["Alf", "Kevin"],
|
||||
"abv": "4.7",
|
||||
"description": "",
|
||||
"image": "finest_love-in-a-canoe.jpeg",
|
||||
"recipe": "https://docs.google.com/document/d/1FL7ibXxW1r_zFNLK338pyjfMiCCaTOi2fzuMoInA3dQ",
|
||||
"order_page": "https://oslo.bryggselv.no/finest/104092/love-in-a-canoe-allgrain-ølsett-25-liter",
|
||||
"untapped": "https://untappd.com/b/kinn-bryggeri-kveldsbris/695024",
|
||||
"color_primary": "#F7F0DF",
|
||||
"color_secondary": "rgba(247, 240, 223, 0.2)"
|
||||
},
|
||||
"date": "1646420400",
|
||||
"by": ["Alf", "Kevin"],
|
||||
"abv": "4.7",
|
||||
"description": "",
|
||||
"image": "finest_love-in-a-canoe.jpeg",
|
||||
"recipe": "https://docs.google.com/document/d/1FL7ibXxW1r_zFNLK338pyjfMiCCaTOi2fzuMoInA3dQ",
|
||||
"order_page": "https://oslo.bryggselv.no/finest/104092/love-in-a-canoe-allgrain-ølsett-25-liter",
|
||||
"untapped": "https://untappd.com/b/kinn-bryggeri-kveldsbris/695024"
|
||||
}, {
|
||||
"beer": {
|
||||
"name": "Utepils",
|
||||
"brewery": "Finest",
|
||||
"category": "",
|
||||
"description": ""
|
||||
{
|
||||
"beer": {
|
||||
"name": "Utepils",
|
||||
"brewery": "Finest",
|
||||
"category": "",
|
||||
"description": ""
|
||||
},
|
||||
"date": "1637694000",
|
||||
"by": ["Alf", "Kevin"],
|
||||
"abv": "5.0",
|
||||
"description": "",
|
||||
"image": "finest_utepils.jpeg",
|
||||
"recipe": "https://docs.google.com/document/d/1FL7ibXxW1r_zFNLK338pyjfMiCCaTOi2fzuMoInA3dQ",
|
||||
"order_page": "https://www.bryggselv.no/finest/105932/kinn-kveldsbris-allgrain-ølsett-25-liter",
|
||||
"untapped": "https://untappd.com/b/kinn-bryggeri-kveldsbris/695024",
|
||||
"color_primary": "#F4E9D3",
|
||||
"color_secondary": "rgba(244, 233, 211, 0.2)"
|
||||
},
|
||||
"date": "1637694000",
|
||||
"by": ["Alf", "Kevin"],
|
||||
"abv": "5.0",
|
||||
"description": "",
|
||||
"image": "finest_utepils.jpeg",
|
||||
"recipe": "https://docs.google.com/document/d/1FL7ibXxW1r_zFNLK338pyjfMiCCaTOi2fzuMoInA3dQ",
|
||||
"order_page": "https://www.bryggselv.no/finest/105932/kinn-kveldsbris-allgrain-ølsett-25-liter",
|
||||
"untapped": "https://untappd.com/b/kinn-bryggeri-kveldsbris/695024"
|
||||
}, {
|
||||
"beer": {
|
||||
"name": "HELLES Tysk Lager",
|
||||
"brewery": "Münchener Helles",
|
||||
"category": "Tysk Lager",
|
||||
"description": ""
|
||||
{
|
||||
"beer": {
|
||||
"name": "HELLES Tysk Lager",
|
||||
"brewery": "Münchener Helles",
|
||||
"category": "Tysk Lager",
|
||||
"description": ""
|
||||
},
|
||||
"date": "1629396000",
|
||||
"by": ["Adrian", "Kevin", "Mats"],
|
||||
"abv": "5.3",
|
||||
"description": "",
|
||||
"image": "helles_tysk-lager.jpeg",
|
||||
"recipe": "https://docs.google.com/document/d/1FL7ibXxW1r_zFNLK338pyjfMiCCaTOi2fzuMoInA3dQ",
|
||||
"order_page": "https://oslo.bryggselv.no/finest/106231/finest-helles-allgrain-ølsett-25-liter",
|
||||
"untapped": "https://untappd.com/b/kinn-bryggeri-kveldsbris/695024",
|
||||
"color_primary": "#C5893D",
|
||||
"color_secondary": "rgba(197, 137, 61, 0.2)"
|
||||
},
|
||||
"date": "1629396000",
|
||||
"by": ["Adrian", "Kevin", "Mats"],
|
||||
"abv": "5.3",
|
||||
"description": "",
|
||||
"image": "helles_tysk-lager.jpeg",
|
||||
"recipe": "https://docs.google.com/document/d/1FL7ibXxW1r_zFNLK338pyjfMiCCaTOi2fzuMoInA3dQ",
|
||||
"order_page": "https://oslo.bryggselv.no/finest/106231/finest-helles-allgrain-ølsett-25-liter",
|
||||
"untapped": "https://untappd.com/b/kinn-bryggeri-kveldsbris/695024"
|
||||
}, {
|
||||
"beer": {
|
||||
"name": "Lazy Days Weiss",
|
||||
"brewery": "Finest",
|
||||
"category": "Weissbier",
|
||||
"description": ""
|
||||
},
|
||||
"date": "1621706400",
|
||||
"by": ["Alf", "Kevin", "Kristian"],
|
||||
"abv": "5.3",
|
||||
"description": "",
|
||||
"image": "finest_lazy-days.jpeg",
|
||||
"recipe": "https://docs.google.com/document/u/0/d/1I6qX4l4jDzK51GxBt3IdEv-HyNQHAx8ijc5dMlG1Xkk",
|
||||
"order_page": "https://oslo.bryggselv.no/finest/106231/finest-helles-allgrain-ølsett-25-liter",
|
||||
"untapped": "https://untappd.com/b/kinn-bryggeri-kveldsbris/695024"
|
||||
}]
|
||||
{
|
||||
"beer": {
|
||||
"name": "Lazy Days Weiss",
|
||||
"brewery": "Finest",
|
||||
"category": "Weissbier",
|
||||
"description": ""
|
||||
},
|
||||
"date": "1621706400",
|
||||
"by": ["Alf", "Kevin", "Kristian"],
|
||||
"abv": "5.3",
|
||||
"description": "",
|
||||
"image": "finest_lazy-days.jpeg",
|
||||
"recipe": "https://docs.google.com/document/u/0/d/1I6qX4l4jDzK51GxBt3IdEv-HyNQHAx8ijc5dMlG1Xkk",
|
||||
"order_page": "https://oslo.bryggselv.no/finest/106231/finest-helles-allgrain-ølsett-25-liter",
|
||||
"untapped": "https://untappd.com/b/kinn-bryggeri-kveldsbris/695024",
|
||||
"color_primary": "#6C8D9E",
|
||||
"color_secondary": "rgba(108, 141, 158, 0.2)"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -94,17 +94,16 @@
|
||||
|
||||
function renderChart() {
|
||||
const context: CanvasRenderingContext2D | null = chartCanvas.getContext('2d');
|
||||
if (!context) return
|
||||
if (!context) return;
|
||||
|
||||
// create labels and singular dataset (data)
|
||||
const labels: string[] = dateLabelsFormatedBasedOnResolution(dataFrames);
|
||||
const data: ChartDataset = {
|
||||
data: dataFrames.map((frame) => frame.value),
|
||||
borderWidth: 3,
|
||||
borderWidth: 3
|
||||
};
|
||||
// based on name, add label and color options to dataset
|
||||
setDataColorAndName(data)
|
||||
|
||||
setDataColorAndName(data);
|
||||
|
||||
// create chart instance, most here is chart options
|
||||
chart = new Chart(context, {
|
||||
@@ -114,9 +113,12 @@
|
||||
datasets: [data]
|
||||
},
|
||||
options: {
|
||||
animation: {
|
||||
duration: 0
|
||||
},
|
||||
elements: {
|
||||
point: {
|
||||
radius: 2
|
||||
radius: 0
|
||||
},
|
||||
line: {
|
||||
tension: 0.5
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
export let data;
|
||||
let brew = data.brew;
|
||||
let temperatureData: IChartFrame[] = data.graphData.temperature;
|
||||
let humidityData: IChartFrame[] = data.graphData.humidity;
|
||||
let temperatureData: IChartFrame[] = data?.graphData?.temperature;
|
||||
let humidityData: IChartFrame[] = data?.graphData?.humidity;
|
||||
|
||||
const dateFormat: Intl.DateTimeFormatOptions = {
|
||||
weekday: 'long',
|
||||
@@ -20,11 +20,11 @@
|
||||
</script>
|
||||
|
||||
<section class="card">
|
||||
<div class="desktop-only image-container" style="height: {height}px">
|
||||
<div class="desktop-only image-container" style="height: {height}px; background-color: {brew.color_primary || '#93a4a0'}">
|
||||
<img src="/images/{brew.image}" alt="Tuborg Sommerøl" aria-label="Tuborg Sommerøl" />
|
||||
</div>
|
||||
|
||||
<div class="beer-container" bind:clientHeight="{height}">
|
||||
<div class="beer-container" bind:clientHeight="{height}" style="background-color: {brew.color_secondary || '#DFE6E5'}">
|
||||
<h1>{brew.beer.name}</h1>
|
||||
|
||||
<div class="links">
|
||||
@@ -57,25 +57,22 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="mobile-only image-container">
|
||||
<div class="mobile-only image-container" style="background-color: {brew.color_primary || '#93a4a0'}">
|
||||
<img src="/images/{brew.image}" alt="Tuborg Sommerøl" aria-label="Tuborg Sommerøl" />
|
||||
</div>
|
||||
|
||||
<h3>Historie</h3>
|
||||
<p>
|
||||
I 1873 ble Tuborg Bryggeri grunnlagt av Carl Frederik Tietgen på Hellerud i Danmark. I 1970
|
||||
ble Tuborg Bryggeri en del av Carlsberg.
|
||||
</p>
|
||||
<h3>Beskrivelse</h3>
|
||||
<p>{brew.description}</p>
|
||||
|
||||
<div class="graph-container">
|
||||
{#if temperatureData}
|
||||
{#if temperatureData && temperatureData?.length}
|
||||
<div class="graph">
|
||||
<h3>Temperature during fermentation</h3>
|
||||
<Graph dataFrames="{temperatureData}" name="Temperature" hideTitle="{true}" />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if humidityData}
|
||||
{#if humidityData && temperatureData?.length}
|
||||
<div class="graph">
|
||||
<h3>Humidity during carbonation</h3>
|
||||
<Graph dataFrames="{humidityData}" name="Humidity" hideTitle="{true}" />
|
||||
@@ -134,7 +131,6 @@
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
min-height: 1px;
|
||||
background-color: #93a4a0;
|
||||
padding: 3rem 1rem;
|
||||
|
||||
@include tablet {
|
||||
@@ -144,7 +140,8 @@
|
||||
}
|
||||
|
||||
@include mobile {
|
||||
margin: 2rem 0;
|
||||
width: calc(100% + 2rem);
|
||||
margin: 2rem 0 2rem -1rem;
|
||||
}
|
||||
|
||||
img {
|
||||
@@ -234,4 +231,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:global(canvas) {
|
||||
background-color: white;
|
||||
border-radius: 0.5rem;
|
||||
padding: 0 0.2rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import Graph from '../../lib/components/Graph.svelte';
|
||||
import type IChartFrame from '../../lib/interfaces/IChartFrame';
|
||||
import type { PageData } from './$types';
|
||||
@@ -21,7 +21,14 @@
|
||||
return fetch(`/api/graph/${unit}`, options).then((resp) => resp.json());
|
||||
}
|
||||
|
||||
const buttonMinutes = [
|
||||
interface IButtonMinute {
|
||||
value: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
let timeout: ReturnType<typeof setTimeout>;
|
||||
const buttonMinutes: Array<IButtonMinute> = [
|
||||
{ value: 2.4, name: 'Realtime' },
|
||||
{ value: 15, name: 'Last 15 minutes' },
|
||||
{ value: 60, name: 'Last hour' },
|
||||
{ value: 360, name: 'Last 6 hours' },
|
||||
@@ -33,8 +40,9 @@
|
||||
{ value: 518400, name: 'Last year' }
|
||||
];
|
||||
|
||||
function reload(mins: number) {
|
||||
minutes = mins;
|
||||
function reload(button: IButtonMinute) {
|
||||
minutes = button.value;
|
||||
clearTimeout(timeout);
|
||||
const to: Date = new Date();
|
||||
const from = new Date(to.getTime() - minutes * 60 * 1000);
|
||||
const size = 40;
|
||||
@@ -42,6 +50,10 @@
|
||||
fetchData('temperature', from, to, size).then((resp) => (temperatureData = resp?.data));
|
||||
fetchData('humidity', from, to, size).then((resp) => (humidityData = resp?.data));
|
||||
fetchData('pressure', from, to, size).then((resp) => (pressureData = resp?.data));
|
||||
|
||||
if (button.name === 'Realtime') {
|
||||
timeout = setTimeout(() => reload(button), 2000);
|
||||
}
|
||||
}
|
||||
|
||||
function scrollSelectedButtonIntoView() {
|
||||
@@ -59,13 +71,13 @@
|
||||
}
|
||||
|
||||
onMount(scrollSelectedButtonIntoView);
|
||||
onDestroy(() => clearTimeout(timeout))
|
||||
</script>
|
||||
|
||||
<div class="button-wrapper">
|
||||
{#each buttonMinutes as button}
|
||||
<button
|
||||
on:click="{() => reload(button.value)}"
|
||||
class="{button.value === minutes ? 'selected' : ''}">{button.name}</button
|
||||
<button on:click="{() => reload(button)}" class="{button.value === minutes ? 'selected' : ''}"
|
||||
>{button.name}</button
|
||||
>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user