refactor: UI 컴포넌트 추상화 및 입금/출금 등록 버튼 추가

- 입금관리, 출금관리 리스트에 등록 버튼 추가
- skeleton, confirm-dialog, empty-state, status-badge UI 컴포넌트 추가
- document-system 컴포넌트 추상화 (ApprovalLine, DocumentHeader 등)
- 여러 페이지 컴포넌트 리팩토링 및 코드 정리

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
유병철
2026-01-22 17:21:42 +09:00
parent 777dccc7bd
commit 269b901e64
86 changed files with 3761 additions and 2614 deletions

View File

@@ -1,15 +1,6 @@
'use client';
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { ConfirmDialog } from '@/components/ui/confirm-dialog';
export interface DuplicateCodeDialogProps {
open: boolean;
@@ -27,27 +18,32 @@ export function DuplicateCodeDialog({
onCancel,
onGoToEdit,
}: DuplicateCodeDialogProps) {
const handleConfirm = () => {
onGoToEdit();
};
const handleOpenChange = (isOpen: boolean) => {
onOpenChange(isOpen);
if (!isOpen) {
onCancel();
}
};
return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle> </AlertDialogTitle>
<AlertDialogDescription>
.
<span className="block mt-2 font-medium text-foreground">
?
</span>
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel onClick={onCancel}>
</AlertDialogCancel>
<AlertDialogAction onClick={onGoToEdit}>
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<ConfirmDialog
open={open}
onOpenChange={handleOpenChange}
onConfirm={handleConfirm}
title="품목코드 중복"
description={
<>
.
<span className="block mt-2 font-medium text-foreground">
?
</span>
</>
}
confirmText="중복 품목 수정하러 가기"
/>
);
}

View File

@@ -16,16 +16,7 @@ import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Checkbox } from '@/components/ui/checkbox';
import { TableRow, TableCell } from '@/components/ui/table';
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { DeleteConfirmDialog } from '@/components/ui/confirm-dialog';
import { Search, Plus, Edit, Trash2, Package } from 'lucide-react';
import { TableLoadingSpinner } from '@/components/ui/loading-spinner';
import { useItemList } from '@/hooks/useItemList';
@@ -503,27 +494,19 @@ export default function ItemListClient() {
/>
{/* 개별 삭제 확인 다이얼로그 */}
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle> </AlertDialogTitle>
<AlertDialogDescription>
&quot;{itemToDelete?.code}&quot;() ?
<br />
.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel></AlertDialogCancel>
<AlertDialogAction
onClick={handleConfirmDelete}
className="bg-red-600 hover:bg-red-700"
>
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<DeleteConfirmDialog
open={deleteDialogOpen}
onOpenChange={setDeleteDialogOpen}
onConfirm={handleConfirmDelete}
title="품목 삭제"
description={
<>
&quot;{itemToDelete?.code}&quot;() ?
<br />
.
</>
}
/>
</>
);
}

View File

@@ -1,7 +1,7 @@
'use client';
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from '@/components/ui/alert-dialog';
import { DeleteConfirmDialog } from '@/components/ui/confirm-dialog';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { Input } from '@/components/ui/input';
@@ -212,32 +212,22 @@ export function TabManagementDialogs({
</Dialog>
{/* 탭 삭제 확인 다이얼로그 */}
<AlertDialog open={isDeleteTabDialogOpen} onOpenChange={setIsDeleteTabDialogOpen}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle> </AlertDialogTitle>
<AlertDialogDescription>
"{customTabs.find(t => t.id === deletingTabId)?.label}" ?
<br />
.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel onClick={() => {
setIsDeleteTabDialogOpen(false);
setDeletingTabId(null);
}}>
</AlertDialogCancel>
<AlertDialogAction
onClick={confirmDeleteTab}
className="bg-red-500 hover:bg-red-600"
>
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<DeleteConfirmDialog
open={isDeleteTabDialogOpen}
onOpenChange={(open) => {
setIsDeleteTabDialogOpen(open);
if (!open) setDeletingTabId(null);
}}
onConfirm={confirmDeleteTab}
title="탭 삭제"
description={
<>
&quot;{customTabs.find(t => t.id === deletingTabId)?.label}&quot; ?
<br />
.
</>
}
/>
{/* 탭 추가/수정 다이얼로그 */}
<Dialog open={isAddTabDialogOpen} onOpenChange={(open) => {
@@ -363,32 +353,22 @@ export function TabManagementDialogs({
</Dialog>
{/* 속성 하위 탭 삭제 확인 다이얼로그 */}
<AlertDialog open={isDeleteAttributeTabDialogOpen} onOpenChange={setIsDeleteAttributeTabDialogOpen}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle> </AlertDialogTitle>
<AlertDialogDescription>
"{attributeSubTabs.find(t => t.id === deletingAttributeTabId)?.label}" ?
<br />
.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel onClick={() => {
setIsDeleteAttributeTabDialogOpen(false);
setDeletingAttributeTabId(null);
}}>
</AlertDialogCancel>
<AlertDialogAction
onClick={confirmDeleteAttributeTab}
className="bg-red-500 hover:bg-red-600"
>
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<DeleteConfirmDialog
open={isDeleteAttributeTabDialogOpen}
onOpenChange={(open) => {
setIsDeleteAttributeTabDialogOpen(open);
if (!open) setDeletingAttributeTabId(null);
}}
onConfirm={confirmDeleteAttributeTab}
title="속성 탭 삭제"
description={
<>
&quot;{attributeSubTabs.find(t => t.id === deletingAttributeTabId)?.label}&quot; ?
<br />
.
</>
}
/>
{/* 속성 하위 탭 추가/수정 다이얼로그 */}
<Dialog open={isAddAttributeTabDialogOpen} onOpenChange={(open) => {