61
src/app/components/PartnerCategorySection.tsx
Normal file
61
src/app/components/PartnerCategorySection.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
"use client";
|
||||
import useSWR from "swr";
|
||||
import { useMemo, useState } from "react";
|
||||
|
||||
const fetcher = (url: string) => fetch(url).then((r) => r.json());
|
||||
|
||||
export default function PartnerCategorySection() {
|
||||
const { data: catData } = useSWR<{ categories: any[] }>("/api/partner-categories", fetcher);
|
||||
const categories = catData?.categories ?? [];
|
||||
const defaultCatId = categories[0]?.id || "";
|
||||
const [selectedId, setSelectedId] = useState<string>(defaultCatId);
|
||||
|
||||
const query = useMemo(() => {
|
||||
const id = selectedId || defaultCatId;
|
||||
return id ? `/api/partners?categoryId=${encodeURIComponent(id)}` : "/api/partners";
|
||||
}, [selectedId, defaultCatId]);
|
||||
|
||||
const { data: partnersData, isLoading } = useSWR<{ partners: any[] }>(query, fetcher);
|
||||
const partners = partnersData?.partners ?? [];
|
||||
|
||||
return (
|
||||
<section>
|
||||
{/* 카테고리 탭 */}
|
||||
<div className="flex gap-2 overflow-x-auto pb-2">
|
||||
{categories.map((c: any) => (
|
||||
<button
|
||||
key={c.id}
|
||||
onClick={() => setSelectedId(c.id)}
|
||||
className={`px-3 h-8 rounded-full border text-sm whitespace-nowrap ${ (selectedId || defaultCatId) === c.id ? "bg-neutral-900 text-white border-neutral-900" : "border-neutral-300 hover:bg-neutral-100"}`}
|
||||
>
|
||||
{c.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 파트너 리스트 */}
|
||||
<div className="mt-4 grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3">
|
||||
{isLoading && partners.length === 0 && (
|
||||
<div className="col-span-full text-sm text-neutral-500">불러오는 중...</div>
|
||||
)}
|
||||
{partners.map((p: any) => (
|
||||
<div key={p.id} className="rounded-lg border border-neutral-200 overflow-hidden bg-white">
|
||||
<div className="w-full aspect-[4/3] bg-neutral-100">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img src={p.imageUrl || "/sample.jpg"} alt={p.name} className="w-full h-full object-cover" />
|
||||
</div>
|
||||
<div className="p-2">
|
||||
<div className="text-sm font-semibold truncate">{p.name}</div>
|
||||
<div className="text-xs text-neutral-500 truncate">{p.address || ""}</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
{!isLoading && partners.length === 0 && (
|
||||
<div className="col-span-full text-sm text-neutral-500">표시할 제휴업체가 없습니다.</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user