feat: layout tweaks; add books

This commit is contained in:
Aaron Yarborough 2025-03-29 11:40:16 +00:00
parent 6fc63fd50c
commit 09bd28f64b
18 changed files with 132 additions and 21 deletions

10
content/books/1984.md Normal file
View file

@ -0,0 +1,10 @@
---
title: '1984'
author: George Orwell
stars: 3
readDate: 2023-07-31T23:00:00.000Z
url: 'https://app.thestorygraph.com/books/6ff3f487-8d37-4ac5-8190-6622d6562639'
thumbnailUrl: 'https://cdn.thestorygraph.com/v43bj24inkwioiogb5uz8nqmpnpw'
tags: 'fiction, dystopian, classics'
---

View file

@ -0,0 +1,10 @@
---
title: A Monster Calls
author: Patrick Ness
stars: 4
readDate: 2024-05-31T23:00:00.000Z
url: 'https://app.thestorygraph.com/books/170c1204-1410-4246-babb-c80e31aebea9'
thumbnailUrl: 'https://cdn.thestorygraph.com/50qkuazqx2lidfd0hk74ltifz9nf'
tags: 'fiction, young adult'
---

View file

@ -0,0 +1,10 @@
---
title: Diary of An Oxygen Thief
author: Anonymous
stars: 4
readDate: 2024-03-01T00:00:00.000Z
url: 'https://app.thestorygraph.com/books/9ce581f2-d9ac-4be1-abf7-4597684bab7f'
thumbnailUrl: 'https://cdn.thestorygraph.com/l5zkpt8v2wj76ri6nkq7ismqsskl'
tags: 'romance, fiction'
---

View file

@ -0,0 +1,10 @@
---
title: No God But God
author: Reza Aslan
stars: 4
readDate: 2023-01-01T00:00:00.000Z
url: 'https://app.thestorygraph.com/books/27cb3f11-77c6-4eca-9344-d64885e6f1c4'
thumbnailUrl: 'https://cdn.thestorygraph.com/gf3c92roqrgdbdsgphns5n111t93'
tags: 'non-fiction, religion, history'
---

View file

@ -0,0 +1,10 @@
---
title: The Nature of Alexander
author: Mary Renault
stars: 4.5
readDate: 2023-03-31T23:00:00.000Z
url: 'https://app.thestorygraph.com/books/bc111e8b-1b3f-466a-9efd-c3316ae4b533'
thumbnailUrl: 'https://cdn.thestorygraph.com/68zjkhp67u2bi6qh3melbyqaly06'
tags: 'non-fiction, history, biography'
---

View file

@ -1,12 +1,17 @@
import { formatDate } from '@/lib/helpers'
import { NextSeo } from 'next-seo'
import Image from 'next/image'
import Link from 'next/link'
import React from 'react'
import style from "./Book.module.css";
import ExternalLink from '../ExternalLink/ExternalLink'
function Book({ attributes, html }) {
return (
<>
<h1>{attributes.title}<br /><small>by {attributes.author}</small></h1>
<Link href='./'>Back...</Link>
<article>
<NextSeo
title={attributes.title} description={attributes.desc} openGraph={
@ -20,10 +25,19 @@ function Book ({ attributes, html }) {
}
}
/>
<div>
<div className={style.layout}>
<Image src={attributes.thumbnailUrl} width={250} height={580} alt='' className={style.thumbnail} />
<div>
<Link href='./'>Back...</Link>
{attributes.pubdate && <p>{formatDate(attributes.pubdate)}</p>}
<div data-test='content' dangerouslySetInnerHTML={{ __html: html || '<p>(no review)</p>' }} />
<p>
<span className='bold'>Rating:</span>&nbsp;{attributes.stars}/5<br />
<span className='bold'>Read on:</span>&nbsp;{formatDate(attributes.readDate)}
</p>
<p><ExternalLink href={attributes.url}>View on The StoryGraph</ExternalLink></p>
</div>
</div>
</div>
</article>
</>

View file

@ -0,0 +1,34 @@
.layout {
display: flex;
flex-direction: row;
gap: 1.25rem;
margin: 1.25rem 0;
}
.layout:first-child {
flex-grow: 0;
flex-shrink: 0;
}
.layout:last-child {
flex-grow: 1;
}
.layout p:first-child {
margin-top: 0;
}
.thumbnail {
border-radius: 8px;
}
@media screen and (max-width: 650px) {
.layout {
flex-direction: column-reverse;
}
.thumbnail {
width: 100%;
}
}

View file

@ -17,7 +17,7 @@ export default function BookListItem ({ href, title, author, stars, readDate, ur
</h2>
<p className={style.author}>{author}</p>
<p>{tags}</p>
<p>{stars}/5</p>
{/* <p>{stars}/5</p> */}
</div>
</div>
)

View file

@ -18,7 +18,7 @@
.thumb {
width: auto;
height: 200px;
height: 290px;
background-position: center;
background-repeat: no-repeat;
background-size: cover;

View file

@ -3,9 +3,7 @@ import style from './Grid.module.css'
export default function Grid ({ columns, children }) {
return (
<div
className={style.grid} style={{
gridTemplateColumns: `repeat(${columns}, 1fr)`
}}
className={style.grid}
>
{children}
</div>

View file

@ -1,4 +1,5 @@
.grid {
display: grid;
gap: 25px;
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
gap: 1rem;
}

View file

@ -1,7 +1,7 @@
import { formatDate } from '@/lib/helpers'
import Link from 'next/link'
export default function StaticContentList ({ entries, urlPrefix }) {
export default function StaticContentList ({ entries, urlPrefix, max = 0 }) {
return (
<table>
<tbody>
@ -12,7 +12,7 @@ export default function StaticContentList ({ entries, urlPrefix }) {
<Link href={`${urlPrefix}${e.slug}`}>{e.attributes.title}</Link>
</td>
</tr>
))}
)).slice(0, max > 0 ? max : entries.length)}
</tbody>
</table>
)

View file

@ -66,8 +66,7 @@ export function getContentTags (contentPath) {
for (const entry of entries) {
if (!entry.attributes.tags) { continue }
const tags = entry.attributes.tags.split(', ')
const tags = entry.attributes.tags;
for (const tag of tags) {
allTags[tag] = !allTags[tag] ? 1 : allTags[tag] + 1
}

View file

@ -7,3 +7,13 @@ export function toSlug (input) {
export function formatDate (date) {
return dateFns.format(Date.parse(date), 'PPP')
}
/**
* Silliness to make sure dates don't get passed to the
* page function below as [object Object]
* @param {*} obj
* @returns
*/
export function stringifyAndParse(obj) {
return JSON.parse(JSON.stringify(obj));
}

View file

@ -33,7 +33,7 @@ export default function Home ({ postEntries }) {
<section>
<h2>Recent posts</h2>
<StaticContentList entries={postEntries} urlPrefix='writing/' />
<StaticContentList entries={postEntries} urlPrefix='writing/' max={5}/>
</section>
</DefaultLayout>

View file

@ -2,9 +2,11 @@ import React from 'react'
import DefaultLayout from '@/layouts/DefaultLayout/DefaultLayout'
import { getStaticEntryPaths, getStaticEntryProps } from '@/lib/content'
import Book from '@/components/Book/Book'
import { stringifyAndParse } from '@/lib/helpers'
export const getStaticPaths = () => getStaticEntryPaths('./content/books')
export const getStaticProps = (ctx) => getStaticEntryProps('./content/books', ctx)
export const getStaticProps = (ctx) =>
stringifyAndParse(getStaticEntryProps('./content/books', ctx));
export default function LibrarySingle ({ attributes, html }) {
return (

View file

@ -2,6 +2,7 @@ import BookListItem from '@/components/BookListItem/BookListItem'
import Grid from '@/components/Grid/Grid'
import DefaultLayout from '@/layouts/DefaultLayout/DefaultLayout'
import { getStaticEntries } from '@/lib/content'
import { stringifyAndParse } from '@/lib/helpers'
import { NextSeo } from 'next-seo'
export const Title = 'Library'
@ -14,11 +15,9 @@ export const getStaticProps = () => {
return {
props: {
// Silliness to make sure dates don't get passed to the
// page function below as [object Object]
bookEntries: JSON.parse(JSON.stringify(bookEntries))
}
bookEntries: stringifyAndParse(bookEntries)
}
};
}
export default function Library ({ bookEntries }) {

View file

@ -18,3 +18,7 @@ td:first-child {
.form-group {
margin: 20px 0;
}
.bold {
font-weight: 700;
}