'use client'; import { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import { api } from '@/lib/api'; import { useAuth } from '@/lib/auth'; import { Card, PageHeader, Input, Select, Button, Banner } from '@/components/ui'; import { UserPlus, KeyRound, Trash2, Shield, ShieldCheck } from 'lucide-react'; interface User { id: number; username: string; role: string; created_at: string; last_login_at: string | null; } export default function AdminUsersPage() { const router = useRouter(); const { user } = useAuth(); const [users, setUsers] = useState([]); const [form, setForm] = useState({ username: '', password: '', role: 'user' }); const [msg, setMsg] = useState<{ level: any; text: string } | null>(null); const [resetTarget, setResetTarget] = useState(null); const [resetPw, setResetPw] = useState(''); useEffect(() => { if (user && user.role !== 'admin') { router.replace('/'); } }, [user]); async function load() { try { const data = await api.get('/api/users'); setUsers(data); } catch (e: any) { setMsg({ level: 'danger', text: e.message }); } } useEffect(() => { load(); }, []); async function add(e: React.FormEvent) { e.preventDefault(); setMsg(null); try { await api.post('/api/users', form); setMsg({ level: 'success', text: `✅ ${form.username} 생성 완료` }); setForm({ username: '', password: '', role: 'user' }); load(); } catch (e: any) { setMsg({ level: 'danger', text: e.message }); } } async function del(u: User) { if (!confirm(`'${u.username}' 계정을 삭제하시겠습니까?`)) return; try { await api.delete(`/api/users/${u.id}`); setMsg({ level: 'success', text: `🗑️ ${u.username} 삭제됨` }); load(); } catch (e: any) { setMsg({ level: 'danger', text: e.message }); } } async function changeRole(u: User, newRole: string) { if (!confirm(`'${u.username}' role 을 ${newRole} 로 변경하시겠습니까?`)) return; try { await api.put(`/api/users/${u.id}/role`, { role: newRole }); setMsg({ level: 'success', text: `🔄 ${u.username} → ${newRole}` }); load(); } catch (e: any) { setMsg({ level: 'danger', text: e.message }); } } async function resetPassword(e: React.FormEvent) { e.preventDefault(); if (resetTarget == null) return; if (resetPw.length < 6) { setMsg({ level: 'danger', text: '비밀번호 6자 이상' }); return; } try { await api.put(`/api/users/${resetTarget}/password`, { new_password: resetPw }); setMsg({ level: 'success', text: '🔑 비밀번호 변경 완료' }); setResetTarget(null); setResetPw(''); } catch (e: any) { setMsg({ level: 'danger', text: e.message }); } } if (user && user.role !== 'admin') { return (
관리자 전용 페이지입니다.
); } return (
{msg &&
{msg.text}
}
{/* 새 사용자 추가 */}
새 사용자 추가
setForm({ ...form, username: e.target.value })} placeholder="username" required autoComplete="off" /> setForm({ ...form, password: e.target.value })} required autoComplete="new-password" />
{/* 사용자 목록 */}
사용자 목록
{['ID', '아이디', '권한', '가입', '마지막 로그인', '작업'].map(h => ( ))} {users.length === 0 && } {users.map(u => { const isMe = u.username === user?.username; return ( ); })}
{h}
로딩 중...
#{u.id} {u.username} {isMe && (나)} {u.role === 'admin' && } {u.role} {(u.created_at || '').slice(0, 16).replace('T', ' ')} {(u.last_login_at || '-').slice(0, 16).replace('T', ' ')}
{!isMe && ( )} {!isMe && ( )}
{/* 비번 리셋 모달 */} {resetTarget != null && (
setResetTarget(null)}>
e.stopPropagation()}>

비밀번호 초기화

{users.find(u => u.id === resetTarget)?.username} 의 새 비밀번호를 설정합니다.

setResetPw(e.target.value)} autoFocus required />
)}
); }