feat(WEB): 리스트 페이지 UI 레이아웃 표준화

- 공통 레이아웃 패턴 적용: [달력] → [프리셋] → [검색창] → [버튼들]
- beforeTableContent → headerActions + createButton 마이그레이션
- DateRangeSelector extraActions prop 활용하여 검색창 통합
- PricingListClient 테이블 행 클릭 → 상세 이동 기능 추가
- 회계 관련 페이지 (입금/출금/매입/매출/어음/카드/예상지출 등) 정리
- 건설 관련 페이지 검색 영역 정리
- 부모 메뉴 리다이렉트 컴포넌트 추가

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
유병철
2026-01-26 22:04:36 +09:00
parent ff93ab7fa2
commit 1f6b592b9f
65 changed files with 1974 additions and 503 deletions

View File

@@ -902,51 +902,9 @@ export function ExpectedExpenseManagement({
},
filterTitle: '예상비용 필터',
// 테이블 헤더 액션 (거래처/정렬 필터)
tableHeaderActions: () => (
// 헤더 액션: 선택 기반 액션 버튼들
headerActions: () => (
<div className="flex items-center gap-2">
{/* 거래처 필터 */}
<Select value={vendorFilter} onValueChange={setVendorFilter}>
<SelectTrigger className="w-[140px] h-8 text-sm">
<SelectValue placeholder="전체" />
</SelectTrigger>
<SelectContent>
{vendorFilterOptions.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
{/* 정렬 필터 (최신순/등록순) */}
<Select value={sortOption} onValueChange={(value) => setSortOption(value as SortOption)}>
<SelectTrigger className="w-[100px] h-8 text-sm">
<SelectValue placeholder="최신순" />
</SelectTrigger>
<SelectContent>
{SORT_OPTIONS.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
),
// 테이블 앞 컨텐츠 (액션 버튼)
beforeTableContent: (
<div className="flex items-center gap-2 flex-wrap">
{/* 등록 버튼 */}
<Button
size="sm"
onClick={handleOpenCreateDialog}
>
<Plus className="h-4 w-4 mr-1" />
</Button>
{/* 예상 지급일 변경 버튼 - 1개 이상 선택 시 활성화 */}
<Button
variant="outline"
@@ -983,6 +941,46 @@ export function ExpectedExpenseManagement({
</div>
),
// 등록 버튼
createButton: {
label: '등록',
icon: Plus,
onClick: handleOpenCreateDialog,
},
// 테이블 헤더 액션 (거래처/정렬 필터)
tableHeaderActions: () => (
<div className="flex items-center gap-2">
{/* 거래처 필터 */}
<Select value={vendorFilter} onValueChange={setVendorFilter}>
<SelectTrigger className="w-[140px] h-8 text-sm">
<SelectValue placeholder="전체" />
</SelectTrigger>
<SelectContent>
{vendorFilterOptions.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
{/* 정렬 필터 (최신순/등록순) */}
<Select value={sortOption} onValueChange={(value) => setSortOption(value as SortOption)}>
<SelectTrigger className="w-[100px] h-8 text-sm">
<SelectValue placeholder="최신순" />
</SelectTrigger>
<SelectContent>
{SORT_OPTIONS.map((option) => (
<SelectItem key={option.value} value={option.value}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
),
// Stats 카드
computeStats: (): StatCard[] => {
const totalExpense = filteredRawData.reduce((sum, d) => sum + d.amount, 0);
@@ -1011,7 +1009,7 @@ export function ExpectedExpenseManagement({
vendorFilter,
vendorFilterOptions,
sortOption,
selectedItems,
selectedItems.size,
handleOpenCreateDialog,
handleOpenDateChangeDialog,
handleElectronicApproval,