- shared/auth 모듈: AuthProvider, ProtectedRoute, useAuth, authApi - 페이지: LoginPage(Google OAuth), PendingPage, DeniedPage - WING_PERMIT 역할 기반 접근 제어 - Topbar에 사용자 이름 + 로그아웃 버튼 추가 - App.tsx에 react-router 라우팅 + AuthProvider 래핑 - DEV 모드 Mock 로그인 지원 (김개발) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
65 lines
2.2 KiB
TypeScript
65 lines
2.2 KiB
TypeScript
type Props = {
|
|
total: number;
|
|
fishing: number;
|
|
transit: number;
|
|
pairLinks: number;
|
|
alarms: number;
|
|
pollingStatus: "idle" | "loading" | "ready" | "error";
|
|
lastFetchMinutes: number | null;
|
|
clock: string;
|
|
adminMode?: boolean;
|
|
onLogoClick?: () => void;
|
|
userName?: string;
|
|
onLogout?: () => void;
|
|
};
|
|
|
|
export function Topbar({ total, fishing, transit, pairLinks, alarms, pollingStatus, lastFetchMinutes, clock, adminMode, onLogoClick, userName, onLogout }: Props) {
|
|
const statusColor =
|
|
pollingStatus === "ready" ? "#22C55E" : pollingStatus === "loading" ? "#F59E0B" : pollingStatus === "error" ? "#EF4444" : "var(--muted)";
|
|
return (
|
|
<div className="topbar">
|
|
<div className="logo" onClick={onLogoClick} style={{ cursor: onLogoClick ? "pointer" : undefined }} title={adminMode ? "ADMIN" : undefined}>
|
|
🛰 <span>WING</span> 조업감시·선단연관 {adminMode ? <span style={{ fontSize: 10, color: "#F59E0B" }}>(ADMIN)</span> : null}
|
|
</div>
|
|
<div className="stats">
|
|
<div className="stat">
|
|
DATA <b style={{ color: "#22C55E" }}>API</b>
|
|
</div>
|
|
<div className="stat">
|
|
POLL{" "}
|
|
<b style={{ color: statusColor }}>
|
|
{pollingStatus.toUpperCase()}
|
|
{lastFetchMinutes ? `(${lastFetchMinutes}m)` : ""}
|
|
</b>
|
|
</div>
|
|
<div className="stat">
|
|
전체 <b>{total}</b>척
|
|
</div>
|
|
<div className="stat">
|
|
조업 <b style={{ color: "#22C55E" }}>{fishing}</b>
|
|
</div>
|
|
<div className="stat">
|
|
항해 <b style={{ color: "#3B82F6" }}>{transit}</b>
|
|
</div>
|
|
<div className="stat">
|
|
쌍연결 <b style={{ color: "#F59E0B" }}>{pairLinks}</b>
|
|
</div>
|
|
<div className="stat">
|
|
경고 <b style={{ color: "#EF4444" }}>{alarms}</b>
|
|
</div>
|
|
</div>
|
|
<div className="time">{clock}</div>
|
|
{userName && (
|
|
<div className="topbar-user">
|
|
<span className="topbar-user__name">{userName}</span>
|
|
{onLogout && (
|
|
<button className="topbar-user__logout" onClick={onLogout}>
|
|
로그아웃
|
|
</button>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|