aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/BlogCard.astro
diff options
context:
space:
mode:
authoraman333nolawz <amananudhiu@gmail.com>2026-03-02 21:49:13 +0530
committeraman333nolawz <amananudhiu@gmail.com>2026-03-02 21:49:13 +0530
commitd41eff9eccf66644c4c60f53cb516bf079937a28 (patch)
tree248a0863a3181369f943d678ec4273911d35efac /src/components/BlogCard.astro
Using astro-erudite for static site generation
Diffstat (limited to 'src/components/BlogCard.astro')
-rw-r--r--src/components/BlogCard.astro105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/components/BlogCard.astro b/src/components/BlogCard.astro
new file mode 100644
index 0000000..1a74025
--- /dev/null
+++ b/src/components/BlogCard.astro
@@ -0,0 +1,105 @@
+---
+import AvatarComponent from '@/components/ui/avatar'
+import { Badge } from '@/components/ui/badge'
+import { Separator } from '@/components/ui/separator'
+import {
+ getCombinedReadingTime,
+ getSubpostCount,
+ isSubpost,
+ parseAuthors,
+} from '@/lib/data-utils'
+import { formatDate } from '@/lib/utils'
+import { Icon } from 'astro-icon/components'
+import { Image } from 'astro:assets'
+import type { CollectionEntry } from 'astro:content'
+import Link from './Link.astro'
+
+interface Props {
+ entry: CollectionEntry<'blog'>
+}
+
+const { entry } = Astro.props
+const formattedDate = formatDate(entry.data.date)
+const readTime = await getCombinedReadingTime(entry.id)
+const authors = await parseAuthors(entry.data.authors ?? [])
+const subpostCount = !isSubpost(entry.id) ? await getSubpostCount(entry.id) : 0
+---
+
+<div
+ class="hover:bg-muted/50 rounded-xl border p-4 transition-colors duration-300 ease-in-out"
+>
+ <Link
+ href={`/${entry.collection}/${entry.id}`}
+ class="flex flex-col gap-4 sm:flex-row"
+ >
+ {
+ entry.data.image && (
+ <div class="w-full sm:max-w-3xs sm:shrink-0">
+ <Image
+ src={entry.data.image}
+ alt={entry.data.title}
+ width={1200}
+ height={630}
+ class="object-cover"
+ />
+ </div>
+ )
+ }
+
+ <div class="grow">
+ <h3 class="mb-1 text-lg font-medium">{entry.data.title}</h3>
+ <p class="text-muted-foreground mb-2 text-sm">{entry.data.description}</p>
+
+ <div
+ class="text-muted-foreground mb-2 flex flex-wrap items-center gap-x-2 text-xs"
+ >
+ {
+ authors.length > 0 && (
+ <>
+ {authors.map((author) => (
+ <div class="flex items-center gap-x-1.5">
+ <AvatarComponent
+ client:load
+ src={author.avatar}
+ alt={author.name}
+ fallback={author.name[0]}
+ className="size-5 rounded-full"
+ />
+ <span>{author.name}</span>
+ </div>
+ ))}
+ <Separator orientation="vertical" className="h-4!" />
+ </>
+ )
+ }
+ <span>{formattedDate}</span>
+ <Separator orientation="vertical" className="h-4!" />
+ <span>{readTime}</span>
+ {
+ subpostCount > 0 && (
+ <>
+ <Separator orientation="vertical" className="h-4!" />
+ <span class="flex items-center gap-1">
+ <Icon name="lucide:file-text" class="size-3" />
+ {subpostCount} subpost{subpostCount === 1 ? '' : 's'}
+ </span>
+ </>
+ )
+ }
+ </div>
+
+ {
+ entry.data.tags && (
+ <div class="flex flex-wrap gap-2">
+ {entry.data.tags.map((tag) => (
+ <Badge variant="muted" className="flex items-center gap-x-1">
+ <Icon name="lucide:hash" class="size-3" />
+ {tag}
+ </Badge>
+ ))}
+ </div>
+ )
+ }
+ </div>
+ </Link>
+</div>