Compare commits

...

7 Commits

Author SHA1 Message Date
a60dc726eb fix: incorrect color secondary key in add_brew script 2023-06-26 16:59:44 +02:00
0bcc49c8cf Fix: added wrong IPA. Hazyday hero --> ink and dagger 2023-06-26 14:01:30 +02:00
3bb08cfbd3 Animate brew progress arrow 1.8s after page load 2023-06-24 22:30:59 +02:00
f5ada7d711 Brew progress help typography (#7)
* Import latest beer to brew progress

* Wrap name in link to brew & arrow for prompting nav

* Help text for showing description by clicking icons
2023-06-24 21:46:36 +02:00
5575d01e63 Brew: Amundsen hazyday hero (#6)
* New brew: amundsen hazyday hero

* Helper script for adding new brews
2023-06-24 21:02:52 +02:00
94c27b0a8d 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
2023-06-24 19:41:50 +02:00
4008b8aee9 Feat: Schleppe Brew logo (#5)
* Added new logo design

* Favicon icons & header links

* Logo max width on mobile

* Logo as svg component. Replaces PageHeader component

* Same brew logo for mobile & desktop
2023-06-24 19:36:53 +02:00
12 changed files with 316 additions and 155 deletions

24
add_brew.sh Normal file
View File

@@ -0,0 +1,24 @@
#!/bin/bash
brewFile=src/brews.json
date=$(date +%s)
# Ask the user for login details
read -p 'Name: ' name
read -p 'Brewery: ' brewery
read -p 'Category: ' category
read -p 'By: ' by
read -p 'Abv: ' abv
read -p 'Description: ' description
read -p 'Image filename: ' image
read -p 'Recipe url: ' recipe
read -p 'Order page url: ' orderPage
read -p 'Untapped url: ' untapped
read -p 'Primary color: ' colorPrimary
brew="{\"beer\":{\"name\":\"$name\",\"brewery\":\"$brewery\",\"category\":\"$category\"},\"date\":\"$date\",\"by\":\"$by\",\"abv\":\"$abv\",\"description\":\"$description\",\"image\":\"$image\",\"recipe\":\"$recipe\",\"order_page\":\"$orderPage\",\"untapped\":\"$untapped\",\"color_primary\":\"$colorPrimary\",\"color_secondary\":\"$colorSecondary\"}"
echo $(cat $brewFile | jq ".brews |= [$brew] + .") > $brewFile
echo "Brew $name added to $brewFile successfully!"

View File

@@ -1,91 +1,129 @@
[{
"beer": {
"name": "Kveldsbris",
"brewery": "Kinn Bryggeri",
"category": "Pilsner/Lys Lager",
"description": ""
},
"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": ""
},
"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": ""
},
"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": ""
},
"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": ""
},
"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"
}]
{
"brews": [
{
"beer": {
"name": "Ink & Dagger",
"brewery": "Amundsen",
"category": "Hazy Session IPA"
},
"date": "1687631876",
"by": ["Andreas", "Ingvild", "Kevin"],
"abv": "4.2",
"description": "Ink & Dagger - Den legendariske IPA`en fra Amundsen Bryggeri er et unikt bryggesett som vil ta deg med på en smaksopplevelse du sent vil glemme. Med et imponerende utvalg av humler, gir dette ølet en kompleks og balansert smak som vil tilfredsstille enhver ølentusiast..",
"image": "amundsen_ink-dagger.jpg",
"recipe": "https://www.dropbox.com/s/uqscpf5jsnxg7fv/Ink%20and%20Dagger%2025ltr.pdf?dl=0",
"order_page": "https://www.hopstore.no/products/amundsen-ink-and-dagger-25l-olsett",
"untapped": "https://untappd.com/b/amundsen-bryggeri-ink-and-dagger/1785462",
"color_primary": "#76C5BF",
"color_secondary": "rgba(118, 197, 191, 0.2)"
},
{
"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)"
},
{
"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)"
},
{
"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)"
},
{
"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)"
},
{
"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)"
},
{
"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)"
}
]
}

View File

@@ -1,4 +1,8 @@
<script lang="ts">
import { onMount } from 'svelte';
import brews from '../../brews.json';
import ArrowRight from '../icons/ArrowRight.svelte';
interface IStep {
icon: string;
name: string;
@@ -10,43 +14,67 @@
interface IBrew {
name: string;
by: string;
date: string;
dates: {
brew: string;
ferment: string;
bottle: string;
consume: string;
};
}
const latestBrew = brews?.brews?.[0];
const { beer, dates } = latestBrew;
const brew: IBrew = {
name: 'Kveldsbris',
by: 'Kinn Bryggeri'
name: beer?.name,
by: beer?.brewery,
date: latestBrew.date,
dates: {
brew: dates?.brew || 'June 24',
ferment: 'July 8',
bottle: 'July 8',
consume: 'July 22'
}
};
let isOpen: number | null;
onMount(() =>
setTimeout(() => document.querySelector('a.brew svg')?.classList.add('animate'), 1800)
);
const steps: Array<IStep> = [
{
icon: 'M9.94 8.007l3.983 3.983 1.06 1.06 1.06-1.06 6.93-6.93-2.12-2.12-6.93 6.93h2.12l-3.982-3.984-2.12 2.12z',
name: 'Brew',
date: 'March 19',
date: brew.dates.brew,
state: 'completed',
description: 'The brew stage involves the creation of the wort, which is the liquid extracted from malted grains (usually barley) through a process called mashing. The grains are crushed and mixed with hot water in a vessel called a mash tun, where enzymes break down the starches into fermentable sugars. The resulting liquid, called the wort, is then separated from the grain husks through a process called lautering. The wort is transferred to a boil kettle where hops are added to provide bitterness, flavor, and aroma. The wort is boiled to sterilize it and to further extract flavors from the hops. After boiling, the wort is cooled rapidly before being transferred to a fermentation vessel.'
description:
'The brew stage involves the creation of the wort, which is the liquid extracted from malted grains (usually barley) through a process called mashing. The grains are crushed and mixed with hot water in a vessel called a mash tun, where enzymes break down the starches into fermentable sugars. The resulting liquid, called the wort, is then separated from the grain husks through a process called lautering. The wort is transferred to a boil kettle where hops are added to provide bitterness, flavor, and aroma. The wort is boiled to sterilize it and to further extract flavors from the hops. After boiling, the wort is cooled rapidly before being transferred to a fermentation vessel.'
},
{
icon: 'M19.803 5h1.572c.226 0 .443.244.603.404l1.772 1.85c.16.16.25.453.25.68v2.832c0 .015 0 .234-1 .234-.415-.854-1.116-1.287-2.124-1.287-.426 0-1.05.173-1.403.356-.14.072-.473.086-.473-.07V5.803c0-.442.36-.803.803-.803zM9.263 3h7.83c.5 0 .907.406.907.906v6.188c0 .5-.406.906-.906.906h-2.138c-.115 0-.214.206-.26.1-.397-.9-1.297-1.387-2.338-1.387-1.04 0-1.94.418-2.338 1.32-.046.104-.145-.033-.26-.033H8.672c-.37 0-.672-.3-.672-.672V4.265C8 3.57 8.57 3 9.264 3zm11.676 7.978c.828 0 1.5.67 1.5 1.5 0 .828-.672 1.5-1.5 1.5-.83 0-1.5-.672-1.5-1.5 0-.83.67-1.5 1.5-1.5zm-8.582-.07c.828 0 1.5.67 1.5 1.5 0 .828-.672 1.5-1.5 1.5s-1.5-.672-1.5-1.5c0-.83.672-1.5 1.5-1.5z',
name: 'Ferment',
date: 'March 23',
state: 'completed',
date: brew.dates.ferment,
state: 'in-progress',
description: `The fermented stage is where the magic happens. The cooled wort is transferred to a fermentation vessel, typically a large container called a fermenter. Yeast is added to the wort, and the fermentation process begins. Yeast consumes the fermentable sugars in the wort and converts them into alcohol and carbon dioxide through a process called fermentation. This stage can last from a few days to several weeks, depending on the beer style and desired characteristics. The temperature and conditions during fermentation play a crucial role in shaping the beer's flavors and aromas.`
},
{
icon: 'M23.45 10.99c-.162-.307-.54-.42-.84-.257l-4.582 2.45-6.557-11.93H8.62c-.347 0-.62.283-.62.628 0 .346.273.628.62.628h2.118l4.825 8.783c-.037-.006-.074-.006-.112-.006-1.37 0-2.482 1.123-2.482 2.508s1.11 2.508 2.483 2.508c1.038 0 1.92-.64 2.293-1.543l5.445-2.92c.304-.164.422-.54.26-.847zm-8 3.874c-.59 0-1.06-.476-1.06-1.072 0-.596.47-1.072 1.06-1.072.59 0 1.063.476 1.063 1.072 0 .596-.472 1.072-1.062 1.072zm8.994-6.698l-5.848 3.288-2.718-4.93 5.847-3.287 2.72 4.93zm-4.288-5.482l-4.882 2.744-1.48-2.683L18.675 0l1.48 2.684z',
name: 'Bottle',
date: 'April 1',
state: 'in-progress',
description: 'Once fermentation is complete, the beer is ready for packaging. The beer is carefully transferred from the fermentation vessel to a bottling bucket or keg. During this transfer, care is taken to avoid disturbing the sediment, known as trub, that has settled at the bottom of the fermenter. If desired, additional priming sugar can be added at this stage to provide carbonation in the bottles. The beer is then filled into clean and sanitized bottles or kegs, ensuring that the containers are properly sealed to prevent oxygen exposure and contamination.'
date: brew.dates.bottle,
state: '',
description:
'Once fermentation is complete, the beer is ready for packaging. The beer is carefully transferred from the fermentation vessel to a bottling bucket or keg. During this transfer, care is taken to avoid disturbing the sediment, known as trub, that has settled at the bottom of the fermenter. If desired, additional priming sugar can be added at this stage to provide carbonation in the bottles. The beer is then filled into clean and sanitized bottles or kegs, ensuring that the containers are properly sealed to prevent oxygen exposure and contamination.'
},
{
icon: 'M15.623 5.014l-4.29 3.577c-.196.168-.327.362-.327.62v6.206c0 .322.335.584.656.584h2.004c.32 0 .584-.262.584-.584l-.033-3.115c0-.16.13-.29.29-.29h2.918c.16 0 .292.13.292.29l.033 3.116c0 .322.263.584.584.584h2.09c.322 0 .585-.262.585-.584V9.48c0-.257-.172-.626-.37-.792l-4.263-3.674c-.218-.184-.536-.184-.754 0zm7.17 2.374l-5.967-5.046C16.606 2.122 16.312 2 16 2c-.312 0-.606.123-.79.31L9.207 7.388c-.245.208-.276.576-.068.822.115.136.28.206.446.206.133 0 .266-.044.376-.137l5.69-4.847c.208-.155.49-.157.697-.002 1.286.962 5.693 4.85 5.693 4.85.246.206.614.177.822-.07.208-.246.177-.614-.068-.822z',
name: 'Carbonate',
date: 'April 14',
date: brew.dates.consume,
state: '',
description: 'After the beer is bottled or kegged, it enters the carbonation stage. If priming sugar was added during the bottling stage, the remaining yeast in the beer consumes the sugar and produces carbon dioxide, naturally carbonating the beer over time. The sealed bottles or kegs are stored at a controlled temperature for a period of time to allow carbonation to occur. This process typically takes a few weeks, during which the flavors and aromas continue to develop. If kegging, carbonation can also be achieved through forced carbonation, where carbon dioxide is directly injected into the keg under pressure.'
description:
'After the beer is bottled or kegged, it enters the carbonation stage. If priming sugar was added during the bottling stage, the remaining yeast in the beer consumes the sugar and produces carbon dioxide, naturally carbonating the beer over time. The sealed bottles or kegs are stored at a controlled temperature for a period of time to allow carbonation to occur. This process typically takes a few weeks, during which the flavors and aromas continue to develop. If kegging, carbonation can also be achieved through forced carbonation, where carbon dioxide is directly injected into the keg under pressure.'
}
];
</script>
@@ -54,7 +82,10 @@
<div class="card">
<h1>Brew progress</h1>
<h2>{brew.name} <span class="company">av {brew.by}</span></h2>
<a href="{`/brews/${brew.date}`}" class="brew">
<h2>{brew.name} <span class="company">av {brew.by}</span></h2>
<ArrowRight />
</a>
<ol class="os-timeline">
{#each steps as step, index}
@@ -82,16 +113,51 @@
{#each steps as step, index}
<div class="{`description ${isOpen === index && 'isOpen'}`}">
<p>{ step.description }</p>
<p>{step.description}</p>
</div>
{/each}
<i class="info">{!isOpen ? 'Click icon for description' : 'Click icon to close'}</i>
</div>
<style lang="scss">
.company {
font-size: 1.25rem;
opacity: 0.8;
display: inline-block;
a.brew {
display: flex;
align-items: center;
justify-content: space-between;
h2 {
margin: 0;
}
.company {
font-size: 1.25rem;
line-height: 1;
margin-left: 6px;
opacity: 0.8;
display: inline-block;
flex-grow: 1;
}
}
:global(a.brew:hover svg, a.brew svg.animate) {
animation: bounce 2s infinite;
}
@keyframes bounce {
0%,
20%,
50%,
80%,
100% {
transform: translateX(0);
}
40% {
transform: translateX(-5px);
}
60% {
transform: translateX(-3px);
}
}
.description {
@@ -110,6 +176,14 @@
}
}
i.info {
display: block;
text-align: center;
margin-top: 0.5rem;
margin-bottom: -1rem;
color: #737373;
}
ol {
display: flex;
justify-content: space-between;

View File

@@ -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

View File

@@ -88,7 +88,7 @@
<div class="mobile-only">
<svg
viewBox="545.506 652.94 1308.988 494.119"
viewBox="37.55 522.904 2324.9 754.192"
width="100%"
height="100%"
xmlns="http://www.w3.org/2000/svg"
@@ -104,40 +104,48 @@
preserveAspectRatio="xMidYMid meet"
color-interpolation-filters="sRGB"
transform="matrix(7.058824, 0, 0, 7.058824, 0, 17.647059)"
style=""
>
<g
fill="#f4400d"
class="icon-text-wrapper icon-svg-group iconsvg"
transform="translate(77.27999877929688,89.99988174438477)"
transform="translate(5.319610595703125,71.57809829711914)"
>
<g class="iconsvg-imagesvg" transform="translate(0,0)">
<g>
<svg
filter="url(#colors7759109557)"
<rect
fill="#f4400d"
fill-opacity="0"
stroke-width="2"
x="0"
y="0"
width="60"
height="70.00023333411112"
filtersec="colorsf9850467616"
width="106.80000000000004"
height="106.84380596044383"
class="image-rect"></rect>
<svg
filter="url(#colors8304882580)"
x="0"
y="0"
width="106.80000000000004"
height="106.84380596044383"
filtersec="colorsf6570116847"
class="image-svg-svg primary"
style="overflow: visible;"
>
<svg
xmlns="http://www.w3.org/2000/svg"
version="1.1"
viewBox="4.992629051208496 5 54.01459503173828 54.03697204589844"
x="0px"
y="0px"
viewBox="14.000142097473145 8 71.99971008300781 84"
enable-background="new 0 0 100 100"
>
<path
d="M16.723,52.83c1.909,0.178,2.384,0.161,3.399,0.153c0.682,9.052,4.603,16.156,4.789,16.487 c0.578,1.03,1.697,1.611,2.836,1.522c0.157-0.012,2.061-0.167,4.803-0.859c2.747,13.368,15.326,21.092,15.906,21.44 C48.932,91.858,49.465,92,50,92s1.068-0.142,1.544-0.428c0.58-0.348,13.159-8.072,15.906-21.44c2.741,0.693,4.646,0.848,4.803,0.859 c1.148,0.09,2.263-0.5,2.836-1.522c0.186-0.331,4.107-7.435,4.789-16.487c1.015,0.009,1.49,0.025,3.399-0.153 c1.636-0.151,2.845-1.589,2.713-3.227C84.451,30.394,70.504,15.676,53,14.152V11c0-1.657-1.343-3-3-3s-3,1.343-3,3v3.152 c-17.504,1.524-31.451,16.242-32.99,35.451C13.878,51.241,15.087,52.679,16.723,52.83z M29.265,64.716 c-1.077-2.426-2.801-7.033-3.179-12.309c1.473-0.276,4.102-0.964,6.17-1.783c0.508,3.546,2.048,7.807,4.579,11.62 C33.873,63.666,31.057,64.375,29.265,64.716z M49.994,85.366c-3.182-2.343-10.273-8.453-11.725-17.187 c0.78-0.34,1.572-0.72,2.372-1.146c3.806,4.069,7.498,6.35,7.815,6.54C48.932,73.858,49.465,74,50,74s1.068-0.142,1.544-0.428 c0.317-0.19,4.009-2.471,7.815-6.54c0.799,0.425,1.591,0.806,2.37,1.146C60.274,76.875,53.171,83.014,49.994,85.366z M49.994,67.366 c-6.35-4.679-11.666-11.733-11.96-19.655C42.277,45.046,46.895,40.6,50,35.549c3.106,5.053,7.736,9.505,11.966,12.161 C61.676,55.611,56.319,62.68,49.994,67.366z M70.735,64.716c-1.793-0.341-4.609-1.051-7.57-2.472 c2.503-3.772,4.058-7.986,4.579-11.62c2.068,0.819,4.696,1.507,6.17,1.783C73.537,57.683,71.812,62.289,70.735,64.716z M50,20 c14.518,0,27.018,11.629,29.625,26.996c-11.352-0.211-22.033-7.692-26.859-19.16C52.297,26.724,51.207,26,50,26 s-2.297,0.724-2.766,1.835C42.518,39.041,31.94,46.78,20.375,46.996C22.982,31.629,35.482,20,50,20z"
></path>
<g>
<path
d="M59,26.76l-.14-.56A27.53,27.53,0,0,0,32.69,5c-.46,0-.93,0-1.36,0A27.54,27.54,0,0,0,5.17,26.19L5,26.76a1.53,1.53,0,0,0,0,.3,1,1,0,0,0,.3.71,1,1,0,0,0,.7.29H6a23,23,0,0,0,2.78-.22,39.49,39.49,0,0,0,3.4,14.54l.9,2a1,1,0,0,0,.7.57L14,45a1,1,0,0,0,.67-.25l1-.91A24.24,24.24,0,0,0,16.93,48a22.7,22.7,0,0,0,3.29,5.59,1,1,0,0,0,.72.38H21a1,1,0,0,0,.71-.29l1.65-1.65.21-.23A18.81,18.81,0,0,0,26,55a19.18,19.18,0,0,0,5.09,3.72l.42.21a1,1,0,0,0,.9,0l.42-.21a18.86,18.86,0,0,0,7.56-6.85l.21.23,1.65,1.65A1,1,0,0,0,43,54h.06a1,1,0,0,0,.72-.38A22.7,22.7,0,0,0,47.07,48a24.24,24.24,0,0,0,1.25-4.19l1,.91A1,1,0,0,0,50,45l.21,0a1,1,0,0,0,.7-.57l.9-2a39.49,39.49,0,0,0,3.4-14.54,23.16,23.16,0,0,0,2.78.22.94.94,0,0,0,.71-.29,1,1,0,0,0,.3-.71V27A1,1,0,0,0,59,26.76ZM39.72,33.23l.15.29-.36,1.81a13.53,13.53,0,0,1-2.74,5.86,12.19,12.19,0,0,1-1,1l-.28.29A13.79,13.79,0,0,1,32,44.9a13.79,13.79,0,0,1-3.54-2.39l-.28-.29a13.37,13.37,0,0,1-3.69-6.88l-.36-1.82c.05-.1.1-.2.16-.3.26-.48.52-1,.77-1.45l.27-.53q.45-.93.87-1.89h0l.05,0,.23.21a12.72,12.72,0,0,0,1,.91,4.63,4.63,0,0,0,.42.32c.32.25.65.47,1,.69l.42.27a16.21,16.21,0,0,0,1.49.78l.78.34a1,1,0,0,0,.8,0l.79-.35a13.84,13.84,0,0,0,1.48-.77l.43-.28a11.11,11.11,0,0,0,1-.67c.15-.11.3-.22.44-.34.34-.27.66-.56,1-.86l.27-.25,0,0h0c.28.64.57,1.28.88,1.9.08.17.16.33.25.5C39.18,32.25,39.44,32.74,39.72,33.23ZM37.85,26.1c-.17.25-.33.5-.52.74a12.77,12.77,0,0,1-4.95,3.9l-.38.17-.37-.16a12.89,12.89,0,0,1-5-3.92c-.18-.23-.34-.48-.52-.75L26.08,26A12.69,12.69,0,0,1,24,19.39c4.3-4.36,6.75-8,8-12.06,1.24,4,3.69,7.7,8,12.06A12.84,12.84,0,0,1,37.85,26.1ZM25.72,7.78A26.06,26.06,0,0,1,30,7.08c-1.21,3.65-3.57,7.08-7.68,11.2l-3,2.65a20.25,20.25,0,0,1-6.19,3.78,20.87,20.87,0,0,1-3.56,1,21.19,21.19,0,0,1-2.28.3A25.46,25.46,0,0,1,25.72,7.78ZM14.36,42.34,14,41.56A37.65,37.65,0,0,1,10.77,27.5c.25-.05.5-.13.74-.19l.54-.15c.6-.17,1.19-.36,1.79-.59a22,22,0,0,0,6.8-4.14l1.51-1.34a14.74,14.74,0,0,0,2.28,6l.06.09.26.38-.09.21c-.32.8-.67,1.6-1.05,2.39l-.12.24c-.4.82-.83,1.63-1.3,2.43-.11.2-.23.4-.35.6a37.54,37.54,0,0,1-6.18,7.66c-.25.26-.52.51-.8.75Zm6.75,9.14a20.35,20.35,0,0,1-2.32-4.21,20.62,20.62,0,0,1-1.36-5.06c.48-.47,1-1,1.42-1.47l.11-.12c.49-.54,1-1.09,1.42-1.66.16-.19.31-.38.46-.58.34-.43.68-.88,1-1.33l.45-.64c.09-.14.19-.27.29-.41,0,.17.08.32.12.48s.07.31.12.46.13.43.2.64.09.28.14.42.17.44.26.66l.15.37c.12.26.25.51.38.77l.11.22c.17.32.36.64.55.95l.14.21c.16.23.32.47.49.7l.26.33.42.53.33.36c.11.12.22.25.34.37-.11.29-.23.56-.35.84s-.2.47-.31.69-.32.62-.48.92-.24.45-.37.67-.37.58-.57.87-.27.43-.42.64c-.27.37-.57.74-.87,1.1-.09.1-.16.21-.25.31a13.22,13.22,0,0,1-1,1.13ZM32,56.88a17.14,17.14,0,0,1-4.53-3.32A16.62,16.62,0,0,1,25,50.26c.2-.24.38-.5.57-.75s.19-.25.29-.38c.35-.49.68-1,1-1.52a3.9,3.9,0,0,0,.19-.35c.24-.41.47-.83.68-1.26l.26-.56c.08-.18.17-.35.25-.54l.11.08a14.93,14.93,0,0,0,1.34.9l.39.24c.51.29,1,.56,1.57.8a1,1,0,0,0,.8,0,15.44,15.44,0,0,0,1.57-.8l.4-.24c.44-.27.87-.56,1.28-.87l.16-.11c.08.19.17.36.25.54s.17.38.26.56c.21.42.43.83.66,1.24l.21.38c.31.51.64,1,1,1.5.1.14.21.27.31.4s.36.5.56.75A16.94,16.94,0,0,1,32,56.88Zm13.21-9.61a20.61,20.61,0,0,1-2.32,4.21l-.83-.84A13.61,13.61,0,0,1,41,49.5c-.4-.46-.77-.93-1.12-1.42-.12-.16-.22-.33-.33-.5s-.45-.65-.65-1-.23-.42-.35-.63-.35-.63-.5-1-.21-.46-.31-.69-.24-.55-.35-.83l.24-.26c0-.06.11-.11.16-.18s.34-.38.52-.59A14.33,14.33,0,0,0,39.38,41c.11-.17.19-.35.29-.53a11.3,11.3,0,0,0,.59-1.08c.11-.22.18-.45.28-.67s.29-.69.41-1,.14-.49.21-.73.19-.6.25-.91c.09.14.19.27.29.4s.3.44.46.66c.32.44.65.88,1,1.3l.48.61q.66.81,1.35,1.56l.18.22c.46.5.94,1,1.42,1.46A20.62,20.62,0,0,1,45.21,47.27ZM50,41.56l-.35.78-.5-.46c-.28-.24-.55-.49-.82-.76a37.58,37.58,0,0,1-6.16-7.66l-.37-.61c-.45-.79-.88-1.59-1.28-2.41l-.13-.25c-.37-.78-.72-1.58-1-2.38a1.8,1.8,0,0,1-.08-.21l.25-.39a14.69,14.69,0,0,0,2.34-6.12l1.5,1.34c.37.32.75.63,1.13.93.13.11.27.2.4.3l.78.56.5.32.73.45.56.31.72.39.6.28c.24.11.47.22.72.32l.62.25.73.27c.22.08.43.15.65.21l.75.23.65.16.34.09A37.65,37.65,0,0,1,50,41.56Zm4.44-15.85a20.16,20.16,0,0,1-9.75-4.78l-3-2.65c-4.11-4.12-6.47-7.55-7.68-11.2a26.72,26.72,0,0,1,4.28.7A25.47,25.47,0,0,1,56.72,26,21.38,21.38,0,0,1,54.43,25.71Z"
></path>
</g>
</svg>
</svg>
<defs>
<filter id="colors7759109557">
<filter id="colors8304882580">
<feColorMatrix
type="matrix"
values="0 0 0 0 0.953125 0 0 0 0 0.25 0 0 0 0 0.05078125 0 0 0 1 0"
@@ -146,9 +154,9 @@
</defs>
</g>
</g>
<g transform="translate(67,5.938072204589844)">
<g transform="translate(113.80000305175781,0.5289802551269531)">
<g fill-rule="" class="tp-name iconsvg-namesvg">
<g transform="scale(1)">
<g transform="scale(1.8200000000000005)">
<g>
<path
d="M7.5 0.31C11.37 0.31 14.73-1.93 14.73-5.44 14.73-11.69 4.55-11.53 4.55-14.44 4.55-15.67 6.09-16.42 7.5-16.42 9.16-16.42 10.57-15.43 10.57-14.24L14.39-14.24C14.39-18.09 10.85-19.73 7.5-19.73 3.57-19.73 0.75-17.57 0.75-14.55 0.75-8.15 10.93-8.9 10.93-5.44 10.93-4.11 9.73-3.25 7.76-3.25 5.47-3.25 4.37-4.84 4.37-6.3L0.52-6.3C0.52-2.42 3.57 0.31 7.5 0.31ZM16.27-9.76C16.27-4.35 20.48 0.29 25.71 0.29 28 0.29 30.11-0.57 31.75-1.98L29.56-4.87C28.5-4.03 27.25-3.46 25.63-3.46 22.2-3.46 20.14-6.61 20.14-9.76 20.14-12.91 22.2-16.06 25.63-16.06 27.25-16.06 28.52-15.51 29.56-14.65L31.75-17.54C30.11-18.95 28-19.8 25.71-19.8 20.48-19.8 16.27-15.17 16.27-9.76ZM33.88-19.52L33.88 0 37.45 0 37.45-5.75 45.02-5.75 45.02 0 48.59 0 48.59-19.52 45.02-19.52 45.02-9.34 37.45-9.34 37.45-19.52ZM59.21-5.83L68.34-5.83 68.34-9.11 62.46-9.11 62.46-10.93 66.52-10.93 67.07-14.16 62.46-14.16 62.46-16.29 68.34-16.29 68.34-19.57 59.21-19.57ZM51.97 0C57.51-1.54 60.59 0 63.66 0 66.02 0 68.34-0.31 70.08-1.33L68.91-4.48C67.77-3.83 66.31-3.28 63.66-3.28 60.66-3.28 59.96-4.22 55.54-3.7L55.54-19.52 51.97-19.52ZM80.21-19.57L71.65-19.57 71.65 0 75.21 0 75.21-6.53 79.66-6.53C83.88-6.53 86.95-9.19 86.95-13.04 86.95-16.89 84.11-19.57 80.21-19.57ZM83.25-13.04C83.25-10.67 80.96-10.1 79.17-10.1L75.21-10.1 75.21-16.01 79.17-16.01C80.96-16.01 83.25-15.41 83.25-13.04ZM97.98-19.57L89.42-19.57 89.42 0 92.99 0 92.99-6.53 97.44-6.53C101.65-6.53 104.72-9.19 104.72-13.04 104.72-16.89 101.89-19.57 97.98-19.57ZM101.03-13.04C101.03-10.67 98.74-10.1 96.94-10.1L92.99-10.1 92.99-16.01 96.94-16.01C98.74-16.01 101.03-15.41 101.03-13.04ZM118.96-15.95L118.96-19.52 107.07-19.52 107.07 0 118.96 0 118.96-3.57 110.63-3.57 110.63-7.34 116.38-7.34 116.9-10.88 110.63-10.88 110.63-15.95Z"
@@ -178,7 +186,7 @@
}
:global(.mobile-only > svg) {
max-width: 340px;
max-width: 350px;
}
.desktop-only {

View File

@@ -9,7 +9,7 @@
let loadedTime: number = new Date().getTime();
let currentTime: number = new Date().getTime();
let autoReload = false;
const currentGoal = 4;
const currentGoal = 18.5;
function updateTime() {
currentTime = new Date().getTime();

View File

@@ -2,5 +2,5 @@ import brews from '../../brews.json';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async () => {
return { brews };
return { brews: brews.brews };
};

View File

@@ -21,7 +21,7 @@ async function fetchGraphData(brew) {
export const load = (async ({ params }) => {
const { date } = params;
const brew = brews.find((b) => b?.date === date);
const brew = brews.brews.find((b) => b?.date === date);
if (!brew) {
throw error(404, 'Brew not found');

View File

@@ -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>

View File

@@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB