summaryrefslogtreecommitdiff
path: root/lib/legal-review/status/request-review-dialog.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/legal-review/status/request-review-dialog.tsx')
-rw-r--r--lib/legal-review/status/request-review-dialog.tsx983
1 files changed, 0 insertions, 983 deletions
diff --git a/lib/legal-review/status/request-review-dialog.tsx b/lib/legal-review/status/request-review-dialog.tsx
deleted file mode 100644
index d99fc0e3..00000000
--- a/lib/legal-review/status/request-review-dialog.tsx
+++ /dev/null
@@ -1,983 +0,0 @@
-"use client"
-
-import * as React from "react"
-import { useForm } from "react-hook-form"
-import { zodResolver } from "@hookform/resolvers/zod"
-import * as z from "zod"
-import { Loader2, Send, FileText, Clock, Upload, X, Building, User, Calendar } from "lucide-react"
-import { toast } from "sonner"
-
-import { Button } from "@/components/ui/button"
-import {
- Dialog,
- DialogContent,
- DialogDescription,
- DialogHeader,
- DialogTitle,
-} from "@/components/ui/dialog"
-import {
- Form,
- FormControl,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
-} from "@/components/ui/form"
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "@/components/ui/select"
-import { Input } from "@/components/ui/input"
-import { Textarea } from "@/components/ui/textarea"
-import { Badge } from "@/components/ui/badge"
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
-import { Switch } from "@/components/ui/switch"
-import TiptapEditor from "@/components/qna/tiptap-editor"
-import { canRequestReview, requestReview } from "../service"
-import { LegalWorksDetailView } from "@/db/schema"
-
-type LegalWorkData = LegalWorksDetailView
-
-interface RequestReviewDialogProps {
- open: boolean
- onOpenChange: (open: boolean) => void
- work: LegalWorkData | null
- onSuccess?: () => void
-}
-
-// 검토요청 폼 스키마
-const requestReviewSchema = z.object({
- // 기본 검토 설정
- dueDate: z.string().min(1, "검토 완료 희망일을 선택해주세요"),
- assignee: z.string().optional(),
- notificationMethod: z.enum(["email", "internal", "both"]).default("both"),
-
- // 법무업무 상세 정보
- reviewDepartment: z.enum(["준법문의", "법무검토"]),
- inquiryType: z.enum(["국내계약", "국내자문", "해외계약", "해외자문"]).optional(),
-
- // 공통 필드
- title: z.string().min(1, "제목을 선택해주세요"),
- requestContent: z.string().min(1, "요청내용을 입력해주세요"),
-
- // 준법문의 전용 필드
- isPublic: z.boolean().default(false),
-
- // 법무검토 전용 필드들
- contractProjectName: z.string().optional(),
- contractType: z.string().optional(),
- contractCounterparty: z.string().optional(),
- counterpartyType: z.enum(["법인", "개인"]).optional(),
- contractPeriod: z.string().optional(),
- contractAmount: z.string().optional(),
- factualRelation: z.string().optional(),
- projectNumber: z.string().optional(),
- shipownerOrderer: z.string().optional(),
- projectType: z.string().optional(),
- governingLaw: z.string().optional(),
-}).refine((data) => {
- // 법무검토 선택시 문의종류 필수
- if (data.reviewDepartment === "법무검토" && !data.inquiryType) {
- return false;
- }
- return true;
-}, {
- message: "법무검토 선택시 문의종류를 선택해주세요",
- path: ["inquiryType"]
-});
-
-type RequestReviewFormValues = z.infer<typeof requestReviewSchema>
-
-export function RequestReviewDialog({
- open,
- onOpenChange,
- work,
- onSuccess
-}: RequestReviewDialogProps) {
- const [isSubmitting, setIsSubmitting] = React.useState(false)
- const [attachments, setAttachments] = React.useState<File[]>([])
- const [editorContent, setEditorContent] = React.useState("")
- const [canRequest, setCanRequest] = React.useState(true)
- const [requestCheckMessage, setRequestCheckMessage] = React.useState("")
- const [isCustomTitle, setIsCustomTitle] = React.useState(false)
-
- // work의 category에 따라 기본 reviewDepartment 결정
- const getDefaultReviewDepartment = () => {
- return work?.category === "CP" ? "준법문의" : "법무검토"
- }
-
- const form = useForm<RequestReviewFormValues>({
- resolver: zodResolver(requestReviewSchema),
- defaultValues: {
- dueDate: "",
- assignee: "",
- notificationMethod: "both",
- reviewDepartment: getDefaultReviewDepartment(),
- title: getDefaultReviewDepartment() === "준법문의" ? "CP검토" : "GTC검토",
- requestContent: "",
- isPublic: false,
- },
- })
-
- // work 변경시 검토요청 가능 여부 확인
- React.useEffect(() => {
- if (work && open) {
- canRequestReview(work.id).then((result) => {
- setCanRequest(result.canRequest)
- setRequestCheckMessage(result.reason || "")
- })
-
- const defaultDepartment = work.category === "CP" ? "준법문의" : "법무검토"
- form.setValue("reviewDepartment", defaultDepartment)
- }
- }, [work, open, form])
-
- // 검토부문 감시
- const reviewDepartment = form.watch("reviewDepartment")
- const inquiryType = form.watch("inquiryType")
- const titleValue = form.watch("title")
-
- // 조건부 필드 활성화 로직
- const isContractTypeActive = inquiryType && ["국내계약", "해외계약", "해외자문"].includes(inquiryType)
- const isDomesticContractFieldsActive = inquiryType === "국내계약"
- const isFactualRelationActive = inquiryType && ["국내자문", "해외자문"].includes(inquiryType)
- const isOverseasFieldsActive = inquiryType && ["해외계약", "해외자문"].includes(inquiryType)
-
- // 제목 "기타" 선택 여부 확인
- // const isTitleOther = titleValue === "기타"
-
- // 검토부문 변경시 관련 필드 초기화
- React.useEffect(() => {
- if (reviewDepartment === "준법문의") {
- setIsCustomTitle(false)
- form.setValue("inquiryType", undefined)
- // 제목 초기화 (기타 상태였거나 값이 없으면 기본값으로)
- const currentTitle = form.getValues("title")
- if (!currentTitle || currentTitle === "GTC검토") {
- form.setValue("title", "CP검토")
- }
- // 법무검토 전용 필드들 초기화
- form.setValue("contractProjectName", "")
- form.setValue("contractType", "")
- form.setValue("contractCounterparty", "")
- form.setValue("counterpartyType", undefined)
- form.setValue("contractPeriod", "")
- form.setValue("contractAmount", "")
- form.setValue("factualRelation", "")
- form.setValue("projectNumber", "")
- form.setValue("shipownerOrderer", "")
- form.setValue("projectType", "")
- form.setValue("governingLaw", "")
- } else {
- setIsCustomTitle(false)
- // 제목 초기화 (기타 상태였거나 값이 없으면 기본값으로)
- const currentTitle = form.getValues("title")
- if (!currentTitle || currentTitle === "CP검토") {
- form.setValue("title", "GTC검토")
- }
- form.setValue("isPublic", false)
- }
- }, [reviewDepartment, form])
-
- // 문의종류 변경시 관련 필드 초기화
- React.useEffect(() => {
- if (inquiryType) {
- // 계약서 종류 초기화 (옵션이 달라지므로)
- form.setValue("contractType", "")
-
- // 조건에 맞지 않는 필드들 초기화
- if (!isDomesticContractFieldsActive) {
- form.setValue("contractCounterparty", "")
- form.setValue("counterpartyType", undefined)
- form.setValue("contractPeriod", "")
- form.setValue("contractAmount", "")
- }
-
- if (!isFactualRelationActive) {
- form.setValue("factualRelation", "")
- }
-
- if (!isOverseasFieldsActive) {
- form.setValue("projectNumber", "")
- form.setValue("shipownerOrderer", "")
- form.setValue("projectType", "")
- form.setValue("governingLaw", "")
- }
- }
- }, [inquiryType, isDomesticContractFieldsActive, isFactualRelationActive, isOverseasFieldsActive, form])
-
- // 에디터 내용이 변경될 때 폼에 반영
- React.useEffect(() => {
- form.setValue("requestContent", editorContent)
- }, [editorContent, form])
-
- // 첨부파일 처리
- const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
- const files = Array.from(event.target.files || [])
- setAttachments(prev => [...prev, ...files])
- }
-
- const removeAttachment = (index: number) => {
- setAttachments(prev => prev.filter((_, i) => i !== index))
- }
-
- // 폼 제출
- async function onSubmit(data: RequestReviewFormValues) {
- if (!work) return
-
- console.log("Request review data:", data)
- console.log("Work to review:", work)
- console.log("Attachments:", attachments)
- setIsSubmitting(true)
-
- try {
- const result = await requestReview(work.id, data, attachments)
-
- if (result.success) {
- toast.success(result.data?.message || `법무업무 #${work.id}에 대한 검토요청이 완료되었습니다.`)
- onOpenChange(false)
- handleReset()
- onSuccess?.()
- } else {
- toast.error(result.error || "검토요청 중 오류가 발생했습니다.")
- }
- } catch (error) {
- console.error("Error requesting review:", error)
- toast.error("검토요청 중 오류가 발생했습니다.")
- } finally {
- setIsSubmitting(false)
- }
- }
-
- // 폼 리셋 함수
- const handleReset = () => {
- const defaultDepartment = getDefaultReviewDepartment()
- setIsCustomTitle(false) // 추가
-
- form.reset({
- dueDate: "",
- assignee: "",
- notificationMethod: "both",
- reviewDepartment: defaultDepartment,
- title: defaultDepartment === "준법문의" ? "CP검토" : "GTC검토",
- requestContent: "",
- isPublic: false,
- })
- setAttachments([])
- setEditorContent("")
- }
-
- // 다이얼로그 닫기 핸들러
- const handleOpenChange = (open: boolean) => {
- onOpenChange(open)
- if (!open) {
- handleReset()
- }
- }
-
- // 제목 옵션 (검토부문에 따라 다름)
- const getTitleOptions = () => {
- if (reviewDepartment === "준법문의") {
- return [
- { value: "CP검토", label: "CP검토" },
- { value: "기타", label: "기타 (직접입력)" }
- ]
- } else {
- return [
- { value: "GTC검토", label: "GTC검토" },
- { value: "기타", label: "기타 (직접입력)" }
- ]
- }
- }
-
- // 계약서 종류 옵션 (문의종류에 따라 다름)
- const getContractTypeOptions = () => {
- if (inquiryType === "국내계약") {
- return [
- { value: "공사도급계약", label: "공사도급계약" },
- { value: "제작납품계약", label: "제작납품계약" },
- { value: "자재매매계약", label: "자재매매계약" },
- { value: "용역위탁계약", label: "용역위탁계약" },
- { value: "기술사용 및 개발계약", label: "기술사용 및 개발계약" },
- { value: "운송 및 자재관리 계약", label: "운송 및 자재관리 계약" },
- { value: "자문 등 위임계약", label: "자문 등 위임계약" },
- { value: "양해각서", label: "양해각서" },
- { value: "양수도 계약", label: "양수도 계약" },
- { value: "합의서", label: "합의서" },
- { value: "공동도급(운영)협약서", label: "공동도급(운영)협약서" },
- { value: "협정서", label: "협정서" },
- { value: "약정서", label: "약정서" },
- { value: "협의서", label: "협의서" },
- { value: "기타", label: "기타" },
- { value: "비밀유지계약서", label: "비밀유지계약서" },
- { value: "분양계약서", label: "분양계약서" },
- ]
- } else {
- // 해외계약/해외자문
- return [
- { value: "Shipbuilding Contract", label: "Shipbuilding Contract" },
- { value: "Offshore Contract (EPCI, FEED)", label: "Offshore Contract (EPCI, FEED)" },
- { value: "Supplementary / Addendum", label: "Supplementary / Addendum" },
- { value: "Subcontract / GTC / PTC / PO", label: "Subcontract / GTC / PTC / PO" },
- { value: "Novation / Assignment", label: "Novation / Assignment" },
- { value: "NDA (Confidential, Secrecy)", label: "NDA (Confidential, Secrecy)" },
- { value: "Warranty", label: "Warranty" },
- { value: "Waiver and Release", label: "Waiver and Release" },
- { value: "Bond (PG, RG, Advanced Payment)", label: "Bond (PG, RG, Advanced Payment)" },
- { value: "MOU / LOI / LOA", label: "MOU / LOI / LOA" },
- { value: "Power of Attorney (POA)", label: "Power of Attorney (POA)" },
- { value: "Commission Agreement", label: "Commission Agreement" },
- { value: "Consortium Agreement", label: "Consortium Agreement" },
- { value: "JV / JDP Agreement", label: "JV / JDP Agreement" },
- { value: "Engineering Service Contract", label: "Engineering Service Contract" },
- { value: "Consultancy Service Agreement", label: "Consultancy Service Agreement" },
- { value: "Purchase / Lease Agreement", label: "Purchase / Lease Agreement" },
- { value: "Financial / Loan / Covenant", label: "Financial / Loan / Covenant" },
- { value: "Other Contract / Agreement", label: "Other Contract / Agreement" },
- ]
- }
- }
-
- // 프로젝트 종류 옵션
- const getProjectTypeOptions = () => {
- return [
- { value: "BARGE VESSEL", label: "BARGE VESSEL" },
- { value: "BULK CARRIER", label: "BULK CARRIER" },
- { value: "CHEMICAL CARRIER", label: "CHEMICAL CARRIER" },
- { value: "FULL CONTAINER", label: "FULL CONTAINER" },
- { value: "CRUDE OIL TANKER", label: "CRUDE OIL TANKER" },
- { value: "CRUISE SHIP", label: "CRUISE SHIP" },
- { value: "DRILL SHIP", label: "DRILL SHIP" },
- { value: "FIELD DEVELOPMENT SHIP", label: "FIELD DEVELOPMENT SHIP" },
- { value: "FLOATING PRODUCTION STORAGE OFFLOADING", label: "FLOATING PRODUCTION STORAGE OFFLOADING" },
- { value: "CAR-FERRY & PASSENGER VESSEL", label: "CAR-FERRY & PASSENGER VESSEL" },
- { value: "FLOATING STORAGE OFFLOADING", label: "FLOATING STORAGE OFFLOADING" },
- { value: "HEAVY DECK CARGO", label: "HEAVY DECK CARGO" },
- { value: "PRODUCT OIL TANKER", label: "PRODUCT OIL TANKER" },
- { value: "HIGH SPEED LINER", label: "HIGH SPEED LINER" },
- { value: "JACK-UP", label: "JACK-UP" },
- { value: "LIQUEFIED NATURAL GAS CARRIER", label: "LIQUEFIED NATURAL GAS CARRIER" },
- { value: "LIQUEFIED PETROLEUM GAS CARRIER", label: "LIQUEFIED PETROLEUM GAS CARRIER" },
- { value: "MULTIPURPOSE CARGO CARRIER", label: "MULTIPURPOSE CARGO CARRIER" },
- { value: "ORE-BULK-OIL CARRIER", label: "ORE-BULK-OIL CARRIER" },
- { value: "OIL TANKER", label: "OIL TANKER" },
- { value: "OTHER VESSEL", label: "OTHER VESSEL" },
- { value: "PURE CAR CARRIER", label: "PURE CAR CARRIER" },
- { value: "PRODUCT CARRIER", label: "PRODUCT CARRIER" },
- { value: "PLATFORM", label: "PLATFORM" },
- { value: "PUSHER", label: "PUSHER" },
- { value: "REEFER TRANSPORT VESSEL", label: "REEFER TRANSPORT VESSEL" },
- { value: "ROLL-ON ROLL-OFF VESSEL", label: "ROLL-ON ROLL-OFF VESSEL" },
- { value: "SEMI RIG", label: "SEMI RIG" },
- { value: "SUPPLY ANCHOR HANDLING VESSEL", label: "SUPPLY ANCHOR HANDLING VESSEL" },
- { value: "SHUTTLE TANKER", label: "SHUTTLE TANKER" },
- { value: "SUPPLY VESSEL", label: "SUPPLY VESSEL" },
- { value: "TOPSIDE", label: "TOPSIDE" },
- { value: "TUG SUPPLY VESSEL", label: "TUG SUPPLY VESSEL" },
- { value: "VERY LARGE CRUDE OIL CARRIER", label: "VERY LARGE CRUDE OIL CARRIER" },
- { value: "WELL INTERVENTION SHIP", label: "WELL INTERVENTION SHIP" },
- { value: "WIND TURBINE INSTALLATION VESSEL", label: "WIND TURBINE INSTALLATION VESSEL" },
- { value: "기타", label: "기타" },
- ]
- }
-
- if (!work) {
- return null
- }
-
- // 검토요청 불가능한 경우 안내 메시지
- if (!canRequest) {
- return (
- <Dialog open={open} onOpenChange={onOpenChange}>
- <DialogContent className="max-w-md">
- <DialogHeader>
- <DialogTitle className="flex items-center gap-2 text-amber-600">
- <FileText className="h-5 w-5" />
- 검토요청 불가
- </DialogTitle>
- <DialogDescription className="pt-4">
- {requestCheckMessage}
- </DialogDescription>
- </DialogHeader>
- <div className="flex justify-end pt-4">
- <Button onClick={() => onOpenChange(false)}>확인</Button>
- </div>
- </DialogContent>
- </Dialog>
- )
- }
-
- return (
- <Dialog open={open} onOpenChange={handleOpenChange}>
- <DialogContent className="max-w-4xl h-[90vh] p-0 flex flex-col">
- {/* 고정 헤더 */}
- <div className="flex-shrink-0 p-6 border-b">
- <DialogHeader>
- <DialogTitle className="flex items-center gap-2">
- <Send className="h-5 w-5" />
- 검토요청 발송
- </DialogTitle>
- <DialogDescription>
- 법무업무 #{work.id}에 대한 상세한 검토를 요청합니다.
- </DialogDescription>
- </DialogHeader>
- </div>
-
- <Form {...form}>
- <form
- onSubmit={form.handleSubmit(onSubmit)}
- className="flex flex-col flex-1 min-h-0"
- >
- {/* 스크롤 가능한 콘텐츠 영역 */}
- <div className="flex-1 overflow-y-auto p-6">
- <div className="space-y-6">
- {/* 선택된 업무 정보 */}
- <Card className="bg-blue-50 border-blue-200">
- <CardHeader>
- <CardTitle className="text-lg flex items-center gap-2">
- <FileText className="h-5 w-5" />
- 검토 대상 업무
- </CardTitle>
- </CardHeader>
- <CardContent>
- <div className="grid grid-cols-2 gap-4 text-sm">
- <div className="space-y-2">
- <div className="flex items-center gap-2">
- <span className="font-medium">업무 ID:</span>
- <Badge variant="outline">#{work.id}</Badge>
- </div>
- <div className="flex items-center gap-2">
- <span className="font-medium">구분:</span>
- <Badge variant={work.category === "CP" ? "default" : "secondary"}>
- {work.category}
- </Badge>
- {work.isUrgent && (
- <Badge variant="destructive" className="text-xs">
- 긴급
- </Badge>
- )}
- </div>
- <div className="flex items-center gap-2">
- <Building className="h-4 w-4" />
- <span className="font-medium">벤더:</span>
- <span>{work.vendorCode} - {work.vendorName}</span>
- </div>
- </div>
- <div className="space-y-2">
- <div className="flex items-center gap-2">
- <User className="h-4 w-4" />
- <span className="font-medium">요청자:</span>
- <span>{work.reviewer || "미지정"}</span>
- </div>
- <div className="flex items-center gap-2">
- <Calendar className="h-4 w-4" />
- <span className="font-medium">답변요청일:</span>
- <span>{work.requestDate || "미설정"}</span>
- </div>
- <div className="flex items-center gap-2">
- <span className="font-medium">상태:</span>
- <Badge variant="outline">{work.status}</Badge>
- </div>
- </div>
- </div>
- </CardContent>
- </Card>
-
- {/* 기본 설정 */}
- <Card>
- <CardHeader>
- <CardTitle className="text-lg">기본 설정</CardTitle>
- </CardHeader>
- <CardContent className="space-y-4">
- {/* 검토 완료 희망일 */}
- <FormField
- control={form.control}
- name="dueDate"
- render={({ field }) => (
- <FormItem>
- <FormLabel className="flex items-center gap-2">
- <Clock className="h-4 w-4" />
- 검토 완료 희망일
- </FormLabel>
- <FormControl>
- <Input type="date" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- </CardContent>
- </Card>
-
- {/* 법무업무 상세 정보 */}
- <Card>
- <CardHeader>
- <CardTitle className="text-lg">법무업무 상세 정보</CardTitle>
- </CardHeader>
- <CardContent className="space-y-4">
- {/* 검토부문 */}
- <FormField
- control={form.control}
- name="reviewDepartment"
- render={({ field }) => (
- <FormItem>
- <FormLabel>검토부문</FormLabel>
- <Select onValueChange={field.onChange} value={field.value}>
- <FormControl>
- <SelectTrigger>
- <SelectValue placeholder="검토부문 선택" />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- <SelectItem value="준법문의">준법문의</SelectItem>
- <SelectItem value="법무검토">법무검토</SelectItem>
- </SelectContent>
- </Select>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* 문의종류 (법무검토 선택시만) */}
- {reviewDepartment === "법무검토" && (
- <FormField
- control={form.control}
- name="inquiryType"
- render={({ field }) => (
- <FormItem>
- <FormLabel>문의종류</FormLabel>
- <Select onValueChange={field.onChange} value={field.value}>
- <FormControl>
- <SelectTrigger>
- <SelectValue placeholder="문의종류 선택" />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- <SelectItem value="국내계약">국내계약</SelectItem>
- <SelectItem value="국내자문">국내자문</SelectItem>
- <SelectItem value="해외계약">해외계약</SelectItem>
- <SelectItem value="해외자문">해외자문</SelectItem>
- </SelectContent>
- </Select>
- <FormMessage />
- </FormItem>
- )}
- />
- )}
-
- {/* 제목 - 조건부 렌더링 */}
- <FormField
- control={form.control}
- name="title"
- render={({ field }) => (
- <FormItem>
- <FormLabel>제목</FormLabel>
- {!isCustomTitle ? (
- // Select 모드
- <Select
- onValueChange={(value) => {
- if (value === "기타") {
- setIsCustomTitle(true)
- field.onChange("") // 빈 값으로 초기화
- } else {
- field.onChange(value)
- }
- }}
- value={field.value}
- >
- <FormControl>
- <SelectTrigger>
- <SelectValue placeholder="제목 선택" />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- {getTitleOptions().map((option) => (
- <SelectItem key={option.value} value={option.value}>
- {option.label}
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
- ) : (
- // Input 모드 (기타 선택시)
- <div className="space-y-2">
- <div className="flex items-center gap-2">
- <Badge variant="outline" className="text-xs">기타</Badge>
- <Button
- type="button"
- variant="ghost"
- size="sm"
- onClick={() => {
- const defaultTitle = reviewDepartment === "준법문의" ? "CP검토" : "GTC검토"
- form.setValue("title", defaultTitle)
- setIsCustomTitle(false) // 상태 초기화
- }}
- className="h-6 text-xs"
- >
- 선택 모드로 돌아가기
- </Button>
- </div>
- <FormControl>
- <Input
- placeholder="제목을 직접 입력하세요"
- value={field.value}
- onChange={(e) => field.onChange(e.target.value)}
- autoFocus
- />
- </FormControl>
- </div>
- )}
- <FormMessage />
- </FormItem>
- )}
-/>
-
- {/* 준법문의 전용 필드들 */}
- {reviewDepartment === "준법문의" && (
- <FormField
- control={form.control}
- name="isPublic"
- render={({ field }) => (
- <FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
- <div className="space-y-0.5">
- <FormLabel className="text-base">공개여부</FormLabel>
- <div className="text-sm text-muted-foreground">
- 준법문의 공개 설정
- </div>
- </div>
- <FormControl>
- <Switch
- checked={field.value}
- onCheckedChange={field.onChange}
- />
- </FormControl>
- </FormItem>
- )}
- />
- )}
-
- {/* 법무검토 전용 필드들 */}
- {reviewDepartment === "법무검토" && (
- <div className="space-y-4">
- {/* 계약명/프로젝트명 */}
- <FormField
- control={form.control}
- name="contractProjectName"
- render={({ field }) => (
- <FormItem>
- <FormLabel>계약명/프로젝트명</FormLabel>
- <FormControl>
- <Input placeholder="계약명 또는 프로젝트명 입력" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* 계약서 종류 - 조건부 활성화 */}
- {isContractTypeActive && (
- <FormField
- control={form.control}
- name="contractType"
- render={({ field }) => (
- <FormItem>
- <FormLabel>계약서 종류</FormLabel>
- <Select onValueChange={field.onChange} value={field.value}>
- <FormControl>
- <SelectTrigger>
- <SelectValue placeholder="계약서 종류 선택" />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- {getContractTypeOptions().map((option) => (
- <SelectItem key={option.value} value={option.value}>
- {option.label}
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
- <FormMessage />
- </FormItem>
- )}
- />
- )}
-
- {/* 국내계약 전용 필드들 */}
- {isDomesticContractFieldsActive && (
- <div className="grid grid-cols-2 gap-4">
- {/* 계약상대방 */}
- <FormField
- control={form.control}
- name="contractCounterparty"
- render={({ field }) => (
- <FormItem>
- <FormLabel>계약상대방</FormLabel>
- <FormControl>
- <Input placeholder="계약상대방 입력" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* 계약상대방 구분 */}
- <FormField
- control={form.control}
- name="counterpartyType"
- render={({ field }) => (
- <FormItem>
- <FormLabel>계약상대방 구분</FormLabel>
- <Select onValueChange={field.onChange} value={field.value}>
- <FormControl>
- <SelectTrigger>
- <SelectValue placeholder="구분 선택" />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- <SelectItem value="법인">법인</SelectItem>
- <SelectItem value="개인">개인</SelectItem>
- </SelectContent>
- </Select>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* 계약기간 */}
- <FormField
- control={form.control}
- name="contractPeriod"
- render={({ field }) => (
- <FormItem>
- <FormLabel>계약기간</FormLabel>
- <FormControl>
- <Input placeholder="계약기간 입력" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* 계약금액 */}
- <FormField
- control={form.control}
- name="contractAmount"
- render={({ field }) => (
- <FormItem>
- <FormLabel>계약금액</FormLabel>
- <FormControl>
- <Input placeholder="계약금액 입력" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- </div>
- )}
-
- {/* 사실관계 - 조건부 활성화 */}
- {isFactualRelationActive && (
- <FormField
- control={form.control}
- name="factualRelation"
- render={({ field }) => (
- <FormItem>
- <FormLabel>사실관계</FormLabel>
- <FormControl>
- <Textarea
- placeholder="사실관계를 상세히 입력해주세요"
- className="min-h-[80px]"
- {...field}
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- )}
-
- {/* 해외 관련 필드들 - 조건부 활성화 */}
- {isOverseasFieldsActive && (
- <div className="grid grid-cols-2 gap-4">
- {/* 프로젝트번호 */}
- <FormField
- control={form.control}
- name="projectNumber"
- render={({ field }) => (
- <FormItem>
- <FormLabel>프로젝트번호</FormLabel>
- <FormControl>
- <Input placeholder="프로젝트번호 입력" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* 선주/발주처 */}
- <FormField
- control={form.control}
- name="shipownerOrderer"
- render={({ field }) => (
- <FormItem>
- <FormLabel>선주/발주처</FormLabel>
- <FormControl>
- <Input placeholder="선주/발주처 입력" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* 프로젝트종류 */}
- <FormField
- control={form.control}
- name="projectType"
- render={({ field }) => (
- <FormItem>
- <FormLabel>프로젝트종류</FormLabel>
- <Select onValueChange={field.onChange} value={field.value}>
- <FormControl>
- <SelectTrigger>
- <SelectValue placeholder="프로젝트종류 선택" />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- {getProjectTypeOptions().map((option) => (
- <SelectItem key={option.value} value={option.value}>
- {option.label}
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* 준거법 */}
- <FormField
- control={form.control}
- name="governingLaw"
- render={({ field }) => (
- <FormItem>
- <FormLabel>준거법</FormLabel>
- <FormControl>
- <Input placeholder="준거법 입력" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- </div>
- )}
- </div>
- )}
-
- {/* 요청내용 - TiptapEditor로 교체 */}
- <FormField
- control={form.control}
- name="requestContent"
- render={({ field }) => (
- <FormItem>
- <FormLabel>요청내용</FormLabel>
- <FormControl>
- <div className="min-h-[250px]">
- <TiptapEditor
- content={editorContent}
- setContent={setEditorContent}
- disabled={isSubmitting}
- height="250px"
- />
- </div>
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* 첨부파일 */}
- <div className="space-y-2">
- <FormLabel>첨부파일</FormLabel>
- <div className="border-2 border-dashed border-muted-foreground/25 rounded-lg p-4">
- <input
- type="file"
- multiple
- onChange={handleFileChange}
- className="hidden"
- id="file-upload"
- />
- <label
- htmlFor="file-upload"
- className="flex flex-col items-center justify-center cursor-pointer"
- >
- <Upload className="h-8 w-8 text-muted-foreground mb-2" />
- <span className="text-sm text-muted-foreground">
- 파일을 선택하거나 여기로 드래그하세요
- </span>
- </label>
- </div>
-
- {/* 선택된 파일 목록 */}
- {attachments.length > 0 && (
- <div className="space-y-2">
- {attachments.map((file, index) => (
- <div key={index} className="flex items-center justify-between bg-muted/50 p-2 rounded">
- <span className="text-sm truncate">{file.name}</span>
- <Button
- type="button"
- variant="ghost"
- size="sm"
- onClick={() => removeAttachment(index)}
- >
- <X className="h-4 w-4" />
- </Button>
- </div>
- ))}
- </div>
- )}
- </div>
- </CardContent>
- </Card>
- </div>
- </div>
-
- {/* 고정 버튼 영역 */}
- <div className="flex-shrink-0 border-t p-6">
- <div className="flex justify-end gap-3">
- <Button
- type="button"
- variant="outline"
- onClick={() => handleOpenChange(false)}
- disabled={isSubmitting}
- >
- 취소
- </Button>
- <Button
- type="submit"
- disabled={isSubmitting}
- className="bg-blue-600 hover:bg-blue-700"
- >
- {isSubmitting ? (
- <>
- <Loader2 className="mr-2 h-4 w-4 animate-spin" />
- 발송 중...
- </>
- ) : (
- <>
- <Send className="mr-2 h-4 w-4" />
- 검토요청 발송
- </>
- )}
- </Button>
- </div>
- </div>
- </form>
- </Form>
- </DialogContent>
- </Dialog>
- )
-} \ No newline at end of file