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

@@ -19,6 +19,7 @@ import { DetailPageSkeleton } from '@/components/ui/skeleton';
import { ErrorCard } from '@/components/ui/error-card';
import { Button } from '@/components/ui/button';
import { DeleteConfirmDialog } from '@/components/ui/confirm-dialog';
import { useDeleteDialog } from '@/hooks/useDeleteDialog';
import { toast } from 'sonner';
import { usePermission } from '@/hooks/usePermission';
@@ -58,8 +59,6 @@ export function BoardDetailClientV2({ boardId, initialMode }: BoardDetailClientV
const [isLoading, setIsLoading] = useState(!isNewMode);
const [error, setError] = useState<string | null>(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [isDeleting, setIsDeleting] = useState(false);
// 데이터 로드
useEffect(() => {
@@ -161,36 +160,17 @@ export function BoardDetailClientV2({ boardId, initialMode }: BoardDetailClientV
};
// 삭제 핸들러
const handleDelete = () => {
setDeleteDialogOpen(true);
};
const confirmDelete = async () => {
if (!boardData) return;
setIsDeleting(true);
try {
const result = await deleteBoard(boardData.id);
const deleteDialog = useDeleteDialog({
onDelete: async (id) => {
const result = await deleteBoard(id);
if (result.success) {
await forceRefreshMenus();
toast.success('게시판이 삭제되었습니다.');
router.push(BASE_PATH);
} else {
setError(result.error || '삭제에 실패했습니다.');
toast.error(result.error || '삭제에 실패했습니다.');
setDeleteDialogOpen(false);
}
} catch (err) {
console.error('게시판 삭제 실패:', err);
setError('게시판 삭제 중 오류가 발생했습니다.');
toast.error('게시판 삭제 중 오류가 발생했습니다.');
setDeleteDialogOpen(false);
} finally {
setIsDeleting(false);
}
};
return result;
},
onSuccess: () => router.push(BASE_PATH),
entityName: '게시판',
});
// 수정 모드 전환
const handleEdit = () => {
@@ -271,13 +251,13 @@ export function BoardDetailClientV2({ boardId, initialMode }: BoardDetailClientV
<BoardDetail
board={boardData}
onEdit={canUpdate ? handleEdit : undefined}
onDelete={canDelete ? handleDelete : undefined}
onDelete={canDelete ? () => deleteDialog.single.open(boardData!.id) : undefined}
/>
<DeleteConfirmDialog
open={deleteDialogOpen}
onOpenChange={setDeleteDialogOpen}
onConfirm={confirmDelete}
open={deleteDialog.single.isOpen}
onOpenChange={deleteDialog.single.onOpenChange}
onConfirm={deleteDialog.single.confirm}
title="게시판 삭제"
description={
<>
@@ -288,7 +268,7 @@ export function BoardDetailClientV2({ boardId, initialMode }: BoardDetailClientV
</span>
</>
}
loading={isDeleting}
loading={deleteDialog.isPending}
/>
</>
);