Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/web/app/app-globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,9 @@ div[style*="z-index"] > div > .custom-marker {
BlinkMacSystemFont, "Segoe UI", "Apple SD Gothic Neo", "Malgun Gothic",
sans-serif;
letter-spacing: 0;
font-size: 15px;
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}

[data-admin-console-content="true"] {
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export default async function RootLayout({
return (
<html
lang="ko"
className={`${pretendard.variable} ${notoSerifKr.variable}`}
className={`${pretendard.variable} ${notoSerifKr.variable} ${pretendard.className}`}
suppressHydrationWarning
>
<head>
Expand Down
48 changes: 18 additions & 30 deletions apps/web/components/admin/AdminConsoleOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -709,11 +709,6 @@ function loadAdminRouteRecommendationModule() {
);
}

function loadAdminSystemStatusCenter() {
return import("@/components/admin/system-status/AdminSystemStatusCenter").then(
(module) => module.AdminSystemStatusCenter,
);
}

const ADMIN_EVALUATION_STATIC_STATUS_FILTERS = ["전체", "미처리", "승인대기", "승인됨", "누락", "삭제됨"] as const;

Expand Down Expand Up @@ -900,10 +895,6 @@ const AdminRouteRecommendationModule = dynamic(
},
);

const AdminSystemStatusCenter = dynamic(loadAdminSystemStatusCenter, {
ssr: false,
loading: () => null,
});
const ADMIN_CONSOLE_INLINE_MODULE_IDS = new Set<AdminModuleId>([
"overview",
"map-overlays",
Expand Down Expand Up @@ -2998,7 +2989,7 @@ const adminDashboardFocusPalette = {
const adminDashboardControlGroupClassName =
"inline-flex h-7 shrink-0 items-center rounded-full border border-border bg-muted/25 p-0.5";
const adminDashboardControlButtonClassName =
"inline-flex h-6 shrink-0 items-center justify-center gap-1 rounded-full px-2.5 text-[11px] font-extrabold leading-none transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary";
"inline-flex h-6 shrink-0 items-center justify-center gap-1 rounded-full px-2 text-[10px] font-extrabold leading-none transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary";
const adminDashboardFullscreenCardClassName =
"fixed inset-2 z-[80] h-[calc(100dvh-1rem)] max-h-[calc(100dvh-1rem)] overflow-auto scrollbar-hide rounded-3xl border-primary/35 bg-card p-4 shadow-2xl sm:inset-4 sm:h-[calc(100dvh-2rem)] sm:max-h-[calc(100dvh-2rem)]";

Expand Down Expand Up @@ -3447,7 +3438,7 @@ function AdminDashboardImpactRankLegend() {
<div
className={cn(
adminDashboardControlGroupClassName,
"gap-1 px-2.5 text-[11px] font-extrabold leading-none text-muted-foreground shadow-sm",
"gap-1 px-2 text-[10px] font-extrabold leading-none text-muted-foreground shadow-sm",
)}
aria-label="상위 영상 영향도 색상 범례: 순위 구분"
data-admin-dashboard-rank-legend="impact"
Expand Down Expand Up @@ -3513,7 +3504,7 @@ function AdminDashboardScrollTable<Row>({
key={column.key}
scope="col"
className={cn(
"min-w-0 border-b border-border/70 px-2.5 py-2 text-left text-[11px] font-extrabold text-muted-foreground",
"min-w-0 border-b border-border/70 px-2.5 py-2 text-left text-[10px] font-extrabold text-muted-foreground",
column.align === "right" && "text-right",
column.className,
)}
Expand Down Expand Up @@ -3804,7 +3795,7 @@ function AdminDashboardManagementSkeleton() {
>
<div className="mb-2 flex shrink-0 flex-col gap-2 md:flex-row md:items-start md:justify-between">
<div className="hidden min-w-0 md:block">
<h1 className="text-xl font-extrabold leading-tight tracking-[0.01em] text-foreground text-balance">
<h1 className="text-sm font-extrabold leading-tight tracking-[0.01em] text-foreground text-balance">
Tzuyang KPI Dashboard
</h1>
</div>
Expand All @@ -3823,7 +3814,7 @@ function AdminDashboardManagementSkeleton() {
type="button"
variant="outline"
size="sm"
className="h-7 shrink-0 rounded-full px-2 text-[11px]"
className="h-7 shrink-0 rounded-full px-2 text-[10px]"
disabled
>
카드 순서
Expand All @@ -3832,7 +3823,7 @@ function AdminDashboardManagementSkeleton() {
type="button"
variant="outline"
size="sm"
className="h-7 shrink-0 rounded-full px-2 text-[11px]"
className="h-7 shrink-0 rounded-full px-2 text-[10px]"
disabled
>
초기화
Expand All @@ -3846,7 +3837,7 @@ function AdminDashboardManagementSkeleton() {
type="button"
variant="outline"
size="sm"
className="h-7 shrink-0 gap-1 rounded-full px-2 text-[11px] font-bold"
className="h-7 shrink-0 gap-1 rounded-full px-2 text-[10px] font-bold"
disabled
>
<FileDown className="h-3.5 w-3.5" aria-hidden="true" />
Expand All @@ -3867,7 +3858,7 @@ function AdminDashboardManagementSkeleton() {
type="button"
variant="outline"
size="sm"
className="order-3 h-7 shrink-0 gap-1 rounded-full px-2 text-[11px] font-bold text-muted-foreground md:hidden"
className="order-3 h-7 shrink-0 gap-1 rounded-full px-2 text-[10px] font-extrabold text-muted-foreground md:hidden"
aria-label="대시보드 타임프레임 로딩 중: 1개월"
disabled
>
Expand All @@ -3884,7 +3875,7 @@ function AdminDashboardManagementSkeleton() {
type="button"
variant={option.value === "1M" ? "default" : "outline"}
size="sm"
className="h-7 shrink-0 rounded-full px-2 text-[11px]"
className="h-7 shrink-0 rounded-full px-2 text-[10px]"
aria-pressed={option.value === "1M"}
disabled
>
Expand Down Expand Up @@ -4151,7 +4142,7 @@ function AdminDashboardCardTitle({
data-admin-dashboard-card-title-row="single-line"
>
<div className="flex min-w-0 max-w-full flex-1 items-center gap-1.5">
<p className="truncate whitespace-nowrap text-xs font-extrabold leading-none text-foreground">
<p className="truncate whitespace-nowrap text-[11px] font-extrabold leading-none text-foreground">
{title}
{metric ? (
<span
Expand Down Expand Up @@ -4320,7 +4311,7 @@ function AdminDashboardKpiCard({
data-admin-dashboard-kpi-title-row="single-line"
>
<div className="flex min-w-0 flex-1 items-center gap-1.5">
<p className="truncate whitespace-nowrap text-xs font-extrabold tracking-[0.04em] text-muted-foreground">
<p className="truncate whitespace-nowrap text-[11px] font-extrabold tracking-[0.04em] text-muted-foreground">
{title}
</p>
{infoLines.length > 0 ? (
Expand Down Expand Up @@ -4373,7 +4364,7 @@ function AdminDashboardKpiCard({
<div className="flex min-h-0 min-w-0 items-center justify-between gap-3">
<div className="min-w-0">
<p
className="whitespace-nowrap text-lg font-black leading-none tracking-[-0.035em] tabular-nums text-foreground sm:text-xl"
className="whitespace-nowrap text-sm font-black leading-none tracking-[-0.035em] tabular-nums text-foreground sm:text-base"
data-admin-dashboard-kpi-value-size="bounded"
>
{value}
Expand Down Expand Up @@ -5601,7 +5592,7 @@ function AdminDashboardPeriodSelector({
type="button"
variant={isSelected ? "default" : "outline"}
size="sm"
className="h-7 shrink-0 rounded-full px-2 text-[11px] font-bold"
className="h-7 shrink-0 rounded-full px-2 text-[10px] font-bold"
aria-pressed={isSelected}
data-admin-dashboard-period-option={option.value}
onClick={() => onChange(option.value)}
Expand All @@ -5617,7 +5608,7 @@ function AdminDashboardPeriodSelector({
type="button"
variant="outline"
size="sm"
className="order-3 h-7 shrink-0 gap-1 rounded-full px-2 text-[11px] font-bold text-muted-foreground hover:text-foreground md:hidden"
className="order-3 h-7 shrink-0 gap-1 rounded-full px-2 text-[10px] font-extrabold text-muted-foreground hover:text-foreground md:hidden"
aria-label={`대시보드 타임프레임 설정: ${selectedOption.label}`}
data-admin-dashboard-period-select-trigger="true"
>
Expand Down Expand Up @@ -5651,7 +5642,7 @@ function AdminDashboardPeriodSelector({
type="button"
variant={isSelected ? "default" : "ghost"}
size="sm"
className="h-11 min-h-11 min-w-[44px] rounded-xl px-2 text-[11px] font-bold"
className="h-11 min-h-11 min-w-[44px] rounded-xl px-2 text-[10px] font-bold"
style={{ minWidth: 44 }}
aria-pressed={isSelected}
data-admin-dashboard-period-option={option.value}
Expand Down Expand Up @@ -7237,7 +7228,7 @@ function AdminDashboardManagementPanel({
>
<div className="mb-2 flex shrink-0 flex-col gap-2 md:flex-row md:items-start md:justify-between">
<div className="hidden min-w-0 md:block">
<h1 className="text-xl font-extrabold leading-tight tracking-[0.01em] text-foreground text-balance">
<h1 className="text-sm font-extrabold leading-tight tracking-[0.01em] text-foreground text-balance">
Tzuyang KPI Dashboard
</h1>
</div>
Expand All @@ -7256,7 +7247,7 @@ function AdminDashboardManagementPanel({
type="button"
variant={isDashboardOrderEditorOpen ? "default" : "outline"}
size="sm"
className="h-7 shrink-0 rounded-full px-2 text-[11px]"
className="h-7 shrink-0 rounded-full px-2 text-[10px]"
aria-label="KPI 카드 직접 드래그 순서 설정"
aria-pressed={isDashboardOrderEditorOpen}
disabled={isDashboardOrderLoading}
Expand All @@ -7277,7 +7268,7 @@ function AdminDashboardManagementPanel({
type="button"
variant="outline"
size="sm"
className="h-7 shrink-0 rounded-full px-2 text-[11px]"
className="h-7 shrink-0 rounded-full px-2 text-[10px]"
disabled={
isDashboardOrderLoading ||
isDashboardOrderSaving ||
Expand Down Expand Up @@ -7960,9 +7951,6 @@ function AdminDashboardManagementPanel({
</AdminDashboardDeferredBody>
</div>
</div>
<div className="mt-2 shrink-0" data-admin-system-status-slot="true">
<AdminSystemStatusCenter isAdmin={isAdmin} />
</div>
</section>
);
}
Expand Down
72 changes: 40 additions & 32 deletions apps/web/components/admin/AdminEmbeddedModuleShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ export function AdminEmbeddedModuleShell({
contentClassName,
scrollOwner,
}: AdminEmbeddedModuleShellProps) {
const hideHeader = moduleId === "overview";

return (
<section
aria-labelledby={titleId}
Expand All @@ -44,42 +46,48 @@ export function AdminEmbeddedModuleShell({
data-admin-embedded-module-id={moduleId}
data-layout-primitives="stack"
>
<div
className={cn(
"shrink-0 border-b border-border bg-card px-2 py-1.5",
headerClassName,
)}
data-admin-module-header="compact"
data-admin-module-header-module={moduleId}
>
<div className="flex min-w-0 flex-row items-start justify-between gap-1.5 lg:items-center">
<div className="min-w-0 flex-1">
<div className="flex min-w-0 items-center gap-2">
<Icon className="h-5 w-5 shrink-0 text-primary" aria-hidden="true" />
<h2
id={titleId}
className="min-w-0 truncate whitespace-nowrap bg-gradient-primary bg-clip-text text-base font-bold text-transparent"
{hideHeader ? (
<h2 id={titleId} className="sr-only">
{title}
</h2>
) : (
<div
className={cn(
"shrink-0 border-b border-border bg-card px-2 py-1.5",
headerClassName,
)}
data-admin-module-header="compact"
data-admin-module-header-module={moduleId}
>
<div className="flex min-w-0 flex-row items-start justify-between gap-1.5 lg:items-center">
<div className="min-w-0 flex-1">
<div className="flex min-w-0 items-center gap-2">
<Icon className="h-5 w-5 shrink-0 text-primary" aria-hidden="true" />
<h2
id={titleId}
className="min-w-0 truncate whitespace-nowrap bg-gradient-primary bg-clip-text text-sm font-bold text-transparent"
>
{title}
</h2>
</div>
<div
className="mt-0.5 min-w-0 truncate text-[11px] text-muted-foreground"
data-admin-module-summary="true"
>
{title}
</h2>
</div>
<div
className="mt-0.5 min-w-0 truncate text-xs text-muted-foreground"
data-admin-module-summary="true"
>
{summary}
{summary}
</div>
</div>
{actions ? (
<div
className="ml-auto flex min-w-0 shrink-0 flex-wrap items-center justify-end gap-1.5"
data-admin-module-actions="top-right"
>
{actions}
</div>
) : null}
</div>
{actions ? (
<div
className="ml-auto flex min-w-0 shrink-0 flex-wrap items-center justify-end gap-1.5"
data-admin-module-actions="top-right"
>
{actions}
</div>
) : null}
</div>
</div>
)}
<div
className={cn("min-h-0 min-w-0 flex-1 overflow-hidden", contentClassName)}
data-admin-module-content="bounded"
Expand Down
21 changes: 11 additions & 10 deletions apps/web/tests-unit/admin-console-uiux-source.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,7 @@ describe("admin console beginner-friendly UI/UX source contract", () => {
);
expect(shellSource).toContain("bg-gradient-primary bg-clip-text");
expect(shellSource).toContain('"min-h-0 min-w-0 flex-1 overflow-hidden"');
expect(shellSource).toContain('moduleId === "overview"');

for (const moduleId of [
"overview",
Expand Down Expand Up @@ -1459,7 +1460,7 @@ describe("admin console beginner-friendly UI/UX source contract", () => {
'[data-admin-console-content="true"] .font-serif',
);
expect(appGlobalsSource).toContain("font-family: inherit;");
expect(appLayoutSource).toContain("className={`${pretendard.variable} ${notoSerifKr.variable}`}");
expect(appLayoutSource).toContain("className={`${pretendard.variable} ${notoSerifKr.variable} ${pretendard.className}`}");
expect(appLayoutSource).toContain('variable: "--font-pretendard"');
expect(appLayoutSource).toContain('variable: "--font-display"');
expect(appGlobalsSource).toContain(
Expand Down Expand Up @@ -1592,11 +1593,11 @@ describe("admin console beginner-friendly UI/UX source contract", () => {
'<div className="hidden min-w-0 md:block">',
);
expect(consoleSource).toContain(
'<h1 className="text-xl font-extrabold leading-tight tracking-[0.01em] text-foreground text-balance">',
'<h1 className="text-sm font-extrabold leading-tight tracking-[0.01em] text-foreground text-balance">',
);
expect(consoleSource).toContain("data-admin-dashboard-kpi-value-size=\"bounded\"");
expect(consoleSource).toContain("text-lg font-black");
expect(consoleSource).toContain("sm:text-xl");
expect(consoleSource).toContain("text-sm font-black");
expect(consoleSource).toContain("sm:text-base");
expect(consoleSource).not.toContain("text-[clamp(1.2rem,1.45vw,1.75rem)]");
expect(consoleSource).toContain("function AdminDashboardTooltipPanel");
expect(consoleSource).toContain("min-w-44 space-y-1");
Expand Down Expand Up @@ -1678,7 +1679,7 @@ describe("admin console beginner-friendly UI/UX source contract", () => {
'const adminDashboardControlGroupClassName =\n "inline-flex h-7 shrink-0 items-center rounded-full border border-border bg-muted/25 p-0.5"',
);
expect(consoleSource).toContain(
'const adminDashboardControlButtonClassName =\n "inline-flex h-6 shrink-0 items-center justify-center gap-1 rounded-full px-2.5 text-[11px] font-extrabold leading-none transition',
'const adminDashboardControlButtonClassName =\n "inline-flex h-6 shrink-0 items-center justify-center gap-1 rounded-full px-2 text-[10px] font-extrabold leading-none transition',
);
expect(consoleSource).toContain(
'"h-7 w-7 border border-border bg-background p-0 text-muted-foreground shadow-sm hover:text-foreground"',
Expand All @@ -1700,7 +1701,7 @@ describe("admin console beginner-friendly UI/UX source contract", () => {
'data-admin-dashboard-card-title-row="single-line"',
);
expect(consoleSource).toContain(
"truncate whitespace-nowrap text-xs font-extrabold leading-none text-foreground",
"truncate whitespace-nowrap text-[11px] font-extrabold leading-none text-foreground",
);
expect(consoleSource).toContain(
'data-admin-dashboard-card-title-actions="single-line-scroll"',
Expand Down Expand Up @@ -2680,7 +2681,7 @@ describe("admin console beginner-friendly UI/UX source contract", () => {
'data-admin-dashboard-kpi-title-row="single-line"',
);
expect(consoleSource).toContain(
"truncate whitespace-nowrap text-xs font-extrabold tracking-[0.04em] text-muted-foreground",
"truncate whitespace-nowrap text-[11px] font-extrabold tracking-[0.04em] text-muted-foreground",
);
expect(consoleSource).toContain(
'data-admin-dashboard-kpi-title-actions="single-line-scroll"',
Expand Down Expand Up @@ -2969,11 +2970,11 @@ describe("admin console beginner-friendly UI/UX source contract", () => {
const viewModelSource = source("lib/admin/system-status/view-model.ts");
const routeSource = source("app/api/admin/system-status/route.ts");

expect(consoleSource).toContain(
expect(consoleSource).not.toContain(
'import("@/components/admin/system-status/AdminSystemStatusCenter")',
);
expect(consoleSource).toContain("<AdminSystemStatusCenter isAdmin={isAdmin} />");
expect(consoleSource).toContain('data-admin-system-status-slot="true"');
expect(consoleSource).not.toContain("<AdminSystemStatusCenter isAdmin={isAdmin} />");
expect(consoleSource).not.toContain('data-admin-system-status-slot="true"');
expect(consoleSource).not.toContain("운영 상태 센터");
expect(centerSource).toContain('data-admin-system-status-center="true"');
expect(centerSource).toContain("data-admin-run-daily-state=");
Expand Down
4 changes: 2 additions & 2 deletions apps/web/tests-unit/web-quality-performance-source.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4411,7 +4411,7 @@ describe("web quality performance source contracts", () => {
expect(layoutSource).toContain('src: "./fonts/pretendard/PretendardVariable.woff2"');
expect(layoutSource).toContain('weight: "45 920"');
expect(layoutSource).toContain("preload: false");
expect(layoutSource).toContain("className={`${pretendard.variable} ${notoSerifKr.variable}`}");
expect(layoutSource).toContain("className={`${pretendard.variable} ${notoSerifKr.variable} ${pretendard.className}`}");
expect(layoutSource).not.toContain("QueryProvider");
expect(layoutSource).not.toContain("AppProviders");
expect(layoutSource).not.toContain("MainLayout");
Expand Down Expand Up @@ -4876,7 +4876,7 @@ describe("web quality performance source contracts", () => {
expect(rootLayoutSource).not.toContain(staticWeightFile);
}
expect(rootLayoutSource).not.toContain("cdn.jsdelivr.net/gh/orioncactus/pretendard");
expect(rootLayoutSource).toContain("className={`${pretendard.variable} ${notoSerifKr.variable}`}");
expect(rootLayoutSource).toContain("className={`${pretendard.variable} ${notoSerifKr.variable} ${pretendard.className}`}");
expect(rootGlobalsSource).toContain("--font-sans: var(--font-pretendard");
expect(rootGlobalsSource).toContain("--font-noto-serif-kr: var(--font-display");
expect(rootGlobalsSource).toContain("font-family: var(--font-sans);");
Expand Down
Loading