diff --git a/apps/cm/src/pages/dashboard/api/banner.ts b/apps/cm/src/pages/dashboard/api/banner.ts new file mode 100644 index 000000000..d27552047 --- /dev/null +++ b/apps/cm/src/pages/dashboard/api/banner.ts @@ -0,0 +1,34 @@ +import { client } from "@/shared/api"; +import { ENDPOINT } from "@/shared/config"; + +export interface Banner { + bnrSn: number; + bnrTypeCd: string; + bnrTypeNm: string; + bnrTtl: string; + lnkgUrlAddr: string; + useYn: string; + atflCd: string; + mdfcnDt: string; + mdfr: string; + mdfrNm: string; +} + +export const getBannerList = async (siteId: string) => { + const response = await client.get( + `${ENDPOINT.CMS_SERVICE.BANNERS}/${siteId}`, + ); + return response.data; +}; + +export const getImageUrlByAtflCd = async (atflCd: string): Promise => { + if (!atflCd) return ""; + const response = await client.get( + `${ENDPOINT.ATTACH_SERVICE.IMAGES}/atflCd/${atflCd}`, + { + responseType: "blob", + }, + ); + const blob = response.data; + return URL.createObjectURL(blob); +}; \ No newline at end of file diff --git a/apps/cm/src/pages/dashboard/ui/banner-list.tsx b/apps/cm/src/pages/dashboard/ui/banner-list.tsx new file mode 100644 index 000000000..2bfaba565 --- /dev/null +++ b/apps/cm/src/pages/dashboard/ui/banner-list.tsx @@ -0,0 +1,106 @@ +"use client"; + +import { useRef } from "react"; +import { useQuery } from "@tanstack/react-query"; +import Autoplay from "embla-carousel-autoplay"; +import { ENDPOINT } from "@/shared/config"; +import { getImageUrlByAtflCd, getBannerList } from "../api/banner"; +import { getCookie } from "@/shared/lib"; + +import { + Carousel, + CarouselContent, + CarouselItem, + CarouselNext, + CarouselPrevious, + } from "@common/components"; + + + type BannerImageProps = { + atflCd: string; + bnrSn: number; + lnkgUrlAddr: string; + }; + +const BannerList: React.FC = () => { + const siteId = getCookie("site-id-key") ?? ""; + + const BannerImage = ({ atflCd, bnrSn, 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 ( +
+
로딩 중...
+
+ ); + } + + if (!imageUrl) { + return ( +
+
이미지 없음
+
+ ); + } + + return ( +
+ 배너 이미지 +
+ ); + }; + const { data: bannerList } = useQuery({ + queryKey: [ENDPOINT.CMS_SERVICE.BANNERS, siteId], + queryFn: () => getBannerList(siteId), + }); + + const plugin = useRef(Autoplay({ delay: 2000, stopOnInteraction: true })); + + return ( +
+ + + {bannerList && bannerList.length > 0 ? ( + bannerList.map((banner) => ( + + + + )) + ) : ( + +
+
배너가 없습니다
+
+
+ )} +
+ + +
+
+ ); +}; + +export default BannerList; \ No newline at end of file diff --git a/apps/cm/src/pages/dashboard/ui/dashboard-page.tsx b/apps/cm/src/pages/dashboard/ui/dashboard-page.tsx index eeb680aa1..1d0109dec 100644 --- a/apps/cm/src/pages/dashboard/ui/dashboard-page.tsx +++ b/apps/cm/src/pages/dashboard/ui/dashboard-page.tsx @@ -24,6 +24,8 @@ import FoFcltCntRt from "./fo-fclt-cnt-rt"; import FoWqltInflEffl from "./fo-wqlt-Infl-effl"; import ReuseChart from "./reuse-chart"; import ReuseStatus from "./reuse-status"; +import NoticeList from "./notice-list"; +import BannerList from "./banner-list"; // Chart.js 등록 ChartJS.register( @@ -198,16 +200,12 @@ function DashboardPage() {
-
-

공지사항

-
-
-
+
{/* 배너 영역 */}
- +
diff --git a/apps/cm/src/pages/dashboard/ui/notice-list.tsx b/apps/cm/src/pages/dashboard/ui/notice-list.tsx index 3462844dc..f6c21a4db 100644 --- a/apps/cm/src/pages/dashboard/ui/notice-list.tsx +++ b/apps/cm/src/pages/dashboard/ui/notice-list.tsx @@ -11,7 +11,7 @@ import { } from "../model/table-columns"; -function NoticeList() { +const NoticeList: React.FC = () => { const router = useRouter(); const noticePostQuery = useQuery({ queryKey: [ENDPOINT.BOARD_SERVICE.POSTS], @@ -48,4 +48,6 @@ function NoticeList() { {noticePostTableComponent} ); -} \ No newline at end of file +}; + +export default NoticeList; \ No newline at end of file diff --git a/apps/cm/src/shared/ui/page-layout.tsx b/apps/cm/src/shared/ui/page-layout.tsx index 8b355dbb4..d792d0ff7 100644 --- a/apps/cm/src/shared/ui/page-layout.tsx +++ b/apps/cm/src/shared/ui/page-layout.tsx @@ -10,7 +10,6 @@ function PageLayout({ children }: { children: React.ReactNode }) { return (
- {children}
); diff --git a/package.json b/package.json index 5f3833d7e..237cfca65 100644 --- a/package.json +++ b/package.json @@ -49,5 +49,5 @@ } }, "license": "ISC", - "packageManager": "pnpm@9.12.3" -} \ No newline at end of file + "packageManager": "pnpm@10.25.0+sha512.5e82639027af37cf832061bcc6d639c219634488e0f2baebe785028a793de7b525ffcd3f7ff574f5e9860654e098fe852ba8ac5dd5cefe1767d23a020a92f501" +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9b0953bda..9011614b3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -121,8 +121,8 @@ importers: specifier: ^0.474.0 version: 0.474.0(react@19.2.1) next: - specifier: 15.3.6 - version: 15.3.6(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + specifier: 15.3.8 + version: 15.3.8(react-dom@19.2.1(react@19.2.1))(react@19.2.1) next-qrcode: specifier: ^2.5.1 version: 2.5.1(react@19.2.1) @@ -251,8 +251,8 @@ importers: specifier: ^3.0.5 version: 3.0.5 next: - specifier: 15.3.6 - version: 15.3.6(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + specifier: 15.3.8 + version: 15.3.8(react-dom@19.2.1(react@19.2.1))(react@19.2.1) next-themes: specifier: ^0.4.6 version: 0.4.6(react-dom@19.2.1(react@19.2.1))(react@19.2.1) @@ -399,8 +399,8 @@ importers: specifier: ^0.474.0 version: 0.474.0(react@19.2.1) next: - specifier: 15.3.6 - version: 15.3.6(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + specifier: 15.3.8 + version: 15.3.8(react-dom@19.2.1(react@19.2.1))(react@19.2.1) next-qrcode: specifier: ^2.5.1 version: 2.5.1(react@19.2.1) @@ -514,8 +514,8 @@ importers: specifier: ^0.474.0 version: 0.474.0(react@19.2.1) next: - specifier: 15.3.6 - version: 15.3.6(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + specifier: 15.3.8 + version: 15.3.8(react-dom@19.2.1(react@19.2.1))(react@19.2.1) react-chartjs-2: specifier: ^5.3.0 version: 5.3.1(chart.js@4.5.1)(react@19.2.1) @@ -611,8 +611,8 @@ importers: specifier: ^0.474.0 version: 0.474.0(react@19.2.1) next: - specifier: 15.3.6 - version: 15.3.6(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + specifier: 15.3.8 + version: 15.3.8(react-dom@19.2.1(react@19.2.1))(react@19.2.1) react-hook-form: specifier: ^7.54.2 version: 7.68.0(react@19.2.1) @@ -696,8 +696,8 @@ importers: specifier: ^3.0.5 version: 3.0.5 next: - specifier: 15.3.6 - version: 15.3.6(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + specifier: 15.3.8 + version: 15.3.8(react-dom@19.2.1(react@19.2.1))(react@19.2.1) ol: specifier: ^7.3.0 version: 7.5.2 @@ -799,8 +799,8 @@ importers: specifier: ^2.30.1 version: 2.30.1 next: - specifier: 15.3.6 - version: 15.3.6(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + specifier: 15.3.8 + version: 15.3.8(react-dom@19.2.1(react@19.2.1))(react@19.2.1) ol: specifier: ^7.3.0 version: 7.5.2 @@ -941,8 +941,8 @@ importers: specifier: ^2.30.1 version: 2.30.1 next: - specifier: 15.3.6 - version: 15.3.6(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + specifier: 15.3.8 + version: 15.3.8(react-dom@19.2.1(react@19.2.1))(react@19.2.1) ol: specifier: ^7.3.0 version: 7.5.2 @@ -2341,8 +2341,8 @@ packages: '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} - '@next/env@15.3.6': - resolution: {integrity: sha512-/cK+QPcfRbDZxmI/uckT4lu9pHCfRIPBLqy88MhE+7Vg5hKrEYc333Ae76dn/cw2FBP2bR/GoK/4DU+U7by/Nw==} + '@next/env@15.3.8': + resolution: {integrity: sha512-SAfHg0g91MQVMPioeFeDjE+8UPF3j3BvHjs8ZKJAUz1BG7eMPvfCKOAgNWJ6s1MLNeP6O2InKQRTNblxPWuq+Q==} '@next/eslint-plugin-next@15.1.7': resolution: {integrity: sha512-kRP7RjSxfTO13NE317ek3mSGzoZlI33nc/i5hs1KaWpK+egs85xg0DJ4p32QEiHnR0mVjuUfhRIun7awqfL7pQ==} @@ -5478,8 +5478,8 @@ packages: react: ^19.2.1 react-dom: ^19.2.1 - next@15.3.6: - resolution: {integrity: sha512-oI6D1zbbsh6JzzZFDCSHnnx6Qpvd1fSkVJu/5d8uluqnxzuoqtodVZjYvNovooznUq8udSAiKp7MbwlfZ8Gm6w==} + next@15.3.8: + resolution: {integrity: sha512-L+4c5Hlr84fuaNADZbB9+ceRX9/CzwxJ+obXIGHupboB/Q1OLbSUapFs4bO8hnS/E6zV/JDX7sG1QpKVR2bguA==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: @@ -7660,7 +7660,7 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@next/env@15.3.6': {} + '@next/env@15.3.8': {} '@next/eslint-plugin-next@15.1.7': dependencies: @@ -11250,9 +11250,9 @@ snapshots: react: 19.2.1 react-dom: 19.2.1(react@19.2.1) - next@15.3.6(react-dom@19.2.1(react@19.2.1))(react@19.2.1): + next@15.3.8(react-dom@19.2.1(react@19.2.1))(react@19.2.1): dependencies: - '@next/env': 15.3.6 + '@next/env': 15.3.8 '@swc/counter': 0.1.3 '@swc/helpers': 0.5.15 busboy: 1.6.0