fix(admin): improve responsive UI styles of admin blog page

This commit is contained in:
2026-06-12 22:02:40 +03:30
parent eb28a00abd
commit cb8eeadba9

View File

@@ -3,6 +3,7 @@
import { useCallback, useEffect, useMemo, useState } from "react"; import { useCallback, useEffect, useMemo, useState } from "react";
import { BookOpenText, CheckCircle2, Clock3, Edit, Eye, Loader2, Plus, Send, XCircle } from "lucide-react"; import { BookOpenText, CheckCircle2, Clock3, Edit, Eye, Loader2, Plus, Send, XCircle } from "lucide-react";
import { Link } from "@/lib/router"; import { Link } from "@/lib/router";
import BlogThumbnail from "@/components/BlogThumbnail";
import { useAuth } from "@/contexts/AuthContext"; import { useAuth } from "@/contexts/AuthContext";
import { api } from "@/lib/api"; import { api } from "@/lib/api";
import type * as Types from "@/lib/types"; import type * as Types from "@/lib/types";
@@ -123,7 +124,6 @@ export default function AdminBlog() {
<CardDescription>دسترسی نویسندهها به نوشتههای خودشان محدود میشود.</CardDescription> <CardDescription>دسترسی نویسندهها به نوشتههای خودشان محدود میشود.</CardDescription>
</div> </div>
<div className="flex flex-col gap-2 sm:flex-row"> <div className="flex flex-col gap-2 sm:flex-row">
<Button variant="outline" onClick={loadPosts}>جستجو</Button>
<Input value={search} onChange={(event) => setSearch(event.target.value)} placeholder="جستجو..." className="w-full text-right sm:w-64" /> <Input value={search} onChange={(event) => setSearch(event.target.value)} placeholder="جستجو..." className="w-full text-right sm:w-64" />
<Select value={status} onValueChange={setStatus}> <Select value={status} onValueChange={setStatus}>
<SelectTrigger className="w-full sm:w-48"><SelectValue /></SelectTrigger> <SelectTrigger className="w-full sm:w-48"><SelectValue /></SelectTrigger>
@@ -144,20 +144,29 @@ export default function AdminBlog() {
<div className="flex justify-center py-10"><Loader2 className="h-5 w-5 animate-spin" /></div> <div className="flex justify-center py-10"><Loader2 className="h-5 w-5 animate-spin" /></div>
) : posts.length ? ( ) : posts.length ? (
posts.map((post) => ( posts.map((post) => (
<div key={post.id} className="flex gap-3 rounded-2xl border p-4 flex-row items-center justify-between"> <div key={post.id} className="flex flex-col gap-4 rounded-2xl border p-3 sm:p-4 md:flex-row md:items-center md:justify-between">
<div className="text-right"> <div className="flex min-w-0 flex-1 items-start gap-3 md:gap-4">
<div className="flex flex-col-reverse md:flex-row flex-wrap items-start gap-2"> <BlogThumbnail
<h3 className="font-semibold">{post.title}</h3> post={post}
imageUrl={post.absolute_featured_image_thumbnail_url || post.absolute_featured_image_preview_url || post.absolute_featured_image_url || post.featured_image}
className="h-20 w-24 shrink-0 rounded-xl sm:h-24 sm:w-36 md:h-28 md:w-44"
imageClassName="group-hover:scale-100"
/>
<div className="min-w-0 flex-1 text-right">
<div className="flex flex-col-reverse flex-wrap items-start gap-2 sm:flex-row sm:items-center">
<h3 className="line-clamp-2 font-semibold leading-7">{post.title}</h3>
<Badge variant={post.status === "published" ? "default" : "secondary"}>{statusLabels[post.status] ?? post.status}</Badge> <Badge variant={post.status === "published" ? "default" : "secondary"}>{statusLabels[post.status] ?? post.status}</Badge>
</div> </div>
<p className="mt-1 text-xs text-muted-foreground"> <p className="mt-1 text-xs text-muted-foreground">
{post.updated_at ? formatJalali(post.updated_at, false) : ""} {post.updated_at ? formatJalali(post.updated_at, false) : ""}
</p> </p>
</div> </div>
<div className="grid grid-cols-2 grid-flow-col grid-rows-2 gap-2 md:flex md:flex-row md:flex-wrap" dir="ltr"> </div>
<div className="flex flex-wrap gap-2 md:grid md:grid-cols-2 md:grid-rows-2" dir="ltr">
<div className="flex flex-1 basis-[calc(33.333%-0.5rem)] md:col-start-1 md:row-start-1 md:block md:basis-auto">
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<Button variant="outline" size="sm" asChild className="w-full md:w-auto"> <Button variant="outline" size="sm" asChild className="w-full">
<Link <Link
to={`/admin/blog/${post.id}/preview`} to={`/admin/blog/${post.id}/preview`}
aria-label="پیش‌نمایش" aria-label="پیش‌نمایش"
@@ -169,10 +178,12 @@ export default function AdminBlog() {
</TooltipTrigger> </TooltipTrigger>
<TooltipContent>پیشنمایش</TooltipContent> <TooltipContent>پیشنمایش</TooltipContent>
</Tooltip> </Tooltip>
</div>
<div className="flex flex-1 basis-[calc(33.333%-0.5rem)] md:col-start-1 md:row-start-2 md:block md:basis-auto">
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<Button variant="secondary" size="sm" asChild className="w-full md:w-auto"> <Button variant="secondary" size="sm" asChild className="w-full">
<Link <Link
to={`/admin/blog/${post.id}/edit`} to={`/admin/blog/${post.id}/edit`}
aria-label="ویرایش" aria-label="ویرایش"
@@ -184,8 +195,10 @@ export default function AdminBlog() {
</TooltipTrigger> </TooltipTrigger>
<TooltipContent>ویرایش</TooltipContent> <TooltipContent>ویرایش</TooltipContent>
</Tooltip> </Tooltip>
</div>
{post.status === "draft" || post.status === "changes_requested" ? ( {post.status === "draft" || post.status === "changes_requested" ? (
<div className="flex flex-1 basis-[calc(33.333%-0.5rem)] md:col-start-2 md:row-start-1 md:block md:basis-auto">
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<Button <Button
@@ -193,35 +206,40 @@ export default function AdminBlog() {
onClick={() => submitPost(post.id)} onClick={() => submitPost(post.id)}
disabled={actingId === post.id} disabled={actingId === post.id}
aria-label="ارسال برای بررسی" aria-label="ارسال برای بررسی"
className="w-full md:w-auto" className="w-full"
> >
<Send className="h-4 w-4" /> <Send className="h-4 w-4" />
</Button> </Button>
</TooltipTrigger> </TooltipTrigger>
<TooltipContent>ارسال برای بررسی</TooltipContent> <TooltipContent>ارسال برای بررسی</TooltipContent>
</Tooltip> </Tooltip>
</div>
) : null} ) : null}
{canReview && post.status === "submitted" ? ( {canReview && post.status === "submitted" ? (
<> <>
<div className="flex flex-1 basis-[calc(33.333%-0.5rem)] md:col-start-2 md:row-start-1 md:block md:basis-auto">
<Button <Button
size="sm" size="sm"
onClick={() => reviewPost(post.id, "publish")} onClick={() => reviewPost(post.id, "publish")}
disabled={actingId === post.id} disabled={actingId === post.id}
className="w-full md:w-auto" className="w-full"
> >
انتشار انتشار
</Button> </Button>
</div>
<div className="flex flex-1 basis-[calc(33.333%-0.5rem)] md:col-start-2 md:row-start-2 md:block md:basis-auto">
<Button <Button
size="sm" size="sm"
variant="outline" variant="outline"
onClick={() => reviewPost(post.id, "request_changes")} onClick={() => reviewPost(post.id, "request_changes")}
disabled={actingId === post.id} disabled={actingId === post.id}
className="w-full md:w-auto" className="w-full"
> >
درخواست اصلاح درخواست اصلاح
</Button> </Button>
</div>
</> </>
) : null} ) : null}
</div> </div>