Skip to content

Commit

Permalink
Merge pull request #89 from a-type/hub
Browse files Browse the repository at this point in the history
Return of Gnocchi recipe publishing
  • Loading branch information
a-type authored May 27, 2024
2 parents c88221a + ed50efc commit a26241b
Show file tree
Hide file tree
Showing 51 changed files with 2,844 additions and 3,137 deletions.
7 changes: 1 addition & 6 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
{
"extends": "next/core-web-vitals",
// not actually using NextJS, so disable next-specific rules
"rules": {
"@next/next/no-img-element": "off",
"react/no-unescaped-entities": "off"
}
"extends": ["eslint:recommended", "plugin:react/recommended"]
}
52 changes: 52 additions & 0 deletions apps/gnocchi/hub/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!doctype html>
<html lang="en">
<head>
<meta
name="viewport"
content="width=device-width, initial-scale=1, user-scalable=no, viewport-fit=cover"
/>
<title>Gnocchi Recipes</title>
<meta name="description" content="Your grocery list, done better" />
<link rel="icon" href="/favicon.ico" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180" />
<link rel="mask-icon" href="/mask-icon.svg" color="#ffffff" />
<meta name="theme-color" content="#fdfdff" />
<meta charset="utf-8" />
<meta property="og:image" content="/og-image.png" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta
property="og:image:alt"
content="A screenshot of a grocery list app transposed over a frying pan with various produce floating above it"
/>
<meta property="og:title" content="Gnocchi" />
<meta property="og:description" content="Your grocery list, done better" />
<meta property="og:url" content="https://gnocchi.biscuits.club" />
<meta property="og:site_name" content="Gnocchi" />

<meta name="twitter:card" content="summary_large_image" />
<meta
name="twitter:image:alt"
content="A screenshot of a grocery list app transposed over a frying pan with various produce floating above it"
/>
<meta name="twitter:title" content="Gnocchi" />
<meta name="twitter:description" content="Your grocery list, done better" />
<meta
name="twitter:image"
content="https://gnocchi.biscuits.club/og-image.png"
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
</head>

<body className="theme-lemon">
<div id="root">
<!--app-html-->
</div>
<script type="module" src="/src/entry-client.tsx"></script>
<script>
// prettier-ignore
window.__SNAPSHOT__ = {/*snapshot*/};
</script>
</body>
</html>
47 changes: 47 additions & 0 deletions apps/gnocchi/hub/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "@gnocchi.biscuits/hub",
"version": "0.0.1",
"private": true,
"type": "module",
"exports": {
".": {
"import": "./dist/server/entry-server.js",
"types": "./dist/server/entry-server.d.ts"
}
},
"scripts": {
"build": "pnpm run build:client && pnpm run build:server",
"build:client": "vite build --outDir dist/client",
"build:server": "vite build --ssr src/entry-server.tsx --outDir dist/server",
"dev": "pnpm run dev:client && pnpm run dev:server && tsc --declaration --emitDeclarationOnly",
"dev:client": "vite build --mode development --outDir dist/client",
"dev:server": "vite build --mode development --ssr src/entry-server.tsx --outDir dist/server",
"typecheck": "tsc --build tsconfig.json"
},
"dependencies": {
"@a-type/ui": "^0.8.15",
"@a-type/utils": "^1.0.8",
"@tiptap/core": "^2.2.4",
"@tiptap/extension-document": "^2.2.4",
"@tiptap/extension-link": "^2.2.4",
"@tiptap/extension-paragraph": "^2.2.4",
"@tiptap/pm": "^2.2.4",
"@tiptap/react": "^2.2.4",
"@tiptap/starter-kit": "^2.2.4",
"prosemirror-model": "1.19.4",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"@originjs/vite-plugin-commonjs": "^1.0.3",
"@types/react": "^18.2.79",
"@types/react-dom": "^18.2.25",
"@unocss/transformer-variant-group": "^0.58.0",
"@vitejs/plugin-react-swc": "^3.5.0",
"concurrently": "^7.5.0",
"dotenv": "^16.0.1",
"typescript": "^5.4.5",
"unocss": "^0.58.0",
"vite": "^5.0.10"
}
}
114 changes: 114 additions & 0 deletions apps/gnocchi/hub/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import React, { Suspense } from 'react';
import {
IngredientList,
IngredientListItem,
} from './components/IngredientList.jsx';
import { Instructions } from './components/Instructions.jsx';
import { MainImage } from './components/MainImage.jsx';
import { Prelude } from './components/Prelude.jsx';
import { TopLineRoot, TopLineTitle } from './components/layout.jsx';
import { Button } from '@a-type/ui/components/button';
import { Divider } from '@a-type/ui/components/divider';
import {
PageContent,
PageFixedArea,
PageRoot,
} from '@a-type/ui/components/layouts';
import { Note } from '@a-type/ui/components/note';
import { H1, H2, P } from '@a-type/ui/components/typography';
import { HubRecipeData } from './types.js';

export function App({
recipe: data,
url,
}: {
recipe: HubRecipeData;
url: string;
}) {
if (!data) {
return (
<PageRoot className="theme-lemon">
<PageContent>
<H1>Not found</H1>
</PageContent>
</PageRoot>
);
}

return (
<PageRoot className="theme-lemon">
<PageContent>
<article
itemScope
itemType="https://schema.org/Recipe"
className="h-recipe"
>
<TopLineRoot>
{data.mainImageUrl && (
<MainImage url={data.mainImageUrl} title={data.title} />
)}
<TopLineTitle>
<H1 itemProp="name" className="p-name">
{data.title}
</H1>
<P itemProp="author" className="p-author">
Published by {data.publisher?.fullName ?? 'Anonymous'}
</P>
</TopLineTitle>
</TopLineRoot>
{data.prelude && (
<div>
<Suspense>
<Prelude content={data.prelude} />
</Suspense>
</div>
)}
<Divider />
<div className="my-4">
<H2 className="gutter-bottom">Ingredients</H2>
<IngredientList>
{data.ingredients.map((ingredient: any) => (
<IngredientListItem key={ingredient.id}>
<div itemProp="recipeIngredient" className="p-ingredient">
{ingredient.text}
</div>
{ingredient.note && (
<Note className="ml-4">{ingredient.note}</Note>
)}
</IngredientListItem>
))}
</IngredientList>
</div>
<Divider />
<div className="mb-12 mt-4">
<H2 className="gutter-bottom">Instructions</H2>
<Suspense>
<Instructions instructions={data.instructions} />
</Suspense>
</div>
<PageFixedArea className="flex flex-row justify-end bottom-4 top-auto mb-4 bg-transparent">
<a
href={`${
import.meta.env.VITE_APP_GNOCCHI_ORIGIN
}?recipeUrl=${encodeURIComponent(url)}&hub=true&skipWelcome=true`}
>
<Button color="primary" className="shadow-lg">
Save Recipe
</Button>
</a>
</PageFixedArea>
<P className="color-gray7 ml-auto text-right text-sm">
Powered by{' '}
<a
className="font-bold color-black"
href="https://gnocchi.biscuits.club/welcome"
>
Gnocchi
</a>
, the freshest way to manage your weekly cooking
</P>
</article>
</PageContent>
</PageRoot>
);
}
17 changes: 17 additions & 0 deletions apps/gnocchi/hub/src/components/IngredientList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ReactNode } from 'react';

export interface IngredientListProps {
children?: ReactNode;
}

export function IngredientList({ children }: IngredientListProps) {
return <ul className="pl-4 m-0">{children}</ul>;
}

export function IngredientListItem({ children }: IngredientListProps) {
return (
<li>
<div className="flex flex-col items-start gap-2 mb-3">{children}</div>
</li>
);
}
Loading

0 comments on commit a26241b

Please sign in to comment.