refactor(WEB): 회계/견적/설정/생산 등 전반적 코드 개선 및 공통화 2차

- 회계 모듈 전면 개선: 청구/입금/출금/매입/매출/세금계산서/일반전표/거래처원장 등
- 견적 모듈 금액 포맷/할인/수식/미리보기 등 코드 정리
- 설정 모듈: 계정관리/직급/직책/권한 상세 간소화
- 생산 모듈: 작업지시서/작업자화면/검수 문서 코드 정리
- UniversalListPage 엑셀 다운로드 및 필터 기능 확장
- 대시보드/게시판/수주 등 날짜 유틸 공통화 적용
- claudedocs 문서 인덱스 업데이트

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
유병철
2026-02-20 10:45:47 +09:00
parent 71352923c8
commit f344dc7d00
123 changed files with 877 additions and 789 deletions

View File

@@ -17,6 +17,7 @@ import {
SelectValue,
} from '@/components/ui/select';
import { DeleteConfirmDialog } from '@/components/ui/confirm-dialog';
import { useDeleteDialog } from '@/hooks/useDeleteDialog';
import { PageLayout } from '@/components/organisms/PageLayout';
import { PageHeader } from '@/components/organisms/PageHeader';
import { toast } from 'sonner';
@@ -39,7 +40,11 @@ export function AccountDetail({ account, mode: initialMode }: AccountDetailProps
const router = useRouter();
const searchParams = useSearchParams();
const [mode, setMode] = useState(initialMode);
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
const deleteDialog = useDeleteDialog({
onDelete: async (id) => deleteBankAccount(Number(id)),
onSuccess: () => router.push('/ko/settings/accounts'),
entityName: '계좌',
});
// URL에서 mode 파라미터 확인
useEffect(() => {
@@ -99,21 +104,6 @@ export function AccountDetail({ account, mode: initialMode }: AccountDetailProps
}
};
const handleDelete = () => {
setShowDeleteDialog(true);
};
const handleConfirmDelete = async () => {
if (!account?.id) return;
const result = await deleteBankAccount(account.id);
if (result.success) {
toast.success('계좌가 삭제되었습니다.');
router.push('/ko/settings/accounts');
} else {
toast.error(result.error || '계좌 삭제에 실패했습니다.');
}
};
const handleCancel = () => {
if (isCreateMode) {
router.push('/ko/settings/accounts');
@@ -202,7 +192,7 @@ export function AccountDetail({ account, mode: initialMode }: AccountDetailProps
</Button>
<div className="flex items-center gap-2">
<Button variant="outline" onClick={handleDelete} className="text-destructive hover:bg-destructive hover:text-destructive-foreground">
<Button variant="outline" onClick={() => account?.id && deleteDialog.single.open(String(account.id))} className="text-destructive hover:bg-destructive hover:text-destructive-foreground">
<Trash2 className="w-4 h-4 mr-2" />
</Button>
@@ -216,8 +206,8 @@ export function AccountDetail({ account, mode: initialMode }: AccountDetailProps
{/* 삭제 확인 다이얼로그 */}
<DeleteConfirmDialog
open={showDeleteDialog}
onOpenChange={setShowDeleteDialog}
open={deleteDialog.single.isOpen}
onOpenChange={deleteDialog.single.onOpenChange}
description={
<>
?
@@ -227,7 +217,8 @@ export function AccountDetail({ account, mode: initialMode }: AccountDetailProps
</span>
</>
}
onConfirm={handleConfirmDelete}
onConfirm={deleteDialog.single.confirm}
loading={deleteDialog.isPending}
/>
</PageLayout>
);