astro/src/components/Entries.astro

114 lines
2.8 KiB
Plaintext

---
import { desc } from "drizzle-orm";
import { db } from "db";
import { guestbookTable } from "db/schema";
import formatDate from "@/utils/formatDate";
import pikachu from "$/images/portrait-0025.png";
const entries = await db.select().from(guestbookTable).orderBy(desc(guestbookTable.published));
---
<section id="entries">
{entries.map(entry => (
<>
<article id={`${entry.username}-${entry.id}`}>
<img src="https://placehold.co/100" width="100" alt="avart" />
<div class="entry">
<header>
<h1>{entry.website
? <a href={entry.website} target="_blank" referrerpolicy="no-referrer">{entry.username}</a>
: <span>{entry.username}</span>}
</h1>
<time datetime={entry.published}>
{formatDate(entry.published, false, 'MMMM D, YYYY')}
</time>
</header>
<div class="content">
<Fragment set:html={entry.message} />
</div>
</div>
</article>
{entry.reply && <article class="reply" id={`reply-${entry.username}-${entry.id}`}>
<img src={pikachu.src} width="80" height="80" alt="a portrait of pikachu" />
<div class="entry">
<header>
<h1>Reply to {entry.username}</h1>
<time datetime={entry.updated}>
{formatDate(entry.updated!, false, 'MMMM D, YYYY')}
</time>
</header>
<div class="content">
<Fragment set:html={entry.reply} />
</div>
</div>
</article>}
</>
))}
{entries.length === 0 && (
<article>
<h1>Huh...</h1>
<p>There's nothing here! Want to be the first to comment?</p>
</article>
)}
</section>
<style>
#entries {
margin: 2rem 0 3rem;
display: flex;
flex-direction: column;
gap: 2rem;
}
article {
image-rendering: pixelated;
display: flex;
align-items: start;
gap: 1rem;
max-width: 50ch;
font-family: var(--sans-font);
font-size: calc(1rem * 2);
letter-spacing: 1px;
color: var(--speech-fg-color);
}
.entry {
flex-grow: 1;
background-color: var(--speech-bg-color);
border-image: var(--border) 7 / 14px / 7px repeat;
padding: 1.5rem;
h1 { font-size: 2rem; }
time { line-height: 0.75; }
header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1rem;
}
&.error {
max-width: max-content;
padding: 1rem;
margin: 0 auto;
text-align: center;
}
.content { line-height: 1; }
@media screen and (width < 1000px) {
max-width: 100%;
padding: 1rem 1.5rem;
}
}
.reply {
flex-direction: row-reverse;
align-self: end;
min-width: min(100%, 45ch);
}
</style>