forked from baron/baron-sso
143 lines
4.2 KiB
TypeScript
143 lines
4.2 KiB
TypeScript
import { ChevronDown, ChevronUp, Wrench } from "lucide-react";
|
|
import type { FC } from "react";
|
|
import { useEffect, useState } from "react";
|
|
import { t } from "../../lib/i18n";
|
|
|
|
const RoleSwitcher: FC = () => {
|
|
const [currentRole, setCurrentRole] = useState<string>("super_admin");
|
|
const [isCollapsed, setIsCollapsed] = useState<boolean>(() => {
|
|
return window.localStorage.getItem("RoleSwitcher-Collapsed") === "true";
|
|
});
|
|
|
|
useEffect(() => {
|
|
// localStorage에서 역할 읽기
|
|
const savedRole = window.localStorage.getItem("X-Mock-Role");
|
|
if (savedRole) {
|
|
setCurrentRole(savedRole);
|
|
} else {
|
|
// 기본값 설정
|
|
window.localStorage.setItem("X-Mock-Role", "super_admin");
|
|
}
|
|
}, []);
|
|
|
|
const toggleCollapse = () => {
|
|
const nextState = !isCollapsed;
|
|
setIsCollapsed(nextState);
|
|
window.localStorage.setItem("RoleSwitcher-Collapsed", String(nextState));
|
|
};
|
|
|
|
const switchRole = (role: string) => {
|
|
// localStorage 설정
|
|
window.localStorage.setItem("X-Mock-Role", role);
|
|
setCurrentRole(role);
|
|
// 페이지 새로고침하여 권한 적용
|
|
window.location.reload();
|
|
};
|
|
|
|
if (import.meta.env.MODE === "production") return null;
|
|
|
|
const roleLabels: Record<string, string> = {
|
|
super_admin: t("ui.admin.role.super_admin", "SUPER ADMIN"),
|
|
tenant_admin: t("ui.admin.role.tenant_admin", "TENANT ADMIN"),
|
|
rp_admin: t("ui.admin.role.rp_admin", "RP ADMIN"),
|
|
tenant_member: t("ui.admin.role.tenant_member", "TENANT MEMBER"),
|
|
};
|
|
|
|
return (
|
|
<div
|
|
style={{
|
|
position: "fixed",
|
|
bottom: "20px",
|
|
right: "20px",
|
|
zIndex: 9999,
|
|
background: "#1A1F2C",
|
|
color: "white",
|
|
padding: "8px 12px",
|
|
borderRadius: "8px",
|
|
boxShadow: "0 4px 12px rgba(0,0,0,0.3)",
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
gap: isCollapsed ? "0" : "8px",
|
|
fontSize: "12px",
|
|
transition: "all 0.3s ease",
|
|
border: "1px solid #333",
|
|
}}
|
|
>
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "space-between",
|
|
gap: "12px",
|
|
cursor: "pointer",
|
|
fontWeight: "bold",
|
|
paddingBottom: isCollapsed ? "0" : "4px",
|
|
borderBottom: isCollapsed ? "none" : "1px solid #444",
|
|
}}
|
|
onClick={toggleCollapse}
|
|
>
|
|
<div style={{ display: "flex", alignItems: "center", gap: "6px" }}>
|
|
<Wrench size={14} className="text-blue-400" />
|
|
{!isCollapsed && (
|
|
<span>{t("ui.admin.dev_role_switcher", "DEV Role Switcher")}</span>
|
|
)}
|
|
{isCollapsed && (
|
|
<span style={{ fontSize: "10px", color: "#888" }}>
|
|
{currentRole.toUpperCase()}
|
|
</span>
|
|
)}
|
|
</div>
|
|
{isCollapsed ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
|
|
</div>
|
|
|
|
{!isCollapsed && (
|
|
<div
|
|
style={{
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
gap: "6px",
|
|
marginTop: "4px",
|
|
}}
|
|
>
|
|
{(
|
|
[
|
|
"super_admin",
|
|
"tenant_admin",
|
|
"rp_admin",
|
|
"tenant_member",
|
|
] as const
|
|
).map((role) => (
|
|
<button
|
|
key={role}
|
|
type="button"
|
|
onClick={() => switchRole(role)}
|
|
style={{
|
|
background: currentRole === role ? "#3b82f6" : "#333",
|
|
color: "white",
|
|
border: "none",
|
|
padding: "4px 8px",
|
|
borderRadius: "4px",
|
|
cursor: "pointer",
|
|
textAlign: "left",
|
|
transition: "background 0.2s",
|
|
display: "flex",
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
}}
|
|
>
|
|
<span>
|
|
{roleLabels[role] ?? role.toUpperCase().replace("_", " ")}
|
|
</span>
|
|
{currentRole === role && (
|
|
<span style={{ marginLeft: "8px" }}>✅</span>
|
|
)}
|
|
</button>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default RoleSwitcher;
|