Files
invyone/frontend/components/admin/provisioning/StatusDot.tsx
T
gbpark 68f85f3736 회사 관리 기능 확장 + 테넌트/비번 보안 하드닝
- 첫 로그인 비번 강제 변경 (RUN_082): FORCE_PASSWORD_CHANGE 컬럼,
  ForcePasswordChangeGuardFilter, /auth/change-password API + 페이지
- 테넌트 일관성 가드: TenantConsistencyGuardFilter 로 JWT.company_code
  ↔ 서브도메인 company_code 대조, CompanyResolver 가 (db_name, company_code)
  동시 반환
- 회사 관리 확장 (RUN_083 audit log, RUN_084 lifecycle 컬럼):
  CompanyAdmin/Members/Templates/Lifecycle/AuditLog 서비스 +
  CompanyMgmtController + SuperAdminGuard
- 회사 관리 UI: CompanyAccordionRow 탭화 + 모달 4종
  (AdminInfo/Deactivate/Delete/RecopyTemplates) + AuditLogDrawer + csvExport
- 프로비저닝 마법사: force_password_change 토글 반영
- 프론트 인증: storage 이벤트 멀티탭 동기화, 403 errorCode
  (PASSWORD_CHANGE_REQUIRED / CROSS_TENANT_REJECTED / TENANT_NOT_RESOLVED)
  전역 리다이렉트
- 기타: StartupSchemaMigrator, OS별 도커 기동 스크립트, CLAUDE.md 트래킹

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 00:36:05 +09:00

43 lines
1.2 KiB
TypeScript

"use client";
/**
* 회사 상태 표시용 작은 컬러 dot + 라벨.
* provisioning 상태일 때만 pulse 애니메이션.
*/
const MAP: Record<string, { color: string; label: string }> = {
active: { color: "rgb(var(--v5-green-rgb))", label: "활성" },
provisioning: { color: "var(--v5-primary)", label: "생성중" },
failed: { color: "var(--v5-red)", label: "실패" },
suspended: { color: "var(--v5-text-muted)", label: "정지" },
inactive: { color: "var(--v5-text-muted)", label: "비활성" },
};
export default function StatusDot({ status }: { status?: string }) {
const m = MAP[status || ""] || { color: "var(--v5-text-muted)", label: status || "—" };
const isProvisioning = status === "provisioning";
return (
<span
style={{
display: "inline-flex",
alignItems: "center",
gap: 6,
fontSize: "0.78rem",
fontWeight: 600,
color: "var(--v5-text)",
}}
>
<span
style={{
width: 7,
height: 7,
borderRadius: "50%",
background: m.color,
boxShadow: `0 0 3px ${m.color}`,
animation: isProvisioning ? "pulsedot 1.4s ease-in-out infinite" : "none",
}}
/>
{m.label}
</span>
);
}