admin 임시 리스트 생성성
This commit is contained in:
@@ -4,11 +4,146 @@ import { useEffect, useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { isAdminLoggedIn } from '../../lib/auth';
|
||||
import LoginPage from '../login/page';
|
||||
import Logout from '../../public/svg/logout';
|
||||
|
||||
const imgArrowDisabled = "http://localhost:3845/assets/6edcb2defc36a2bf4a05a3abe53b8da3d42b2cb4.svg";
|
||||
const imgArrowDefault = "http://localhost:3845/assets/ad0cb4418492f1b020bb38a2ff038a331294ce87.svg";
|
||||
const imgArrowNext = "http://localhost:3845/assets/6328cf96ee1169c1425c2ce55e7a2dcca0374508.svg";
|
||||
|
||||
interface User {
|
||||
id: number;
|
||||
joinDate: string;
|
||||
name: string;
|
||||
email: string;
|
||||
role: string;
|
||||
accountStatus: string;
|
||||
accountManagement: string;
|
||||
}
|
||||
|
||||
type PaginationMove = "Previous" | "Next";
|
||||
type PaginationStatus = "Default" | "Disabled";
|
||||
|
||||
function PaginationBtnMove({ status = "Default", move = "Previous" }: { status?: PaginationStatus; move?: PaginationMove }) {
|
||||
const isDisabled = status === "Disabled";
|
||||
const isNext = move === "Next";
|
||||
|
||||
if (isDisabled && isNext) {
|
||||
return (
|
||||
<div className="border border-[#eeeeee] border-solid relative rounded-[8px] shrink-0 size-[30px]">
|
||||
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||
<div className="absolute flex items-center justify-center left-[5px] size-[20px] top-[5px]">
|
||||
<div className="flex-none rotate-[180deg]">
|
||||
<div className="overflow-clip relative size-[20px]">
|
||||
<div className="absolute flex inset-[15.63%_30.21%] items-center justify-center">
|
||||
<div className="flex-none h-[16.5px] rotate-[180deg] w-[9.5px]">
|
||||
<div className="relative size-full">
|
||||
<div className="absolute inset-0">
|
||||
<img alt="" className="block max-w-none size-full" style={{ filter: 'opacity(0.88) brightness(0) saturate(100%) invert(88%)', opacity: 1 }} src={imgArrowNext} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isDisabled && !isNext) {
|
||||
return (
|
||||
<div className="border border-[#eeeeee] border-solid relative rounded-[8px] shrink-0 size-[30px]">
|
||||
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||
<div className="absolute flex items-center justify-center left-[5px] size-[20px] top-[5px]">
|
||||
<div className="flex-none rotate-[180deg]">
|
||||
<div className="overflow-clip relative size-[20px]">
|
||||
<div className="absolute inset-[15.63%_30.21%]">
|
||||
<div className="absolute inset-0">
|
||||
<img alt="" className="block max-w-none size-full" style={{ filter: 'opacity(0.88) brightness(0) saturate(100%) invert(88%)', opacity: 1 }} src={imgArrowDefault} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isNext) {
|
||||
return (
|
||||
<div className="border border-[#eeeeee] border-solid relative rounded-[8px] shrink-0 size-[30px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||
<div className="absolute flex items-center justify-center left-[5px] size-[20px] top-[5px]">
|
||||
<div className="flex-none rotate-[180deg]">
|
||||
<div className="overflow-clip relative size-[20px]">
|
||||
<div className="absolute flex inset-[15.63%_30.21%] items-center justify-center">
|
||||
<div className="flex-none h-[16.5px] rotate-[180deg] w-[9.5px]">
|
||||
<div className="relative size-full">
|
||||
<div className="absolute inset-0">
|
||||
<img alt="" className="block max-w-none size-full" src={imgArrowNext} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="border border-[#eeeeee] border-solid relative rounded-[8px] shrink-0 size-[30px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||
<div className="absolute flex items-center justify-center left-[5px] size-[20px] top-[5px]">
|
||||
<div className="flex-none rotate-[180deg]">
|
||||
<div className="overflow-clip relative size-[20px]">
|
||||
<div className="absolute inset-[15.63%_30.21%]">
|
||||
<div className="absolute inset-0">
|
||||
<img alt="" className="block max-w-none size-full" src={imgArrowDefault} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function AdminHomePage() {
|
||||
const router = useRouter();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
||||
const [selectedTab, setSelectedTab] = useState<'전체' | '학습자' | '강사' | '운영자'>('전체');
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
|
||||
// 샘플 사용자 데이터
|
||||
const [users, setUsers] = useState<User[]>([
|
||||
{ id: 39, joinDate: '2026-01-15', name: '홍길동', email: 'hong@example.com', role: '학습자', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 38, joinDate: '2026-01-14', name: '김철수', email: 'kim@example.com', role: '강사', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 37, joinDate: '2026-01-13', name: '이영희', email: 'lee@example.com', role: '학습자', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 36, joinDate: '2026-01-12', name: '박민수', email: 'park@example.com', role: '운영자', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 35, joinDate: '2026-01-11', name: '최지영', email: 'choi@example.com', role: '학습자', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 34, joinDate: '2026-01-10', name: '정대현', email: 'jung@example.com', role: '강사', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 33, joinDate: '2026-01-09', name: '강미영', email: 'kang@example.com', role: '학습자', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 32, joinDate: '2026-01-08', name: '윤성호', email: 'yoon@example.com', role: '학습자', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 31, joinDate: '2026-01-07', name: '임수진', email: 'lim@example.com', role: '강사', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 30, joinDate: '2026-01-06', name: '한지훈', email: 'han@example.com', role: '학습자', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 29, joinDate: '2026-01-05', name: '송민경', email: 'song@example.com', role: '학습자', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 28, joinDate: '2026-01-04', name: '오준혁', email: 'oh@example.com', role: '운영자', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 27, joinDate: '2026-01-03', name: '류현우', email: 'ryu@example.com', role: '학습자', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 26, joinDate: '2026-01-02', name: '신동욱', email: 'shin@example.com', role: '강사', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 25, joinDate: '2026-01-01', name: '조은서', email: 'cho@example.com', role: '학습자', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 24, joinDate: '2025-12-31', name: '배성민', email: 'bae@example.com', role: '학습자', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 23, joinDate: '2025-12-30', name: '전혜진', email: 'jeon@example.com', role: '강사', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 22, joinDate: '2025-12-29', name: '남궁준', email: 'namgung@example.com', role: '학습자', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 21, joinDate: '2025-12-28', name: '서아름', email: 'seo@example.com', role: '학습자', accountStatus: '활성', accountManagement: '관리' },
|
||||
{ id: 20, joinDate: '2025-12-27', name: '권태영', email: 'kwon@example.com', role: '운영자', accountStatus: '활성', accountManagement: '관리' },
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
// 관리자 인증 확인
|
||||
@@ -36,13 +171,293 @@ export default function AdminHomePage() {
|
||||
return <LoginPage />;
|
||||
}
|
||||
|
||||
const itemsPerPage = 13;
|
||||
const totalPages = Math.ceil(users.length / itemsPerPage);
|
||||
const pageNumbers = Array.from({ length: totalPages }, (_, i) => i + 1);
|
||||
const startIndex = (currentPage - 1) * itemsPerPage;
|
||||
const endIndex = startIndex + itemsPerPage;
|
||||
const currentUsers = users.slice(startIndex, endIndex);
|
||||
|
||||
return (
|
||||
<div className="bg-white relative size-full min-h-screen">
|
||||
<div className="flex items-center justify-center min-h-screen">
|
||||
<div className="text-center">
|
||||
<h1 className="text-2xl font-bold text-[#404040] mb-4">관리자 홈</h1>
|
||||
<p className="text-[#515151]">관리자 페이지에 오신 것을 환영합니다.</p>
|
||||
{/* 사이드바 */}
|
||||
<div className="absolute bg-white border-r border-[#eeeeee] border-solid box-border content-stretch flex flex-col gap-[45px] items-center left-0 min-h-[1080px] pb-8 pt-[30px] px-0 top-0 w-[250px]">
|
||||
{/* 로고 */}
|
||||
<button
|
||||
onClick={() => router.push('/')}
|
||||
className="h-[102px] relative shrink-0 w-[99px] cursor-pointer hover:opacity-80 transition-opacity"
|
||||
>
|
||||
<div className="absolute inset-0 flex items-center justify-center overflow-hidden pointer-events-none">
|
||||
<img alt="로고" className="h-full w-full object-contain" src="/logo.svg" />
|
||||
</div>
|
||||
</button>
|
||||
{/* 메뉴 */}
|
||||
<div className="box-border content-stretch flex flex-col items-center pb-0 pt-4 px-0 relative shrink-0 w-[250px]">
|
||||
<div className="box-border content-stretch flex flex-col gap-2 items-start p-3 relative shrink-0 w-full">
|
||||
<button className="bg-[#f7f7f7] box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer">
|
||||
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||
권한 설정
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => router.push('/admin_lecture1')}
|
||||
className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||
교육 과정 관리
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => router.push('/admin_lecture2')}
|
||||
className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||
강좌 관리
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||
문제 은행 관리
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||
수료증 발급
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||
공지사항
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||
학습 자료실
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||
로그/접속 기록
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||
배너 관리
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/* 로그아웃 */}
|
||||
<div className="content-stretch flex gap-[9px] items-center relative shrink-0">
|
||||
<div className="flex items-center justify-center relative shrink-0">
|
||||
<div className="flex-none rotate-[180deg] scale-y-[-100%]">
|
||||
<div className="h-[23.12px] relative w-[22px]">
|
||||
<Logout />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => {
|
||||
localStorage.removeItem('isLoggedIn');
|
||||
localStorage.removeItem('isAdminLoggedIn');
|
||||
router.push('/');
|
||||
}}
|
||||
className="content-stretch flex h-[36px] items-center justify-between relative shrink-0 w-[76px] cursor-pointer hover:opacity-80 transition-opacity"
|
||||
>
|
||||
<div className="box-border content-stretch flex gap-[10px] items-center justify-center px-[10px] py-[5px] relative shrink-0">
|
||||
<p className="font-medium leading-[1.6] not-italic relative shrink-0 text-[16px] text-[#404040] text-nowrap whitespace-pre">
|
||||
로그아웃
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 메인 콘텐츠 */}
|
||||
<div className="absolute left-[250px] top-0 right-0 min-h-screen">
|
||||
{/* 페이지 타이틀 탭 */}
|
||||
<div className="absolute content-stretch flex gap-[24px] items-center left-[48px] top-[45px]">
|
||||
<button
|
||||
onClick={() => setSelectedTab('전체')}
|
||||
className={`border-b-[2px] border-solid box-border content-stretch flex gap-[150px] items-center relative shrink-0 ${selectedTab === '전체' ? 'border-[#2b82e8]' : 'border-transparent'}`}
|
||||
>
|
||||
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
|
||||
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre">
|
||||
전체
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedTab('학습자')}
|
||||
className={`border-b-[2px] border-solid box-border content-stretch flex gap-[150px] items-center relative shrink-0 ${selectedTab === '학습자' ? 'border-[#2b82e8]' : 'border-transparent'}`}
|
||||
>
|
||||
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
|
||||
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre">
|
||||
학습자
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedTab('강사')}
|
||||
className={`border-b-[2px] border-solid box-border content-stretch flex gap-[150px] items-center relative shrink-0 ${selectedTab === '강사' ? 'border-[#2b82e8]' : 'border-transparent'}`}
|
||||
>
|
||||
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
|
||||
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre">
|
||||
강사
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedTab('운영자')}
|
||||
className={`border-b-[2px] border-solid box-border content-stretch flex gap-[150px] items-center relative shrink-0 ${selectedTab === '운영자' ? 'border-[#2b82e8]' : 'border-transparent'}`}
|
||||
>
|
||||
<div className="box-border content-stretch flex gap-[10px] items-center justify-center p-[10px] relative shrink-0">
|
||||
<p className="font-bold leading-[normal] not-italic relative shrink-0 text-[#515151] text-[18px] text-nowrap whitespace-pre">
|
||||
운영자
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* 사용자 목록 테이블 */}
|
||||
<div className="absolute content-stretch flex flex-col items-start left-[48px] right-[101px] top-[135px] h-[671px] overflow-hidden">
|
||||
{/* 테이블 헤더 */}
|
||||
<div className="bg-[rgba(235,247,255,0.5)] content-stretch flex h-[41px] items-center relative shrink-0 w-full">
|
||||
<div className="content-stretch flex items-center relative shrink-0 w-full">
|
||||
<div className="basis-0 border-[0.5px_0px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||
<div className="basis-0 flex flex-col font-bold grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||
<p className="leading-[normal]">가입일</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-0 border-[0.5px_0px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||
<div className="basis-0 flex flex-col font-bold grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||
<p className="leading-[normal]">사용자명</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-0 border-[0.5px_0px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||
<div className="basis-0 flex flex-col font-bold grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||
<p className="leading-[normal]">아이디(이메일)</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-0 border-[0.5px_0px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||
<div className="basis-0 flex flex-col font-bold grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||
<p className="leading-[normal]">권한</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-0 border-[0.5px_0px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||
<div className="basis-0 flex flex-col font-bold grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||
<p className="leading-[normal]">계정 상태</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-0 border-[0.5px_0px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||
<div className="basis-0 flex flex-col font-bold grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||
<p className="leading-[normal]">계정 관리</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 테이블 바디 */}
|
||||
{users.length === 0 ? (
|
||||
<div className="relative w-full flex items-center justify-center" style={{ minHeight: '400px' }}>
|
||||
<div className="content-stretch flex flex-col gap-[16px] items-center relative shrink-0">
|
||||
<div className="content-stretch flex flex-col gap-[2px] items-center relative shrink-0">
|
||||
<p className="font-medium leading-[1.6] not-italic relative shrink-0 text-[16px] text-[#969696] text-nowrap whitespace-pre">
|
||||
존재하는 계정이 없어요.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="content-stretch flex flex-col items-start relative shrink-0 w-full max-h-[630px] overflow-y-auto">
|
||||
{currentUsers.map((user) => (
|
||||
<div key={user.id} className="bg-white content-stretch flex items-center relative shrink-0 w-full">
|
||||
<div className="content-stretch flex items-center relative shrink-0 w-full">
|
||||
<div className="basis-0 border-[0.5px_0px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||
<div className="basis-0 flex flex-col font-medium grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||
<p className="leading-[normal]">{user.joinDate}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-0 border-[0.5px_0px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||
<div className="basis-0 flex flex-col font-medium grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||
<p className="leading-[normal]">{user.name}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-0 border-[0.5px_0px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||
<div className="basis-0 flex flex-col font-medium grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||
<p className="leading-[normal]">{user.email}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-0 border-[0.5px_0px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||
<div className="basis-0 flex flex-col font-medium grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||
<p className="leading-[normal]">{user.role}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-0 border-[0.5px_0px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||
<div className="basis-0 flex flex-col font-medium grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||
<p className="leading-[normal]">{user.accountStatus}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-0 border-[0.5px_0px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||
<div className="basis-0 flex flex-col font-medium grow justify-center leading-[0] min-h-px min-w-px not-italic relative shrink-0 text-[18px] text-[#515151]">
|
||||
<p className="leading-[normal]">{user.accountManagement}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 페이지네이션 */}
|
||||
{users.length > 0 && (
|
||||
<div className="absolute content-stretch flex gap-2 items-center justify-center left-[48px] right-[101px] top-[909px]">
|
||||
<button onClick={() => setCurrentPage(Math.max(1, currentPage - 1))}>
|
||||
<PaginationBtnMove status={currentPage === 1 ? "Disabled" : "Default"} move="Previous" />
|
||||
</button>
|
||||
<div className="content-stretch flex gap-2 items-center relative shrink-0">
|
||||
{pageNumbers.map((pageNum) => (
|
||||
<button
|
||||
key={pageNum}
|
||||
onClick={() => setCurrentPage(pageNum)}
|
||||
className={`relative rounded-[8px] shrink-0 size-[30px] cursor-pointer transition-colors ${currentPage === pageNum
|
||||
? 'bg-[#1d1d1d]'
|
||||
: 'border border-[#eeeeee] border-solid hover:bg-gray-50'
|
||||
}`}
|
||||
>
|
||||
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||
<div className={`absolute flex flex-col font-medium justify-center leading-[0] left-[15.5px] not-italic text-[14px] text-center text-nowrap top-[15px] translate-x-[-50%] translate-y-[-50%] ${currentPage === pageNum ? 'text-white' : 'text-[#515151]'
|
||||
}`}>
|
||||
<p className="leading-[1.6] whitespace-pre">{pageNum}</p>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<button onClick={() => setCurrentPage(Math.min(totalPages, currentPage + 1))}>
|
||||
<PaginationBtnMove status={currentPage === totalPages ? "Disabled" : "Default"} move="Next" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -277,7 +277,10 @@ export default function AdminLecture1Page() {
|
||||
{/* 메뉴 */}
|
||||
<div className="box-border content-stretch flex flex-col items-center pb-0 pt-4 px-0 relative shrink-0 w-[250px]">
|
||||
<div className="box-border content-stretch flex flex-col gap-2 items-start p-3 relative shrink-0 w-full">
|
||||
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||
<button
|
||||
onClick={() => router.push('/admin_home')}
|
||||
className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||
권한 설정
|
||||
|
||||
@@ -6,6 +6,104 @@ import { isAdminLoggedIn } from '../../lib/auth';
|
||||
import LoginPage from '../login/page';
|
||||
import Logout from '../../public/svg/logout';
|
||||
|
||||
const imgArrowDisabled = "http://localhost:3845/assets/6edcb2defc36a2bf4a05a3abe53b8da3d42b2cb4.svg";
|
||||
const imgArrowDefault = "http://localhost:3845/assets/ad0cb4418492f1b020bb38a2ff038a331294ce87.svg";
|
||||
const imgArrowNext = "http://localhost:3845/assets/6328cf96ee1169c1425c2ce55e7a2dcca0374508.svg";
|
||||
|
||||
type PaginationMove = "Previous" | "Next";
|
||||
type PaginationStatus = "Default" | "Disabled";
|
||||
|
||||
function PaginationBtnMove({ status = "Default", move = "Previous" }: { status?: PaginationStatus; move?: PaginationMove }) {
|
||||
const isDisabled = status === "Disabled";
|
||||
const isNext = move === "Next";
|
||||
|
||||
if (isDisabled && isNext) {
|
||||
return (
|
||||
<div className="border border-[#eeeeee] border-solid relative rounded-[8px] shrink-0 size-[30px]">
|
||||
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||
<div className="absolute flex items-center justify-center left-[5px] size-[20px] top-[5px]">
|
||||
<div className="flex-none rotate-[180deg]">
|
||||
<div className="overflow-clip relative size-[20px]">
|
||||
<div className="absolute flex inset-[15.63%_30.21%] items-center justify-center">
|
||||
<div className="flex-none h-[16.5px] rotate-[180deg] w-[9.5px]">
|
||||
<div className="relative size-full">
|
||||
<div className="absolute inset-0">
|
||||
<img alt="" className="block max-w-none size-full" style={{ filter: 'opacity(0.88) brightness(0) saturate(100%) invert(88%)', opacity: 1 }} src={imgArrowNext} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isDisabled && !isNext) {
|
||||
return (
|
||||
<div className="border border-[#eeeeee] border-solid relative rounded-[8px] shrink-0 size-[30px]">
|
||||
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||
<div className="absolute flex items-center justify-center left-[5px] size-[20px] top-[5px]">
|
||||
<div className="flex-none rotate-[180deg]">
|
||||
<div className="overflow-clip relative size-[20px]">
|
||||
<div className="absolute inset-[15.63%_30.21%]">
|
||||
<div className="absolute inset-0">
|
||||
<img alt="" className="block max-w-none size-full" style={{ filter: 'opacity(0.88) brightness(0) saturate(100%) invert(88%)', opacity: 1 }} src={imgArrowDefault} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isNext) {
|
||||
return (
|
||||
<div className="border border-[#eeeeee] border-solid relative rounded-[8px] shrink-0 size-[30px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||
<div className="absolute flex items-center justify-center left-[5px] size-[20px] top-[5px]">
|
||||
<div className="flex-none rotate-[180deg]">
|
||||
<div className="overflow-clip relative size-[20px]">
|
||||
<div className="absolute flex inset-[15.63%_30.21%] items-center justify-center">
|
||||
<div className="flex-none h-[16.5px] rotate-[180deg] w-[9.5px]">
|
||||
<div className="relative size-full">
|
||||
<div className="absolute inset-0">
|
||||
<img alt="" className="block max-w-none size-full" src={imgArrowNext} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="border border-[#eeeeee] border-solid relative rounded-[8px] shrink-0 size-[30px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||
<div className="absolute flex items-center justify-center left-[5px] size-[20px] top-[5px]">
|
||||
<div className="flex-none rotate-[180deg]">
|
||||
<div className="overflow-clip relative size-[20px]">
|
||||
<div className="absolute inset-[15.63%_30.21%]">
|
||||
<div className="absolute inset-0">
|
||||
<img alt="" className="block max-w-none size-full" src={imgArrowDefault} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface Lecture {
|
||||
id: number;
|
||||
courseName: string;
|
||||
@@ -20,7 +118,29 @@ export default function AdminLecture2Page() {
|
||||
const router = useRouter();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
||||
const [lectures, setLectures] = useState<Lecture[]>([]);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [lectures, setLectures] = useState<Lecture[]>([
|
||||
{ id: 39, courseName: '방사선 적용', lectureName: '방사선 기본 원리', attachedFile: '파일1.pdf', questionCount: 10, registrar: '이철수', createdAt: '2026-01-15' },
|
||||
{ id: 38, courseName: '방사선 적용', lectureName: '방사선 안전 관리', attachedFile: '파일2.pdf', questionCount: 15, registrar: '이철수', createdAt: '2026-01-14' },
|
||||
{ id: 37, courseName: '방사선 원리', lectureName: '방사선 측정 기법', attachedFile: '파일3.pdf', questionCount: 12, registrar: '김등록', createdAt: '2026-01-13' },
|
||||
{ id: 36, courseName: '방사선 적용', lectureName: '방사선 장비 사용법', attachedFile: '파일4.pdf', questionCount: 8, registrar: '이철수', createdAt: '2026-01-12' },
|
||||
{ id: 35, courseName: '방사선 원리', lectureName: '방사선 물리학 기초', attachedFile: '파일5.pdf', questionCount: 20, registrar: '김등록', createdAt: '2026-01-11' },
|
||||
{ id: 34, courseName: '방사선 적용', lectureName: '방사선 보호 장비', attachedFile: '파일6.pdf', questionCount: 14, registrar: '이철수', createdAt: '2026-01-10' },
|
||||
{ id: 33, courseName: '방사선 적용', lectureName: '방사선 응용 실습', attachedFile: '파일7.pdf', questionCount: 16, registrar: '이철수', createdAt: '2026-01-09' },
|
||||
{ id: 32, courseName: '방사선 원리', lectureName: '방사선 화학 반응', attachedFile: '파일8.pdf', questionCount: 11, registrar: '김등록', createdAt: '2026-01-08' },
|
||||
{ id: 31, courseName: '방사선 적용', lectureName: '방사선 의료 응용', attachedFile: '파일9.pdf', questionCount: 18, registrar: '이철수', createdAt: '2026-01-07' },
|
||||
{ id: 30, courseName: '방사선 적용', lectureName: '방사선 산업 응용', attachedFile: '파일10.pdf', questionCount: 13, registrar: '이철수', createdAt: '2026-01-06' },
|
||||
{ id: 29, courseName: '방사선 원리', lectureName: '방사선 생물학', attachedFile: '파일11.pdf', questionCount: 17, registrar: '김등록', createdAt: '2026-01-05' },
|
||||
{ id: 28, courseName: '방사선 적용', lectureName: '방사선 환경 모니터링', attachedFile: '파일12.pdf', questionCount: 9, registrar: '이철수', createdAt: '2026-01-04' },
|
||||
{ id: 27, courseName: '방사선 적용', lectureName: '방사선 검사 기법', attachedFile: '파일13.pdf', questionCount: 19, registrar: '이철수', createdAt: '2026-01-03' },
|
||||
{ id: 26, courseName: '방사선 원리', lectureName: '방사선 에너지 전달', attachedFile: '파일14.pdf', questionCount: 21, registrar: '김등록', createdAt: '2026-01-02' },
|
||||
{ id: 25, courseName: '방사선 적용', lectureName: '방사선 처리 기술', attachedFile: '파일15.pdf', questionCount: 7, registrar: '이철수', createdAt: '2026-01-01' },
|
||||
{ id: 24, courseName: '방사선 적용', lectureName: '방사선 품질 관리', attachedFile: '파일16.pdf', questionCount: 22, registrar: '이철수', createdAt: '2025-12-31' },
|
||||
{ id: 23, courseName: '방사선 원리', lectureName: '방사선 방어 이론', attachedFile: '파일17.pdf', questionCount: 6, registrar: '김등록', createdAt: '2025-12-30' },
|
||||
{ id: 22, courseName: '방사선 적용', lectureName: '방사선 계측법', attachedFile: '파일18.pdf', questionCount: 24, registrar: '이철수', createdAt: '2025-12-29' },
|
||||
{ id: 21, courseName: '방사선 적용', lectureName: '방사선 안전 규정', attachedFile: '파일19.pdf', questionCount: 5, registrar: '이철수', createdAt: '2025-12-28' },
|
||||
{ id: 20, courseName: '방사선 원리', lectureName: '방사선 핵물리학', attachedFile: '파일20.pdf', questionCount: 25, registrar: '김등록', createdAt: '2025-12-27' },
|
||||
]);
|
||||
|
||||
// 관리자 인증 확인
|
||||
useEffect(() => {
|
||||
@@ -48,6 +168,13 @@ export default function AdminLecture2Page() {
|
||||
return <LoginPage />;
|
||||
}
|
||||
|
||||
const itemsPerPage = 13;
|
||||
const totalPages = Math.ceil(lectures.length / itemsPerPage);
|
||||
const pageNumbers = Array.from({ length: totalPages }, (_, i) => i + 1);
|
||||
const startIndex = (currentPage - 1) * itemsPerPage;
|
||||
const endIndex = startIndex + itemsPerPage;
|
||||
const currentLectures = lectures.slice(startIndex, endIndex);
|
||||
|
||||
return (
|
||||
<div className="bg-white relative size-full min-h-screen">
|
||||
{/* 사이드바 */}
|
||||
@@ -64,7 +191,10 @@ export default function AdminLecture2Page() {
|
||||
{/* 메뉴 */}
|
||||
<div className="box-border content-stretch flex flex-col items-center pb-0 pt-4 px-0 relative shrink-0 w-[250px]">
|
||||
<div className="box-border content-stretch flex flex-col gap-2 items-start p-3 relative shrink-0 w-full">
|
||||
<button className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors">
|
||||
<button
|
||||
onClick={() => router.push('/admin_home')}
|
||||
className="box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||
권한 설정
|
||||
@@ -181,7 +311,7 @@ export default function AdminLecture2Page() {
|
||||
</button>
|
||||
|
||||
{/* 테이블 */}
|
||||
<div className="absolute content-stretch flex flex-col items-start left-[48px] right-[101px] top-[186px]">
|
||||
<div className="absolute content-stretch flex flex-col items-start left-[48px] right-[101px] top-[186px] h-[671px] overflow-hidden">
|
||||
{/* 테이블 헤더 */}
|
||||
<div className="bg-[rgba(235,247,255,0.5)] content-stretch flex h-[41px] items-center relative shrink-0 w-full">
|
||||
<div className="content-stretch flex items-center relative shrink-0 w-full">
|
||||
@@ -218,7 +348,7 @@ export default function AdminLecture2Page() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 빈 상태 또는 테이블 바디 */}
|
||||
{/* 테이블 바디 */}
|
||||
{lectures.length === 0 ? (
|
||||
<div className="relative w-full flex items-center justify-center" style={{ minHeight: '400px' }}>
|
||||
<div className="content-stretch flex flex-col gap-[16px] items-center relative shrink-0">
|
||||
@@ -230,8 +360,8 @@ export default function AdminLecture2Page() {
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="content-stretch flex flex-col items-start relative shrink-0 w-full">
|
||||
{lectures.map((lecture) => (
|
||||
<div className="content-stretch flex flex-col items-start relative shrink-0 w-full max-h-[630px] overflow-y-auto">
|
||||
{currentLectures.map((lecture) => (
|
||||
<div key={lecture.id} className="bg-white content-stretch flex items-center relative shrink-0 w-full">
|
||||
<div className="content-stretch flex items-center relative shrink-0 w-full">
|
||||
<div className="basis-0 border-[0.5px_0px_0.5px_0.5px] border-[#b9b9b9] border-solid box-border content-stretch flex gap-[10px] grow items-center min-h-px min-w-px p-[10px] relative shrink-0">
|
||||
@@ -270,6 +400,37 @@ export default function AdminLecture2Page() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* 페이지네이션 */}
|
||||
{lectures.length > 0 && (
|
||||
<div className="absolute content-stretch flex gap-2 items-center justify-center left-[48px] right-[101px] top-[909px]">
|
||||
<button onClick={() => setCurrentPage(Math.max(1, currentPage - 1))}>
|
||||
<PaginationBtnMove status={currentPage === 1 ? "Disabled" : "Default"} move="Previous" />
|
||||
</button>
|
||||
<div className="content-stretch flex gap-2 items-center relative shrink-0">
|
||||
{pageNumbers.map((pageNum) => (
|
||||
<button
|
||||
key={pageNum}
|
||||
onClick={() => setCurrentPage(pageNum)}
|
||||
className={`relative rounded-[8px] shrink-0 size-[30px] cursor-pointer transition-colors ${currentPage === pageNum
|
||||
? 'bg-[#1d1d1d]'
|
||||
: 'border border-[#eeeeee] border-solid hover:bg-gray-50'
|
||||
}`}
|
||||
>
|
||||
<div className="overflow-clip relative rounded-[inherit] size-[30px]">
|
||||
<div className={`absolute flex flex-col font-medium justify-center leading-[0] left-[15.5px] not-italic text-[14px] text-center text-nowrap top-[15px] translate-x-[-50%] translate-y-[-50%] ${currentPage === pageNum ? 'text-white' : 'text-[#515151]'
|
||||
}`}>
|
||||
<p className="leading-[1.6] whitespace-pre">{pageNum}</p>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<button onClick={() => setCurrentPage(Math.min(totalPages, currentPage + 1))}>
|
||||
<PaginationBtnMove status={currentPage === totalPages ? "Disabled" : "Default"} move="Next" />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -5,8 +5,8 @@ import Image from 'next/image';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import logo from '../logo.svg';
|
||||
|
||||
const checkIcon = "http://localhost:3845/assets/68720b08a673d8b68ae6482d642eeab286c9462b.svg";
|
||||
import CheckboxOff from '../../public/svg/checkbox_off';
|
||||
import CheckboxOn from '../../public/svg/checkbox_on';
|
||||
|
||||
type CheckboxProps = {
|
||||
checked: boolean;
|
||||
@@ -20,18 +20,9 @@ function Checkbox({ checked, onChange, label }: CheckboxProps) {
|
||||
<button
|
||||
type="button"
|
||||
onClick={onChange}
|
||||
className="relative w-[18px] h-[18px] rounded-[4px]"
|
||||
className="relative w-[18px] h-[18px] flex items-center justify-center"
|
||||
>
|
||||
{checked ? (
|
||||
<>
|
||||
<div className="absolute bg-[#515151] left-0 rounded-[4px] w-[18px] h-[18px] top-0" />
|
||||
<div className="absolute left-[3px] w-3 h-3 top-[3px]">
|
||||
<img alt="" className="block max-w-none w-full h-full" src={checkIcon} />
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="absolute border border-[#b9b9b9] border-solid left-0 rounded-[4px] w-[18px] h-[18px] top-0" />
|
||||
)}
|
||||
{checked ? <CheckboxOn /> : <CheckboxOff />}
|
||||
</button>
|
||||
<span className="text-sm text-[#515151] leading-[1.6]">{label}</span>
|
||||
</div>
|
||||
|
||||
@@ -90,7 +90,10 @@ export default function HomePage() {
|
||||
{/* 메뉴 */}
|
||||
<div className="box-border content-stretch flex flex-col items-center pb-0 pt-4 px-0 relative shrink-0 w-[250px]">
|
||||
<div className="box-border content-stretch flex flex-col gap-2 items-start p-3 relative shrink-0 w-full">
|
||||
<button className="bg-[#f7f7f7] box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer">
|
||||
<button
|
||||
onClick={() => router.push('/admin_home')}
|
||||
className="bg-[#f7f7f7] box-border content-stretch flex gap-2 h-[34px] items-center pl-2 pr-2 py-1 relative rounded-lg shrink-0 w-[226px] cursor-pointer"
|
||||
>
|
||||
<div className="basis-0 content-stretch flex gap-2 grow items-center min-h-px min-w-px relative shrink-0 pl-2">
|
||||
<p className="[white-space-collapse:collapse] basis-0 font-medium grow leading-[1.6] min-h-px min-w-px not-italic overflow-ellipsis overflow-hidden relative shrink-0 text-[14px] text-[#404040] text-left text-nowrap">
|
||||
권한 설정
|
||||
|
||||
7
public/svg/checkbox_off.tsx
Normal file
7
public/svg/checkbox_off.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
export default function CheckboxOff() {
|
||||
return (
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.5" y="0.5" width="17" height="17" rx="3.5" stroke="#B9B9B9" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
15
public/svg/checkbox_on.tsx
Normal file
15
public/svg/checkbox_on.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
export default function CheckboxOn() {
|
||||
return (
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="18" height="18" rx="4" fill="#515151" />
|
||||
<g clipPath="url(#clip0_40000058_4306)">
|
||||
<path d="M7.49999 11.0849L5.41499 8.99992L4.70499 9.70492L7.49999 12.4999L13.5 6.49992L12.795 5.79492L7.49999 11.0849Z" fill="white" />
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_40000058_4306">
|
||||
<rect width="12" height="12" fill="white" transform="translate(3 3)" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user