summaryrefslogtreecommitdiff
path: root/components/signup/join-form.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-08-21 06:57:36 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-08-21 06:57:36 +0000
commit02b1cf005cf3e1df64183d20ba42930eb2767a9f (patch)
treee932c54d5260b0e6fda2b46be2a6ba1c3ee30434 /components/signup/join-form.tsx
parentd78378ecd7ceede1429359f8058c7a99ac34b1b7 (diff)
(대표님, 최겸) 설계메뉴추가, 작업사항 업데이트
설계메뉴 - 문서관리 설계메뉴 - 벤더 데이터 gtc 메뉴 업데이트 정보시스템 - 메뉴리스트 및 정보 업데이트 파일 라우트 업데이트 엑셀임포트 개선 기본계약 개선 벤더 가입과정 변경 및 개선 벤더 기본정보 - pq 돌체 오류 수정 및 개선 벤더 로그인 과정 이메일 오류 수정
Diffstat (limited to 'components/signup/join-form.tsx')
-rw-r--r--components/signup/join-form.tsx143
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">