Files
aitestbank/src/pages/reviews/[slug].astro

158 lines
3.8 KiB
Plaintext

---
import { getCollection, render } from "astro:content";
import Base from "../../layouts/Base.astro";
import Cover from "../../components/Cover.astro";
import RobotScore from "../../components/RobotScore.astro";
export async function getStaticPaths() {
const all = await getCollection("reviews");
return all.map((entry) => ({
params: { slug: entry.id },
props: { entry },
}));
}
const { entry } = Astro.props;
const { Content } = await render(entry);
const d = entry.data;
const dateFormatter = new Intl.DateTimeFormat("nl-NL", {
day: "numeric",
month: "long",
year: "numeric",
});
---
<Base title={d.title} description={d.verdict}>
<article class="review">
<p class="breadcrumb"><a href="/">← Alle reviews</a></p>
<Cover hue={d.coverHue} logo={d.logo} company={d.company} size="hero" />
<h1>{d.title}</h1>
<div class="review-meta">
{d.date && <span class="tabnum">{dateFormatter.format(d.date)}</span>}
{d.date && <span>·</span>}
<span>{d.category}</span>
<span>·</span>
<span>{d.location}</span>
<span>·</span>
<a href={d.website} target="_blank" rel="noopener">{d.company} →</a>
</div>
<div class="verdict">
<div>
<div class="label">Eindoordeel</div>
<p class="oneliner">{d.verdict}</p>
</div>
<div class="score-block">
<RobotScore score={d.score} size="lg" showNumber={false} />
<span class="score-num tabnum">{d.score} / 5</span>
</div>
</div>
<dl class="specs">
<div>
<dt>Voor wie</dt>
<dd>{d.for_who}</dd>
</div>
<div>
<dt>Vanaf</dt>
<dd class="tabnum">{d.price_from}</dd>
</div>
<div>
<dt>Hosting</dt>
<dd>{d.hosting}</dd>
</div>
</dl>
<div class="body">
<Content />
</div>
</article>
</Base>
<style>
.breadcrumb {
font-family: var(--mono);
font-size: 13px;
color: var(--muted);
margin: 30px 0 20px;
}
.breadcrumb a { color: var(--muted); }
article.review h1 {
font-size: 40px;
margin: 0 0 10px;
text-wrap: balance;
letter-spacing: -0.01em;
}
.review-meta {
font-family: var(--mono);
font-size: 13.5px;
color: var(--muted);
margin-bottom: 22px;
display: flex;
gap: 14px;
flex-wrap: wrap;
}
.verdict {
background: var(--paper-raised);
border: 1px solid var(--line);
border-radius: var(--radius);
padding: 22px 24px;
display: grid;
grid-template-columns: 1fr auto;
gap: 12px 24px;
align-items: center;
margin-bottom: 36px;
}
.verdict .label {
font-family: var(--mono);
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--muted);
margin-bottom: 6px;
}
.verdict .oneliner { margin: 0; font-size: 17px; max-width: 46ch; }
.verdict .score-block { text-align: right; }
.verdict .score-block .score-num {
font-family: var(--mono);
font-size: 16px;
color: var(--muted);
display: block;
margin: 6px 0 0;
}
.specs {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 18px;
margin: 0 0 36px;
padding: 18px 0;
border-top: 1px solid var(--line);
border-bottom: 1px solid var(--line);
}
.specs dt {
font-family: var(--mono);
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--muted);
margin: 0 0 4px;
}
.specs dd { margin: 0; font-size: 16px; }
.body { max-width: 64ch; }
.body :global(h2) { font-size: 22px; margin: 42px 0 12px; letter-spacing: -0.005em; }
.body :global(p) { margin: 0 0 17px; }
@media (max-width: 620px) {
.specs { grid-template-columns: 1fr 1fr; }
.verdict { grid-template-columns: 1fr; }
.verdict .score-block { text-align: left; }
}
</style>