1
0
forked from baron/baron-sso

프론트엔드 UI/UX를 전면 개편

This commit is contained in:
2026-02-20 17:56:53 +09:00
parent 2ec2653bfb
commit 919bcd27e8
18 changed files with 1092 additions and 736 deletions

View File

@@ -30,11 +30,6 @@ const navItems = [
to: "/tenants",
icon: Building2,
},
{
label: "ui.admin.nav.user_groups",
to: "/user-groups",
icon: Users,
},
{ label: "ui.admin.nav.users", to: "/users", icon: Users },
{ label: "ui.admin.nav.api_keys", to: "/api-keys", icon: Key },
{ label: "ui.admin.nav.audit_logs", to: "/audit-logs", icon: NotebookTabs },

View File

@@ -1,9 +1,13 @@
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에서 역할 읽기
@@ -16,6 +20,12 @@ const RoleSwitcher: FC = () => {
}
}, []);
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);
@@ -42,47 +52,80 @@ const RoleSwitcher: FC = () => {
zIndex: 9999,
background: "#1A1F2C",
color: "white",
padding: "10px",
padding: "8px 12px",
borderRadius: "8px",
boxShadow: "0 4px 12px rgba(0,0,0,0.3)",
display: "flex",
flexDirection: "column",
gap: "8px",
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",
borderBottom: "1px solid #444",
paddingBottom: "4px",
marginBottom: "4px",
paddingBottom: isCollapsed ? "0" : "4px",
borderBottom: isCollapsed ? "none" : "1px solid #444",
}}
onClick={toggleCollapse}
>
{t("ui.admin.dev_role_switcher", "🛠 DEV Role Switcher")}
<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>
{(
["super_admin", "tenant_admin", "rp_admin", "tenant_member"] as const
).map((role) => (
<button
key={role}
type="button"
onClick={() => switchRole(role)}
{!isCollapsed && (
<div
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",
flexDirection: "column",
gap: "6px",
marginTop: "4px",
}}
>
{roleLabels[role] ?? role.toUpperCase().replace("_", " ")}{" "}
{currentRole === role ? "✅" : ""}
</button>
))}
{(
["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>
);
};