import { useState } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { Badge } from "@/components/ui/badge"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogTrigger } from "@/components/ui/dialog"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Textarea } from "@/components/ui/textarea"; import { toast } from "sonner"; import { Search, Plus, Download, Filter, Eye, Edit, Trash2, Package, Zap, Users, Building, FileText } from "lucide-react"; interface Product { id: string; code: string; name: string; type: string; unit: string; standardTime: number; materialCost: number; laborCost: number; description: string; status: string; } interface BOM { id: string; productCode: string; productName: string; materialCode: string; materialName: string; quantity: number; unit: string; notes: string; } interface Process { id: string; code: string; name: string; workCenter: string; standardTime: number; setupTime: number; description: string; nextProcess?: string; } interface Customer { id: string; code: string; name: string; type: "고객" | "공급업체" | "양방향"; contact: string; phone: string; address: string; status: string; } export function MasterData() { const [products, setProducts] = useState([ { id: "P001", code: "PRD-001", name: "스마트폰 케이스", type: "완제품", unit: "개", standardTime: 30, materialCost: 5000, laborCost: 2000, description: "iPhone 호환 케이스", status: "사용" }, { id: "P002", code: "PRD-002", name: "태블릿 스탠드", type: "완제품", unit: "개", standardTime: 45, materialCost: 8000, laborCost: 3000, description: "각도 조절 가능", status: "사용" }, { id: "P003", code: "PRD-003", name: "무선 충전기", type: "완제품", unit: "개", standardTime: 60, materialCost: 15000, laborCost: 5000, description: "고속 무선 충전", status: "사용" }, ]); const [bomData, setBomData] = useState([ { id: "BOM001", productCode: "PRD-001", productName: "스마트폰 케이스", materialCode: "MAT-001", materialName: "플라스틱 원료 A", quantity: 0.05, unit: "kg", notes: "주요 소재" }, { id: "BOM002", productCode: "PRD-001", productName: "스마트폰 케이스", materialCode: "MAT-003", materialName: "실리콘 패드", quantity: 2, unit: "개", notes: "충격 흡수용" }, { id: "BOM003", productCode: "PRD-002", productName: "태블릿 스탠드", materialCode: "MAT-002", materialName: "알루미늄 판재", quantity: 1, unit: "장", notes: "메인 프레임" }, { id: "BOM004", productCode: "PRD-003", productName: "무선 충전기", materialCode: "MAT-005", materialName: "전자부품 모듈", quantity: 1, unit: "개", notes: "핵심 부품" }, ]); const [processes, setProcesses] = useState([ { id: "PROC001", code: "PROC-001", name: "사출성형", workCenter: "성형라인 1", standardTime: 15, setupTime: 30, description: "플라스틱 사출성형 공정" }, { id: "PROC002", code: "PROC-002", name: "조립", workCenter: "조립라인 1", standardTime: 10, setupTime: 15, description: "부품 조립 공정", nextProcess: "PROC-003" }, { id: "PROC003", code: "PROC-003", name: "검사", workCenter: "품질검사실", standardTime: 5, setupTime: 5, description: "품질 검사 공정" }, { id: "PROC004", code: "PROC-004", name: "포장", workCenter: "포장라인", standardTime: 3, setupTime: 5, description: "최종 포장 공정" }, ]); const [customers, setCustomers] = useState([ { id: "C001", code: "CUST-001", name: "삼성전자", type: "고객", contact: "김구매", phone: "02-1234-5678", address: "서울시 강남구", status: "활성" }, { id: "C002", code: "SUPP-001", name: "ABC 원료", type: "공급업체", contact: "이공급", phone: "031-234-5678", address: "경기도 성남시", status: "활성" }, { id: "C003", code: "CUST-002", name: "LG전자", type: "고객", contact: "박주문", phone: "02-3456-7890", address: "서울시 영등포구", status: "활성" }, { id: "C004", code: "BOTH-001", name: "현대모비스", type: "양방향", contact: "최거래", phone: "031-456-7890", address: "경기도 용인시", status: "활성" }, ]); const [activeTab, setActiveTab] = useState("products"); const [isModalOpen, setIsModalOpen] = useState(false); const [isViewModalOpen, setIsViewModalOpen] = useState(false); const [isEditModalOpen, setIsEditModalOpen] = useState(false); const [selectedItem, setSelectedItem] = useState(null); const [formData, setFormData] = useState({}); const handleCreate = () => { switch (activeTab) { case "products": const newProduct: Product = { id: `P${String(products.length + 1).padStart(3, '0')}`, code: formData.code || "", name: formData.name || "", type: formData.type || "", unit: formData.unit || "", standardTime: formData.standardTime || 0, materialCost: formData.materialCost || 0, laborCost: formData.laborCost || 0, description: formData.description || "", status: "사용", }; setProducts([...products, newProduct]); break; case "bom": const newBOM: BOM = { id: `BOM${String(bomData.length + 1).padStart(3, '0')}`, productCode: formData.productCode || "", productName: products.find(p => p.code === formData.productCode)?.name || "", materialCode: formData.materialCode || "", materialName: formData.materialName || "", quantity: formData.quantity || 0, unit: formData.unit || "", notes: formData.notes || "", }; setBomData([...bomData, newBOM]); break; case "processes": const newProcess: Process = { id: `PROC${String(processes.length + 1).padStart(3, '0')}`, code: formData.code || "", name: formData.name || "", workCenter: formData.workCenter || "", standardTime: formData.standardTime || 0, setupTime: formData.setupTime || 0, description: formData.description || "", nextProcess: formData.nextProcess || "", }; setProcesses([...processes, newProcess]); break; case "customers": const newCustomer: Customer = { id: `C${String(customers.length + 1).padStart(3, '0')}`, code: formData.code || "", name: formData.name || "", type: formData.type || "고객", contact: formData.contact || "", phone: formData.phone || "", address: formData.address || "", status: "활성", }; setCustomers([...customers, newCustomer]); break; } setFormData({}); setIsModalOpen(false); toast.success("등록이 완료되었습니다."); }; const handleUpdate = () => { if (!selectedItem) return; switch (activeTab) { case "products": const updatedProducts = products.map(item => item.id === selectedItem.id ? { ...item, ...formData } : item ); setProducts(updatedProducts); break; case "bom": const updatedBOM = bomData.map(item => item.id === selectedItem.id ? { ...item, ...formData } : item ); setBomData(updatedBOM); break; case "processes": const updatedProcesses = processes.map(item => item.id === selectedItem.id ? { ...item, ...formData } : item ); setProcesses(updatedProcesses); break; case "customers": const updatedCustomers = customers.map(item => item.id === selectedItem.id ? { ...item, ...formData } : item ); setCustomers(updatedCustomers); break; } setFormData({}); setSelectedItem(null); setIsEditModalOpen(false); toast.success("수정이 완료되었습니다."); }; const handleDelete = (id: string) => { switch (activeTab) { case "products": setProducts(products.filter(item => item.id !== id)); break; case "bom": setBomData(bomData.filter(item => item.id !== id)); break; case "processes": setProcesses(processes.filter(item => item.id !== id)); break; case "customers": setCustomers(customers.filter(item => item.id !== id)); break; } toast.success("삭제가 완료되었습니다."); }; const getStatusColor = (status: string) => { switch (status) { case "사용": case "활성": return "bg-green-500"; case "중단": case "비활성": return "bg-red-500"; default: return "bg-gray-500"; } }; const getTypeColor = (type: string) => { switch (type) { case "고객": return "text-blue-600"; case "공급업체": return "text-green-600"; case "양방향": return "text-purple-600"; default: return "text-gray-600"; } }; return (
{/* 모바일 우선 헤더 */}

기준정보 관리

제품, BOM, 공정, 거래처 등 기준 정보 관리

{/* 기준정보 대시보드 - 모바일 2열, 태블릿 2열, 데스크톱 4열 */}
제품 마스터
{products.length}개

등록된 제품 수

BOM 구성
{bomData.length}건

BOM 구성 정보

공정 마스터
{processes.length}개

등록된 공정 수

거래처
{customers.length}개

등록된 거래처 수

{/* 기준정보 현황 - 모바일 1열, 데스크톱 2열 */}
제품별 BOM 구성 현황
{products.slice(0, 3).map((product) => { const bomCount = bomData.filter(bom => bom.productCode === product.code).length; return (

{product.name}

{product.code}

{bomCount}개 자재

{product.type}

); })}
거래처 유형별 현황
{["고객", "공급업체", "양방향"].map((type) => { const count = customers.filter(c => c.type === type).length; return (

{type}

거래처 유형

{count}개

{type}

); })}
{/* 탭 메뉴 - 모바일 스크롤 */}
제품 BOM 공정 거래처
{/* 제품 마스터 탭 */}
제품 마스터
{/* 모바일: 카드 레이아웃, 데스크톱: 테이블 */}
{products.map((product) => (

{product.name}

{product.code}

{product.status}
유형: {product.type}
단위: {product.unit}
표준시간: {product.standardTime}분
재료비: {product.materialCost.toLocaleString()}원
제품 삭제 {product.name} 제품을 삭제하시겠습니까? 취소 handleDelete(product.id)} className="min-h-[44px] touch-manipulation" > 삭제
))}
{/* 데스크톱 테이블 */}
제품코드 제품명 유형 단위 표준시간(분) 재료비 상태 관리 {products.map((product) => ( {product.code} {product.name} {product.type} {product.unit} {product.standardTime}분 {product.materialCost.toLocaleString()}원 {product.status}
제품 삭제 {product.name} 제품을 삭제하시겠습니까? 취소 handleDelete(product.id)}> 삭제
))}
{/* BOM 탭 */} BOM (Bill of Materials) {/* 모바일 카드 레이아웃 */}
{bomData.map((bom) => (

{bom.productName}

{bom.productCode}

자재: {bom.materialName}
코드: {bom.materialCode}
소요량: {bom.quantity} {bom.unit}
비고: {bom.notes}
BOM 삭제 이 BOM 항목을 삭제하시겠습니까? 취소 handleDelete(bom.id)} className="min-h-[44px] touch-manipulation" > 삭제
))}
{/* 데스크톱 테이블 */}
제품코드 제품명 자재코드 자재명 소요량 단위 관리 {bomData.map((bom) => ( {bom.productCode} {bom.productName} {bom.materialCode} {bom.materialName} {bom.quantity} {bom.unit}
BOM 삭제 이 BOM 항목을 삭제하시겠습니까? 취소 handleDelete(bom.id)}> 삭제
))}
{/* 공정 마스터 탭 */} 공정 마스터 {/* 모바일 카드 레이아웃 */}
{processes.map((process) => (

{process.name}

{process.code}

작업장: {process.workCenter}
표준시간: {process.standardTime}분
준비시간: {process.setupTime}분
다음공정: {process.nextProcess || "-"}
공정 삭제 {process.name} 공정을 삭제하시겠습니까? 취소 handleDelete(process.id)} className="min-h-[44px] touch-manipulation" > 삭제
))}
{/* 데스크톱 테이블 */}
공정코드 공정명 작업장 표준시간(분) 준비시간(분) 다음공정 관리 {processes.map((process) => ( {process.code} {process.name} {process.workCenter} {process.standardTime}분 {process.setupTime}분 {process.nextProcess || "-"}
공정 삭제 {process.name} 공정을 삭제하시겠습니까? 취소 handleDelete(process.id)}> 삭제
))}
{/* 거래처 탭 */} 거래처 관리 {/* 모바일 카드 레이아웃 */}
{customers.map((customer) => (

{customer.name}

{customer.code}

{customer.status}

{customer.type}

담당자: {customer.contact}
연락처: {customer.phone}
주소: {customer.address}
거래처 삭제 {customer.name} 거래처를 삭제하시겠습니까? 취소 handleDelete(customer.id)} className="min-h-[44px] touch-manipulation" > 삭제
))}
{/* 데스크톱 테이블 */}
거래처코드 거래처명 유형 담당자 연락처 상태 관리 {customers.map((customer) => ( {customer.code} {customer.name} {customer.type} {customer.contact} {customer.phone} {customer.status}
거래처 삭제 {customer.name} 거래처를 삭제하시겠습니까? 취소 handleDelete(customer.id)}> 삭제
))}
{/* 신규 등록 모달 */} {activeTab === "products" && "제품 등록"} {activeTab === "bom" && "BOM 등록"} {activeTab === "processes" && "공정 등록"} {activeTab === "customers" && "거래처 등록"} 새로운 {activeTab === "products" && "제품"} {activeTab === "bom" && "BOM"} {activeTab === "processes" && "공정"} {activeTab === "customers" && "거래처"} 정보를 등록합니다.
{activeTab === "products" && ( <>
setFormData({...formData, code: e.target.value})} className="min-h-[44px] touch-manipulation" />
setFormData({...formData, name: e.target.value})} className="min-h-[44px] touch-manipulation" />
setFormData({...formData, unit: e.target.value})} className="min-h-[44px] touch-manipulation" />
setFormData({...formData, standardTime: Number(e.target.value)})} className="min-h-[44px] touch-manipulation" />
setFormData({...formData, materialCost: Number(e.target.value)})} className="min-h-[44px] touch-manipulation" />