From ba8cd44a0ed2c613a5f2cee06bfc9bd0f61f21c7 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Fri, 7 Nov 2025 08:39:04 +0000 Subject: (최겸) 입찰/견적 수정사항 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/create-general-contract-dialog.tsx | 156 +++++++++++++-------- .../main/general-contract-update-sheet.tsx | 53 +++++-- .../main/general-contracts-table-columns.tsx | 34 +---- .../main/general-contracts-table.tsx | 5 +- 4 files changed, 148 insertions(+), 100 deletions(-) (limited to 'lib/general-contracts/main') diff --git a/lib/general-contracts/main/create-general-contract-dialog.tsx b/lib/general-contracts/main/create-general-contract-dialog.tsx index 2c3fc8bc..168b8cbc 100644 --- a/lib/general-contracts/main/create-general-contract-dialog.tsx +++ b/lib/general-contracts/main/create-general-contract-dialog.tsx @@ -20,11 +20,12 @@ import { Textarea } from "@/components/ui/textarea" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Calendar } from "@/components/ui/calendar" import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" -import { CalendarIcon } from "lucide-react" +import { CalendarIcon, Check, ChevronsUpDown } from "lucide-react" +import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from "@/components/ui/command" import { format } from "date-fns" import { ko } from "date-fns/locale" import { cn } from "@/lib/utils" -import { createContract, getVendors, getProjects } from "@/lib/general-contracts/service" +import { createContract, getVendors } from "@/lib/general-contracts/service" import { GENERAL_CONTRACT_CATEGORIES, GENERAL_CONTRACT_TYPES, @@ -39,7 +40,6 @@ interface CreateContractForm { type: string executionMethod: string vendorId: number | null - projectId: number | null startDate: Date | undefined endDate: Date | undefined validityEndDate: Date | undefined @@ -52,7 +52,8 @@ export function CreateGeneralContractDialog() { const [open, setOpen] = React.useState(false) const [isLoading, setIsLoading] = React.useState(false) const [vendors, setVendors] = React.useState>([]) - const [projects, setProjects] = React.useState>([]) + const [vendorSearchTerm, setVendorSearchTerm] = React.useState("") + const [vendorOpen, setVendorOpen] = React.useState(false) const [form, setForm] = React.useState({ contractNumber: '', @@ -61,7 +62,6 @@ export function CreateGeneralContractDialog() { type: '', executionMethod: '', vendorId: null, - projectId: null, startDate: undefined, endDate: undefined, validityEndDate: undefined, @@ -70,36 +70,54 @@ export function CreateGeneralContractDialog() { // 업체 목록 조회 React.useEffect(() => { - const fetchVendors = async () => { + const fetchData = async () => { try { const vendorList = await getVendors() + console.log('vendorList', vendorList) setVendors(vendorList) } catch (error) { - console.error('Error fetching vendors:', error) + console.error('데이터 조회 오류:', error) + toast.error('데이터를 불러오는데 실패했습니다') + setVendors([]) } } - fetchVendors() + fetchData() }, []) - // 프로젝트 목록 조회 - React.useEffect(() => { - const fetchProjects = async () => { - try { - const projectList = await getProjects() - console.log(projectList) - setProjects(projectList) - } catch (error) { - console.error('Error fetching projects:', error) - } - } - fetchProjects() - }, []) + // 협력업체 검색 필터링 + const filteredVendors = React.useMemo(() => { + if (!vendorSearchTerm.trim()) return vendors + const lowerSearch = vendorSearchTerm.toLowerCase() + return vendors.filter( + vendor => + vendor.vendorName.toLowerCase().includes(lowerSearch) || + (vendor.vendorCode && vendor.vendorCode.toLowerCase().includes(lowerSearch)) + ) + }, [vendors, vendorSearchTerm]) const handleSubmit = async () => { // 필수 필드 검증 - if (!form.name || !form.category || !form.type || !form.executionMethod || - !form.vendorId || !form.startDate || !form.endDate) { - toast.error("필수 항목을 모두 입력해주세요.") + const validationErrors: string[] = [] + + if (!form.name) validationErrors.push('계약명') + if (!form.category) validationErrors.push('계약구분') + if (!form.type) validationErrors.push('계약종류') + if (!form.executionMethod) validationErrors.push('체결방식') + if (!form.vendorId) validationErrors.push('협력업체') + + // AD, LO, OF 계약이 아닌 경우에만 계약기간 필수값 체크 + if (!['AD', 'LO', 'OF'].includes(form.type)) { + if (!form.startDate) validationErrors.push('계약시작일') + if (!form.endDate) validationErrors.push('계약종료일') + } + + // LO 계약인 경우 계약체결유효기간 필수값 체크 + if (form.type === 'LO' && !form.validityEndDate) { + validationErrors.push('유효기간') + } + + if (validationErrors.length > 0) { + toast.error(`다음 필수 항목을 입력해주세요: ${validationErrors.join(', ')}`) return } @@ -116,7 +134,6 @@ export function CreateGeneralContractDialog() { category: form.category, type: form.type, executionMethod: form.executionMethod, - projectId: form.projectId, contractSourceType: 'manual', vendorId: form.vendorId!, startDate: form.startDate!.toISOString().split('T')[0], @@ -152,7 +169,6 @@ export function CreateGeneralContractDialog() { type: '', executionMethod: '', vendorId: null, - projectId: null, startDate: undefined, endDate: undefined, validityEndDate: undefined, @@ -231,15 +247,14 @@ export function CreateGeneralContractDialog() { 'AL': '연간운송계약', 'OS': '외주용역계약', 'OW': '도급계약', - 'IS': '검사계약', 'LO': 'LOI', 'FA': 'FA', 'SC': '납품합의계약', 'OF': '클레임상계계약', 'AW': '사전작업합의', 'AD': '사전납품합의', - 'AM': '설계계약', - 'SC_SELL': '폐기물매각계약' + 'SG': '임치(물품보관)계약', + 'SR': '폐기물매각계약' } return ( @@ -268,36 +283,63 @@ export function CreateGeneralContractDialog() { -
- - -
-
- + + + + + + + + + 검색 결과가 없습니다 + + {filteredVendors.map((vendor) => ( + { + setForm(prev => ({ ...prev, vendorId: vendor.id })) + setVendorOpen(false) + setVendorSearchTerm("") + }} + > + + {vendor.vendorName} + {vendor.vendorCode && ( + ({vendor.vendorCode}) + )} + + ))} + + + + +
diff --git a/lib/general-contracts/main/general-contract-update-sheet.tsx b/lib/general-contracts/main/general-contract-update-sheet.tsx index 54f4ae4e..18095516 100644 --- a/lib/general-contracts/main/general-contract-update-sheet.tsx +++ b/lib/general-contracts/main/general-contract-update-sheet.tsx @@ -44,14 +44,41 @@ const updateContractSchema = z.object({ type: z.string().min(1, "계약종류를 선택해주세요"), executionMethod: z.string().min(1, "체결방식을 선택해주세요"), name: z.string().min(1, "계약명을 입력해주세요"), - startDate: z.string().min(1, "계약시작일을 선택해주세요"), - endDate: z.string().min(1, "계약종료일을 선택해주세요"), - validityEndDate: z.string().min(1, "유효기간종료일을 선택해주세요"), + startDate: z.string().optional(), // AD, LO, OF 계약인 경우 선택사항 + endDate: z.string().optional(), // AD, LO, OF 계약인 경우 선택사항 + validityEndDate: z.string().optional(), // LO 계약인 경우에만 필수값으로 처리 contractScope: z.string().min(1, "계약확정범위를 선택해주세요"), notes: z.string().optional(), linkedRfqOrItb: z.string().optional(), linkedPoNumber: z.string().optional(), linkedBidNumber: z.string().optional(), +}).superRefine((data, ctx) => { + // AD, LO, OF 계약이 아닌 경우 계약기간 필수값 체크 + if (!['AD', 'LO', 'OF'].includes(data.type)) { + if (!data.startDate) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "계약시작일을 선택해주세요", + path: ["startDate"], + }) + } + if (!data.endDate) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "계약종료일을 선택해주세요", + path: ["endDate"], + }) + } + } + + // LO 계약인 경우 계약체결유효기간 필수값 체크 + if (data.type === 'LO' && !data.validityEndDate) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "LO 계약의 경우 계약체결유효기간은 필수 항목입니다", + path: ["validityEndDate"], + }) + } }) type UpdateContractFormData = z.infer @@ -219,15 +246,14 @@ export function GeneralContractUpdateSheet({ 'AL': '연간운송계약', 'OS': '외주용역계약', 'OW': '도급계약', - 'IS': '검사계약', 'LO': 'LOI', 'FA': 'FA', 'SC': '납품합의계약', 'OF': '클레임상계계약', 'AW': '사전작업합의', 'AD': '사전납품합의', - 'AM': '설계계약', - 'SC_SELL': '폐기물매각계약' + 'SG': '임치(물품보관)계약', + 'SR': '폐기물매각계약' } return ( @@ -293,7 +319,10 @@ export function GeneralContractUpdateSheet({ name="startDate" render={({ field }) => ( - 계약시작일 * + + 계약시작일 + {!['AD', 'LO', 'OF'].includes(form.watch('type')) && *} + @@ -308,7 +337,10 @@ export function GeneralContractUpdateSheet({ name="endDate" render={({ field }) => ( - 계약종료일 * + + 계약종료일 + {!['AD', 'LO', 'OF'].includes(form.watch('type')) && *} + @@ -323,7 +355,10 @@ export function GeneralContractUpdateSheet({ name="validityEndDate" render={({ field }) => ( - 유효기간종료일 * + + 유효기간종료일 + {form.watch('type') === 'LO' && *} + diff --git a/lib/general-contracts/main/general-contracts-table-columns.tsx b/lib/general-contracts/main/general-contracts-table-columns.tsx index a08d8b81..932446d2 100644 --- a/lib/general-contracts/main/general-contracts-table-columns.tsx +++ b/lib/general-contracts/main/general-contracts-table-columns.tsx @@ -48,9 +48,6 @@ export interface GeneralContractListItem { vendorId?: number vendorName?: string vendorCode?: string - projectId?: number - projectName?: string - projectCode?: string managerName?: string lastUpdatedByName?: string } @@ -64,9 +61,6 @@ const getStatusBadgeVariant = (status: string) => { switch (status) { case 'Draft': return 'outline' - case 'Request to Review': - case 'Confirm to Review': - return 'secondary' case 'Contract Accept Request': return 'default' case 'Complete the Contract': @@ -84,10 +78,6 @@ const getStatusText = (status: string) => { switch (status) { case 'Draft': return '임시저장' - case 'Request to Review': - return '조건검토요청' - case 'Confirm to Review': - return '조건검토완료' case 'Contract Accept Request': return '계약승인요청' case 'Complete the Contract': @@ -138,8 +128,6 @@ const getTypeText = (type: string) => { return '외주용역계약' case 'OW': return '도급계약' - case 'IS': - return '검사계약' case 'LO': return 'LOI' case 'FA': @@ -152,9 +140,9 @@ const getTypeText = (type: string) => { return '사전작업합의' case 'AD': return '사전납품합의' - case 'AM': - return '설계계약' - case 'SC_SELL': + case 'SG': + return '임치(물품보관)계약' + case 'SR': return '폐기물매각계약' default: return type @@ -360,22 +348,6 @@ export function getGeneralContractsColumns({ setRowAction }: GetColumnsProps): C size: 150, meta: { excelHeader: "협력업체명" }, }, - - { - accessorKey: "projectName", - header: ({ column }) => , - cell: ({ row }) => ( -
- {row.original.projectName || '-'} - - {row.original.projectCode ? row.original.projectCode : "-"} - -
- ), - size: 150, - meta: { excelHeader: "프로젝트명" }, - }, - ] }, diff --git a/lib/general-contracts/main/general-contracts-table.tsx b/lib/general-contracts/main/general-contracts-table.tsx index e4c96ee3..503527b3 100644 --- a/lib/general-contracts/main/general-contracts-table.tsx +++ b/lib/general-contracts/main/general-contracts-table.tsx @@ -49,15 +49,14 @@ const contractTypeLabels = { 'AL': '연간운송계약', 'OS': '외주용역계약', 'OW': '도급계약', - 'IS': '검사계약', 'LO': 'LOI', 'FA': 'FA', 'SC': '납품합의계약', 'OF': '클레임상계계약', 'AW': '사전작업합의', 'AD': '사전납품합의', - 'AM': '설계계약', - 'SC_SELL': '폐기물매각계약' + 'SG': '임치(물품보관)계약', + 'SR': '폐기물매각계약' } interface GeneralContractsTableProps { -- cgit v1.2.3