기능 추가 — 옵저버 계정 및 현황 조회 포털

읽기 전용 옵저버 역할 추가. 신고 현황 확인만 가능하며 모든 쓰기 동작 차단.

- auth.py: require_viewer(admin+observer) 의존성 추가
- auth_router.py: register 엔드포인트에 role 파라미터 추가 (mechanic/observer)
- login.html: 회원가입 시 정비사/옵저버 역할 카드 선택 UI, 역할별 안내문구
- 로그인 후 observer → /pages/observer/dashboard.html 라우팅
- observer/dashboard.html: 통계 카드(상태별 건수) + 신고 현황 테이블(읽기전용)
- observer/reports.html: 상태·충전기ID·충전소명 필터 신고 목록
- accounts.html: 옵저버 필터·생성·승인 대기 역할 표시 추가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
byun
2026-06-01 15:25:47 +09:00
parent 81c3428aa1
commit 124ad0d165
7 changed files with 274 additions and 7 deletions

View File

@@ -55,6 +55,7 @@
<div style="display:flex;gap:10px;margin-bottom:14px;align-items:center;flex-wrap:wrap;">
<select id="fRole" onchange="load()" style="width:auto">
<option value="">전체</option><option value="mechanic">정비사</option>
<option value="observer">옵저버</option>
<option value="manufacturer">제조사</option><option value="admin">관리자</option>
</select>
<label style="display:flex;align-items:center;gap:6px;font-size:13px;cursor:pointer;">
@@ -80,6 +81,7 @@
<div class="form-group"><label>역할 <span class="req">*</span></label>
<select id="eRole" onchange="toggleFields()">
<option value="mechanic">정비사</option>
<option value="observer">옵저버</option>
<option value="manufacturer">제조사</option>
<option value="admin">관리자</option>
</select>
@@ -130,7 +132,7 @@ async function bulkDelete() {
catch(e) { alert('처리 중 오류가 발생했습니다: ' + e.message); }
}
const ROLE_LABEL = {admin:'관리자',mechanic:'정비사',manufacturer:'제조사'};
const ROLE_LABEL = {admin:'관리자',mechanic:'정비사',manufacturer:'제조사',observer:'옵저버'};
async function loadPending() {
const all = await API.get('/accounts');
@@ -141,7 +143,7 @@ async function loadPending() {
document.getElementById('pendingBadge').textContent = pending.length + '명 대기 중';
document.getElementById('pendingTbody').innerHTML = pending.map(u => `
<tr>
<td><strong>${u.name}</strong></td>
<td><strong>${u.name}</strong> <span style="font-size:11px;background:#F3F4F6;color:#374151;padding:1px 7px;border-radius:8px;font-weight:600;">${ROLE_LABEL[u.role]||u.role}</span></td>
<td style="color:var(--gray4)">${u.username}</td>
<td>${u.company ? `<span style="background:#EFF6FF;color:#1E40AF;font-size:11px;font-weight:600;padding:2px 8px;border-radius:8px">${u.company}</span>` : '<span style="color:var(--gray4)">-</span>'}</td>
<td>${u.phone||'-'}</td>