refactor(WEB): 프론트엔드 대규모 코드 정리 및 리팩토링

- 미사용 코드 삭제: ThemeContext, itemStore, utils/date.ts, utils/formatAmount.ts
- 유틸리티 이동: date, formatAmount → src/lib/utils/ (중앙 집중화)
- 다수 page.tsx 클라이언트 컴포넌트 패턴 통일
- DateRangeSelector 리팩토링 및 date-range-picker UI 컴포넌트 추가
- ThemeSelect/themeStore Zustand 직접 연동으로 전환
- 건설/회계/영업/품목/출하 등 전반적 컴포넌트 개선
- UniversalListPage, IntegratedListTemplateV2 타입 확장
- 프론트엔드 종합 리뷰 문서 및 개선 체크리스트 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
유병철
2026-02-19 16:30:07 +09:00
parent b8dcb69e47
commit a2c3e4c41e
136 changed files with 1987 additions and 896 deletions

View File

@@ -4,6 +4,7 @@ import { ReactNode, useCallback } from 'react';
import { format, startOfYear, endOfYear, subMonths, startOfMonth, endOfMonth, subDays } from 'date-fns';
import { Button } from '@/components/ui/button';
import { DatePicker } from '@/components/ui/date-picker';
import { DateRangePicker } from '@/components/ui/date-range-picker';
import { ScrollableButtonGroup } from '@/components/atoms/ScrollableButtonGroup';
/**
@@ -54,6 +55,8 @@ interface DateRangeSelectorProps {
dateInputWidth?: string;
/** 프리셋 버튼 위치: 'inline' (날짜 옆), 'below' (별도 줄) */
presetsPosition?: 'inline' | 'below';
/** 날짜 입력 변형: 'split' (DatePicker 2개), 'combined' (DateRangePicker 1개) */
variant?: 'split' | 'combined';
}
/**
@@ -89,6 +92,7 @@ export function DateRangeSelector({
hideDateInputs = false,
dateInputWidth = 'w-[140px]',
presetsPosition = 'inline',
variant = 'combined',
}: DateRangeSelectorProps) {
// 프리셋 클릭 핸들러
@@ -167,33 +171,53 @@ export function DateRangeSelector({
);
};
// 날짜 입력 영역 렌더링
const renderDateInputs = () => {
if (hideDateInputs) return null;
if (variant === 'combined') {
return (
<div className="w-full xl:w-auto xl:shrink-0">
<DateRangePicker
startDate={startDate}
endDate={endDate}
onStartDateChange={onStartDateChange}
onEndDateChange={onEndDateChange}
className="w-full xl:w-auto"
size="sm"
/>
</div>
);
}
return (
<div className="flex items-center gap-1 w-full xl:w-auto xl:shrink-0">
<DatePicker
value={startDate}
onChange={onStartDateChange}
className="flex-1 xl:flex-none xl:w-[170px]"
size="sm"
displayFormat="yyyy년 MM월 dd일"
/>
<span className="text-muted-foreground shrink-0">~</span>
<DatePicker
value={endDate}
onChange={onEndDateChange}
className="flex-1 xl:flex-none xl:w-[170px]"
size="sm"
displayFormat="yyyy년 MM월 dd일"
/>
</div>
);
};
// presetsPosition이 'below'일 때: 달력+extraActions 같은 줄, 프리셋은 아래 줄
if (presetsPosition === 'below') {
return (
<div className="flex flex-col gap-2 w-full">
{/* 1줄: 날짜 + extraActions */}
<div className="flex items-center gap-2">
{/* 날짜 범위 선택 */}
{!hideDateInputs && (
<div className="flex items-center gap-1 w-full xl:w-auto xl:shrink-0">
<DatePicker
value={startDate}
onChange={onStartDateChange}
className="flex-1 xl:flex-none xl:w-[170px]"
size="sm"
displayFormat="yyyy년 MM월 dd일"
/>
<span className="text-muted-foreground shrink-0">~</span>
<DatePicker
value={endDate}
onChange={onEndDateChange}
className="flex-1 xl:flex-none xl:w-[170px]"
size="sm"
displayFormat="yyyy년 MM월 dd일"
/>
</div>
)}
{/* extraActions (검색창 등) */}
{renderDateInputs()}
{extraActions}
</div>
@@ -210,25 +234,7 @@ export function DateRangeSelector({
return (
<div className="flex flex-col xl:flex-row xl:flex-wrap xl:items-center gap-2">
{/* 날짜 범위 선택 */}
{!hideDateInputs && (
<div className="flex items-center gap-1 w-full xl:w-auto xl:shrink-0">
<DatePicker
value={startDate}
onChange={onStartDateChange}
className="flex-1 xl:flex-none xl:w-[170px]"
size="sm"
displayFormat="yyyy년 MM월 dd일"
/>
<span className="text-muted-foreground shrink-0">~</span>
<DatePicker
value={endDate}
onChange={onEndDateChange}
className="flex-1 xl:flex-none xl:w-[170px]"
size="sm"
displayFormat="yyyy년 MM월 dd일"
/>
</div>
)}
{renderDateInputs()}
{/* 기간 버튼들 - 달력 바로 옆 */}
{renderPresets()}