146 lines
4.9 KiB
TypeScript
146 lines
4.9 KiB
TypeScript
import { useRef } from "react";
|
|
import Autoplay from "embla-carousel-autoplay";
|
|
import { useQuery } from "@tanstack/react-query";
|
|
import { ENDPOINT } from "../../config";
|
|
import { getSiteInfo, getBannerList, getImageUrlByAtflCd } from "../../api";
|
|
import { getCookie } from "../../lib";
|
|
import {
|
|
Carousel,
|
|
CarouselContent,
|
|
CarouselItem,
|
|
CarouselNext,
|
|
CarouselPrevious,
|
|
} from "../carousel";
|
|
|
|
type BannerImageProps = {
|
|
atflCd: string;
|
|
bnrSn: number;
|
|
lnkgUrlAddr: string;
|
|
};
|
|
|
|
const BannerImage = ({ atflCd, lnkgUrlAddr }: BannerImageProps) => {
|
|
const { data: imageUrl, isLoading } = useQuery({
|
|
queryKey: [ENDPOINT.ATTACH_SERVICE.IMAGES, atflCd],
|
|
queryFn: () => getImageUrlByAtflCd(atflCd),
|
|
enabled: !!atflCd,
|
|
});
|
|
|
|
const handleClick = () => {
|
|
if (lnkgUrlAddr) {
|
|
window.open(lnkgUrlAddr, "_blank");
|
|
}
|
|
};
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="relative mx-auto flex h-24 items-center justify-center bg-accent">
|
|
<div className="text-sm text-muted-foreground">로딩 중...</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!imageUrl) {
|
|
return (
|
|
<div className="relative mx-auto flex h-24 items-center justify-center bg-accent">
|
|
<div className="text-sm text-muted-foreground">이미지 없음</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div
|
|
className="relative mx-auto flex h-24 cursor-pointer items-center justify-center transition-opacity hover:opacity-80"
|
|
onClick={handleClick}
|
|
>
|
|
<img
|
|
src={imageUrl}
|
|
className="h-full w-full object-contain"
|
|
alt="배너 이미지"
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export function Footer() {
|
|
const siteId = getCookie("site-id-key") ?? "";
|
|
|
|
const { data: siteInfo } = useQuery({
|
|
queryKey: [ENDPOINT.CMS_SERVICE.SITES, siteId],
|
|
queryFn: () => getSiteInfo(siteId),
|
|
});
|
|
|
|
const { data: bannerList } = useQuery({
|
|
queryKey: [ENDPOINT.CMS_SERVICE.BANNERS, siteId],
|
|
queryFn: () => getBannerList(siteId),
|
|
});
|
|
|
|
// MAIN 타입 배너만 필터링
|
|
const mainBanners =
|
|
bannerList?.filter((banner) => banner.bnrTypeCd === "BNRFTER") ?? [];
|
|
|
|
const plugin = useRef(Autoplay({ delay: 2000, stopOnInteraction: true }));
|
|
|
|
return (
|
|
<footer className="flex w-full shrink-0 flex-col items-start border-t border-solid border-border bg-background px-3 pb-1 pt-4 text-foreground sm:flex-row sm:px-6">
|
|
<div className="mb-4 w-full sm:mb-0 sm:w-[55%]">
|
|
<h6 className="mb-2 text-lg font-bold sm:mb-4 sm:text-xl md:text-2xl">
|
|
{siteInfo?.siteNm ?? ""}
|
|
</h6>
|
|
<p className="my-1 text-sm opacity-60 sm:text-base md:text-xl">
|
|
{siteInfo?.siteAddr ?? ""}
|
|
</p>
|
|
<p className="my-1 text-sm opacity-60 sm:text-base md:text-xl">
|
|
전화: {siteInfo?.telNo ?? ""} / 팩스: {siteInfo?.faxNumber ?? ""}
|
|
</p>
|
|
<p className="my-1 text-sm opacity-60 sm:text-base md:text-xl">
|
|
{siteInfo?.lwndCn ?? ""}
|
|
</p>
|
|
</div>
|
|
<div className="flex w-full flex-col sm:w-[45%]">
|
|
<div className="mb-4 flex flex-wrap justify-start gap-2 sm:mb-0 sm:justify-end sm:gap-4">
|
|
<span className="text-sm sm:text-base md:text-xl">
|
|
개인정보처리방침
|
|
</span>
|
|
<span className="text-sm sm:text-base md:text-xl">이용약관</span>
|
|
<span className="text-sm sm:text-base md:text-xl">사이트맵</span>
|
|
<span className="text-sm sm:text-base md:text-xl">고객센터</span>
|
|
</div>
|
|
<div className="hidden sm:block">
|
|
<Carousel
|
|
plugins={[plugin.current]}
|
|
opts={{ loop: true }}
|
|
className="relative my-4 h-20 sm:my-8 sm:h-24"
|
|
>
|
|
<CarouselContent>
|
|
{mainBanners && mainBanners.length > 0 ? (
|
|
mainBanners.map((banner) => (
|
|
<CarouselItem
|
|
key={`banner-${banner.bnrSn}`}
|
|
className="basis-1/2 sm:basis-1/3"
|
|
>
|
|
<BannerImage
|
|
atflCd={banner.atflCd}
|
|
bnrSn={banner.bnrSn}
|
|
lnkgUrlAddr={banner.lnkgUrlAddr}
|
|
/>
|
|
</CarouselItem>
|
|
))
|
|
) : (
|
|
<CarouselItem className="basis-1/2 sm:basis-1/3">
|
|
<div className="relative flex h-20 w-full items-center justify-center bg-accent sm:h-24">
|
|
<div className="text-sm text-muted-foreground">
|
|
배너가 없습니다
|
|
</div>
|
|
</div>
|
|
</CarouselItem>
|
|
)}
|
|
</CarouselContent>
|
|
<CarouselPrevious className="absolute left-2 top-1/2 z-10 !bg-background text-accent-foreground" />
|
|
<CarouselNext className="absolute right-2 top-1/2 z-10 !bg-background text-accent-foreground" />
|
|
</Carousel>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
);
|
|
}
|