관리자 사용자 목록: 게스트 삭제 예정 시각 표시
게스트는 사이트를 나가고 하루 지나면 자동 삭제된다. 목록과 상세에 마지막 접속 + 24시간을 보여 주고, 접속 중이거나 방에 자리가 있으면 삭제 보류로 표시한다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,9 @@ function useLoad<T>(path: string): [T | null, () => void, string | null] {
|
||||
}
|
||||
|
||||
const time = (ms: number) => (ms ? new Date(ms).toLocaleString('ko-KR', { dateStyle: 'short', timeStyle: 'short' }) : '-');
|
||||
/** Idle guests are deleted a day after they leave the site (docs/05 §5). */
|
||||
const guestDeletion = (u: { kind: string; deleteAt: number | null }) =>
|
||||
u.kind !== 'guest' ? null : u.deleteAt ? `삭제 예정 ${time(u.deleteAt)}` : '사이트나 방에 남아 있어 삭제 보류';
|
||||
|
||||
export default function AdminApp() {
|
||||
const nav = useNavigate();
|
||||
@@ -454,6 +457,7 @@ function Users() {
|
||||
<tr key={u.id} className="clickable" onClick={() => setOpen(u.id)} tabIndex={0} onKeyDown={(e) => e.key === 'Enter' && setOpen(u.id)}>
|
||||
<td>
|
||||
<strong>{u.nickname}</strong>
|
||||
{guestDeletion(u) && <div className="muted small">{guestDeletion(u)}</div>}
|
||||
</td>
|
||||
<td className="wide-only small">{u.kind === 'member' ? `디스코드 ${u.discordName ?? ''} (${u.discordId})` : '게스트'}</td>
|
||||
<td>{u.role === 'superadmin' ? '슈퍼어드민' : u.role === 'admin' ? '어드민' : '-'}</td>
|
||||
@@ -498,6 +502,7 @@ function UserSheet({ id, onClose }: { id: string; onClose: () => void }) {
|
||||
<br />
|
||||
{d.user.discordId ? `디스코드 ID ${d.user.discordId}` : '게스트'} · 가입 {time(d.user.createdAt)} · 마지막 접속 {time(d.user.lastSeenAt)}
|
||||
{d.user.activeRoom && <> · 지금 방 {formatRoomCode(d.user.activeRoom)}</>}
|
||||
{guestDeletion(d.user) && <> · {guestDeletion(d.user)}</>}
|
||||
</p>
|
||||
<p className="small">{d.stats.length ? d.stats.map((s) => `${s.gameId} ${s.played}판 ${s.wins}승`).join(' · ') : '기록 없음'}</p>
|
||||
<div className="row">
|
||||
|
||||
Reference in New Issue
Block a user