From ef4c533ebacc2cdc97e518f30e9a9350004fcdfb Mon Sep 17 00:00:00 2001 From: dujinkim Date: Mon, 28 Apr 2025 02:13:30 +0000 Subject: ~20250428 작업사항 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/signup/join-form.tsx | 323 +++++++++++++++++++++++++++++++++------- 1 file changed, 270 insertions(+), 53 deletions(-) (limited to 'components/signup/join-form.tsx') diff --git a/components/signup/join-form.tsx b/components/signup/join-form.tsx index 6f9ad891..e53e779f 100644 --- a/components/signup/join-form.tsx +++ b/components/signup/join-form.tsx @@ -39,7 +39,7 @@ import { Check, ChevronsUpDown, Loader2, Plus, X } from "lucide-react" import { cn } from "@/lib/utils" import { useTranslation } from "@/i18n/client" -import { createVendor } from "@/lib/vendors/service" +import { createVendor, getVendorTypes } from "@/lib/vendors/service" import { createVendorSchema, CreateVendorSchema } from "@/lib/vendors/validations" import { Select, @@ -81,6 +81,63 @@ const countryArray = Object.entries(countryMap).map(([code, label]) => ({ label, })) +// Sort countries to put Korea first, then alphabetically +const sortedCountryArray = [...countryArray].sort((a, b) => { + // Put Korea (KR) at the top + if (a.code === "KR") return -1; + if (b.code === "KR") return 1; + + // Otherwise sort alphabetically + return a.label.localeCompare(b.label); +}); + +// Add English names for Korean locale +const enhancedCountryArray = sortedCountryArray.map(country => ({ + ...country, + label: locale === "ko" && country.code === "KR" + ? "대한민국 (South Korea)" + : country.label +})); + +// Comprehensive list of country dial codes +const countryDialCodes: { [key: string]: string } = { + AF: "+93", AL: "+355", DZ: "+213", AS: "+1-684", AD: "+376", AO: "+244", + AI: "+1-264", AG: "+1-268", AR: "+54", AM: "+374", AW: "+297", AU: "+61", + AT: "+43", AZ: "+994", BS: "+1-242", BH: "+973", BD: "+880", BB: "+1-246", + BY: "+375", BE: "+32", BZ: "+501", BJ: "+229", BM: "+1-441", BT: "+975", + BO: "+591", BA: "+387", BW: "+267", BR: "+55", BN: "+673", BG: "+359", + BF: "+226", BI: "+257", KH: "+855", CM: "+237", CA: "+1", CV: "+238", + KY: "+1-345", CF: "+236", TD: "+235", CL: "+56", CN: "+86", CO: "+57", + KM: "+269", CG: "+242", CD: "+243", CR: "+506", CI: "+225", HR: "+385", + CU: "+53", CY: "+357", CZ: "+420", DK: "+45", DJ: "+253", DM: "+1-767", + DO: "+1-809", EC: "+593", EG: "+20", SV: "+503", GQ: "+240", ER: "+291", + EE: "+372", ET: "+251", FJ: "+679", FI: "+358", FR: "+33", GA: "+241", + GM: "+220", GE: "+995", DE: "+49", GH: "+233", GR: "+30", GD: "+1-473", + GT: "+502", GN: "+224", GW: "+245", GY: "+592", HT: "+509", HN: "+504", + HK: "+852", HU: "+36", IS: "+354", IN: "+91", ID: "+62", IR: "+98", + IQ: "+964", IE: "+353", IL: "+972", IT: "+39", JM: "+1-876", JP: "+81", + JO: "+962", KZ: "+7", KE: "+254", KI: "+686", KR: "+82", KW: "+965", + KG: "+996", LA: "+856", LV: "+371", LB: "+961", LS: "+266", LR: "+231", + LY: "+218", LI: "+423", LT: "+370", LU: "+352", MK: "+389", MG: "+261", + MW: "+265", MY: "+60", MV: "+960", ML: "+223", MT: "+356", MH: "+692", + MR: "+222", MU: "+230", MX: "+52", FM: "+691", MD: "+373", MC: "+377", + MN: "+976", ME: "+382", MA: "+212", MZ: "+258", MM: "+95", NA: "+264", + NR: "+674", NP: "+977", NL: "+31", NZ: "+64", NI: "+505", NE: "+227", + NG: "+234", NU: "+683", KP: "+850", NO: "+47", OM: "+968", PK: "+92", + PW: "+680", PS: "+970", PA: "+507", PG: "+675", PY: "+595", PE: "+51", + PH: "+63", PL: "+48", PT: "+351", PR: "+1-787", QA: "+974", RO: "+40", + RU: "+7", RW: "+250", KN: "+1-869", LC: "+1-758", VC: "+1-784", WS: "+685", + SM: "+378", ST: "+239", SA: "+966", SN: "+221", RS: "+381", SC: "+248", + SL: "+232", SG: "+65", SK: "+421", SI: "+386", SB: "+677", SO: "+252", + ZA: "+27", SS: "+211", ES: "+34", LK: "+94", SD: "+249", SR: "+597", + SZ: "+268", SE: "+46", CH: "+41", SY: "+963", TW: "+886", TJ: "+992", + TZ: "+255", TH: "+66", TL: "+670", TG: "+228", TK: "+690", TO: "+676", + TT: "+1-868", TN: "+216", TR: "+90", TM: "+993", TV: "+688", UG: "+256", + UA: "+380", AE: "+971", GB: "+44", US: "+1", UY: "+598", UZ: "+998", + VU: "+678", VA: "+39-06", VE: "+58", VN: "+84", YE: "+967", ZM: "+260", + ZW: "+263" +}; + const MAX_FILE_SIZE = 3e9 export function JoinForm() { @@ -92,16 +149,54 @@ export function JoinForm() { const searchParams = useSearchParams() || new URLSearchParams(); const defaultTaxId = searchParams.get("taxID") ?? "" + // Define VendorType interface + interface VendorType { + id: number; + code: string; + nameKo: string; + nameEn: string; + } + + // Vendor Types state with proper typing + const [vendorTypes, setVendorTypes] = React.useState([]) + const [isLoadingVendorTypes, setIsLoadingVendorTypes] = React.useState(true) + // File states const [selectedFiles, setSelectedFiles] = React.useState([]) const [isSubmitting, setIsSubmitting] = React.useState(false) + // Fetch vendor types on component mount + React.useEffect(() => { + async function loadVendorTypes() { + setIsLoadingVendorTypes(true) + try { + const result = await getVendorTypes() + if (result.data) { + setVendorTypes(result.data) + } + } catch (error) { + console.error("Failed to load vendor types:", error) + toast({ + variant: "destructive", + title: "Error", + description: "Failed to load vendor types", + }) + } finally { + setIsLoadingVendorTypes(false) + } + } + + loadVendorTypes() + }, []) + // React Hook Form const form = useForm({ resolver: zodResolver(createVendorSchema), defaultValues: { vendorName: "", + vendorTypeId: undefined, + items: "", taxId: defaultTaxId, address: "", email: "", @@ -126,7 +221,9 @@ export function JoinForm() { mode: "onChange", }) const isFormValid = form.formState.isValid - + console.log("Form errors:", form.formState.errors); + console.log("Form values:", form.getValues()); + console.log("Form valid:", form.formState.isValid); // Field array for contacts @@ -168,6 +265,8 @@ export function JoinForm() { const vendorData = { vendorName: values.vendorName, + vendorTypeId: values.vendorTypeId, + items: values.items, vendorCode: values.vendorCode, website: values.website, taxId: values.taxId, @@ -194,7 +293,7 @@ export function JoinForm() { title: "등록 완료", description: "회사 등록이 완료되었습니다. (status=PENDING_REVIEW)", }) - router.push("/") + router.push("/ko/partners") } else { toast({ variant: "destructive", @@ -214,6 +313,12 @@ export function JoinForm() { } } + // Get country code for phone number placeholder + const getPhonePlaceholder = (countryCode: string) => { + if (!countryCode || !countryDialCodes[countryCode]) return "전화번호"; + return `${countryDialCodes[countryCode]} 전화번호`; + }; + // Render return (
@@ -244,79 +349,123 @@ export function JoinForm() {

기본 정보

- {/* vendorName is required in the schema → show * */} + {/* Vendor Type - New Field */} ( - - - 업체명 - - - - - - - )} - /> - - {/* Address (optional, no * here) */} - ( - - 주소 - - - - - - )} + name="vendorTypeId" + render={({ field }) => { + const selectedType = vendorTypes.find(type => type.id === field.value); + const displayName = lng === "ko" ? + (selectedType?.nameKo || "") : + (selectedType?.nameEn || ""); + + return ( + + + 업체유형 + + + + + + + + + + + + No vendor type found. + + {vendorTypes.map((type) => ( + field.onChange(type.id)} + > + + {lng === "ko" ? type.nameKo : type.nameEn} + + ))} + + + + + + + + ); + }} /> + {/* vendorName */} ( - 대표 전화 + + 업체명 + + + {form.watch("country") === "KR" + ? "사업자 등록증에 표기된 정확한 회사명을 입력하세요." + : "해외 업체의 경우 영문 회사명을 입력하세요."} + )} /> - {/* email is required → show * */} + {/* Items - New Field */} ( - 대표 이메일 + 공급품목 - 회사 대표 이메일(관리자 로그인에 사용될 수 있음) + 공급 가능한 제품/서비스를 입력하세요 )} /> - {/* website optional */} + {/* Address */} ( - 웹사이트 + 주소 @@ -325,17 +474,18 @@ export function JoinForm() { )} /> + {/* Country - Updated with enhanced list */} { - const selectedCountry = countryArray.find( + const selectedCountry = enhancedCountryArray.find( (c) => c.code === field.value ) return ( - Country + 국가 @@ -351,18 +501,18 @@ export function JoinForm() { > {selectedCountry ? selectedCountry.label - : "Select a country"} + : "국가 선택"} - + No country found. - {countryArray.map((country) => ( + {enhancedCountryArray.map((country) => ( + + {/* Phone - Updated with country code hint */} + ( + + + 대표 전화 + + + + + + + )} + /> + + {/* Email - Updated with company domain guidance */} + ( + + + 대표 이메일 + + + + + + 회사 도메인 이메일을 사용하세요. (naver.com, gmail.com, daum.net 등의 개인 이메일은 지양해주세요) + + + + )} + /> + + {/* Website */} + ( + + 웹사이트 + + + + + + )} + />
@@ -425,7 +631,7 @@ export function JoinForm() { className="bg-muted/10 rounded-md p-4 space-y-4" >
- {/* contactName → required */} + {/* contactName - All required now */} - {/* contactPosition → optional */} + {/* contactPosition - Now required */} ( - 직급 / 부서 + + 직급 / 부서 + @@ -457,7 +665,7 @@ export function JoinForm() { )} /> - {/* contactEmail → required */} + {/* contactEmail */} - {/* contactPhone → optional */} + {/* contactPhone - Now required */} ( - 전화번호 + + 전화번호 + - + @@ -515,7 +729,7 @@ export function JoinForm() {

한국 사업자 정보

- {/* 대표자 등... all optional or whichever you want * for */} + {/* 대표자 등... all now required for Korean companies */}
첨부 파일 + + 사업자등록증, ISO 9001 인증서, 회사 브로셔, 기본 소개자료 등을 첨부해주세요. +