forked from Shopify/hydrogen-v1
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request Shopify#48 from Shopify/fd-journal
Add journal pages
- Loading branch information
Showing
5 changed files
with
340 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import { | ||
json, | ||
type MetaFunction, | ||
type SerializeFrom, | ||
type LoaderArgs, | ||
type LinksFunction, | ||
} from "@remix-run/cloudflare"; | ||
import { useLoaderData } from "@remix-run/react"; | ||
import { Image } from "@shopify/hydrogen-ui-alpha"; | ||
import invariant from "tiny-invariant"; | ||
import { Button, PageHeader, Section, Text } from "~/components"; | ||
import { getArticle } from "~/data"; | ||
import { ATTR_LOADING_EAGER } from "~/lib/const"; | ||
import styles from "../../styles/custom-font.css"; | ||
|
||
const BLOG_HANDLE = "journal"; | ||
|
||
export async function loader({ request, params }: LoaderArgs) { | ||
// TODO figure out localization | ||
const languageCode = "EN"; | ||
const countryCode = "US"; | ||
|
||
invariant(params.journalHandle, "Missing journal handle"); | ||
|
||
const article = await getArticle({ | ||
blogHandle: BLOG_HANDLE, | ||
articleHandle: params.journalHandle, | ||
language: languageCode, | ||
}); | ||
|
||
if (!article) { | ||
throw new Response("Not found", { status: 404 }); | ||
} | ||
|
||
const formattedDate = new Intl.DateTimeFormat( | ||
`${languageCode}-${countryCode}`, | ||
{ | ||
year: "numeric", | ||
month: "long", | ||
day: "numeric", | ||
} | ||
).format(new Date(article.publishedAt)); | ||
|
||
return json( | ||
{ article, formattedDate }, | ||
{ | ||
headers: { | ||
// TODO cacheLong() | ||
}, | ||
} | ||
); | ||
} | ||
|
||
export const meta: MetaFunction = ({ | ||
data, | ||
}: { | ||
data: SerializeFrom<typeof loader> | undefined; | ||
}) => { | ||
return { | ||
title: data?.article?.seo?.title ?? "Article", | ||
description: data?.article?.seo?.description, | ||
}; | ||
}; | ||
|
||
export const links: LinksFunction = () => { | ||
return [{ rel: "stylesheet", href: styles }]; | ||
}; | ||
|
||
export default function Article() { | ||
const { article, formattedDate } = useLoaderData<typeof loader>(); | ||
|
||
const { title, image, contentHtml, author } = article; | ||
|
||
return ( | ||
<> | ||
<PageHeader heading={title} variant="blogPost"> | ||
<span> | ||
{formattedDate} · {author.name} | ||
</span> | ||
</PageHeader> | ||
<Section as="article" padding="x"> | ||
{image && ( | ||
<Image | ||
data={image} | ||
className="w-full mx-auto mt-8 md:mt-16 max-w-7xl" | ||
sizes="90vw" | ||
widths={[400, 800, 1200]} | ||
width="100px" | ||
loading={ATTR_LOADING_EAGER} | ||
loaderOptions={{ | ||
scale: 2, | ||
crop: "center", | ||
}} | ||
/> | ||
)} | ||
<div | ||
dangerouslySetInnerHTML={{ __html: contentHtml }} | ||
className="article" | ||
/> | ||
</Section> | ||
</> | ||
); | ||
} | ||
|
||
export function CatchBoundary() { | ||
const type = "article"; | ||
const heading = `We’ve lost this ${type}`; | ||
const description = `We couldn’t find the ${type} you’re looking for. Try checking the URL or heading back to the home page.`; | ||
|
||
return ( | ||
<> | ||
<PageHeader heading={heading}> | ||
<Text width="narrow" as="p"> | ||
{description} | ||
</Text> | ||
<Button width="auto" variant="secondary" to={"/"}> | ||
Take me to the home page | ||
</Button> | ||
</PageHeader> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import { json, type MetaFunction } from "@remix-run/cloudflare"; | ||
import { Link, useLoaderData } from "@remix-run/react"; | ||
import { flattenConnection, Image } from "@shopify/hydrogen-ui-alpha"; | ||
import type { Article } from "@shopify/hydrogen-ui-alpha/storefront-api-types"; | ||
import { Grid, PageHeader, Section } from "~/components"; | ||
import { getBlog } from "~/data"; | ||
import { getImageLoadingPriority, PAGINATION_SIZE } from "~/lib/const"; | ||
|
||
const BLOG_HANDLE = "Journal"; | ||
|
||
export const loader = async () => { | ||
// TODO figure out localization | ||
const languageCode = "EN"; | ||
const countryCode = "US"; | ||
|
||
const journals = await getBlog({ | ||
language: languageCode, | ||
blogHandle: BLOG_HANDLE, | ||
paginationSize: PAGINATION_SIZE, | ||
}); | ||
|
||
const articles = flattenConnection(journals).map((article) => { | ||
const { publishedAt } = article; | ||
return { | ||
...article, | ||
publishedAt: new Intl.DateTimeFormat(`${languageCode}-${countryCode}`, { | ||
year: "numeric", | ||
month: "long", | ||
day: "numeric", | ||
}).format(new Date(publishedAt!)), | ||
}; | ||
}); | ||
|
||
return json( | ||
{ articles }, | ||
{ | ||
headers: { | ||
// TODO cacheLong() | ||
}, | ||
} | ||
); | ||
}; | ||
|
||
export const meta: MetaFunction = () => { | ||
return { | ||
title: "All Journals", | ||
}; | ||
}; | ||
|
||
export default function Journals() { | ||
const { articles } = useLoaderData<typeof loader>(); | ||
|
||
return ( | ||
<> | ||
<PageHeader heading={BLOG_HANDLE} /> | ||
<Section> | ||
<Grid as="ol" layout="blog" gap="blog"> | ||
{articles.map((article, i) => ( | ||
<ArticleCard | ||
blogHandle={BLOG_HANDLE.toLowerCase()} | ||
article={article as Article} | ||
key={article.id} | ||
loading={getImageLoadingPriority(i, 2)} | ||
/> | ||
))} | ||
</Grid> | ||
</Section> | ||
</> | ||
); | ||
} | ||
|
||
function ArticleCard({ | ||
blogHandle, | ||
article, | ||
loading, | ||
}: { | ||
blogHandle: string; | ||
article: Article; | ||
loading?: HTMLImageElement["loading"]; | ||
}) { | ||
return ( | ||
<li key={article.id}> | ||
<Link to={`/${blogHandle}/${article.handle}`}> | ||
{article.image && ( | ||
<div className="card-image aspect-[3/2]"> | ||
<Image | ||
alt={article.image.altText || article.title} | ||
className="object-cover w-full" | ||
data={article.image} | ||
height={400} | ||
loading={loading} | ||
sizes="(min-width: 768px) 50vw, 100vw" | ||
width={600} | ||
loaderOptions={{ | ||
scale: 2, | ||
crop: "center", | ||
}} | ||
/> | ||
</div> | ||
)} | ||
<h2 className="mt-4 font-medium">{article.title}</h2> | ||
<span className="block mt-1">{article.publishedAt}</span> | ||
</Link> | ||
</li> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
@font-face { | ||
font-family: 'IBMPlexSerif'; | ||
font-display: swap; | ||
font-weight: 400; | ||
src: url('/fonts/IBMPlexSerif-Text.woff2') format('woff2'); | ||
} | ||
@font-face { | ||
font-family: 'IBMPlexSerif'; | ||
font-display: swap; | ||
font-weight: 400; | ||
font-style: italic; | ||
src: url('/fonts/IBMPlexSerif-TextItalic.woff2') format('woff2'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters