114 lines
2.8 KiB
Plaintext
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> |