style(ui): maximize topic card images and fix RTL wizard arrows

Frontend-only application of prod_v2 (55e959b, 9e99b46).
Dev docker-compose.yml changes excluded.
This commit is contained in:
MMD
2026-09-15 14:30:43 +03:30
parent 2573f1e583
commit e7f465f74f
2 changed files with 49 additions and 24 deletions
+38 -15
View File
@@ -5,39 +5,62 @@ import { faNum } from "../lib/formatters";
import { cn } from "../lib/utils";
export interface TopicGridProps {
topics: Topic[]; // از store (API) می‌آید
topics: Topic[];
selectedTopic?: string;
onSelect: (topicName: string) => void;
showCounts?: boolean; // تعداد تأمین‌کننده‌های هر تاپیک
counts?: Record<string, number>; // topic name → count
showCounts?: boolean;
counts?: Record<string, number>;
}
// گرید تاپیک‌ها (از /material-categories — نه لیست ثابت)
export function TopicGrid({ topics, selectedTopic, onSelect, showCounts = false, counts }: TopicGridProps) {
if (!topics.length) {
return <EmptyState emoji="🗂️" text="در حال بارگذاری دسته‌بندی‌ها…" />;
}
return (
<div className="grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4">
<div className="grid grid-cols-2 gap-3 sm:gap-4 sm:grid-cols-3 lg:grid-cols-4">
{topics.map((t) => {
const selected = selectedTopic != null && normalize(selectedTopic) === normalize(t.name);
const count = counts?.[t.name] ?? 0;
return (
<button
type="button"
key={t.key}
className={cn("topic-card flex flex-col items-center justify-center p-4", selected && "selected")}
onClick={() => onSelect(t.name)}
className={cn(
"group relative flex flex-col items-center justify-between rounded-2xl border bg-white p-2.5 sm:p-4 text-center transition-all duration-200 cursor-pointer shadow-xs active:scale-[0.98] overflow-hidden",
selected
? "border-blue-600 ring-2 ring-blue-600/25 shadow-md bg-blue-50/20"
: "border-slate-200 hover:border-blue-300 hover:shadow-md"
)}
>
{/* استفاده از استایل اینلاین برای تضمین تغییر سایز و دور زدن CSSهای قبلی */}
<img
src={t.icon}
alt=""
style={{ width: '130px', height: '80px', objectFit: 'contain' }}
className="mb-2"
/>
<div className="t-name text-[13px] font-semibold">{t.name}</div>
{showCounts && <div className="t-count text-[11px] text-muted">{faNum(count)} تأمین‌کننده</div>}
{/* کادر تصویر بسیار بزرگ‌تر شده برای پر کردن تمام فضای مربع */}
<div className="flex h-36 sm:h-48 md:h-52 w-full items-center justify-center overflow-hidden rounded-xl bg-slate-50/50">
<img
src={t.icon}
alt={t.name}
className="h-full w-full object-contain transform scale-115 group-hover:scale-125 transition-transform duration-300 drop-shadow-xs"
loading="lazy"
/>
</div>
{/* بخش عنوان و تعداد */}
<div className="mt-3 w-full pb-1">
<div
className={cn(
"truncate text-[13px] sm:text-[15px] font-bold transition-colors",
selected ? "text-blue-600" : "text-slate-800 group-hover:text-blue-600"
)}
>
{t.name}
</div>
{showCounts && (
<div className="mt-0.5 truncate text-[11px] sm:text-xs text-slate-400 font-medium">
{faNum(count)} تأمین‌کننده
</div>
)}
</div>
</button>
);
})}