summaryrefslogtreecommitdiff
path: root/lib/tech-vendors/table/update-vendor-sheet.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tech-vendors/table/update-vendor-sheet.tsx')
-rw-r--r--lib/tech-vendors/table/update-vendor-sheet.tsx1035
1 files changed, 623 insertions, 412 deletions
diff --git a/lib/tech-vendors/table/update-vendor-sheet.tsx b/lib/tech-vendors/table/update-vendor-sheet.tsx
index 1d05b0c4..8498df51 100644
--- a/lib/tech-vendors/table/update-vendor-sheet.tsx
+++ b/lib/tech-vendors/table/update-vendor-sheet.tsx
@@ -1,413 +1,624 @@
-"use client"
-
-import * as React from "react"
-import { zodResolver } from "@hookform/resolvers/zod"
-import { useForm } from "react-hook-form"
-import {
- Loader,
- Activity,
- AlertCircle,
- AlertTriangle,
- Circle as CircleIcon,
- Building,
-} from "lucide-react"
-import { toast } from "sonner"
-
-import { Button } from "@/components/ui/button"
-import {
- Form,
- FormControl,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
- FormDescription
-} from "@/components/ui/form"
-import { Input } from "@/components/ui/input"
-import {
- Sheet,
- SheetClose,
- SheetContent,
- SheetDescription,
- SheetFooter,
- SheetHeader,
- SheetTitle,
-} from "@/components/ui/sheet"
-import {
- Select,
- SelectContent,
- SelectGroup,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from "@/components/ui/select"
-import { useSession } from "next-auth/react" // Import useSession
-
-import { TechVendor, techVendors } from "@/db/schema/techVendors"
-import { updateTechVendorSchema, type UpdateTechVendorSchema } from "../validations"
-import { modifyTechVendor } from "../service"
-
-interface UpdateVendorSheetProps
- extends React.ComponentPropsWithRef<typeof Sheet> {
- vendor: TechVendor | null
-}
-type StatusType = (typeof techVendors.status.enumValues)[number];
-
-type StatusConfig = {
- Icon: React.ElementType;
- className: string;
- label: string;
-};
-
-// 상태 표시 유틸리티 함수
-const getStatusConfig = (status: StatusType): StatusConfig => {
- switch(status) {
- case "ACTIVE":
- return {
- Icon: Activity,
- className: "text-emerald-600",
- label: "활성 상태"
- };
- case "INACTIVE":
- return {
- Icon: AlertCircle,
- className: "text-gray-600",
- label: "비활성 상태"
- };
- case "BLACKLISTED":
- return {
- Icon: AlertTriangle,
- className: "text-slate-800",
- label: "거래 금지"
- };
- case "PENDING_REVIEW":
- return {
- Icon: AlertTriangle,
- className: "text-slate-800",
- label: "비교 견적"
- };
- default:
- return {
- Icon: CircleIcon,
- className: "text-gray-600",
- label: status
- };
- }
-};
-
-
-// 폼 컴포넌트
-export function UpdateVendorSheet({ vendor, ...props }: UpdateVendorSheetProps) {
- const [isPending, startTransition] = React.useTransition()
- const { data: session } = useSession()
- // 폼 정의 - UpdateVendorSchema 타입을 직접 사용
- const form = useForm<UpdateTechVendorSchema>({
- resolver: zodResolver(updateTechVendorSchema),
- defaultValues: {
- // 업체 기본 정보
- vendorName: vendor?.vendorName ?? "",
- vendorCode: vendor?.vendorCode ?? "",
- address: vendor?.address ?? "",
- country: vendor?.country ?? "",
- phone: vendor?.phone ?? "",
- email: vendor?.email ?? "",
- website: vendor?.website ?? "",
- techVendorType: vendor?.techVendorType ? vendor.techVendorType.split(',').map(s => s.trim()).filter(Boolean) as ("조선" | "해양TOP" | "해양HULL")[] : [],
- status: vendor?.status ?? "ACTIVE",
- },
- })
-
- React.useEffect(() => {
- if (vendor) {
- form.reset({
- vendorName: vendor?.vendorName ?? "",
- vendorCode: vendor?.vendorCode ?? "",
- address: vendor?.address ?? "",
- country: vendor?.country ?? "",
- phone: vendor?.phone ?? "",
- email: vendor?.email ?? "",
- website: vendor?.website ?? "",
- techVendorType: vendor?.techVendorType ? vendor.techVendorType.split(',').map(s => s.trim()).filter(Boolean) as ("조선" | "해양TOP" | "해양HULL")[] : [],
- status: vendor?.status ?? "ACTIVE",
-
- });
- }
- }, [vendor, form]);
-
-
- // 제출 핸들러
- async function onSubmit(data: UpdateTechVendorSchema) {
- if (!vendor) return
-
- if (!session?.user?.id) {
- toast.error("사용자 인증 정보를 찾을 수 없습니다.")
- return
- }
- startTransition(async () => {
- try {
- // Add status change comment if status has changed
- const oldStatus = vendor.status ?? "ACTIVE" // Default to ACTIVE if undefined
- const newStatus = data.status ?? "ACTIVE" // Default to ACTIVE if undefined
-
- const statusComment =
- oldStatus !== newStatus
- ? `상태 변경: ${getStatusConfig(oldStatus).label} → ${getStatusConfig(newStatus).label}`
- : "" // Empty string instead of undefined
-
- // 업체 정보 업데이트 - userId와 상태 변경 코멘트 추가
- const { error } = await modifyTechVendor({
- id: String(vendor.id),
- userId: Number(session.user.id), // Add user ID from session
- comment: statusComment, // Add comment for status changes
- ...data, // 모든 데이터 전달 - 서비스 함수에서 필요한 필드만 처리
- techVendorType: Array.isArray(data.techVendorType) ? data.techVendorType.join(',') : undefined,
- })
-
- if (error) throw new Error(error)
-
- toast.success("업체 정보가 업데이트되었습니다!")
- form.reset()
- props.onOpenChange?.(false)
- } catch (err: unknown) {
- toast.error(String(err))
- }
- })
-}
-
- return (
- <Sheet {...props}>
- <SheetContent className="flex flex-col gap-6 sm:max-w-lg overflow-y-auto">
- <SheetHeader className="text-left">
- <SheetTitle>업체 정보 수정</SheetTitle>
- <SheetDescription>
- 업체 세부 정보를 수정하고 변경 사항을 저장하세요
- </SheetDescription>
- </SheetHeader>
- <Form {...form}>
- <form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-6">
- {/* 업체 기본 정보 섹션 */}
- <div className="space-y-4">
- <div className="flex items-center">
- <Building className="mr-2 h-5 w-5 text-muted-foreground" />
- <h3 className="text-sm font-medium">업체 기본 정보</h3>
- </div>
- <FormDescription>
- 업체가 제공한 기본 정보입니다. 필요시 수정하세요.
- </FormDescription>
- <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
- {/* vendorName */}
- <FormField
- control={form.control}
- name="vendorName"
- render={({ field }) => (
- <FormItem>
- <FormLabel>업체명</FormLabel>
- <FormControl>
- <Input placeholder="업체명 입력" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* vendorCode */}
- <FormField
- control={form.control}
- name="vendorCode"
- render={({ field }) => (
- <FormItem>
- <FormLabel>업체 코드</FormLabel>
- <FormControl>
- <Input placeholder="예: ABC123" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* address */}
- <FormField
- control={form.control}
- name="address"
- render={({ field }) => (
- <FormItem className="md:col-span-2">
- <FormLabel>주소</FormLabel>
- <FormControl>
- <Input placeholder="주소 입력" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* country */}
- <FormField
- control={form.control}
- name="country"
- render={({ field }) => (
- <FormItem>
- <FormLabel>국가</FormLabel>
- <FormControl>
- <Input placeholder="예: 대한민국" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* phone */}
- <FormField
- control={form.control}
- name="phone"
- render={({ field }) => (
- <FormItem>
- <FormLabel>전화번호</FormLabel>
- <FormControl>
- <Input placeholder="예: 010-1234-5678" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* email */}
- <FormField
- control={form.control}
- name="email"
- render={({ field }) => (
- <FormItem>
- <FormLabel>이메일</FormLabel>
- <FormControl>
- <Input placeholder="예: info@company.com" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* website */}
- <FormField
- control={form.control}
- name="website"
- render={({ field }) => (
- <FormItem>
- <FormLabel>웹사이트</FormLabel>
- <FormControl>
- <Input placeholder="예: https://www.company.com" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* techVendorType */}
- <FormField
- control={form.control}
- name="techVendorType"
- render={({ field }) => (
- <FormItem className="md:col-span-2">
- <FormLabel>벤더 타입 *</FormLabel>
- <div className="space-y-2">
- {["조선", "해양TOP", "해양HULL"].map((type) => (
- <div key={type} className="flex items-center space-x-2">
- <input
- type="checkbox"
- id={`update-${type}`}
- checked={field.value?.includes(type as "조선" | "해양TOP" | "해양HULL")}
- onChange={(e) => {
- const currentValue = Array.isArray(field.value) ? field.value : [];
- if (e.target.checked) {
- field.onChange([...currentValue, type]);
- } else {
- field.onChange(currentValue.filter((v: string) => v !== type));
- }
- }}
- className="w-4 h-4"
- />
- <label htmlFor={`update-${type}`} className="text-sm font-medium cursor-pointer">
- {type}
- </label>
- </div>
- ))}
- </div>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* status with icons */}
- <FormField
- control={form.control}
- name="status"
- render={({ field }) => {
- // 현재 선택된 상태의 구성 정보 가져오기
- const selectedConfig = getStatusConfig(field.value ?? "ACTIVE");
- const SelectedIcon = selectedConfig?.Icon || CircleIcon;
-
- return (
- <FormItem>
- <FormLabel>업체승인상태</FormLabel>
- <FormControl>
- <Select
- value={field.value || ""}
- onValueChange={field.onChange}
- >
- <SelectTrigger className="w-full">
- <SelectValue>
- {field.value && (
- <div className="flex items-center">
- <SelectedIcon className={`mr-2 h-4 w-4 ${selectedConfig.className}`} />
- <span>{selectedConfig.label}</span>
- </div>
- )}
- </SelectValue>
- </SelectTrigger>
- <SelectContent>
- <SelectGroup>
- {techVendors.status.enumValues.map((status) => {
- const config = getStatusConfig(status);
- const StatusIcon = config.Icon;
- return (
- <SelectItem key={status} value={status}>
- <div className="flex items-center">
- <StatusIcon className={`mr-2 h-4 w-4 ${config.className}`} />
- <span>{config.label}</span>
- </div>
- </SelectItem>
- );
- })}
- </SelectGroup>
- </SelectContent>
- </Select>
- </FormControl>
- <FormMessage />
- </FormItem>
- );
- }}
- />
-
-
-
-
- </div>
- </div>
-
- <SheetFooter className="gap-2 pt-2 sm:space-x-0">
- <SheetClose asChild>
- <Button type="button" variant="outline">
- 취소
- </Button>
- </SheetClose>
- <Button disabled={isPending}>
- {isPending && (
- <Loader className="mr-2 h-4 w-4 animate-spin" aria-hidden="true" />
- )}
- 저장
- </Button>
- </SheetFooter>
- </form>
- </Form>
- </SheetContent>
- </Sheet>
- )
+"use client"
+
+import * as React from "react"
+import { zodResolver } from "@hookform/resolvers/zod"
+import { useForm } from "react-hook-form"
+import {
+ Loader,
+ Activity,
+ AlertCircle,
+ AlertTriangle,
+ Circle as CircleIcon
+} from "lucide-react"
+import { toast } from "sonner"
+
+import { Button } from "@/components/ui/button"
+import {
+ Form,
+ FormControl,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage
+} from "@/components/ui/form"
+import { Input } from "@/components/ui/input"
+import {
+ Sheet,
+ SheetClose,
+ SheetContent,
+ SheetDescription,
+ SheetFooter,
+ SheetHeader,
+ SheetTitle,
+} from "@/components/ui/sheet"
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select"
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
+import { useSession } from "next-auth/react"
+
+import { TechVendor, techVendors } from "@/db/schema/techVendors"
+import { updateTechVendorSchema, type UpdateTechVendorSchema } from "../validations"
+import { modifyTechVendor } from "../service"
+
+interface UpdateVendorSheetProps
+ extends React.ComponentPropsWithRef<typeof Sheet> {
+ vendor: TechVendor | null
+}
+type StatusType = (typeof techVendors.status.enumValues)[number];
+
+type StatusConfig = {
+ Icon: React.ElementType;
+ className: string;
+ label: string;
+};
+
+// 상태 표시 유틸리티 함수
+const getStatusConfig = (status: StatusType): StatusConfig => {
+ switch(status) {
+ case "ACTIVE":
+ return {
+ Icon: Activity,
+ className: "text-emerald-600",
+ label: "활성 상태"
+ };
+ case "INACTIVE":
+ return {
+ Icon: AlertCircle,
+ className: "text-gray-600",
+ label: "비활성 상태"
+ };
+ case "BLACKLISTED":
+ return {
+ Icon: AlertTriangle,
+ className: "text-slate-800",
+ label: "거래 금지"
+ };
+ case "QUOTE_COMPARISON":
+ return {
+ Icon: AlertTriangle,
+ className: "text-slate-800",
+ label: "비교 견적"
+ };
+ case "PENDING_INVITE":
+ return {
+ Icon: AlertTriangle,
+ className: "text-slate-800",
+ label: "초대 대기"
+ };
+ case "INVITED":
+ return {
+ Icon: AlertTriangle,
+ className: "text-slate-800",
+ label: "초대 완료"
+ };
+ default:
+ return {
+ Icon: CircleIcon,
+ className: "text-gray-600",
+ label: status
+ };
+ }
+};
+
+// 폼 컴포넌트
+export function UpdateVendorSheet({ vendor, ...props }: UpdateVendorSheetProps) {
+ const [isPending, startTransition] = React.useTransition()
+ const { data: session } = useSession()
+
+ // 폼 정의 - UpdateVendorSchema 타입을 직접 사용
+ const form = useForm<UpdateTechVendorSchema>({
+ resolver: zodResolver(updateTechVendorSchema),
+ defaultValues: {
+ // 업체 기본 정보
+ vendorName: vendor?.vendorName ?? "",
+ vendorCode: vendor?.vendorCode ?? "",
+ address: vendor?.address ?? "",
+ country: vendor?.country ?? "",
+ countryEng: vendor?.countryEng ?? "",
+ countryFab: vendor?.countryFab ?? "",
+ phone: vendor?.phone ?? "",
+ email: vendor?.email ?? "",
+ website: vendor?.website ?? "",
+ techVendorType: vendor?.techVendorType ? vendor.techVendorType.split(',').map(s => s.trim()).filter(Boolean) as ("조선" | "해양TOP" | "해양HULL")[] : [],
+ status: vendor?.status ?? "ACTIVE",
+ // 에이전트 정보
+ agentName: vendor?.agentName ?? "",
+ agentEmail: vendor?.agentEmail ?? "",
+ agentPhone: vendor?.agentPhone ?? "",
+ // 대표자 정보
+ representativeName: vendor?.representativeName ?? "",
+ representativeEmail: vendor?.representativeEmail ?? "",
+ representativePhone: vendor?.representativePhone ?? "",
+ representativeBirth: vendor?.representativeBirth ?? "",
+ },
+ })
+
+ React.useEffect(() => {
+ if (vendor) {
+ form.reset({
+ vendorName: vendor?.vendorName ?? "",
+ vendorCode: vendor?.vendorCode ?? "",
+ address: vendor?.address ?? "",
+ country: vendor?.country ?? "",
+ countryEng: vendor?.countryEng ?? "",
+ countryFab: vendor?.countryFab ?? "",
+ phone: vendor?.phone ?? "",
+ email: vendor?.email ?? "",
+ website: vendor?.website ?? "",
+ techVendorType: vendor?.techVendorType ? vendor.techVendorType.split(',').map(s => s.trim()).filter(Boolean) as ("조선" | "해양TOP" | "해양HULL")[] : [],
+ status: vendor?.status ?? "ACTIVE",
+ // 에이전트 정보
+ agentName: vendor?.agentName ?? "",
+ agentEmail: vendor?.agentEmail ?? "",
+ agentPhone: vendor?.agentPhone ?? "",
+ // 대표자 정보
+ representativeName: vendor?.representativeName ?? "",
+ representativeEmail: vendor?.representativeEmail ?? "",
+ representativePhone: vendor?.representativePhone ?? "",
+ representativeBirth: vendor?.representativeBirth ?? "",
+ });
+ }
+ }, [vendor, form]);
+
+ // 제출 핸들러
+ async function onSubmit(data: UpdateTechVendorSchema) {
+ if (!vendor) return
+
+ if (!session?.user?.id) {
+ toast.error("사용자 인증 정보를 찾을 수 없습니다.")
+ return
+ }
+
+ startTransition(async () => {
+ try {
+ // Add status change comment if status has changed
+ const oldStatus = vendor.status ?? "ACTIVE" // Default to ACTIVE if undefined
+ const newStatus = data.status ?? "ACTIVE" // Default to ACTIVE if undefined
+
+ const statusComment =
+ oldStatus !== newStatus
+ ? `상태 변경: ${getStatusConfig(oldStatus).label} → ${getStatusConfig(newStatus).label}`
+ : "" // Empty string instead of undefined
+
+ // 업체 정보 업데이트 - userId와 상태 변경 코멘트 추가
+ const { error } = await modifyTechVendor({
+ id: String(vendor.id),
+ userId: Number(session.user.id), // Add user ID from session
+ comment: statusComment, // Add comment for status changes
+ ...data, // 모든 데이터 전달 - 서비스 함수에서 필요한 필드만 처리
+ techVendorType: Array.isArray(data.techVendorType) ? data.techVendorType.join(',') : undefined,
+ })
+
+ if (error) throw new Error(error)
+
+ toast.success("업체 정보가 업데이트되었습니다!")
+ form.reset()
+ props.onOpenChange?.(false)
+ } catch (err: unknown) {
+ toast.error(String(err))
+ }
+ })
+ }
+
+ return (
+ <Sheet {...props}>
+ <SheetContent className="flex flex-col gap-6 sm:max-w-xl overflow-y-auto">
+ <SheetHeader className="text-left">
+ <SheetTitle>업체 정보 수정</SheetTitle>
+ <SheetDescription>
+ 업체 세부 정보를 수정하고 변경 사항을 저장하세요
+ </SheetDescription>
+ </SheetHeader>
+
+ <Form {...form}>
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
+
+ {/* 업체 기본 정보 섹션 */}
+ <Card>
+ <CardHeader className="pb-3">
+ <CardTitle className="text-base">
+ 업체 기본 정보
+ </CardTitle>
+ <CardDescription>
+ 업체의 기본 정보를 관리합니다
+ </CardDescription>
+ </CardHeader>
+ <CardContent className="space-y-4">
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
+ {/* 업체명 */}
+ <FormField
+ control={form.control}
+ name="vendorName"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>업체명</FormLabel>
+ <FormControl>
+ <Input placeholder="업체명 입력" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ {/* 업체 코드 */}
+ <FormField
+ control={form.control}
+ name="vendorCode"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>업체 코드</FormLabel>
+ <FormControl>
+ <Input placeholder="예: ABC123" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ {/* 이메일 */}
+ <FormField
+ control={form.control}
+ name="email"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>이메일</FormLabel>
+ <FormControl>
+ <Input placeholder="예: info@company.com" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ {/* 전화번호 */}
+ <FormField
+ control={form.control}
+ name="phone"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>전화번호</FormLabel>
+ <FormControl>
+ <Input placeholder="예: 010-1234-5678" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ {/* 웹사이트 */}
+ <FormField
+ control={form.control}
+ name="website"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>웹사이트</FormLabel>
+ <FormControl>
+ <Input placeholder="예: https://www.company.com" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ </div>
+
+ {/* 주소 */}
+ <FormField
+ control={form.control}
+ name="address"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>주소</FormLabel>
+ <FormControl>
+ <Input placeholder="주소 입력" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
+ {/* 국가 */}
+ <FormField
+ control={form.control}
+ name="country"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>국가</FormLabel>
+ <FormControl>
+ <Input placeholder="예: 대한민국" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ {/* 국가(영문) */}
+ <FormField
+ control={form.control}
+ name="countryEng"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>국가(영문)</FormLabel>
+ <FormControl>
+ <Input placeholder="예: South Korea" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ {/* 제조국가 */}
+ <FormField
+ control={form.control}
+ name="countryFab"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>제조국가</FormLabel>
+ <FormControl>
+ <Input placeholder="제조국가 입력" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ </div>
+
+ {/* 벤더 타입 */}
+ <FormField
+ control={form.control}
+ name="techVendorType"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>벤더 타입 *</FormLabel>
+ <div className="flex gap-6">
+ {["조선", "해양TOP", "해양HULL"].map((type) => (
+ <div key={type} className="flex items-center space-x-2">
+ <input
+ type="checkbox"
+ id={`update-${type}`}
+ checked={field.value?.includes(type as "조선" | "해양TOP" | "해양HULL")}
+ onChange={(e) => {
+ const currentValue = Array.isArray(field.value) ? field.value : [];
+ if (e.target.checked) {
+ field.onChange([...currentValue, type]);
+ } else {
+ field.onChange(currentValue.filter((v: string) => v !== type));
+ }
+ }}
+ className="w-4 h-4"
+ />
+ <label htmlFor={`update-${type}`} className="text-sm font-medium cursor-pointer">
+ {type}
+ </label>
+ </div>
+ ))}
+ </div>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ </CardContent>
+ </Card>
+
+ {/* 승인 상태 섹션 */}
+ <Card>
+ <CardHeader className="pb-3">
+ <CardTitle className="text-base">
+ 승인 상태
+ </CardTitle>
+ <CardDescription>
+ 업체의 승인 상태를 관리합니다
+ </CardDescription>
+ </CardHeader>
+ <CardContent>
+ <FormField
+ control={form.control}
+ name="status"
+ render={({ field }) => {
+ const selectedConfig = getStatusConfig(field.value ?? "ACTIVE");
+ const SelectedIcon = selectedConfig?.Icon || CircleIcon;
+
+ return (
+ <FormItem>
+ <FormLabel>업체 승인 상태</FormLabel>
+ <FormControl>
+ <Select
+ value={field.value || ""}
+ onValueChange={field.onChange}
+ >
+ <SelectTrigger className="w-full">
+ <SelectValue>
+ {field.value && (
+ <div className="flex items-center">
+ <SelectedIcon className={`mr-2 h-4 w-4 ${selectedConfig.className}`} />
+ <span>{selectedConfig.label}</span>
+ </div>
+ )}
+ </SelectValue>
+ </SelectTrigger>
+ <SelectContent>
+ <SelectGroup>
+ {techVendors.status.enumValues.map((status) => {
+ const config = getStatusConfig(status);
+ const StatusIcon = config.Icon;
+ return (
+ <SelectItem key={status} value={status}>
+ <div className="flex items-center">
+ <StatusIcon className={`mr-2 h-4 w-4 ${config.className}`} />
+ <span>{config.label}</span>
+ </div>
+ </SelectItem>
+ );
+ })}
+ </SelectGroup>
+ </SelectContent>
+ </Select>
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ );
+ }}
+ />
+ </CardContent>
+ </Card>
+
+ {/* 에이전트 정보 섹션 */}
+ <Card>
+ <CardHeader className="pb-3">
+ <CardTitle className="text-base">
+ 에이전트 정보
+ </CardTitle>
+ <CardDescription>
+ 해당 업체의 에이전트 정보를 관리합니다
+ </CardDescription>
+ </CardHeader>
+ <CardContent>
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
+ {/* 에이전트명 */}
+ <FormField
+ control={form.control}
+ name="agentName"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>에이전트명</FormLabel>
+ <FormControl>
+ <Input placeholder="에이전트명 입력" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ {/* 에이전트 전화번호 */}
+ <FormField
+ control={form.control}
+ name="agentPhone"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>에이전트 전화번호</FormLabel>
+ <FormControl>
+ <Input placeholder="에이전트 전화번호 입력" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ {/* 에이전트 이메일 */}
+ <FormField
+ control={form.control}
+ name="agentEmail"
+ render={({ field }) => (
+ <FormItem className="md:col-span-2">
+ <FormLabel>에이전트 이메일</FormLabel>
+ <FormControl>
+ <Input type="email" placeholder="에이전트 이메일 입력" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ </div>
+ </CardContent>
+ </Card>
+
+ {/* 대표자 정보 섹션 */}
+ <Card>
+ <CardHeader className="pb-3">
+ <CardTitle className="text-base">
+ 대표자 정보
+ </CardTitle>
+ <CardDescription>
+ 업체 대표자의 정보를 관리합니다
+ </CardDescription>
+ </CardHeader>
+ <CardContent>
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
+ {/* 대표자명 */}
+ <FormField
+ control={form.control}
+ name="representativeName"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>대표자명</FormLabel>
+ <FormControl>
+ <Input placeholder="대표자명 입력" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ {/* 대표자 생년월일 */}
+ <FormField
+ control={form.control}
+ name="representativeBirth"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>대표자 생년월일</FormLabel>
+ <FormControl>
+ <Input placeholder="YYYY-MM-DD" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ {/* 대표자 전화번호 */}
+ <FormField
+ control={form.control}
+ name="representativePhone"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>대표자 전화번호</FormLabel>
+ <FormControl>
+ <Input placeholder="대표자 전화번호 입력" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+
+ {/* 대표자 이메일 */}
+ <FormField
+ control={form.control}
+ name="representativeEmail"
+ render={({ field }) => (
+ <FormItem>
+ <FormLabel>대표자 이메일</FormLabel>
+ <FormControl>
+ <Input type="email" placeholder="대표자 이메일 입력" {...field} />
+ </FormControl>
+ <FormMessage />
+ </FormItem>
+ )}
+ />
+ </div>
+ </CardContent>
+ </Card>
+
+ <SheetFooter className="gap-2 pt-2 sm:space-x-0">
+ <SheetClose asChild>
+ <Button type="button" variant="outline">
+ 취소
+ </Button>
+ </SheetClose>
+ <Button disabled={isPending}>
+ {isPending && (
+ <Loader className="mr-2 h-4 w-4 animate-spin" aria-hidden="true" />
+ )}
+ 저장
+ </Button>
+ </SheetFooter>
+ </form>
+ </Form>
+ </SheetContent>
+ </Sheet>
+ )
} \ No newline at end of file