'use client'; import { useState, useEffect, useRef, useMemo } from "react"; import AdminSidebar from "@/app/components/AdminSidebar"; import DropdownIcon from "@/app/svgs/dropdownicon"; import ChevronDownSvg from "@/app/svgs/chevrondownsvg"; type TabType = 'all' | 'learner' | 'instructor' | 'admin'; type RoleType = 'learner' | 'instructor' | 'admin'; type AccountStatus = 'active' | 'inactive'; export type UserRow = { id: string; joinDate: string; name: string; email: string; role: RoleType; status: AccountStatus; }; // 랜덤 데이터 생성 함수 function generateRandomUsers(count: number): UserRow[] { const surnames = ['김', '이', '박', '최', '정', '강', '조', '윤', '장', '임', '한', '오', '서', '신', '권', '황', '안', '송', '전', '홍']; const givenNames = ['민준', '서준', '도윤', '예준', '시우', '하준', '주원', '지호', '준서', '건우', '서연', '서윤', '지우', '서현', '민서', '하은', '예은', '윤서', '채원', '지원']; const roles: RoleType[] = ['learner', 'instructor', 'admin']; const statuses: AccountStatus[] = ['active', 'inactive']; const users: UserRow[] = []; const startDate = new Date('2024-01-01'); const endDate = new Date('2025-03-01'); for (let i = 1; i <= count; i++) { const surname = surnames[Math.floor(Math.random() * surnames.length)]; const givenName = givenNames[Math.floor(Math.random() * givenNames.length)]; const name = `${surname}${givenName}`; const email = `user${i}@example.com`; // 랜덤 날짜 생성 const randomTime = startDate.getTime() + Math.random() * (endDate.getTime() - startDate.getTime()); const randomDate = new Date(randomTime); const joinDate = randomDate.toISOString().split('T')[0]; const role = roles[Math.floor(Math.random() * roles.length)]; const status = statuses[Math.floor(Math.random() * statuses.length)]; users.push({ id: String(i), joinDate, name, email, role, status, }); } return users; } const mockUsers: UserRow[] = generateRandomUsers(111); // 강사 목록 가져오기 함수 export // TODO: 나중에 DB에서 가져오도록 변경 예정 // 예: export async function getInstructors(): Promise { // const response = await fetch('/api/instructors'); // return response.json(); // } export function getInstructors(): UserRow[] { // 현재는 mock 데이터 사용, 나중에 DB에서 가져오도록 변경 return mockUsers.filter(user => user.role === 'instructor' && user.status === 'active'); } const roleLabels: Record = { learner: '학습자', instructor: '강사', admin: '관리자', }; const statusLabels: Record = { active: '활성화', inactive: '비활성화', }; export default function AdminIdPage() { const [activeTab, setActiveTab] = useState('all'); const [users, setUsers] = useState(mockUsers); const [openDropdownId, setOpenDropdownId] = useState(null); const [isActivateModalOpen, setIsActivateModalOpen] = useState(false); const [isDeactivateModalOpen, setIsDeactivateModalOpen] = useState(false); const [selectedUserId, setSelectedUserId] = useState(null); const [showToast, setShowToast] = useState(false); const [toastMessage, setToastMessage] = useState(''); const [currentPage, setCurrentPage] = useState(1); const dropdownRefs = useRef<{ [key: string]: HTMLDivElement | null }>({}); const ITEMS_PER_PAGE = 10; const filteredUsers = useMemo(() => { return activeTab === 'all' ? users : users.filter(user => user.role === activeTab); }, [activeTab, users]); const totalPages = Math.ceil(filteredUsers.length / ITEMS_PER_PAGE); const paginatedUsers = useMemo(() => { const startIndex = (currentPage - 1) * ITEMS_PER_PAGE; const endIndex = startIndex + ITEMS_PER_PAGE; return filteredUsers.slice(startIndex, endIndex); }, [filteredUsers, currentPage]); // 탭 변경 시 첫 페이지로 리셋 useEffect(() => { setCurrentPage(1); }, [activeTab]); // 외부 클릭 시 드롭다운 닫기 useEffect(() => { function handleClickOutside(event: MouseEvent) { if (openDropdownId) { const dropdownElement = dropdownRefs.current[openDropdownId]; if (dropdownElement && !dropdownElement.contains(event.target as Node)) { setOpenDropdownId(null); } } } document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, [openDropdownId]); function openActivateModal(userId: string) { setSelectedUserId(userId); setIsActivateModalOpen(true); } function handleActivateConfirm() { if (selectedUserId) { setUsers(prevUsers => prevUsers.map(user => user.id === selectedUserId ? { ...user, status: 'active' } : user ) ); setToastMessage('계정을 활성화했습니다.'); setShowToast(true); setTimeout(() => { setShowToast(false); }, 3000); } setIsActivateModalOpen(false); setSelectedUserId(null); } function handleActivateCancel() { setIsActivateModalOpen(false); setSelectedUserId(null); } function openDeactivateModal(userId: string) { setSelectedUserId(userId); setIsDeactivateModalOpen(true); } function handleDeactivateConfirm() { if (selectedUserId) { setUsers(prevUsers => prevUsers.map(user => user.id === selectedUserId ? { ...user, status: 'inactive' } : user ) ); setToastMessage('계정을 비활성화했습니다.'); setShowToast(true); setTimeout(() => { setShowToast(false); }, 3000); } setIsDeactivateModalOpen(false); setSelectedUserId(null); } function handleDeactivateCancel() { setIsDeactivateModalOpen(false); setSelectedUserId(null); } function toggleAccountStatus(userId: string) { const user = users.find(u => u.id === userId); if (user && user.status === 'inactive') { openActivateModal(userId); } else if (user && user.status === 'active') { openDeactivateModal(userId); } } function toggleDropdown(userId: string) { setOpenDropdownId(openDropdownId === userId ? null : userId); } function changeUserRole(userId: string, newRole: RoleType) { setUsers(prevUsers => prevUsers.map(user => user.id === userId ? { ...user, role: newRole } : user ) ); setOpenDropdownId(null); } return (
{/* 메인 레이아웃 */}
{/* 사이드바 */}
{/* 메인 콘텐츠 */}
{/* 제목 영역 */}

권한 설정

{/* 탭 네비게이션 */}
{[ { id: 'all' as TabType, label: '전체' }, { id: 'learner' as TabType, label: '학습자' }, { id: 'instructor' as TabType, label: '강사' }, { id: 'admin' as TabType, label: '관리자' }, ].map((tab) => ( ))}
{/* 콘텐츠 영역 */}
{filteredUsers.length === 0 ? (

현재 관리할 수 있는 회원 계정이 없습니다.

) : ( <>
{paginatedUsers.map((user) => ( ))}
가입일 성명 아이디(이메일) 권한설정 계정상태 계정관리
{user.joinDate} {user.name} {user.email}
{roleLabels[user.role]}
{ dropdownRefs.current[user.id] = el; }} className="relative" > {openDropdownId === user.id && (
{(['learner', 'instructor', 'admin'] as RoleType[]).map((role) => ( ))}
)}
{user.status === 'active' ? (
{statusLabels[user.status]}
) : (
{statusLabels[user.status]}
)}
{/* 페이지네이션 - 10개 초과일 때만 표시 */} {filteredUsers.length > ITEMS_PER_PAGE && (() => { // 페이지 번호를 10단위로 표시 const pageGroup = Math.floor((currentPage - 1) / 10); const startPage = pageGroup * 10 + 1; const endPage = Math.min(startPage + 9, totalPages); const visiblePages = Array.from({ length: endPage - startPage + 1 }, (_, i) => startPage + i); return (
{/* First (맨 앞으로) */} {/* Prev */} {/* Numbers */} {visiblePages.map((n) => { const active = n === currentPage; return ( ); })} {/* Next */} {/* Last (맨 뒤로) */}
); })()} )}
{/* 활성화 확인 모달 */} {isActivateModalOpen && (
)} {/* 비활성화 확인 모달 */} {isDeactivateModalOpen && (
)} {/* 활성화 완료 토스트 */} {showToast && (

{toastMessage}

)}
); }