Files
frontend/packages/common/components/src/ui/footer/index.tsx
T

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>
);
}