1
0
forked from baron/baron-sso

devfront: 개요 페이지 경로와 레이아웃 정리

This commit is contained in:
2026-05-14 17:01:50 +09:00
parent c0894eeb8a
commit 0327409631
5 changed files with 26 additions and 72 deletions

View File

@@ -8,7 +8,7 @@ import {
Layers3,
ShieldCheck,
} from "lucide-react";
import { type ReactNode, useMemo, useState } from "react";
import { useMemo, useState } from "react";
import { useAuth } from "react-oidc-context";
import { useNavigate } from "react-router-dom";
import {
@@ -22,6 +22,11 @@ import {
} from "../../lib/devApi";
import { t } from "../../lib/i18n";
import { resolveProfileRole } from "../../lib/role";
import {
OverviewAxisNotes,
OverviewMetric,
OverviewSelectionChips,
} from "../../../../common/core/components/overview";
type ClientDistribution = {
activeClients: number;
@@ -261,24 +266,6 @@ function formatMetric(value: number | undefined) {
return value === undefined ? "-" : value.toLocaleString();
}
function OverviewMetric({
icon,
label,
value,
}: {
icon: ReactNode;
label: string;
value: string;
}) {
return (
<span className="inline-flex items-center gap-2 whitespace-nowrap text-sm">
<span className="text-muted-foreground">{icon}</span>
<span className="text-muted-foreground">{label}</span>
<span className="font-semibold tabular-nums">{value}</span>
</span>
);
}
function RPUsageMixedChart({
period,
rows,
@@ -425,10 +412,10 @@ function RPUsageMixedChart({
</svg>
</div>
<div className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-muted-foreground">
<span>{t("ui.dev.dashboard.chart.x_axis", "X축: 기간")}</span>
<span>{t("ui.dev.dashboard.chart.y_axis", "Y축: 로그인 요청 수")}</span>
</div>
<OverviewAxisNotes
xAxisLabel={t("ui.common.chart.axis.x", "X축: 기간")}
yAxisLabel={t("ui.common.chart.axis.y", "Y축: 로그인 요청 수")}
/>
{multiLinePoints && multiLinePoints.length > 0 ? (
<div className="grid gap-x-6 gap-y-2 border-t border-border/60 pt-2 text-xs md:grid-cols-2 xl:grid-cols-3">
@@ -486,7 +473,7 @@ function RPUsageMixedChart({
);
}
function DashboardPage() {
function GlobalOverviewPage() {
const navigate = useNavigate();
const auth = useAuth();
const hasAccessToken = Boolean(auth.user?.access_token);
@@ -633,7 +620,7 @@ function DashboardPage() {
<div className="rounded-xl border border-border/60 bg-card p-8 text-center">
<div className="space-y-3">
<h2 className="text-2xl font-semibold tracking-tight">
{t("ui.dev.dashboard.title", "대시보드")}
{t("ui.common.overview.title", "운영 현황")}
</h2>
<p className="font-medium text-foreground">
{isDeveloperRequestPending
@@ -678,7 +665,7 @@ function DashboardPage() {
<div className="flex flex-wrap items-end justify-between gap-4">
<div className="space-y-1">
<h2 className="text-2xl font-semibold tracking-tight">
{t("ui.dev.dashboard.title", "Dashboard")}
{t("ui.common.overview.title", "운영 현황")}
</h2>
<p className="text-sm text-muted-foreground">
{t(
@@ -736,9 +723,9 @@ function DashboardPage() {
</div>
<div className="flex h-8 items-center gap-1" aria-label="집계 단위">
{[
["day", t("ui.dev.dashboard.chart.period_day", "일")],
["week", t("ui.dev.dashboard.chart.period_week", "주")],
["month", t("ui.dev.dashboard.chart.period_month", "월")],
["day", t("ui.common.chart.period.day", "일")],
["week", t("ui.common.chart.period.week", "주")],
["month", t("ui.common.chart.period.month", "월")],
].map(([value, label]) => (
<button
key={value}
@@ -757,31 +744,13 @@ function DashboardPage() {
</div>
</div>
<div className="flex flex-wrap gap-2 rounded-xl border border-border/60 bg-card/60 p-3">
<label className="inline-flex items-center gap-2 rounded-full border border-border/60 px-3 py-1.5 text-xs">
<input
type="checkbox"
checked={isAllClientsSelected}
onChange={selectAllClients}
className="h-3.5 w-3.5"
/>
<span>{t("ui.dev.dashboard.chart.filter_all", "전체")}</span>
</label>
{clientFilterOptions.map((client) => (
<label
key={client.id}
className="inline-flex items-center gap-2 rounded-full border border-border/60 px-3 py-1.5 text-xs"
>
<input
type="checkbox"
checked={selectedClientIds.includes(client.id)}
onChange={() => toggleClientSelection(client.id)}
className="h-3.5 w-3.5"
/>
<span>{client.label}</span>
</label>
))}
</div>
<OverviewSelectionChips
allLabel={t("ui.dev.dashboard.chart.filter_all", "전체")}
options={clientFilterOptions}
selectedIds={selectedClientIds}
onSelectAll={selectAllClients}
onToggle={toggleClientSelection}
/>
{usageQuery.isError ? (
<div className="text-sm text-muted-foreground">{usageErrorText}</div>
@@ -910,4 +879,4 @@ function DashboardPage() {
);
}
export default DashboardPage;
export default GlobalOverviewPage;