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

@@ -32,6 +32,7 @@ import {
type StatCard,
} from '@/components/templates/UniversalListPage';
import { ListMobileCard, InfoField } from '@/components/organisms/MobileCard';
import { toast } from 'sonner';
// Debounce 훅
function useDebounce<T>(value: T, delay: number): T {
@@ -182,7 +183,7 @@ export default function ItemListClient() {
} catch (error) {
if (isNextRedirectError(error)) throw error;
console.error('품목 삭제 실패:', error);
alert(error instanceof Error ? error.message : '품목 삭제에 실패했습니다.');
toast.error(error instanceof Error ? error.message : '품목 삭제에 실패했습니다.');
} finally {
setDeleteDialogOpen(false);
setItemToDelete(null);
@@ -225,10 +226,10 @@ export default function ItemListClient() {
}
if (successCount > 0) {
alert(`${successCount}개 품목이 삭제되었습니다.${failCount > 0 ? ` (${failCount}개 실패)` : ''}`);
toast.success(`${successCount}개 품목이 삭제되었습니다.${failCount > 0 ? ` (${failCount}개 실패)` : ''}`);
refresh();
} else {
alert('품목 삭제에 실패했습니다.');
toast.error('품목 삭제에 실패했습니다.');
}
};
@@ -316,22 +317,22 @@ export default function ItemListClient() {
const errorMessages = result.errors.slice(0, 5).map(
(err) => `${err.row}행: ${err.message}`
).join('\n');
alert(`업로드 오류:\n${errorMessages}${result.errors.length > 5 ? `\n... ${result.errors.length - 5}` : ''}`);
toast.error('업로드 오류', { description: `${errorMessages}${result.errors.length > 5 ? ` (${result.errors.length - 5})` : ''}` });
return;
}
if (result.data.length === 0) {
alert('업로드할 데이터가 없습니다.');
toast.warning('업로드할 데이터가 없습니다.');
return;
}
// TODO: 실제 API 호출로 데이터 저장
// 지금은 파싱 결과만 확인
alert(`${result.data.length}건의 데이터가 파싱되었습니다.\n(실제 등록 기능은 추후 구현 예정)`);
toast.info(`${result.data.length}건의 데이터가 파싱되었습니다. (실제 등록 기능은 추후 구현 예정)`);
} catch (error) {
console.error('[Excel Upload] 오류:', error);
alert('파일 업로드에 실패했습니다.');
toast.error('파일 업로드에 실패했습니다.');
} finally {
// input 초기화 (같은 파일 재선택 가능하도록)
if (fileInputRef.current) {