기능 추가 — 옵저버 계정 및 현황 조회 포털
읽기 전용 옵저버 역할 추가. 신고 현황 확인만 가능하며 모든 쓰기 동작 차단. - 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:
@@ -65,7 +65,23 @@ body { display:flex; align-items:center; justify-content:center; min-height:100v
|
||||
|
||||
<!-- 회원가입 -->
|
||||
<div class="pane" id="paneRegister">
|
||||
<div class="reg-notice">
|
||||
<div class="form-group" style="margin-bottom:12px">
|
||||
<label>계정 유형 <span style="color:var(--red)">*</span></label>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:4px">
|
||||
<label id="roleCardMechanic" onclick="selectRole('mechanic')" style="border:2px solid var(--accent);border-radius:8px;padding:10px 12px;cursor:pointer;text-align:center;transition:all .15s;background:#E3EDFF;">
|
||||
<div style="font-size:18px;margin-bottom:2px">🔧</div>
|
||||
<div style="font-size:13px;font-weight:700;color:var(--navy)">정비사</div>
|
||||
<div style="font-size:11px;color:var(--gray4)">조치 입력·처리</div>
|
||||
</label>
|
||||
<label id="roleCardObserver" onclick="selectRole('observer')" style="border:2px solid var(--gray3);border-radius:8px;padding:10px 12px;cursor:pointer;text-align:center;transition:all .15s;">
|
||||
<div style="font-size:18px;margin-bottom:2px">👁</div>
|
||||
<div style="font-size:13px;font-weight:700;color:var(--navy)">옵저버</div>
|
||||
<div style="font-size:11px;color:var(--gray4)">현황 조회만 가능</div>
|
||||
</label>
|
||||
</div>
|
||||
<input type="hidden" id="regRole" value="mechanic">
|
||||
</div>
|
||||
<div id="regNotice" class="reg-notice">
|
||||
📌 정비사 계정으로 가입됩니다.<br>
|
||||
가입 후 <strong>관리자 승인</strong>이 완료되어야 로그인 가능합니다.
|
||||
</div>
|
||||
@@ -133,6 +149,7 @@ async function doLogin() {
|
||||
Auth.save(data.access_token, data.role, data.name, data.user_id);
|
||||
if (data.role === 'admin') location.href = '/pages/admin/dashboard.html';
|
||||
else if (data.role === 'mechanic') location.href = '/pages/mechanic/dashboard.html';
|
||||
else if (data.role === 'observer') location.href = '/pages/observer/dashboard.html';
|
||||
else location.href = '/pages/manufacturer/dashboard.html';
|
||||
} catch(e) {
|
||||
document.getElementById('err').textContent = e.message;
|
||||
@@ -140,6 +157,22 @@ async function doLogin() {
|
||||
}
|
||||
}
|
||||
|
||||
// ── 계정 유형 선택 ──
|
||||
function selectRole(role) {
|
||||
document.getElementById('regRole').value = role;
|
||||
const mc = document.getElementById('roleCardMechanic');
|
||||
const oc = document.getElementById('roleCardObserver');
|
||||
if (role === 'mechanic') {
|
||||
mc.style.cssText = 'border:2px solid var(--accent);border-radius:8px;padding:10px 12px;cursor:pointer;text-align:center;transition:all .15s;background:#E3EDFF;';
|
||||
oc.style.cssText = 'border:2px solid var(--gray3);border-radius:8px;padding:10px 12px;cursor:pointer;text-align:center;transition:all .15s;';
|
||||
document.getElementById('regNotice').innerHTML = '📌 정비사 계정으로 가입됩니다.<br>가입 후 <strong>관리자 승인</strong>이 완료되어야 로그인 가능합니다.';
|
||||
} else {
|
||||
oc.style.cssText = 'border:2px solid var(--accent);border-radius:8px;padding:10px 12px;cursor:pointer;text-align:center;transition:all .15s;background:#E3EDFF;';
|
||||
mc.style.cssText = 'border:2px solid var(--gray3);border-radius:8px;padding:10px 12px;cursor:pointer;text-align:center;transition:all .15s;';
|
||||
document.getElementById('regNotice').innerHTML = '👁 현황 조회 전용 계정입니다.<br>신고 등록·조치 등 쓰기 기능은 사용할 수 없습니다.<br>가입 후 <strong>관리자 승인</strong>이 완료되어야 로그인 가능합니다.';
|
||||
}
|
||||
}
|
||||
|
||||
// ── 제조사 목록 로드 (비인증) ──
|
||||
async function loadCompanies() {
|
||||
try {
|
||||
@@ -178,6 +211,7 @@ async function doRegister() {
|
||||
fd.append('name', name);
|
||||
fd.append('phone', phone);
|
||||
fd.append('company', company);
|
||||
fd.append('role', document.getElementById('regRole').value);
|
||||
const res = await fetch('/api/auth/register', { method:'POST', body: fd });
|
||||
if (!res.ok) { const e = await res.json(); throw new Error(e.detail); }
|
||||
document.getElementById('regOk').style.display = 'block';
|
||||
|
||||
Reference in New Issue
Block a user