feat(WEB): 리스트 페이지 헤더 영역 스켈레톤 추가

- ListPageSkeleton에 showDateRange, showCreateButton props 추가
- 페이지 타이틀, 날짜 범위 선택기, 프리셋 버튼, 등록 버튼 스켈레톤 구현
- Skeleton 컴포넌트 대신 직접 div 사용하여 색상 가시성 개선
- IntegratedListTemplateV2에서 새 props 전달

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
유병철
2026-01-22 22:08:10 +09:00
parent 19237be4aa
commit 208f4d08e5
2 changed files with 69 additions and 10 deletions

View File

@@ -5,7 +5,7 @@ import { LucideIcon, Trash2, Plus, Loader2 } from "lucide-react";
import { DateRangeSelector } from "@/components/molecules/DateRangeSelector";
import { Card, CardContent } from "@/components/ui/card";
import { Tabs, TabsContent } from "@/components/ui/tabs";
import { TableSkeleton, MobileCardGridSkeleton } from "@/components/ui/skeleton";
import { TableSkeleton, MobileCardGridSkeleton, StatCardGridSkeleton, ListPageSkeleton } from "@/components/ui/skeleton";
import { Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Checkbox } from "@/components/ui/checkbox";
import { Button } from "@/components/ui/button";
@@ -483,6 +483,27 @@ export function IntegratedListTemplateV2<T = any>({
setShowDeleteDialog(false);
};
// 로딩 시 전체 페이지 스켈레톤 표시
// - isLoading이 true면 전체 스켈레톤 표시 (헤더, 달력, 버튼, 카드, 테이블 모두)
// - 이렇게 하면 "따닥" 현상 없이 매끄러운 로딩 경험 제공
if (isLoading) {
return (
<PageLayout>
<ListPageSkeleton
showHeader={true}
showDateRange={dateRangeSelector?.enabled ?? false}
showCreateButton={!!createButton}
showFilters={!hideSearch}
showStats={stats !== undefined && stats.length > 0}
statsCount={stats?.length || 4}
tableRows={pagination.itemsPerPage || 10}
tableColumns={tableColumns.length || 6}
mobileCards={6}
/>
</PageLayout>
);
}
return (
<PageLayout>
{/* 페이지 헤더 */}
@@ -530,11 +551,15 @@ export function IntegratedListTemplateV2<T = any>({
)}
{/* 통계 카드 - 태블릿/데스크톱 */}
{stats && stats.length > 0 && (
{isLoading && stats !== undefined ? (
<div className="hidden md:block">
<StatCardGridSkeleton count={stats.length || 4} />
</div>
) : stats && stats.length > 0 ? (
<div className="hidden md:block">
<StatCards stats={stats} />
</div>
)}
) : null}
{/* 경고 배너 (통계 카드와 검색 영역 사이) */}
{alertBanner}