summaryrefslogtreecommitdiff
path: root/src/components/templates
diff options
context:
space:
mode:
authorJoão Augusto Costa Branco Marado Torres <torres.dev@disroot.org>2025-06-28 18:14:22 -0300
committerJoão Augusto Costa Branco Marado Torres <torres.dev@disroot.org>2025-06-28 18:14:22 -0300
commit79fd506d30eef3d113f4a8e3ab9ebd9004f1e8cc (patch)
tree96ff57c92e897c3cc3331e23043d20f1665c7d0a /src/components/templates
parenta1eac976b20e39f86d5944fbec68e2a0f8ffb746 (diff)
feat: index page
Signed-off-by: João Augusto Costa Branco Marado Torres <torres.dev@disroot.org>
Diffstat (limited to 'src/components/templates')
-rw-r--r--src/components/templates/MicroBlog.astro114
-rw-r--r--src/components/templates/Search.astro67
-rw-r--r--src/components/templates/SimplePostList.astro81
3 files changed, 262 insertions, 0 deletions
diff --git a/src/components/templates/MicroBlog.astro b/src/components/templates/MicroBlog.astro
new file mode 100644
index 0000000..b7019c5
--- /dev/null
+++ b/src/components/templates/MicroBlog.astro
@@ -0,0 +1,114 @@
+---
+import Date from "@components/organisms/Date.astro";
+import KeywordsList from "@components/organisms/KeywordsList.astro";
+import { getFirstUserID, getLastUpdate } from "@lib/collection/helpers";
+import { Micro } from "@lib/collection/schemas";
+import type { CollectionEntry, z } from "astro:content";
+
+interface Props extends CollectionEntry<"blog"> {
+ data: z.infer<typeof Micro>;
+}
+
+const micro = Astro.props;
+const { id, data, rendered } = micro;
+const { title, lang, keywords } = data;
+const date = getLastUpdate(micro);
+const user = await getFirstUserID(micro);
+const display = user?.name ?? user?.email ?? user?.entity ?? "";
+const [first, ...names] = display.split(/\s/);
+const last = names.length > 0 ? names[names.length - 1] : "";
+const little = ((first?.[0] ?? "") + (last?.[0] ?? "")).slice(0, 2);
+---
+<article>
+ <header>
+ <h3 class="title">
+ <a href={`/blog/read/${id}`}>{title}</a>
+ </h3>
+ <span class="profile_picture">{
+ user?.website ? <a href={user.website}>{little}</a> : (
+ <span>{little}</span>
+ )
+ }</span>
+ <div>
+ {first} {last} <small>· <Date
+ {date}
+ locales={lang}
+ options={{ month: "short", day: "numeric" }}
+ /></small>
+ </div>
+ </header>
+ <div class="content">
+ <small {lang}>
+ <Fragment set:html={rendered?.html} />
+ </small>
+ <footer>
+ <div class="keywords small"><KeywordsList {keywords} /></div>
+ </footer>
+ </div>
+ <aside>
+ <small><a href="/blog/micro/1">Ver todos os microposts</a></small>
+ </aside>
+</article>
+
+<style is:inline>
+ .content > [lang] > *:first-child {
+ margin-block-start: 0;
+ }
+ .content > [lang] > *:last-child {
+ margin-block-end: 0;
+ }
+</style>
+<style>
+ article {
+ border-radius: calc(var(--size-1) * 1em);
+ box-shadow: 0 0 calc(var(--size-1) * 1em) var(--color-light);
+ padding: calc(var(--size-4) * 1em);
+ display: grid;
+ grid-template-rows: repeat(3, auto);
+ grid-template-columns: calc(var(--size-9) * 1em) auto;
+ gap: calc(var(--size-1) * 1em);
+
+ & > header {
+ display: contents;
+ }
+
+ & > aside {
+ grid-row: 3 / 4;
+ grid-column: 1 / 3;
+ border-block-start: 1px solid #e7e7e7;
+ padding-block-start: calc(var(--size-1) * 1em);
+ }
+ }
+
+ .profile_picture {
+ grid-row: 1 / 3;
+ grid-column: 1 / 2;
+
+ & > * {
+ display: inline-grid;
+ place-content: center;
+ width: calc(var(--size-9) * 1em);
+ height: calc(var(--size-9) * 1em);
+ aspect-ratio: 1 / 1;
+ background-color: var(--color-active);
+ color: #fff;
+ font-weight: 950;
+ font-size: smaller;
+ border-radius: calc(infinity * 1px);
+ text-align: center;
+ text-transform: uppercase;
+ }
+ }
+
+ .title {
+ display: none;
+ }
+ .content {
+ grid-row: 2/3;
+ grid-column: 2 / 3;
+ }
+
+ .keywords {
+ margin-block-end: 0;
+ }
+</style>
diff --git a/src/components/templates/Search.astro b/src/components/templates/Search.astro
new file mode 100644
index 0000000..5245643
--- /dev/null
+++ b/src/components/templates/Search.astro
@@ -0,0 +1,67 @@
+---
+const { site } = Astro;
+---
+
+<search>
+ <link rel="dns-prefetch" href="https://www.google.com/search">
+ <form
+ action="https://www.google.com/search"
+ target="_blank"
+ rel="external noreferrer search"
+ role="search"
+ autocomplete="on"
+ name="search"
+ >
+ <details>
+ <summary>Pesquisar no website</summary>
+ <div class="details">
+ <p>
+ <label>Barra de pesquisa <input
+ name="q"
+ type="search"
+ placeholder={`site:${site} consulta de pesquisa`}
+ value={`site:${site} `}
+ required
+ title={`"site:${site} " é usado para que os resultados da pesquisa fiquem restritos a este website`}
+ pattern={`site:${site} .+`}
+ size={`site:${site} .+`.length}
+ /></label>
+ </p>
+ <p class="mute">
+ <small>Esta pesquisa é efectuada pelo Google e <strong>utiliza
+ software proprietário.</strong></small>
+ </p>
+ <p><button type="submit">🔍 Pesquisar</button></p>
+ </div>
+ </details>
+ </form>
+</search>
+
+<style>
+ search {
+ padding-block-end: calc(var(--size-4) * 1em);
+ }
+
+ summary {
+ font-size: calc(var(--size-3) * 1rem);
+ font-weight: bolder;
+ }
+
+ .details {
+ border-radius: calc(var(--size-1) * 1em);
+ border: 1px solid var(--color-light);
+ margin-block-start: calc(var(--size-1) * 1em);
+ font-size: calc(var(--size-3) * 1rem);
+ padding-inline: calc(var(--size-4) * 1em);
+ padding-block: calc(var(--size-2) * 1em);
+
+ & > p {
+ margin-block: calc(var(--size-2) * 1em);
+ line-height: calc(var(--size-8) * 1rem);
+ }
+
+ & input[type="search"] {
+ width: 100%;
+ }
+ }
+</style>
diff --git a/src/components/templates/SimplePostList.astro b/src/components/templates/SimplePostList.astro
new file mode 100644
index 0000000..0ec33e3
--- /dev/null
+++ b/src/components/templates/SimplePostList.astro
@@ -0,0 +1,81 @@
+---
+import Date from "@components/organisms/Date.astro";
+import KeywordsList from "@components/organisms/KeywordsList.astro";
+import { getFirstUserID, getLastUpdate } from "@lib/collection/helpers";
+import type { Original } from "@lib/collection/schemas";
+import type { z } from "astro:content";
+import type { CollectionEntry } from "astro:content";
+
+interface Props {
+ posts: (CollectionEntry<"blog"> & { data: z.infer<typeof Original> })[];
+}
+
+const { posts } = Astro.props;
+---
+<ol>
+ {
+ await Promise.all(posts.map(async (post) => {
+ const { id, data } = post;
+ const { title, description, lang, keywords } = data;
+ const { name, email, entity } = await getFirstUserID(post);
+ const display = name ?? email ?? entity;
+ return (
+ <li>
+ <article>
+ <h3><a href={`/blog/read/${id}`}>{title}</a></h3>
+ {
+ description &&
+ description.split("\n\n").map((paragraph) => (
+ <p class="small">{paragraph}</p>
+ ))
+ }
+
+ <footer class="small">
+ <Date
+ date={getLastUpdate(post)}
+ locales={lang}
+ options={{
+ year: "numeric",
+ month: "long",
+ day: "numeric",
+ }}
+ />{display}
+ <KeywordsList {keywords} />
+ </footer>
+ </article>
+ </li>
+ );
+ }))
+ }
+</ol>
+
+<style>
+ ol {
+ margin-inline-start: calc(var(--size-7) * 1em);
+ margin-block: calc(var(--size-7) * 1em);
+ & > li {
+ margin-block-start: calc(var(--size-2) * 1em);
+ & > article {
+ padding-inline-end: calc(var(--size-9) * 1em);
+
+ & > p:not(:first-of-type) {
+ margin-block-start: 1.5em;
+ }
+
+ & > footer {
+ display: flex;
+ flex-direction: column;
+ gap: calc(var(--size-1) * 1em);
+ }
+ }
+ }
+ }
+
+ @media (width >= 40rem) {
+ ol > li > article > footer {
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+ }
+ }
+</style>