Files
atridotdad/src/pages/posts.astro
Atridad Lahiji 203f83bfcb
All checks were successful
Docker Deploy / build-and-push (push) Successful in 5m47s
Updated UX to remove the weird looking cards. No more cards!
2025-12-15 10:28:48 -07:00

133 lines
5.9 KiB
Plaintext

---
import Layout from "../layouts/Layout.astro";
import { getCollection, type CollectionEntry } from "astro:content";
import { Icon } from "astro-icon/components";
// Get all posts from the content collection
const posts = await getCollection("posts");
// Sort posts by date, newest first
const sortedPosts = posts.sort(
(a: CollectionEntry<"posts">, b: CollectionEntry<"posts">) =>
new Date(b.data.pubDate).valueOf() - new Date(a.data.pubDate).valueOf(),
);
function formatDate(date: Date): string {
return date.toLocaleDateString("en-us", {
month: "short",
day: "numeric",
year: "numeric",
});
}
---
<Layout>
<div class="w-full p-4 sm:p-8">
<h1
class="text-3xl sm:text-4xl font-bold text-primary mb-6 sm:mb-8 text-center"
>
Posts
</h1>
{/* Mobile: One-sided compact timeline */}
<ul class="timeline timeline-vertical timeline-compact timeline-snap-icon max-w-3xl mx-auto px-4 md:hidden">
{
sortedPosts.map((post, index) => (
<li>
{index > 0 && <hr class="bg-primary" />}
<div class="timeline-middle">
<Icon name="mdi:circle" class="w-4 h-4 text-primary" />
</div>
<div class="timeline-end mb-8 ml-4">
<div class="border border-base-content/20 rounded-box p-4 bg-base-200 hover:border-primary transition-colors">
<time class="font-mono text-sm opacity-60">
{formatDate(new Date(post.data.pubDate))}
</time>
<a
href={`/post/${post.slug}`}
class="block group"
>
<h3 class="text-lg font-bold text-primary group-hover:text-accent transition-colors">
{post.data.title}
</h3>
<p class="text-sm opacity-80 mt-1">
{post.data.description || "No description available."}
</p>
</a>
{post.data.tags && post.data.tags.length > 0 && (
<div class="flex gap-1 flex-wrap mt-2">
{post.data.tags.slice(0, 3).map((tag: string) => (
<span class="badge badge-sm badge-outline">{tag}</span>
))}
</div>
)}
</div>
</div>
{index < sortedPosts.length - 1 && <hr class="bg-primary" />}
</li>
))
}
</ul>
{/* Desktop: Dual-sided alternating timeline */}
<ul class="timeline timeline-vertical timeline-snap-icon max-w-3xl mx-auto px-4 hidden md:block">
{
sortedPosts.map((post, index) => (
<li>
{index > 0 && <hr class="bg-primary" />}
<div class="timeline-middle">
<Icon name="mdi:circle" class="w-4 h-4 text-primary" />
</div>
<div class={`timeline-${index % 2 === 0 ? 'start' : 'end'} text-${index % 2 === 0 ? 'end' : 'start'} mb-8 mx-4`}>
<div class="border border-base-content/20 rounded-box p-4 bg-base-200 hover:border-primary transition-colors">
<time class="font-mono text-sm opacity-60">
{formatDate(new Date(post.data.pubDate))}
</time>
<a
href={`/post/${post.slug}`}
class="block group"
>
<h3 class="text-lg font-bold text-primary group-hover:text-accent transition-colors">
{post.data.title}
</h3>
<p class="text-sm opacity-80 mt-1">
{post.data.description || "No description available."}
</p>
</a>
{post.data.tags && post.data.tags.length > 0 && (
<div class={`flex gap-1 flex-wrap mt-2 ${index % 2 === 0 ? 'justify-end' : 'justify-start'}`}>
{post.data.tags.slice(0, 3).map((tag: string) => (
<span class="badge badge-sm badge-outline">{tag}</span>
))}
</div>
)}
</div>
</div>
{index < sortedPosts.length - 1 && <hr class="bg-primary" />}
</li>
))
}
</ul>
{
sortedPosts.length === 0 && (
<p class="text-center text-gray-500 mt-12">
No posts available yet. Check back soon!
</p>
)
}
</div>
</Layout>