mirror of
https://github.com/Patiun/com.gregkilmer.www.git
synced 2026-11-08 04:08:24 +00:00
Phase 5: every page of the site, the resume PDF and RSS
Landing, About, Now, Resume (with a generated PDF), Work and case studies, Inquiries and the sent page, Library and the Shelf, Workshop and craft pages, Tabletop, Blog with topics and posts, RSS, the Store, product lines, the order form and the 404, all rendered from the content service's notes. Schema: experience previousRoles, skills stack core items, page stats, make tags and deck favorite. Icon names from notes map to brand icons in one place, and HTML comments are dropped when Markdown renders. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012aSbo2D1qP8cMFQCykf7kx
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
---
|
||||
/**
|
||||
* One board game on The Shelf: box art (or star-chart art), how it plays,
|
||||
* title, blurb, its states and a link to BoardGameGeek. The card is the
|
||||
* game's anchor (`#slug`); the data-* attributes feed the filter and sort
|
||||
* script.
|
||||
*/
|
||||
import Card from "@gk/ui/components/Card.astro";
|
||||
import Star from "@gk/ui/components/Star.astro";
|
||||
import StarChartArt from "@gk/ui/components/StarChartArt.astro";
|
||||
import StatusPill from "@gk/ui/components/StatusPill.astro";
|
||||
import StatusChip from "../StatusChip.astro";
|
||||
import { formatDate, mediaSrc, type SiteIndex } from "../../lib/site.ts";
|
||||
import type { Game } from "../../lib/library.ts";
|
||||
|
||||
interface Props {
|
||||
game: Game;
|
||||
site: SiteIndex;
|
||||
hidden?: boolean;
|
||||
}
|
||||
const { game, site, hidden } = Astro.props;
|
||||
const d = game.data;
|
||||
const plays = d.howItPlays ?? [];
|
||||
const status = site.statusFor(game);
|
||||
---
|
||||
<li
|
||||
id={game.slug}
|
||||
class="game"
|
||||
data-p={plays.map((p) => p.toLowerCase()).join("|") || undefined}
|
||||
data-o={d.owned ? "1" : undefined}
|
||||
data-w={d.wantToPlay ? "1" : undefined}
|
||||
data-f={d.favorite ? "1" : undefined}
|
||||
data-lp={d.lastPlayed}
|
||||
data-c={d.created}
|
||||
hidden={hidden}
|
||||
>
|
||||
<Card as="div" class="game-card">
|
||||
<StarChartArt class="box" ratio="1 / 1" seal="tria-prima" src={mediaSrc(d.cover)} alt="" />
|
||||
<div class="body">
|
||||
{plays.length > 0 && <span class="plays">{plays.join(" · ")}</span>}
|
||||
<h3 class="t">
|
||||
{game.title}
|
||||
{d.favorite && <><Star size={12} /><span class="gk-visually-hidden">Favorite</span></>}
|
||||
</h3>
|
||||
<p class="blurb">{d.blurb}</p>
|
||||
{
|
||||
(status || d.wantToPlay || !d.owned || d.lastPlayed) && (
|
||||
<div class="states">
|
||||
{status && <StatusChip status={status} site={site} />}
|
||||
{d.wantToPlay && <StatusPill kind="state">Want to play</StatusPill>}
|
||||
{!d.owned && <StatusPill kind="neutral">Not owned</StatusPill>}
|
||||
{d.lastPlayed && <span class="played">Last played {formatDate(d.lastPlayed)}</span>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<a class="gk-text gk-quiet bgg" href={`https://boardgamegeek.com/boardgame/${d.bggId}`} rel="external noopener">
|
||||
BoardGameGeek<span class="gk-visually-hidden">: {game.title}</span>
|
||||
</a>
|
||||
</div>
|
||||
</Card>
|
||||
</li>
|
||||
|
||||
<style>
|
||||
.game {
|
||||
display: flex;
|
||||
scroll-margin-top: 24px;
|
||||
}
|
||||
.game[hidden] {
|
||||
display: none;
|
||||
}
|
||||
.game :global(.game-card) {
|
||||
flex: 1;
|
||||
padding: 0;
|
||||
gap: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.game:target :global(.game-card) {
|
||||
border-color: var(--gk-gold);
|
||||
}
|
||||
.game :global(.box) {
|
||||
border-radius: 0;
|
||||
border-bottom: 1px solid var(--gk-lines);
|
||||
}
|
||||
.body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
padding: 14px;
|
||||
}
|
||||
.plays {
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.16em;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
color: var(--gk-muted);
|
||||
}
|
||||
.t {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 15px;
|
||||
line-height: 1.3;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
.blurb {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
line-height: 1.45;
|
||||
color: var(--gk-muted);
|
||||
}
|
||||
.states {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.played {
|
||||
font-size: 12px;
|
||||
color: var(--gk-muted);
|
||||
}
|
||||
.bgg {
|
||||
align-self: flex-start;
|
||||
margin-top: auto;
|
||||
padding-top: 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user