diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-08-21 06:57:36 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-08-21 06:57:36 +0000 |
| commit | 02b1cf005cf3e1df64183d20ba42930eb2767a9f (patch) | |
| tree | e932c54d5260b0e6fda2b46be2a6ba1c3ee30434 /components/signup/join-form.tsx | |
| parent | d78378ecd7ceede1429359f8058c7a99ac34b1b7 (diff) | |
(대표님, 최겸) 설계메뉴추가, 작업사항 업데이트
설계메뉴 - 문서관리
설계메뉴 - 벤더 데이터
gtc 메뉴 업데이트
정보시스템 - 메뉴리스트 및 정보 업데이트
파일 라우트 업데이트
엑셀임포트 개선
기본계약 개선
벤더 가입과정 변경 및 개선
벤더 기본정보 - pq
돌체 오류 수정 및 개선
벤더 로그인 과정 이메일 오류 수정
Diffstat (limited to 'components/signup/join-form.tsx')
| -rw-r--r-- | components/signup/join-form.tsx | 143 |
1 files changed, 134 insertions, 9 deletions
diff --git a/components/signup/join-form.tsx b/components/signup/join-form.tsx index 71ecbd1c..999b87dc 100644 --- a/components/signup/join-form.tsx +++ b/components/signup/join-form.tsx @@ -114,6 +114,8 @@ interface VendorData { items: string; taxId: string; address: string; + addressDetail: string; + postalCode: string; email: string; phone: string; country: string; @@ -165,6 +167,46 @@ const getCountryData = (lng: string): CountryOption[] => { const MAX_FILE_SIZE = 3e9; +// ========== 전화번호 정규화 함수 ========== + +/** + * 전화번호를 E.164 형식으로 정규화 (저장용) + */ +function normalizePhoneForStorage(phoneNumber: string, countryCode: string): string | null { + try { + if (!phoneNumber || !countryCode) return null; + + const parsed = parsePhoneNumberFromString(phoneNumber, countryCode); + + if (!parsed || !parsed.isValid()) { + return null; + } + + // E.164 형식으로 반환 (+821012345678) + return parsed.format('E.164'); + } catch (error) { + console.error('Phone normalization error:', error); + return null; + } +} + +/** + * E.164 형식의 전화번호를 표시용으로 포맷팅 + */ +function formatPhoneForDisplay(phoneNumber: string): string { + try { + if (!phoneNumber) return ''; + + const parsed = parsePhoneNumberFromString(phoneNumber); + if (parsed) { + return parsed.formatNational(); // 국내 형식으로 표시 + } + return phoneNumber; + } catch { + return phoneNumber; + } +} + // ========== 전화번호 처리 유틸리티 함수들 ========== /** @@ -338,8 +380,10 @@ function PhoneInput({ const formatPhone = usePhoneFormatter(countryCode); useEffect(() => { - setLocalValue(value || ''); - }, [value]); + // E.164 형식으로 저장된 번호를 표시용으로 변환 + const displayValue = value ? formatPhoneForDisplay(value) : ''; + setLocalValue(displayValue); + }, [value, countryCode]); const validation = validatePhoneNumber(localValue, countryCode, t); @@ -432,6 +476,8 @@ export default function JoinForm() { items: "", taxId: defaultTaxId, address: "", + addressDetail: "", + postalCode: "", email: "", phone: "", country: "", @@ -686,12 +732,23 @@ function AccountStep({ setIsLoading(true); setEmailCheckError(''); + try { + // 전화번호 정규화 + const normalizedPhone = normalizePhoneForStorage(data.phone, data.country); + if (!normalizedPhone) { + setEmailCheckError('전화번호 형식이 올바르지 않습니다'); + return; + } + const isUsed = await checkEmailExists(data.email); if (isUsed) { setEmailCheckError(t('emailAlreadyInUse')); return; } + + // 정규화된 전화번호로 데이터 업데이트 + onChange(prev => ({ ...prev, phone: normalizedPhone })); onNext(); } catch (error) { setEmailCheckError(t('emailCheckError')); @@ -914,6 +971,7 @@ function CompleteVendorForm({ const creditReportHandler = createFileUploadHandler(setCreditReportFiles, creditReportFiles); const bankAccountHandler = createFileUploadHandler(setBankAccountFiles, bankAccountFiles); + // 유효성 검사 const validateRequiredFiles = (): string[] => { const errors: string[] = []; @@ -945,10 +1003,10 @@ function CompleteVendorForm({ contact.contactPhone ? validatePhoneNumber(contact.contactPhone, data.country, t).isValid : true ); - const isFormValid = data.vendorName && data.vendorTypeId && data.items && + const isFormValid = data.vendorName && data.vendorTypeId && data.items && data.country && data.phone && vendorPhoneValidation.isValid && data.email && contactsValid && - validateRequiredFiles().length === 0; + validateRequiredFiles().length === 0 // 최종 제출 const handleSubmit = async () => { @@ -964,12 +1022,51 @@ function CompleteVendorForm({ setIsSubmitting(true); try { + // 업체 전화번호 정규화 + const normalizedVendorPhone = normalizePhoneForStorage(data.phone, data.country); + if (!normalizedVendorPhone) { + toast({ + variant: "destructive", + title: t('error'), + description: '업체 전화번호 형식이 올바르지 않습니다', + }); + return; + } + + // 담당자 전화번호들 정규화 + const normalizedContacts = data.contacts.map(contact => { + if (contact.contactPhone) { + const normalizedContactPhone = normalizePhoneForStorage(contact.contactPhone, data.country); + if (!normalizedContactPhone) { + throw new Error(`담당자 ${contact.contactName}의 전화번호 형식이 올바르지 않습니다`); + } + return { ...contact, contactPhone: normalizedContactPhone }; + } + return contact; + }); + + // 대표자 전화번호 정규화 (한국 업체인 경우) + let normalizedRepresentativePhone = data.representativePhone; + if (data.country === "KR" && data.representativePhone) { + const normalized = normalizePhoneForStorage(data.representativePhone, "KR"); + if (!normalized) { + throw new Error('대표자 전화번호 형식이 올바르지 않습니다'); + } + normalizedRepresentativePhone = normalized; + } + const formData = new FormData(); const completeData = { - account: accountData, + account: { + ...accountData, + // accountData.phone은 이미 AccountStep에서 정규화됨 + }, vendor: { ...data, + phone: normalizedVendorPhone, + representativePhone: normalizedRepresentativePhone, + contacts: normalizedContacts, email: data.email || accountData.email, }, consents: { @@ -1004,7 +1101,7 @@ function CompleteVendorForm({ if (data.country !== "KR") { bankAccountFiles.forEach(file => { - formData.append('bankAccountCopy', file); + formData.append('bankAccount', file); }); } @@ -1032,8 +1129,8 @@ function CompleteVendorForm({ console.error(error); toast({ variant: "destructive", - title: t('serverError'), - description: t('errorOccurred'), + title: t('error'), + description: error instanceof Error ? error.message : t('errorOccurred'), }); } finally { setIsSubmitting(false); @@ -1152,7 +1249,9 @@ function CompleteVendorForm({ {/* 주소 */} <div> - <label className="block text-sm font-medium mb-1">{t('address')}</label> + <label className="block text-sm font-medium mb-1"> + {t('address')} <span className="text-red-500">*</span> + </label> <Input value={data.address} onChange={(e) => handleInputChange('address', e.target.value)} @@ -1160,6 +1259,32 @@ function CompleteVendorForm({ /> </div> + {/* 상세주소 */} + <div> + <label className="block text-sm font-medium mb-1"> + 상세주소 <span className="text-red-500">*</span> + </label> + <Input + value={data.addressDetail} + onChange={(e) => handleInputChange('addressDetail', e.target.value)} + disabled={isSubmitting} + placeholder="상세주소를 입력해주세요" + /> + </div> + + {/* 우편번호 */} + <div> + <label className="block text-sm font-medium mb-1"> + 우편번호 <span className="text-red-500">*</span> + </label> + <Input + value={data.postalCode} + onChange={(e) => handleInputChange('postalCode', e.target.value)} + disabled={isSubmitting} + placeholder="우편번호를 입력해주세요" + /> + </div> + {/* 국가 */} <div> <label className="block text-sm font-medium mb-1"> |
