181 lines
7.6 KiB
TypeScript
181 lines
7.6 KiB
TypeScript
|
|
'use client';
|
||
|
|
|
||
|
|
import { useState } from "react";
|
||
|
|
import AdminSidebar from "@/app/components/AdminSidebar";
|
||
|
|
import BannerRegistrationModal, { type Banner } from "./BannerRegistrationModal";
|
||
|
|
|
||
|
|
export default function AdminBannerPage() {
|
||
|
|
// TODO: 나중에 실제 데이터로 교체
|
||
|
|
const [banners, setBanners] = useState<Banner[]>([
|
||
|
|
{
|
||
|
|
id: 1,
|
||
|
|
order: 1,
|
||
|
|
imageUrl: "http://localhost:3845/assets/43be88ae6f992fc221d0d9c29e82073e7b202f46.png",
|
||
|
|
title: "XR 교육 플랫폼에 오신 것을 환영합니다",
|
||
|
|
description: "다양한 강좌와 함께 성장하는 학습 경험을 시작하세요.",
|
||
|
|
registeredDate: "2025-09-10",
|
||
|
|
},
|
||
|
|
]);
|
||
|
|
|
||
|
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||
|
|
const [editingBanner, setEditingBanner] = useState<Banner | null>(null);
|
||
|
|
|
||
|
|
const handleRegister = () => {
|
||
|
|
setEditingBanner(null);
|
||
|
|
setIsModalOpen(true);
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleModalClose = () => {
|
||
|
|
setIsModalOpen(false);
|
||
|
|
setEditingBanner(null);
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleSaveBanner = (title: string, description: string, imageKey?: string) => {
|
||
|
|
// TODO: API가 추가되면 실제로 배너를 저장하고 리스트를 새로고침
|
||
|
|
console.log('배너 저장:', { title, description, imageKey });
|
||
|
|
setIsModalOpen(false);
|
||
|
|
setEditingBanner(null);
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleDeleteBanner = () => {
|
||
|
|
// TODO: API가 추가되면 실제로 배너를 삭제하고 리스트를 새로고침
|
||
|
|
console.log('배너 삭제');
|
||
|
|
setIsModalOpen(false);
|
||
|
|
setEditingBanner(null);
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleRowClick = (banner: Banner) => {
|
||
|
|
setEditingBanner(banner);
|
||
|
|
setIsModalOpen(true);
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="min-h-screen flex flex-col bg-white">
|
||
|
|
{/* 메인 레이아웃 */}
|
||
|
|
<div className="flex flex-1 min-h-0 justify-center">
|
||
|
|
<div className="w-[1440px] flex min-h-0">
|
||
|
|
{/* 사이드바 */}
|
||
|
|
<div className="flex">
|
||
|
|
<AdminSidebar />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 메인 콘텐츠 */}
|
||
|
|
<main className="w-[1120px] bg-white">
|
||
|
|
<div className="h-full flex flex-col px-8">
|
||
|
|
{/* 제목 영역 */}
|
||
|
|
<div className="h-[100px] flex items-center">
|
||
|
|
<h1 className="text-[24px] font-bold leading-[1.5] text-[#1b2027]">
|
||
|
|
배너 관리
|
||
|
|
</h1>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 콘텐츠 영역 */}
|
||
|
|
<div className="flex-1 pt-8 flex flex-col gap-4">
|
||
|
|
{/* 상단 정보 및 버튼 */}
|
||
|
|
<div className="flex items-center justify-between">
|
||
|
|
<p className="text-[15px] font-medium leading-[1.5] text-[#333c47]">
|
||
|
|
총 {banners.length}건
|
||
|
|
</p>
|
||
|
|
<div className="flex gap-3">
|
||
|
|
<button
|
||
|
|
type="button"
|
||
|
|
onClick={handleRegister}
|
||
|
|
className="bg-[#1f2b91] text-white text-[16px] font-semibold leading-[1.5] px-4 py-2 rounded-lg hover:bg-[#1a2478] transition-colors"
|
||
|
|
>
|
||
|
|
등록하기
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 테이블 */}
|
||
|
|
{banners.length === 0 ? (
|
||
|
|
<div className="rounded-lg border border-[#dee1e6] bg-white min-h-[400px] flex items-center justify-center">
|
||
|
|
<p className="text-[16px] font-medium leading-[1.5] text-[#333c47]">
|
||
|
|
현재 관리할 수 있는 항목이 없습니다.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
) : (
|
||
|
|
<div className="border border-[#dee1e6] rounded-lg overflow-hidden">
|
||
|
|
<div className="flex flex-col">
|
||
|
|
{/* 테이블 헤더 */}
|
||
|
|
<div className="bg-gray-50 flex h-12">
|
||
|
|
<div className="border-r border-[#dee1e6] flex items-center justify-center px-4 py-3 shrink-0 w-[57px]">
|
||
|
|
<p className="text-[14px] font-semibold leading-[1.5] text-[#4c5561]">
|
||
|
|
순서
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<div className="border-r border-[#dee1e6] flex items-center px-4 py-3 shrink-0 w-[240px]">
|
||
|
|
<p className="text-[14px] font-semibold leading-[1.5] text-[#4c5561]">
|
||
|
|
배너 이미지
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<div className="border-r border-[#dee1e6] flex items-center px-4 py-3 flex-1 min-w-0">
|
||
|
|
<p className="text-[14px] font-semibold leading-[1.5] text-[#4c5561]">
|
||
|
|
배너 문구
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<div className="flex items-center px-4 py-3 shrink-0 w-[140px]">
|
||
|
|
<p className="text-[14px] font-semibold leading-[1.5] text-[#4c5561]">
|
||
|
|
등록일
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* 테이블 바디 */}
|
||
|
|
{banners.map((banner) => (
|
||
|
|
<div
|
||
|
|
key={banner.id}
|
||
|
|
className="border-t border-[#dee1e6] flex cursor-pointer hover:bg-[#F5F7FF] transition-colors"
|
||
|
|
onClick={() => handleRowClick(banner)}
|
||
|
|
>
|
||
|
|
<div className="border-r border-[#dee1e6] flex items-center justify-center px-4 py-3 shrink-0 w-[57px]">
|
||
|
|
<p className="text-[15px] font-medium leading-[1.5] text-[#1b2027]">
|
||
|
|
{banner.order}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<div className="border-r border-[#dee1e6] flex items-center justify-center px-4 py-3 shrink-0 w-[240px]">
|
||
|
|
<div className="h-[120px] w-[208px] rounded overflow-hidden">
|
||
|
|
<img
|
||
|
|
src={banner.imageUrl}
|
||
|
|
alt={banner.title}
|
||
|
|
className="w-full h-full object-cover"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div className="border-r border-[#dee1e6] flex items-center px-4 py-3 flex-1 min-w-0">
|
||
|
|
<div className="flex flex-col gap-1">
|
||
|
|
<p className="text-[16px] font-semibold leading-[1.5] text-[#1b2027]">
|
||
|
|
{banner.title}
|
||
|
|
</p>
|
||
|
|
<p className="text-[14px] font-medium leading-[1.5] text-[#333c47]">
|
||
|
|
{banner.description}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div className="flex items-center px-4 py-3 shrink-0 w-[140px]">
|
||
|
|
<p className="text-[15px] font-medium leading-[1.5] text-[#1b2027]">
|
||
|
|
{banner.registeredDate}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</main>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<BannerRegistrationModal
|
||
|
|
open={isModalOpen}
|
||
|
|
onClose={handleModalClose}
|
||
|
|
onSave={handleSaveBanner}
|
||
|
|
onDelete={handleDeleteBanner}
|
||
|
|
editingBanner={editingBanner}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|