feat: 생산/품질/자재/출고/주문 관리 페이지 구현

- 생산관리: 대시보드, 작업지시, 작업실적, 작업자화면
- 품질관리: 검사관리 (리스트/등록/상세)
- 자재관리: 입고관리, 재고현황
- 출고관리: 출하관리 (리스트/등록/상세/수정)
- 주문관리: 수주관리, 생산의뢰
- 기존 컴포넌트 개선: CardTransactionInquiry, VendorDetail, QuoteRegistration
- IntegratedListTemplateV2 개선
- 공통 컴포넌트 분석 문서 추가

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
byeongcheolryu
2025-12-23 21:13:07 +09:00
parent 2ebcea0255
commit f0e8e51d06
108 changed files with 21156 additions and 84 deletions

View File

@@ -7,7 +7,16 @@ import { Tabs, TabsContent } from "@/components/ui/tabs";
import { Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Checkbox } from "@/components/ui/checkbox";
import { Button } from "@/components/ui/button";
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 { PageLayout } from "@/components/organisms/PageLayout";
import { PageHeader } from "@/components/organisms/PageHeader";
import { StatCards } from "@/components/organisms/StatCards";
@@ -86,6 +95,9 @@ export interface IntegratedListTemplateV2Props<T = any> {
// 통계 카드
stats?: StatCard[];
// 경고 배너 (통계 카드와 검색 영역 사이)
alertBanner?: ReactNode;
// 버전 이력
versionHistory?: VersionHistoryItem[];
versionHistoryTitle?: string;
@@ -152,6 +164,7 @@ export function IntegratedListTemplateV2<T = any>({
headerActions,
tabsContent,
stats,
alertBanner,
versionHistory,
versionHistoryTitle = "수정 이력",
searchValue,
@@ -234,6 +247,9 @@ export function IntegratedListTemplateV2<T = any>({
</div>
)}
{/* 경고 배너 (통계 카드와 검색 영역 사이) */}
{alertBanner}
{/* 버전 이력 */}
{versionHistory && versionHistory.length > 0 && (
<ScreenVersionHistory
@@ -284,17 +300,23 @@ export function IntegratedListTemplateV2<T = any>({
))}
</div>
<div className="flex items-center gap-2">
{/* 선택된 항목 수 표시 */}
{selectedItems.size > 0 && (
<span className="text-sm text-muted-foreground">
{selectedItems.size}
</span>
)}
{/* 테이블 헤더 액션 (필터/정렬 셀렉트박스 등) */}
{tableHeaderActions}
{selectedItems.size >= 2 && onBulkDelete && (
{selectedItems.size >= 1 && onBulkDelete && (
<Button
variant="destructive"
variant="outline"
size="sm"
onClick={handleBulkDeleteClick}
className="flex items-center gap-2"
className="flex items-center gap-2 bg-gray-900 text-white hover:bg-gray-800 hover:text-white"
>
<Trash2 className="h-4 w-4" />
({selectedItems.size})
({selectedItems.size})
</Button>
)}
</div>
@@ -474,33 +496,44 @@ export function IntegratedListTemplateV2<T = any>({
</div>
)}
{/* 일괄 삭제 확인 다이얼로그 */}
<Dialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle> </DialogTitle>
<DialogDescription>
? .
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button
variant="outline"
size="sm"
onClick={() => setShowDeleteDialog(false)}
>
</Button>
<Button
variant="destructive"
size="sm"
{/* 일괄 삭제 확인 다이얼로그 - 단일 삭제와 동일한 디자인 */}
<AlertDialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
<AlertDialogContent className="max-w-md">
<AlertDialogHeader>
<AlertDialogTitle className="flex items-center gap-2">
<span className="text-yellow-600"></span>
</AlertDialogTitle>
<AlertDialogDescription asChild>
<div className="space-y-4">
<p className="text-foreground">
<strong>{selectedItems.size}</strong> ?
</p>
<div className="bg-gray-100 rounded-lg p-3">
<div className="flex items-start gap-2">
<span className="text-yellow-600 mt-0.5"></span>
<div className="text-sm text-muted-foreground">
<span className="font-medium text-foreground"></span>
<br />
. .
</div>
</div>
</div>
</div>
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel></AlertDialogCancel>
<AlertDialogAction
onClick={handleConfirmDelete}
className="bg-gray-900 hover:bg-gray-800 text-white gap-2"
>
<Trash2 className="h-4 w-4" />
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</PageLayout>
);
}