forked from baron/baron-sso
devfront: 개요 페이지 경로와 레이아웃 정리
This commit is contained in:
@@ -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;
|
||||
Reference in New Issue
Block a user