forked from baron/baron-sso
[#365] Devfront 프로필 메뉴 개선 및 상세 페이지 구현
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import {
|
||||
BadgeCheck,
|
||||
LogOut,
|
||||
@@ -5,6 +6,7 @@ import {
|
||||
NotebookTabs,
|
||||
ShieldHalf,
|
||||
Sun,
|
||||
User as UserIcon,
|
||||
} from "lucide-react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useAuth } from "react-oidc-context";
|
||||
@@ -13,6 +15,8 @@ import { t } from "../../lib/i18n";
|
||||
import { resolveProfileRole } from "../../lib/role";
|
||||
import LanguageSelector from "../common/LanguageSelector";
|
||||
import { Toaster } from "../ui/toaster";
|
||||
import { Badge } from "../ui/badge";
|
||||
import { fetchMe } from "../../features/auth/authApi";
|
||||
|
||||
const navItems = [
|
||||
{
|
||||
@@ -41,6 +45,13 @@ function AppLayout() {
|
||||
const [isRefreshingSession, setIsRefreshingSession] = useState(false);
|
||||
const [nowMs, setNowMs] = useState(() => Date.now());
|
||||
|
||||
const hasAccessToken = Boolean(auth.user?.access_token);
|
||||
const { data: profile } = useQuery({
|
||||
queryKey: ["userMe"],
|
||||
queryFn: fetchMe,
|
||||
enabled: hasAccessToken,
|
||||
});
|
||||
|
||||
const handleLogout = () => {
|
||||
if (window.confirm(t("msg.dev.logout_confirm", "로그아웃 하시겠습니까?"))) {
|
||||
auth.removeUser();
|
||||
@@ -100,6 +111,10 @@ function AppLayout() {
|
||||
const currentRole = resolveProfileRole(
|
||||
auth.user?.profile as Record<string, unknown> | undefined,
|
||||
);
|
||||
|
||||
// Use profile.role from API if available, otherwise fallback to local role
|
||||
const displayRoleKey = profile?.role || currentRole;
|
||||
|
||||
const isDevConsoleAllowed = [
|
||||
"super_admin",
|
||||
"tenant_admin",
|
||||
@@ -306,14 +321,35 @@ function AppLayout() {
|
||||
<p className="text-xs uppercase tracking-[0.16em] text-muted-foreground">
|
||||
{t("ui.dev.profile.menu_title", "Account")}
|
||||
</p>
|
||||
<div className="mt-2 rounded-lg border border-border px-3 py-2">
|
||||
<p className="truncate text-sm font-semibold text-foreground">
|
||||
{profileName}
|
||||
</p>
|
||||
<p className="truncate text-xs text-muted-foreground">
|
||||
{profileEmail}
|
||||
</p>
|
||||
<div className="mt-2 rounded-lg border border-border px-3 py-3 flex flex-col gap-2">
|
||||
<div>
|
||||
<p className="truncate text-sm font-semibold text-foreground">
|
||||
{profileName}
|
||||
</p>
|
||||
<p className="truncate text-xs text-muted-foreground">
|
||||
{profileEmail}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center pt-1">
|
||||
<Badge variant="outline" className="text-[10px] px-2 py-0">
|
||||
{t(`ui.common.role.${displayRoleKey}`, displayRoleKey.toUpperCase())}
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
className="mt-2 w-full flex items-center gap-2 rounded-lg border border-border px-3 py-2 text-left text-sm text-foreground transition hover:bg-muted/20"
|
||||
onClick={() => {
|
||||
navigate("/profile");
|
||||
setIsProfileMenuOpen(false);
|
||||
}}
|
||||
>
|
||||
<UserIcon size={16} className="text-muted-foreground" />
|
||||
<span>{t("ui.dev.profile.title", "내 정보")}</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
|
||||
Reference in New Issue
Block a user