feat(blog): redesign post list cards

This commit is contained in:
2026-06-10 11:56:09 +03:30
parent 039158e0c4
commit 0d01933f9d
3 changed files with 135 additions and 45 deletions

View File

@@ -1,12 +1,14 @@
"use client";
import { useCallback, useEffect, useState } from "react";
import BlogThumbnail from "@/components/BlogThumbnail";
import { Input } from "@/components/ui/input";
import { Link, useLocation, useNavigate } from "@/lib/router";
import { api } from "@/lib/api";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import type * as Types from "@/lib/types";
import { blogPostPath } from "@/lib/blog-routes";
import { apiBaseUrl, toAbsoluteUrl } from "@/lib/site";
import type * as Types from "@/lib/types";
import { formatJalaliDate, getBlogCardImageUrl } from "@/lib/utils";
type BlogProps = {
initialPosts?: Types.PostListSchema[];
@@ -60,59 +62,55 @@ export default function Blog({
}, [location.pathname, navigate, search]);
return (
<div className="min-h-screen bg-background">
<div className="container mx-auto px-4 py-8">
<h1 className="text-4xl font-bold mb-8">وبلاگ</h1>
<div className="mb-8">
<div className="min-h-screen bg-[linear-gradient(180deg,hsl(var(--background)),hsl(var(--muted)/0.32))]" dir="rtl">
<div className="container mx-auto px-4 py-10">
<div className="mb-8 flex flex-col gap-5 md:flex-row md:items-end md:justify-between">
<div className="text-right">
<p className="mb-2 text-sm font-medium text-primary">خواندنیهای انجمن</p>
<h1 className="text-4xl font-black tracking-tight">بلاگ</h1>
<p className="mt-3 max-w-2xl text-sm leading-7 text-muted-foreground">
نوشتههای آموزشی، تجربههای دانشجویی و یادداشتهای تخصصی اعضای انجمن علمی.
</p>
</div>
<Input
type="text"
placeholder="جستجو در مقالات..."
placeholder="جستجو در نوشته‌ها..."
value={search}
onChange={(e) => setSearch(e.target.value)}
className="max-w-md"
onChange={(event) => setSearch(event.target.value)}
className="max-w-md rounded-full bg-background/80 text-right shadow-sm backdrop-blur"
/>
</div>
{loading ? (
<p className="text-center text-muted-foreground">در حال بارگذاری...</p>
) : posts.length === 0 ? (
<p className="text-center text-muted-foreground">مقالهای یافت نشد</p>
<p className="rounded-3xl border border-dashed bg-background/70 p-10 text-center text-muted-foreground">
نوشتهای پیدا نشد.
</p>
) : (
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
<div className="grid gap-6 md:grid-cols-2 xl:grid-cols-3">
{posts.map((post) => (
<Link key={post.id} to={blogPostPath(post.slug)}>
<Card className="h-full hover:shadow-lg transition-shadow">
{(post.absolute_featured_image_thumbnail_url || post.absolute_featured_image_preview_url || post.absolute_featured_image_url || post.featured_image) ? (
<div className="aspect-video overflow-hidden rounded-t-lg bg-muted">
<img
src={post.absolute_featured_image_thumbnail_url || post.absolute_featured_image_preview_url || post.absolute_featured_image_url || post.featured_image}
alt={post.title}
className="h-full w-full object-cover transition duration-300 group-hover:scale-[1.02]"
loading="lazy"
/>
</div>
) : null}
<CardHeader>
<CardTitle className="line-clamp-2">{post.title}</CardTitle>
<CardDescription>
{post.category?.name && (
<span className="text-primary ml-2">{post.category.name}</span>
)}
{new Date(post.created_at).toLocaleDateString("fa-IR")}
</CardDescription>
</CardHeader>
<CardContent>
{post.excerpt && (
<p className="text-muted-foreground line-clamp-3 mb-4">
{post.excerpt}
</p>
)}
<p className="text-sm">
نویسنده: {post.author.first_name} {post.author.last_name}
</p>
</CardContent>
</Card>
<Link
key={post.id}
to={blogPostPath(post.slug)}
className="group overflow-hidden rounded-[2rem] border border-border/70 bg-card/85 shadow-sm transition duration-300 hover:-translate-y-1 hover:shadow-xl hover:shadow-primary/10"
>
<BlogThumbnail
post={post}
imageUrl={toAbsoluteUrl(getBlogCardImageUrl(post), apiBaseUrl)}
className="aspect-[16/10] rounded-t-[2rem]"
/>
<article className="space-y-4 p-5 text-right">
<h2 className="line-clamp-2 text-xl font-bold leading-9 transition group-hover:text-primary">
{post.title}
</h2>
<p className="line-clamp-3 min-h-[5.25rem] text-sm leading-7 text-muted-foreground">
{post.excerpt || post.seo_description || "خلاصه‌ای برای این نوشته ثبت نشده است."}
</p>
<time className="block text-xs font-medium text-primary/80" dateTime={post.published_at || post.created_at}>
{formatJalaliDate(post.published_at || post.created_at)}
</time>
</article>
</Link>
))}
</div>