Skip to content

Commit

Permalink
feat: implement a few different glass types
Browse files Browse the repository at this point in the history
  • Loading branch information
danielgtaylor committed Apr 3, 2023
1 parent 33b7d57 commit 342cabd
Show file tree
Hide file tree
Showing 21 changed files with 2,792 additions and 150 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
"build": "vite build",
"serve": "vite preview",
"wrangler": "wrangler pages dev -- vite",
"diagrams": "npx bytefield-svg -s docs/types.clj -o src/assets/types.svg && npx bytefield-svg -s docs/recipe.clj -o src/assets/recipe.svg && npx bytefield-svg -s docs/fermentable.clj -o src/assets/fermentable.svg && npx bytefield-svg -s docs/hop.clj -o src/assets/hop.svg && npx bytefield-svg -s docs/misc.clj -o src/assets/misc.svg && npx bytefield-svg -s docs/yeast.clj -o src/assets/yeast.svg && npx bytefield-svg -s docs/mash.clj -o src/assets/mash.svg && npx bytefield-svg -s docs/fermstep.clj -o src/assets/fermstep.svg"
"diagrams": "npx bytefield-svg -s docs/types.clj -o src/assets/types.svg && npx bytefield-svg -s docs/recipe.clj -o src/assets/recipe.svg && npx bytefield-svg -s docs/fermentable.clj -o src/assets/fermentable.svg && npx bytefield-svg -s docs/hop.clj -o src/assets/hop.svg && npx bytefield-svg -s docs/misc.clj -o src/assets/misc.svg && npx bytefield-svg -s docs/yeast.clj -o src/assets/yeast.svg && npx bytefield-svg -s docs/mash.clj -o src/assets/mash.svg && npx bytefield-svg -s docs/fermstep.clj -o src/assets/fermstep.svg",
"dump-recipes": "npx esbuild --bundle ./src/dumpRecipes.ts --loader:.svg=empty | node >./src/assets/recipes.json",
"crush-recipes": "npx esbuild --bundle ./src/crushRecipes.ts --loader:.svg=empty | node >./src/assets/recipes-crushed.json"
},
"license": "MIT",
"devDependencies": {
Expand Down
30 changes: 15 additions & 15 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,21 @@ const App: Component = () => {
<A href="/about">👤 About</A>
</div>
</nav>
<Suspense fallback={<article>Loading...</article>}>
<Routes>
<Route path="/" element={<Home bh={bh} />} />
<Route
path="/r/:encoded?/:dialog?"
element={<Editor bh={bh} setBh={setBh} />}
/>
<Route
path="/settings"
element={<article style="padding: 12px">Coming soon...</article>}
/>
<Route path="/about" component={About} />
<Route path="/about/format" component={Format} />
</Routes>
</Suspense>
{/* <Suspense fallback={<article>Loading...</article>}> */}
<Routes>
<Route path="/" element={<Home bh={bh} />} />
<Route
path="/r/:encoded?/:dialog?"
element={<Editor bh={bh} setBh={setBh} />}
/>
<Route
path="/settings"
element={<article style="padding: 12px">Coming soon...</article>}
/>
<Route path="/about" component={About} />
<Route path="/about/format" component={Format} />
</Routes>
{/* </Suspense> */}
<footer class="col gap">
<div class="row gap" style="justify-content: space-between">
<div class="col">
Expand Down
25 changes: 20 additions & 5 deletions src/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@ import { crush, load } from "./crush";

import type { Component } from "solid-js";
import { Editable } from "./Editable";
import { GlassPicker } from "./GlassPicker";
import { LbOz } from "./LbOz";
import QRCode from "qrcode-svg";
import { StylePicker } from "./StylePicker";
import { StyleValue } from "./StyleValue";
import bjcp2021 from "./assets/bjcp2021.json?url";
import createURLStore from "./urlstore";
import { debounce } from "@solid-primitives/scheduled";
import tulip from "./assets/tulip.svg";
import { glasses } from "./glasses";

type StyleCategory = {
title: string;
Expand Down Expand Up @@ -243,7 +244,15 @@ const Editor: Component<{
return (
<article class="col gap">
<header>
<div class="glass-container col gap">
<div
class="glass-container col gap"
classList={{ edit: edit() }}
onclick={(e) => {
if (edit()) {
navigate(location.pathname + "/glasses", { scroll: false });
}
}}
>
<div
id="bubble"
onanimationend={(e) => e.currentTarget.classList.remove("animated")}
Expand All @@ -254,7 +263,7 @@ const Editor: Component<{
height="160px"
style="margin: 0 -26px"
>
<use href={tulip + "#img"} />
<use href={glasses[recipe.glass] + "#img"} />
</svg>
</div>
<div class="recipe-info col gap">
Expand Down Expand Up @@ -299,8 +308,8 @@ const Editor: Component<{
for="edit"
style="padding: 6px 6px; margin: 0"
>
<Show when={edit()} fallback="🗂 Edit">
💾 Save
<Show when={edit()} fallback=" Edit">
👀 View
</Show>
</label>
</div>
Expand Down Expand Up @@ -1655,6 +1664,12 @@ const Editor: Component<{
}).svg()}
></div>
</div>
<Show when={params.dialog == "glasses"}>
<GlassPicker
glass={recipe.glass}
setGlass={(g) => setRecipe("glass", g)}
/>
</Show>
<Show when={params.dialog == "styles"}>
<StylePicker
styles={styles()}
Expand Down
1 change: 1 addition & 0 deletions src/Format.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const fatTire: Recipe = {
boilSize: 26,
servingSizeMl: 355,
style: 57,
glass: "tulip",
fermentables: [
{
percentYield: 80,
Expand Down
54 changes: 54 additions & 0 deletions src/GlassPicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { Component, For, createEffect, createSignal, onMount } from "solid-js";
import { glasses, names } from "./glasses";

export const GlassPicker: Component<{
glass: string;
setGlass: (glass: string) => void;
}> = (props) => {
return (
<div
class="modal"
onclick={(e) => {
if (e.target.classList.contains("modal")) history.back();
}}
>
<div class="contents">
<div class="header">
<h2>Glass Picker</h2>
</div>
<div class="body">
<div class="row gap wrap">
<For each={names}>
{(glass) => (
<div
class="item col"
style="width: 108px"
onclick={(e) => props.setGlass(glass)}
>
<div style="text-align: center;">
{glass.charAt(0).toUpperCase() + glass.slice(1)}
</div>
<svg
class="glass"
width="160px"
height="160px"
style="margin: 0 -26px"
>
<use href={glasses[glass] + "#img"} />
</svg>
</div>
)}
</For>
</div>
</div>
<div class="footer">
<div class="buttons">
<button class="warn" onclick={() => history.back()}>
Cancel
</button>
</div>
</div>
</div>
</div>
);
};
41 changes: 20 additions & 21 deletions src/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,11 @@ import { Component, For, createEffect, createSignal } from "solid-js";
import { Brauhaus } from "./brauhaus/types";
import { RecipeCard } from "./RecipeCard";
import { load } from "./crush";
import origRecipes from "./assets/recipes-crushed.json";

const recipes = [
"47jG7w9ZbADe-QKUE4McO5YEXmICDHVgSigGyik5Cr1gZ2IOyCzOARq1go2FDeKd5axMcuATMoEMZrALBdiUWUBBnAChDjCKCEAPl4UfydrCFMCFWI4L5PEB83YSYmiQ8bCNAPpZmAA",
"49jBBxcAH74uEQzsSACLZ7_UssSURB3IEkMg5bhUQXEF1wxGZrBy8CUMS7p55jHCyhNg0H2J4jNih7peRBTO_CKnBGdvsYQzGYIEkc_xA2cFpuM2AuhnYH6w4QAfWZtfWgIA",
"49jJ5wY0NATURAYfvi7rB6n90zNLc3VAUxUl4HmqzLxiHQVn_2UOki84uDhgZrzgYeRDDp0l7Bye0GMAVbnXMl5hhAUQsCQQ4M5jCwEdB1lSwGfEhUiPi42EMIK8mMFDFqMVDRkHgbSlmw7v0eCHHggAO575yx4O2Nm2_MwcPMwmAA",
"42IQhbTgIGMWkPQLlBUOTwQd9AQeeXJx1gGd42QkzB0ouLQzixMSEMDgf9rDyAjRoQHyiubbTkaoJDDOVgjxOEJLWaRQWtTDYY2cXj7oahvxIod28QNGXXZIwio-rMvEBjl5msGDH9YKSwGmD6AXFomyh_IBAA",
"4zghAGzuJIMOEC8ugRy_LuKaUwnaXaIDOqAMtLRJRyHccY2B5gteXmYUzU8nM6mhhwSw8FzcwcUMcwVDEyM7sF-Tl5-fXaCdxwoaPUxMCOCAhcxndhkE5zBUniGQB-o9sI8YN9sIoJ-LuVGEDwA",
"4_jA5VRUBD14XSQ8MwVoog78BCkdBf-geQGSK3hnMDKj6HvawcQMs2kFN48krFQBZqOl3TyXGWF8YAmwtI_5Pgdq1SQgsYCRHZptN8hsYWRzLS0CloIL3NihfmfwlYC2h8B5DtmbjJttBNCPyQQA",
"47KRgLTgIGMWkPQLORlUODwRdNYTePDJxVkHdJSTkTB3guTSzixOSFgAY-BpN6MxLBSA_n_aw8gIMUMD5DnNFdw8fEhBMo-LbQsXInXN72Newo4aEg90jXiRA7_4gRyawAY-DU54tDP4cSFKg0UiLCHsAA",
"41jECWpRgM9dFwFmsoz8_Gwd0MlkoDVNOgrhjksNJF9wcTGDdYGvXnjczTiPEeZxYIAt6WHxhB39BzKSwYgLkdgCRJB5H5i0kbkMvhLQVg84ZyF7hnG3hQD6YZgA",
"41gn4l6aCV5DDy2XwUewS8IEdaAnjeiAzhwGNVuWBnCu4J3FyIxizPw-3l3cqEG9pJ3FGBo8i3pZmFES5lxOZjbwwaQgvQLyKWx-4EWHDN6i0FYQuLUAbzwwbrYQQD8Zc6EIHwA",
"47jMDu08CHvkp6Ynglcf6kBatqW5c5QlV_B4MCPrX9LjwYycKL54s1aw-YEXDQawGwmgZY9iF10uyEAOKNAZ-Djhx5swsAthHv7_gA9ZhY80tFEE7tag9XWY8mx4kI8e3WwjgH565iERthA-AA",
"45jLhWi2SYKOGwUd8KwD9YcONAdVznHgXNrlxoxwwQp2N2aosSu42fiRvL2Kn00QrQspwDaNkQOYu7NLc1KLGYLFgBk5CXPwg8l2jwDSDQLgsy932wign4n5UIQPAA",
"k9knBJqtBo3flILOqQYfwC4NWaAPLrx0QNMVJZCj7nUUnB3nrGBKkHzBxcsMNgd8GcOjHsZ9TLCgAIXCkg6-aJDlQIG8JX0c9zlQfbuoi2M1I6KUmd_Dsos7CFK_gGNJINSNHTrF_YFJJoof7bTXAylczsDoAQ1IJuYwBPBAwwLsfcbdNgLoh2gCAA",
"47gt6pMI2t6okFIK6kyBzpsHncEuGZqXCaxPS1N1wEOuSTmVOtBT5uckC75g52aGmrmJVYIRnMJWckkwIxy4uIOFGeaSFVxMjoh8sbiXKRklzwjwmQugZariAG0NUXjUIpcLDHyc8ANSGGQEMQ55ZGDkgG2aYgiQgbapwAu70Jd8NW62EUA_btOGlSvenOGjOB8A",
]
const recipes = origRecipes
.sort(() => (Math.random() > 0.5 ? 1 : -1))
.map((r) => load(r));
.map((r) => ({ crushed: r, recipe: load(r) }));

export const Home: Component<{
bh: Brauhaus;
Expand All @@ -32,17 +19,23 @@ export const Home: Component<{
setFilteredRecipes(
search()
? recipes.filter(
(r) =>
r.name.toLowerCase().indexOf(search().toLowerCase()) !== -1 ||
r.description.toLowerCase().indexOf(search().toLowerCase()) !== -1
(i) =>
i.recipe.name.toLowerCase().indexOf(search().toLowerCase()) !==
-1 ||
i.recipe.description
.toLowerCase()
.indexOf(search().toLowerCase()) !== -1
)
: [...recipes]
);
});

return (
<article style="padding: 12px">
<h1 style="text-align: center; font-size: 1000%; margin: 12px; margin-bottom: -28px;">
<h1
class="hero"
style="text-align: center; font-size: 1000%; margin: 12px; margin-bottom: -28px;"
>
Malt<span class="slightly-muted">.io</span>
</h1>
<div style="text-align: center; font-size: 240%; margin-bottom: 32px;">
Expand All @@ -59,7 +52,13 @@ export const Home: Component<{
</div>
<div class="recipe-cards">
<For each={filteredRecipes()} fallback={"No matches"}>
{(recipe) => <RecipeCard bh={props.bh} recipe={recipe} />}
{(entry) => (
<RecipeCard
bh={props.bh}
crushed={entry.crushed}
recipe={entry.recipe}
/>
)}
</For>
</div>
</article>
Expand Down
16 changes: 7 additions & 9 deletions src/RecipeCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import {

import { A } from "@solidjs/router";
import bjcp2021 from "./assets/bjcp2021.json?url";
import { crush } from "./crush";
import tulip from "./assets/tulip.svg";
import { glasses } from "./glasses";

type StyleCategory = {
title: string;
Expand All @@ -32,17 +31,16 @@ type Style = {
export const RecipeCard: Component<{
bh: Brauhaus;
recipe: Recipe;
crushed: string;
}> = (props) => {
let stats = calculateFermentables(props.bh, props.recipe);
let ebc = calculateColor(props.recipe);
let hops = calculateHops(props.bh, props.recipe);
let crushed = crush(props.recipe);

createEffect(() => {
stats = calculateFermentables(props.bh, props.recipe);
ebc = calculateColor(props.recipe);
hops = calculateHops(props.bh, props.recipe);
crushed = crush(props.recipe);
});

const [styles] = createResource(bjcp2021, async (url: string) => {
Expand Down Expand Up @@ -76,12 +74,12 @@ export const RecipeCard: Component<{
"margin: 0 -24px 0 -38px; --color-beer: " + ebcToCss(ebc) + ";"
}
>
<use href={tulip + "#img"} />
<use href={glasses[props.recipe.glass] + "#img"} />
</svg>
</div>
<div class="col gap grow">
<h2>
<A href={"/r/" + crushed}>{props.recipe.name}</A>
<A href={"/r/" + props.crushed}>{props.recipe.name}</A>
</h2>
<div>{props.recipe.description || "No description"}</div>
<div>{findStyle(props.recipe.style)}</div>
Expand All @@ -108,13 +106,13 @@ export const RecipeCard: Component<{
</div>
</div>
<div class="row gap right">
<a class="btn" href={"/r/" + crushed + ".json"}>
<a class="btn" href={"/r/" + props.crushed + ".json"}>
JSON
</a>
<a class="btn" href={"/r/" + crushed + ".xml"}>
<a class="btn" href={"/r/" + props.crushed + ".xml"}>
XML
</a>
<A class="btn primary" href={"/r/" + crushed}>
<A class="btn primary" href={"/r/" + props.crushed}>
View
</A>
</div>
Expand Down
Loading

0 comments on commit 342cabd

Please sign in to comment.