From 98708a9b6e6e39699940580fdca111106a05bea5 Mon Sep 17 00:00:00 2001 From: AleksandrSl Date: Sun, 21 Apr 2024 18:45:18 +0200 Subject: [PATCH 01/16] fix: add fallback font --- src/components/Timer.astro | 243 +++++++++++++++++++------------------ 1 file changed, 127 insertions(+), 116 deletions(-) diff --git a/src/components/Timer.astro b/src/components/Timer.astro index a0d467a..8578829 100644 --- a/src/components/Timer.astro +++ b/src/components/Timer.astro @@ -1,9 +1,9 @@ --- interface Props { steps: { - description: null | string; - time: number; - water: number; + description: null | string + time: number + water: number } } @@ -16,9 +16,15 @@ const { steps } = Astro.props - +
@@ -56,14 +62,19 @@ const { steps } = Astro.props @font-palette-values --segmented-1 { font-family: Segmented; - override-colors: 0 oklch(0 0 0), 1 oklch(0 0 0 / 0.08); + override-colors: + 0 oklch(0 0 0), + 1 oklch(0 0 0 / 0.08); } .segmented-1 { - font-family: Segmented; + font-family: Segmented, system-ui; font-palette: --segmented-1; /*font-feature-settings: 'ss${formattedCurrentStyleNumber}' on;*/ - font-variation-settings: 'wght' 600, 'wdth' 100, 'slnt' 5; + font-variation-settings: + 'wght' 600, + 'wdth' 100, + 'slnt' 5; } .steps { @@ -98,131 +109,131 @@ const { steps } = Astro.props From 7313eb163c544661182cdde8b724575caede8d5b Mon Sep 17 00:00:00 2001 From: AleksandrSl Date: Sun, 21 Apr 2024 21:53:02 +0200 Subject: [PATCH 02/16] feat: add timer as a separate page --- src/components/Recipe.astro | 15 +++- src/components/Timer.astro | 69 ++++++++++++----- .../{[name].astro => [name]/index.astro} | 0 .../recipes/[method]/[name]/timer.astro | 75 +++++++++++++++++++ src/styles/colors.css | 6 ++ 5 files changed, 145 insertions(+), 20 deletions(-) rename src/pages/[lang]/recipes/[method]/{[name].astro => [name]/index.astro} (100%) create mode 100644 src/pages/[lang]/recipes/[method]/[name]/timer.astro diff --git a/src/components/Recipe.astro b/src/components/Recipe.astro index a81257f..1e25fb0 100644 --- a/src/components/Recipe.astro +++ b/src/components/Recipe.astro @@ -15,13 +15,15 @@ type Entry = CollectionEntry<'recipes'> type Props = { recipe: Entry['data'] } const { recipe } = Astro.props +const { name } = Astro.params const locale = Astro.currentLocale || 'en' const messages = commonMessages(locale) const recipeMessages = getRecipeMessages(locale) const { time, weight } = createPropertyFormatters(Astro.currentLocale) -const href = getRelativeLocaleUrl(locale, `/recipes/${recipe.method}`) +const methodHref = getRelativeLocaleUrl(locale, `/recipes/${recipe.method}`) +const timerHref = getRelativeLocaleUrl(locale, `/recipes/${recipe.method}/${name}/timer`) const DEFAULT_GROUP = Symbol('default') const formattedSteps = recipe.steps @@ -61,7 +63,7 @@ const groupedSteps = formattedSteps

- {messages[recipe.method as keyof typeof messages]} / {recipe.name} + {messages[recipe.method as keyof typeof messages]} / {recipe.name}

@@ -98,6 +100,9 @@ const groupedSteps = formattedSteps {messages.source}:
+ {recipe.steps + ? Open timer + : null}
diff --git a/src/components/Timer.astro b/src/components/Timer.astro index 8578829..c3d12f1 100644 --- a/src/components/Timer.astro +++ b/src/components/Timer.astro @@ -26,7 +26,7 @@ const { steps } = Astro.props stroke-linecap="round" stroke-width="8"> -
+
@@ -36,18 +36,18 @@ const { steps } = Astro.props
-
- - - +
+ + +
@@ -112,7 +145,7 @@ const { steps } = Astro.props type Step = { description: null | string time: number - water: number + water: string } let startTime: number @@ -130,9 +163,9 @@ const { steps } = Astro.props const steps: Step[] = root?.dataset.steps ? JSON.parse(root.dataset.steps).map((it: Step) => ({ - ...it, - time: it.time * 1000 - })) + ...it, + time: it.time * 1000 + })) : [] let step = steps[stepIndex] @@ -145,7 +178,7 @@ const { steps } = Astro.props step = steps[stepIndex] nextStep = steps[stepIndex + 1] descriptionSlot.textContent = step.description - totalWeightSlot.textContent = `${step.water}g` + totalWeightSlot.textContent = step.water // nextStepSlot.textContent = nextStep ? nextStep.description : ""; } diff --git a/src/pages/[lang]/recipes/[method]/[name].astro b/src/pages/[lang]/recipes/[method]/[name]/index.astro similarity index 100% rename from src/pages/[lang]/recipes/[method]/[name].astro rename to src/pages/[lang]/recipes/[method]/[name]/index.astro diff --git a/src/pages/[lang]/recipes/[method]/[name]/timer.astro b/src/pages/[lang]/recipes/[method]/[name]/timer.astro new file mode 100644 index 0000000..b46122d --- /dev/null +++ b/src/pages/[lang]/recipes/[method]/[name]/timer.astro @@ -0,0 +1,75 @@ +--- +import type { GetStaticPaths } from 'astro' +import type { CollectionEntry } from 'astro:content' + +import { getCollection } from 'astro:content' +import { getRelativeLocaleUrl } from 'astro:i18n' + +import Timer from '../../../../../components/Timer.astro' +import { commonMessages } from '../../../../../i18n/locales/common/en' +import { createPropertyFormatters } from '../../../../../i18n/utils' +import Layout from '../../../../../layouts/Layout.astro' + +interface Props { + entry: CollectionEntry<'recipes'> +} + +const { entry } = Astro.props +const { method, name } = Astro.params +const locale = Astro.currentLocale || 'en' +const messages = commonMessages(locale) + +export const getStaticPaths = (async () => { + const recipes = await getCollection('recipes') + return recipes + .filter(entry => entry.data.steps !== undefined) + .map(entry => { + const [lang, method, name] = entry.slug.split('/') + + return { + params: { lang, method, name }, + props: { entry } + } + }) +}) satisfies GetStaticPaths +const { weight } = createPropertyFormatters(Astro.currentLocale) + +function timeToSeconds (s: string) { + const coefficients = [1, 60, 24 * 60] + return s.split(':').map(Number).reverse().reduce((acc, cur, index) => acc + cur * coefficients[index], 0) +} + +const methodHref = getRelativeLocaleUrl(locale, `/recipes/${method}`) +const recipeHref = getRelativeLocaleUrl(locale, `/recipes/${method}/${name}`) +const formattedSteps = entry.data.steps.map(step => ({ + ...step, + time: timeToSeconds(step.time), + water: weight(step.water) +})) +--- + + +

+ {messages[entry.data.method]} + / {entry.data.name} + / Timer +

+ +
+ + diff --git a/src/styles/colors.css b/src/styles/colors.css index 70d6295..e13b70b 100644 --- a/src/styles/colors.css +++ b/src/styles/colors.css @@ -21,6 +21,9 @@ --color-author-icon-background: transparent; --color-focus: black; + + --color-timer-progress-arc: oklch(0 0 0); + --color-timer-base-arc: oklch(0 0 0 / 0.08); } html[data-theme='dark'] { @@ -42,4 +45,7 @@ html[data-theme='dark'] { --color-footer-boder: transparent; --color-author-icon-background: white; --color-focus: white; + + --color-timer-progress-arc: oklch(100 0 0); + --color-timer-base-arc: oklch(100 0 0 / 0.08); } From f9a752afe8f3623cda3c30b970c8783d332a3bd7 Mon Sep 17 00:00:00 2001 From: AleksandrSl Date: Sun, 21 Apr 2024 22:06:41 +0200 Subject: [PATCH 03/16] fix: correct type errors and links --- src/components/Recipe.astro | 2 +- src/components/Timer.astro | 4 ++-- src/pages/[lang]/recipes/[method]/[name]/timer.astro | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/Recipe.astro b/src/components/Recipe.astro index 1e25fb0..45cebf1 100644 --- a/src/components/Recipe.astro +++ b/src/components/Recipe.astro @@ -63,7 +63,7 @@ const groupedSteps = formattedSteps

- {messages[recipe.method as keyof typeof messages]} / {recipe.name} + {messages[recipe.method as keyof typeof messages]} / {recipe.name}

diff --git a/src/components/Timer.astro b/src/components/Timer.astro index c3d12f1..355e7eb 100644 --- a/src/components/Timer.astro +++ b/src/components/Timer.astro @@ -1,10 +1,10 @@ --- -interface Props { +type Props = { steps: { description: null | string time: number water: number - } + }[] } const { steps } = Astro.props diff --git a/src/pages/[lang]/recipes/[method]/[name]/timer.astro b/src/pages/[lang]/recipes/[method]/[name]/timer.astro index b46122d..5e75f36 100644 --- a/src/pages/[lang]/recipes/[method]/[name]/timer.astro +++ b/src/pages/[lang]/recipes/[method]/[name]/timer.astro @@ -5,7 +5,7 @@ import type { CollectionEntry } from 'astro:content' import { getCollection } from 'astro:content' import { getRelativeLocaleUrl } from 'astro:i18n' -import Timer from '../../../../../components/Timer.astro' +import TimerComponent from '../../../../../components/Timer.astro' import { commonMessages } from '../../../../../i18n/locales/common/en' import { createPropertyFormatters } from '../../../../../i18n/utils' import Layout from '../../../../../layouts/Layout.astro' @@ -41,7 +41,7 @@ function timeToSeconds (s: string) { const methodHref = getRelativeLocaleUrl(locale, `/recipes/${method}`) const recipeHref = getRelativeLocaleUrl(locale, `/recipes/${method}/${name}`) -const formattedSteps = entry.data.steps.map(step => ({ +const formattedSteps = entry.data.steps!.map(step => ({ ...step, time: timeToSeconds(step.time), water: weight(step.water) @@ -50,11 +50,11 @@ const formattedSteps = entry.data.steps.map(step => ({

- {messages[entry.data.method]} + {messages[entry.data.method]} / {entry.data.name} / Timer

- +
@@ -160,6 +162,7 @@ const { steps } = Astro.props const totalWeightSlot = document.getElementById('totalWeight') const nextStepSlot = document.getElementById('nextStep') const progressArc = document.getElementById('progressArc') + const startTimerBtn = document.getElementById('startTimer')! const steps: Step[] = root?.dataset.steps ? JSON.parse(root.dataset.steps).map((it: Step) => ({ @@ -191,14 +194,24 @@ const { steps } = Astro.props progressArc.setAttribute('stroke-dasharray', getDashArray((displayTime / step.time) * 100)) } + function toggleTimer() { + if (isRunning) { + stopTimer() + } else { + startTimer() + } + } + function startTimer() { isRunning = true startTime = performance.now() - elapsedTime requestAnimationFrame(updateTimer) + startTimerBtn.textContent = 'Pause' } function stopTimer() { isRunning = false + startTimerBtn.textContent = 'Start' } function resetTimer() { @@ -229,10 +242,8 @@ const { steps } = Astro.props const totalMilliseconds = Math.floor(time) const minutes = Math.floor((totalMilliseconds % 3600_000) / 60_000) const seconds = Math.floor((totalMilliseconds % 60_000) / 1000) - // const milliseconds = totalMilliseconds % 1000; return pad(minutes) + ':' + pad(seconds) - // + ":" + milliseconds.toString().padStart(3, "0"); } function getDashArray(percent: number) { @@ -250,19 +261,12 @@ const { steps } = Astro.props resetTimer() } - const startTimerBtn = document.getElementById('startTimer') - const stopTimerBtn = document.getElementById('stopTimer') const stopBrewBtn = document.getElementById('stopBrew') - if (startTimerBtn && stopBrewBtn && stopTimerBtn) { + if (startTimerBtn && stopBrewBtn) { startTimerBtn.addEventListener('click', () => { - startTimer() + toggleTimer() }) - - stopTimerBtn.addEventListener('click', () => { - stopTimer() - }) - stopBrewBtn.addEventListener('click', () => { stopBrew() }) From 8899c56e92415b722e5f0af12edc44215ffd6b11 Mon Sep 17 00:00:00 2001 From: Aleksandr Slepchenkov Date: Wed, 15 Jan 2025 11:15:13 +0100 Subject: [PATCH 05/16] feat: move timer link above the source I'd say the source is the least helpful information --- src/components/Recipe.astro | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Recipe.astro b/src/components/Recipe.astro index 45cebf1..5064097 100644 --- a/src/components/Recipe.astro +++ b/src/components/Recipe.astro @@ -96,13 +96,13 @@ const groupedSteps = formattedSteps }
+ {recipe.steps + ? Open timer + : null}
{messages.source}:
- {recipe.steps - ? Open timer - : null}
From dd48bf89d7a685280bd7dae34a6a77d38010121b Mon Sep 17 00:00:00 2001 From: Aleksandr Slepchenkov Date: Wed, 15 Jan 2025 11:47:43 +0100 Subject: [PATCH 08/16] feat: strictly parse methods --- src/components/Recipe.astro | 2 +- src/constants/brewMethods.ts | 8 ++++++++ src/content/config.ts | 4 +++- 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 src/constants/brewMethods.ts diff --git a/src/components/Recipe.astro b/src/components/Recipe.astro index e2e1640..6eb0cc7 100644 --- a/src/components/Recipe.astro +++ b/src/components/Recipe.astro @@ -63,7 +63,7 @@ const groupedSteps = formattedSteps

- {messages[recipe.method as keyof typeof messages]} / {recipe.name} + {messages[recipe.method]} / {recipe.name}

diff --git a/src/constants/brewMethods.ts b/src/constants/brewMethods.ts new file mode 100644 index 0000000..86cfabd --- /dev/null +++ b/src/constants/brewMethods.ts @@ -0,0 +1,8 @@ +export const BREW_METHODS = [ + 'aeropress', + 'cezve', + 'chemex', + 'coldbrew', + 'pourover', + 'summer' +] as const diff --git a/src/content/config.ts b/src/content/config.ts index a30b940..5b7b4b1 100644 --- a/src/content/config.ts +++ b/src/content/config.ts @@ -1,6 +1,8 @@ /* eslint-disable perfectionist/sort-objects */ import { defineCollection, z } from 'astro:content' +import { BREW_METHODS } from '@/constants/brewMethods.ts' + const recipeStep = z.object({ description: z.string().optional(), time: z.string(), @@ -13,7 +15,7 @@ const recipesCollection = defineCollection({ title: z.string(), description: z.string(), name: z.string(), - method: z.string(), + method: z.enum(BREW_METHODS), properties: z.object({ coffeeWeight: z.number(), water: z.number(), From 3b29f43b214acf9455e1c1b20bea8e2802b9d4a1 Mon Sep 17 00:00:00 2001 From: Aleksandr Slepchenkov Date: Wed, 15 Jan 2025 11:48:23 +0100 Subject: [PATCH 09/16] chore: linter --- src/pages/[lang]/recipes/[method]/[name]/timer.astro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/[lang]/recipes/[method]/[name]/timer.astro b/src/pages/[lang]/recipes/[method]/[name]/timer.astro index 5e75f36..26aac7e 100644 --- a/src/pages/[lang]/recipes/[method]/[name]/timer.astro +++ b/src/pages/[lang]/recipes/[method]/[name]/timer.astro @@ -48,7 +48,7 @@ const formattedSteps = entry.data.steps!.map(step => ({ })) --- - +

{messages[entry.data.method]} / {entry.data.name} From 1ab12b5a30ed9e519129b31eba12e50efb0bf413 Mon Sep 17 00:00:00 2001 From: Aleksandr Slepchenkov Date: Wed, 15 Jan 2025 12:13:50 +0100 Subject: [PATCH 10/16] feat: translate timer --- src/components/Timer.astro | 17 ++++++++++++----- src/i18n/locales/common/en.ts | 3 +++ src/i18n/locales/common/ru.json | 5 ++++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/components/Timer.astro b/src/components/Timer.astro index 01e3a5b..37e967e 100644 --- a/src/components/Timer.astro +++ b/src/components/Timer.astro @@ -1,4 +1,5 @@ --- +import { commonMessages } from '@/i18n/locales/common/en' interface Props { steps: { description: null | string @@ -6,11 +7,13 @@ interface Props { water: number }[] } +const locale = Astro.currentLocale || 'en' +const messages = commonMessages(locale) const { steps } = Astro.props --- -
+
@@ -37,8 +40,8 @@ const { steps } = Astro.props
- - + +
@@ -144,6 +147,8 @@ const { steps } = Astro.props