Frontend-only application of prod_v2 (55e959b, 9e99b46). Dev docker-compose.yml changes excluded.
69 lines
2.7 KiB
TypeScript
69 lines
2.7 KiB
TypeScript
import { EmptyState } from "./EmptyState";
|
|
import type { Topic } from "../lib/types";
|
|
import { normalize } from "../lib/normalize";
|
|
import { faNum } from "../lib/formatters";
|
|
import { cn } from "../lib/utils";
|
|
|
|
export interface TopicGridProps {
|
|
topics: Topic[];
|
|
selectedTopic?: string;
|
|
onSelect: (topicName: string) => void;
|
|
showCounts?: boolean;
|
|
counts?: Record<string, number>;
|
|
}
|
|
|
|
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: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}
|
|
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"
|
|
)}
|
|
>
|
|
{/* کادر تصویر بسیار بزرگتر شده برای پر کردن تمام فضای مربع */}
|
|
<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>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
} |