1
0
forked from baron/baron-sso

feat(adminfront): remove unused tenant dashboard and update global overview quick links

This commit is contained in:
2026-03-04 09:41:49 +09:00
parent cb16a8a9a5
commit 69470e8e4a
7 changed files with 27 additions and 264 deletions

View File

@@ -6,7 +6,6 @@ import AuditLogsPage from "../features/audit/AuditLogsPage";
import AuthCallbackPage from "../features/auth/AuthCallbackPage";
import AuthPage from "../features/auth/AuthPage";
import LoginPage from "../features/auth/LoginPage";
import DashboardPage from "../features/dashboard/DashboardPage";
import GlobalOverviewPage from "../features/overview/GlobalOverviewPage";
import { TenantAdminsAndOwnersTab } from "../features/tenants/routes/TenantAdminsAndOwnersTab";
import TenantCreatePage from "../features/tenants/routes/TenantCreatePage";
@@ -35,7 +34,6 @@ export const router = createBrowserRouter(
element: <AppLayout />,
children: [
{ index: true, element: <GlobalOverviewPage /> },
{ path: "dashboard", element: <DashboardPage /> },
{ path: "audit-logs", element: <AuditLogsPage /> },
{ path: "auth", element: <AuthPage /> },
{ path: "users", element: <UserListPage /> },

View File

@@ -24,11 +24,6 @@ import RoleSwitcher from "./RoleSwitcher";
const navItems = [
{ label: "ui.admin.nav.overview", to: "/", icon: LayoutDashboard },
{
label: "ui.admin.nav.tenant_dashboard",
to: "/dashboard",
icon: ShieldHalf,
},
{
label: "ui.admin.nav.tenants",
to: "/tenants",

View File

@@ -1,243 +0,0 @@
import {
Activity,
ArrowRight,
Building2,
CheckCircle2,
LineChart,
Radio,
ShieldCheck,
Sparkles,
} from "lucide-react";
const guardHighlights = [
{
title: "Tenant isolation",
body: "All admin calls expect X-Tenant-ID and are prepared for tenant-aware headers.",
metric: "Header guard",
accent: "active",
},
{
title: "Admin TTL",
body: "Session budget kept short for admins. App session vs admin session split is explicit.",
metric: "15m default",
accent: "ttl",
},
{
title: "Audit-first",
body: "Every management action should log to ClickHouse. Hooks in place for later wiring.",
metric: "per-action",
accent: "audit",
},
];
const stackReadiness = [
"React 19 + Vite 7, strict TS, Router v6 data router.",
"TanStack Query 5 provider ready with sane defaults.",
"Axios client stub with bearer + tenant header injector.",
"Tailwind v4 tokens tuned for admin dark plane.",
"React Hook Form + Zod planned for client forms.",
"IdP-neutral auth hook point reserved for role guard.",
];
const nextSteps = [
"Add IdP-neutral OIDC/OAuth auth layer and enforce admin role in RequireAuth.",
"Persist tenant picklist and feed X-Tenant-ID for every admin call.",
"Add shadcn/ui primitives for forms and tables; lock lint/format.",
];
function DashboardPage() {
return (
<div className="space-y-10">
<section className="relative overflow-hidden rounded-2xl border border-[var(--color-border)] bg-[var(--color-panel)] p-7 shadow-[var(--shadow-card)]">
<div className="pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_24%_20%,rgba(54,211,153,0.14),transparent_32%)]" />
<div className="relative flex flex-col gap-6 md:flex-row md:items-center md:justify-between">
<div className="space-y-3 max-w-2xl">
<div className="inline-flex items-center gap-2 rounded-full border border-[var(--color-border)] px-3 py-1 text-xs uppercase tracking-[0.2em] text-[var(--color-muted)]">
<Sparkles size={14} />
adminfront ready
</div>
<h2 className="text-3xl font-semibold leading-tight">
Build the admin plane with{" "}
<span className="text-[var(--color-accent)]">tenant-aware</span>{" "}
defaults and{" "}
<span className="text-[var(--color-accent-strong)]">
least privilege
</span>{" "}
UX.
</h2>
<p className="text-[var(--color-muted)]">
Route, query, and styling scaffolds are in place. Use this canvas
to ship RP registry, audit exploration, and guarded login aligned
with issue #60 while keeping providers swappable.
</p>
<div className="flex flex-wrap gap-3 text-sm">
<span className="rounded-full bg-[rgba(54,211,153,0.16)] px-3 py-2 text-[var(--color-accent)]">
Router + Query wired
</span>
<span className="rounded-full border border-[var(--color-border)] px-3 py-2 text-[var(--color-muted)]">
Admin namespace only
</span>
<span className="rounded-full bg-[rgba(249,168,38,0.16)] px-3 py-2 font-semibold text-[var(--color-accent-strong)]">
Auth hook pending
</span>
</div>
</div>
<div className="grid gap-3 text-sm">
<div className="flex items-center gap-2 rounded-xl border border-[var(--color-border)] bg-[rgba(255,255,255,0.02)] px-4 py-3 text-[var(--color-muted)]">
<ShieldCheck size={16} />
Admin guard scoped to /admin
</div>
<div className="flex items-center gap-2 rounded-xl border border-[var(--color-border)] bg-[rgba(255,255,255,0.02)] px-4 py-3 text-[var(--color-muted)]">
<Building2 size={16} />
Tenant selection placeholder ready
</div>
<div className="flex items-center gap-2 rounded-xl border border-[var(--color-border)] bg-[rgba(255,255,255,0.02)] px-4 py-3 text-[var(--color-muted)]">
<Radio size={16} />
Audit stream hook for ClickHouse
</div>
</div>
</div>
</section>
<section className="grid gap-4 md:grid-cols-3">
{guardHighlights.map((item) => (
<div
key={item.title}
className="relative overflow-hidden rounded-xl border border-[var(--color-border)] bg-[var(--color-panel)] p-5 transition hover:-translate-y-1 hover:shadow-[0_16px_48px_rgba(7,15,26,0.4)]"
>
<div className="absolute inset-0 bg-[radial-gradient(circle_at_25%_25%,rgba(54,211,153,0.12),transparent_45%)]" />
<div className="relative flex items-center justify-between gap-2">
<div className="text-xs uppercase tracking-[0.2em] text-[var(--color-muted)]">
{item.metric}
</div>
<span className="rounded-full border border-[var(--color-border)] px-3 py-1 text-[11px] text-[var(--color-muted)]">
{item.accent}
</span>
</div>
<div className="relative mt-3 space-y-2">
<h3 className="text-lg font-semibold">{item.title}</h3>
<p className="text-sm text-[var(--color-muted)]">{item.body}</p>
</div>
</div>
))}
</section>
<section className="grid gap-6 md:grid-cols-[1.2fr,0.8fr]">
<div className="rounded-2xl border border-[var(--color-border)] bg-[var(--color-panel)] p-6">
<div className="flex items-center justify-between gap-3">
<div>
<p className="text-xs uppercase tracking-[0.2em] text-[var(--color-muted)]">
Stack readiness
</p>
<h3 className="text-xl font-semibold">Matches issue #60</h3>
</div>
<button
type="button"
className="inline-flex items-center gap-2 rounded-full border border-[var(--color-border)] px-3 py-2 text-sm text-[var(--color-muted)] transition hover:border-[var(--color-accent)] hover:text-[var(--color-accent)]"
>
Setup notes
<ArrowRight size={14} />
</button>
</div>
<div className="mt-4 grid gap-3 md:grid-cols-2">
{stackReadiness.map((item) => (
<div
key={item}
className="flex items-center gap-3 rounded-xl border border-[var(--color-border)] bg-[rgba(255,255,255,0.02)] px-4 py-3"
>
<CheckCircle2
size={16}
className="text-[var(--color-accent)]"
/>
<p className="text-sm">{item}</p>
</div>
))}
</div>
</div>
<div className="rounded-2xl border border-[var(--color-border)] bg-[var(--color-panel)] p-6">
<p className="text-xs uppercase tracking-[0.2em] text-[var(--color-muted)]">
Next actions
</p>
<h3 className="mt-2 text-xl font-semibold">
Ship the first guarded flows
</h3>
<div className="mt-4 space-y-3">
{nextSteps.map((item, idx) => (
<div
key={item}
className="flex gap-3 rounded-xl border border-[var(--color-border)] bg-[rgba(255,255,255,0.02)] px-4 py-3"
>
<div className="grid h-8 w-8 place-items-center rounded-full bg-[rgba(249,168,38,0.12)] text-sm font-semibold text-[var(--color-accent-strong)]">
{idx + 1}
</div>
<p className="text-sm text-[var(--color-text)]">{item}</p>
</div>
))}
</div>
</div>
</section>
<section className="rounded-2xl border border-[var(--color-border)] bg-[var(--color-panel)] p-6">
<div className="flex flex-col gap-2 md:flex-row md:items-center md:justify-between">
<div>
<p className="text-xs uppercase tracking-[0.2em] text-[var(--color-muted)]">
Ops board
</p>
<h3 className="text-xl font-semibold">What to prototype next</h3>
</div>
<div className="flex items-center gap-2 text-sm text-[var(--color-muted)]">
<span className="rounded-full border border-[var(--color-border)] px-3 py-2">
Audit ClickHouse
</span>
<span className="rounded-full border border-[var(--color-border)] px-3 py-2">
RP registry
</span>
</div>
</div>
<div className="mt-4 grid gap-4 md:grid-cols-3">
<div className="rounded-xl border border-[var(--color-border)] bg-[rgba(255,255,255,0.02)] p-4">
<div className="flex items-center gap-2 text-[var(--color-muted)]">
<LineChart size={16} />
<span className="text-xs uppercase tracking-[0.16em]">
Metrics
</span>
</div>
<h4 className="mt-2 text-lg font-semibold">
RP registration funnel
</h4>
<p className="text-sm text-[var(--color-muted)]">
Visualize create secret rotate redirect URI edits per tenant.
</p>
</div>
<div className="rounded-xl border border-[var(--color-border)] bg-[rgba(255,255,255,0.02)] p-4">
<div className="flex items-center gap-2 text-[var(--color-muted)]">
<Activity size={16} />
<span className="text-xs uppercase tracking-[0.16em]">Audit</span>
</div>
<h4 className="mt-2 text-lg font-semibold">Admin action stream</h4>
<p className="text-sm text-[var(--color-muted)]">
Live feed of admin API calls with per-action tenant, actor, and
rate-limit outcome.
</p>
</div>
<div className="rounded-xl border border-[var(--color-border)] bg-[rgba(255,255,255,0.02)] p-4">
<div className="flex items-center gap-2 text-[var(--color-muted)]">
<ShieldCheck size={16} />
<span className="text-xs uppercase tracking-[0.16em]">
Access
</span>
</div>
<h4 className="mt-2 text-lg font-semibold">Admin login journey</h4>
<p className="text-sm text-[var(--color-muted)]">
Outline SMS + app-based MFA choice and emphasize admin session
TTL with logout.
</p>
</div>
</div>
</section>
</div>
);
}
export default DashboardPage;

View File

@@ -193,10 +193,10 @@ function GlobalOverviewPage() {
className="w-full justify-between"
variant="outline"
>
<Link to="/audit-logs">
<Link to="/users">
{t(
"ui.admin.overview.quick_links.view_audit_logs",
"감사 로그 보기",
"ui.admin.overview.quick_links.user_management",
"사용자 관리",
)}
<ArrowUpRight size={16} />
</Link>
@@ -206,10 +206,23 @@ function GlobalOverviewPage() {
className="w-full justify-between"
variant="outline"
>
<Link to="/dashboard">
<Link to="/api-keys">
{t(
"ui.admin.overview.quick_links.tenant_dashboard",
"테넌트 대시보드",
"ui.admin.overview.quick_links.api_key_management",
"API 키 관리",
)}
<ArrowUpRight size={16} />
</Link>
</Button>
<Button
asChild
className="w-full justify-between"
variant="outline"
>
<Link to="/audit-logs">
{t(
"ui.admin.overview.quick_links.view_audit_logs",
"감사 로그 보기",
)}
<ArrowUpRight size={16} />
</Link>

View File

@@ -732,9 +732,10 @@ title = "Tenant-independent control plane"
title = "Admin playbook"
[ui.admin.overview.quick_links]
add_tenant = "Tenant Add"
tenant_dashboard = "Tenant Dashboard"
title = "Title"
add_tenant = "Add Tenant"
api_key_management = "API Key Management"
title = "Quick Links"
user_management = "User Management"
view_audit_logs = "View Audit Logs"
[ui.admin.role]
@@ -1393,7 +1394,6 @@ auth_guard = "Auth Guard"
logout = "Logout"
overview = "Overview"
relying_parties = "Apps (RP)"
tenant_dashboard = "Tenant Dashboard"
user_groups = "Organization"
tenants = "Tenants"
users = "Users"

View File

@@ -777,8 +777,9 @@ title = "운영 플레이북"
[ui.admin.overview.quick_links]
add_tenant = "테넌트 추가"
tenant_dashboard = "테넌트 대시보드"
api_key_management = "API 키 관리"
title = "빠른 이동"
user_management = "사용자 관리"
view_audit_logs = "감사 로그 보기"
[ui.admin.overview.summary]
@@ -1485,7 +1486,6 @@ auth_guard = "인증 가드"
logout = "로그아웃"
overview = "개요"
relying_parties = "애플리케이션(RP)"
tenant_dashboard = "테넌트 대시보드"
user_groups = "조직 관리"
tenants = "테넌트"
users = "사용자"

View File

@@ -691,7 +691,6 @@ auth_guard = ""
logout = ""
overview = ""
relying_parties = ""
tenant_dashboard = ""
user_groups = ""
tenants = ""
users = ""
@@ -705,8 +704,9 @@ title = ""
[ui.admin.overview.quick_links]
add_tenant = ""
tenant_dashboard = ""
api_key_management = ""
title = ""
user_management = ""
view_audit_logs = ""
[ui.admin.role]