1
0
forked from baron/baron-sso

i18n refresh and frontend fixes

This commit is contained in:
Lectom C Han
2026-02-10 19:15:51 +09:00
parent 2441c64598
commit b6d3b69cda
44 changed files with 8603 additions and 1760 deletions

View File

@@ -20,6 +20,7 @@ import {
TableRow,
} from "../../components/ui/table";
import { deleteApiKey, fetchApiKeys } from "../../lib/adminApi";
import { t } from "../../lib/i18n";
function ApiKeyListPage() {
const query = useQuery({
@@ -37,12 +38,25 @@ function ApiKeyListPage() {
const errorMsg = (query.error as AxiosError<{ error?: string }>)?.response
?.data?.error;
const fallbackError =
!errorMsg && query.isError ? "API 키 목록 조회에 실패했습니다." : null;
!errorMsg && query.isError
? t(
"msg.admin.api_keys.list.fetch_error",
"API 키 목록 조회에 실패했습니다.",
)
: null;
const items = query.data?.items ?? [];
const handleDelete = (id: string, name: string) => {
if (!window.confirm(`API 키 "${name}"를 삭제할까요?`)) {
if (
!window.confirm(
t(
"msg.admin.api_keys.list.delete_confirm",
'API 키 "{{name}}"를 삭제할까요?',
{ name },
),
)
) {
return;
}
deleteMutation.mutate(id);
@@ -53,14 +67,22 @@ function ApiKeyListPage() {
<header className="flex flex-wrap items-start justify-between gap-4">
<div className="space-y-2">
<div className="flex items-center gap-2 text-sm text-[var(--color-muted)]">
<span>API Keys</span>
<span>
{t("ui.admin.api_keys.list.breadcrumb.section", "API Keys")}
</span>
<span>/</span>
<span className="text-foreground">List</span>
<span className="text-foreground">
{t("ui.admin.api_keys.list.breadcrumb.list", "List")}
</span>
</div>
<h2 className="text-3xl font-semibold">API (M2M)</h2>
<h2 className="text-3xl font-semibold">
{t("ui.admin.api_keys.list.title", "API 키 관리 (M2M)")}
</h2>
<p className="text-sm text-[var(--color-muted)]">
(Machine-to-Machine) API
.
{t(
"msg.admin.api_keys.list.subtitle",
"서버 간 통신(Machine-to-Machine)을 위한 API 키를 발급하고 관리합니다.",
)}
</p>
</div>
<div className="flex items-center gap-2">
@@ -70,12 +92,12 @@ function ApiKeyListPage() {
disabled={query.isFetching}
>
<RefreshCw size={16} />
{t("ui.common.refresh", "새로고침")}
</Button>
<Button asChild>
<Link to="/api-keys/new">
<Plus size={16} />
API
{t("ui.admin.api_keys.list.add", "API 키 생성")}
</Link>
</Button>
</div>
@@ -84,12 +106,18 @@ function ApiKeyListPage() {
<Card className="bg-[var(--color-panel)]">
<CardHeader className="flex flex-row items-center justify-between">
<div>
<CardTitle>API Key Registry</CardTitle>
<CardTitle>
{t("ui.admin.api_keys.list.registry.title", "API Key Registry")}
</CardTitle>
<CardDescription>
{query.data?.total ?? 0} API
{t(
"msg.admin.api_keys.list.registry.count",
"총 {{count}}개 API 키",
{ count: query.data?.total ?? 0 },
)}
</CardDescription>
</div>
<Badge variant="muted">System</Badge>
<Badge variant="muted">{t("ui.common.badge.system", "System")}</Badge>
</CardHeader>
<CardContent>
{(errorMsg || fallbackError) && (
@@ -101,22 +129,39 @@ function ApiKeyListPage() {
<Table>
<TableHeader>
<TableRow>
<TableHead>NAME</TableHead>
<TableHead>CLIENT ID</TableHead>
<TableHead>SCOPES</TableHead>
<TableHead>LAST USED</TableHead>
<TableHead className="text-right">ACTIONS</TableHead>
<TableHead>
{t("ui.admin.api_keys.list.table.name", "NAME")}
</TableHead>
<TableHead>
{t("ui.admin.api_keys.list.table.client_id", "CLIENT ID")}
</TableHead>
<TableHead>
{t("ui.admin.api_keys.list.table.scopes", "SCOPES")}
</TableHead>
<TableHead>
{t("ui.admin.api_keys.list.table.last_used", "LAST USED")}
</TableHead>
<TableHead className="text-right">
{t("ui.admin.api_keys.list.table.actions", "ACTIONS")}
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{query.isLoading && (
<TableRow>
<TableCell colSpan={5}> ...</TableCell>
<TableCell colSpan={5}>
{t("msg.common.loading", "로딩 중...")}
</TableCell>
</TableRow>
)}
{!query.isLoading && items.length === 0 && (
<TableRow>
<TableCell colSpan={5}> API .</TableCell>
<TableCell colSpan={5}>
{t(
"msg.admin.api_keys.list.empty",
"등록된 API 키가 없습니다.",
)}
</TableCell>
</TableRow>
)}
{items.map((key) => (
@@ -146,7 +191,7 @@ function ApiKeyListPage() {
<TableCell>
{key.lastUsedAt
? new Date(key.lastUsedAt).toLocaleString("ko-KR")
: "Never"}
: t("ui.common.never", "Never")}
</TableCell>
<TableCell className="text-right">
<Button
@@ -156,7 +201,7 @@ function ApiKeyListPage() {
disabled={deleteMutation.isPending}
>
<Trash2 size={14} />
{t("ui.common.delete", "삭제")}
</Button>
</TableCell>
</TableRow>