/* portal/dashboard/public/dashboard.js — 대시보드 요약 카드·주의 항목·최근 활동 렌더(30초마다 갱신). */ (() => { const el = document.getElementById('dash'); if (!el) return; const ACT = { 'deploy.start': '배포 시작', 'deploy.done': '배포 완료', 'order.created': '주문 제출', 'order.approve': '주문 승인', 'member.invited': '구성원 초대', 'member.joined': '구성원 참여', 'member.role': '역할 변경', 'group.settings': '그룹 설정 변경', 'permission.site': '사이트 권한 변경', 'ownership.group_transferred': '그룹 소유권 이전', 'member.suspended': '구성원 정지' }; const fmtKrw = (n) => `${Number(n || 0).toLocaleString('ko-KR')}원`; async function load() { try { const d = await aw.api('GET', '/api/dashboard'); const s = d.summary; const card = (title, stat, sub) => `
| 시각 | 내용 | 주체 | 결과 |
|---|---|---|---|
| ${aw.esc(aw.fmt(r.at))} | ${aw.esc(ACT[r.action] || r.action)}${r.subjectType ? ` ${aw.esc(r.subjectType)} ${aw.esc(r.subjectId || '')}` : ''} | ${r.automatic ? '⚙ 자동' : `👤 ${aw.esc(r.actor)}`} | ${r.outcome === 'ok' ? '✔ 성공' : `✘ ${aw.esc(r.outcome)}`} |
마지막 갱신 ${aw.esc(aw.fmt(d.generatedAt))}
`; } catch (err) { aw.state(el, err.status === 403 ? 'forbidden' : err.code === 'service_unreachable' ? 'stale' : 'failed', err.message, { retry: load }); } } load(); aw.poll(load, 30000); })();