Elint 오류 수정

This commit is contained in:
2025-08-10 19:18:17 +09:00
parent f8bcac3d2b
commit 96deebdaad
2 changed files with 11565 additions and 87 deletions
@@ -3,7 +3,6 @@
import React, { useState, useEffect } from "react";
import { SignupClient } from "@/shared/api/signup-client";
import { BASE_URL, ENDPOINT } from "@/shared/config";
import type { UserSaveData } from "@/entities/user";
import "./user-signup-modal.css";
interface UserSignupModalProps {
@@ -31,8 +30,6 @@ interface UserSignupData {
enoCd?: string;
}
// 익명 사용자용 CodeSelect 컴포넌트
interface AnonymousCodeSelectProps {
upCd: string;
@@ -42,24 +39,32 @@ interface AnonymousCodeSelectProps {
placeholder?: string;
}
function AnonymousCodeSelect({ upCd, value, onValueChange, disabled, placeholder = "선택" }: AnonymousCodeSelectProps) {
const [codes, setCodes] = useState<Array<{ lwpoCd: string; lwpoCdNm: string }>>([]);
function AnonymousCodeSelect({
upCd,
value,
onValueChange,
disabled,
placeholder = "선택",
}: AnonymousCodeSelectProps) {
const [codes, setCodes] = useState<
Array<{ lwpoCd: string; lwpoCdNm: string }>
>([]);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
const fetchCodes = async () => {
if (!upCd) return;
setIsLoading(true);
try {
const signupClient = SignupClient.getInstance({
baseURL: BASE_URL
baseURL: BASE_URL,
});
const response = await signupClient.get(
`${ENDPOINT.CMS_SERVICE.CODE}/${upCd}`
`${ENDPOINT.CMS_SERVICE.CODE}/${upCd}`,
);
if (response.data && Array.isArray(response.data)) {
setCodes(response.data);
} else {
@@ -94,7 +99,9 @@ function AnonymousCodeSelect({ upCd, value, onValueChange, disabled, placeholder
}
function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
const [currentStep, setCurrentStep] = useState<'agreement' | 'signup'>('agreement');
const [currentStep, setCurrentStep] = useState<"agreement" | "signup">(
"agreement",
);
const [agreed, setAgreed] = useState(false);
const [formData, setFormData] = useState({
userId: "",
@@ -126,7 +133,7 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
// 모달이 닫힐 때 초기화
useEffect(() => {
if (!open) {
setCurrentStep('agreement');
setCurrentStep("agreement");
setAgreed(false);
setFormData({
userId: "",
@@ -159,17 +166,19 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
const handleNextStep = () => {
if (agreed) {
setCurrentStep('signup');
setCurrentStep("signup");
}
};
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>) => {
const handleInputChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>,
) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
setFormData((prev) => ({ ...prev, [name]: value }));
// 에러 초기화
if (errors[name]) {
setErrors(prev => ({ ...prev, [name]: "" }));
setErrors((prev) => ({ ...prev, [name]: "" }));
}
};
@@ -182,20 +191,27 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
if (!formData.userId) newErrors.userId = "아이디를 입력해주세요.";
if (!formData.userName) newErrors.userName = "이름을 입력해주세요.";
if (!formData.password) newErrors.password = "비밀번호를 입력해주세요.";
if (!formData.confirmPassword) newErrors.confirmPassword = "비밀번호 확인을 입력해주세요.";
if (!formData.confirmPassword)
newErrors.confirmPassword = "비밀번호 확인을 입력해주세요.";
if (!formData.pswdHnt) newErrors.pswdHnt = "비밀번호 힌트를 선택해주세요.";
if (!formData.laeSeCd) newErrors.laeSeCd = "법인구분을 선택해주세요.";
if (!formData.ogdpSeCd) newErrors.ogdpSeCd = "기관구분을 선택해주세요.";
// 비밀번호 확인
if (formData.password && formData.confirmPassword && formData.password !== formData.confirmPassword) {
if (
formData.password &&
formData.confirmPassword &&
formData.password !== formData.confirmPassword
) {
newErrors.confirmPassword = "비밀번호가 일치하지 않습니다.";
}
// 비밀번호 정규식 검증
const passwordRegex = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]).{8,20}$/;
const passwordRegex =
/^(?=.*[a-zA-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]).{8,20}$/;
if (formData.password && !passwordRegex.test(formData.password)) {
newErrors.password = "비밀번호는 8~20자, 영문/숫자/특수기호를 모두 포함해야 합니다.";
newErrors.password =
"비밀번호는 8~20자, 영문/숫자/특수기호를 모두 포함해야 합니다.";
}
// 이메일 형식 검증
@@ -204,8 +220,10 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
}
// 중복 체크 검증
if (idAvailable === false) newErrors.userId = "이미 사용 중인 아이디입니다.";
if (emailAvailable === false) newErrors.email = "이미 사용 중인 이메일입니다.";
if (idAvailable === false)
newErrors.userId = "이미 사용 중인 아이디입니다.";
if (emailAvailable === false)
newErrors.email = "이미 사용 중인 이메일입니다.";
setErrors(newErrors);
const isValid = Object.keys(newErrors).length === 0;
@@ -215,7 +233,7 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
const checkUserIdDuplicate = async () => {
if (!formData.userId) {
setErrors(prev => ({ ...prev, userId: "아이디를 입력해주세요." }));
setErrors((prev) => ({ ...prev, userId: "아이디를 입력해주세요." }));
return;
}
@@ -226,19 +244,25 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
});
const response = await signupClient.post<boolean>(
`${ENDPOINT.USER_SERVICE.USERS}/existsUserId`,
{ userId: formData.userId }
{ userId: formData.userId },
);
const exists = response.data;
setIdAvailable(!exists);
if (exists) {
setErrors(prev => ({ ...prev, userId: "이미 사용 중인 아이디입니다." }));
setErrors((prev) => ({
...prev,
userId: "이미 사용 중인 아이디입니다.",
}));
} else {
setErrors(prev => ({ ...prev, userId: "" }));
setErrors((prev) => ({ ...prev, userId: "" }));
}
} catch (error) {
console.error("아이디 중복 체크 오류:", error);
setErrors(prev => ({ ...prev, userId: "아이디 중복 체크 중 오류가 발생했습니다." }));
setErrors((prev) => ({
...prev,
userId: "아이디 중복 체크 중 오류가 발생했습니다.",
}));
} finally {
setIsCheckingId(false);
}
@@ -246,7 +270,7 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
const checkEmailDuplicate = async () => {
if (!formData.email) {
setErrors(prev => ({ ...prev, email: "이메일을 입력해주세요." }));
setErrors((prev) => ({ ...prev, email: "이메일을 입력해주세요." }));
return;
}
@@ -257,19 +281,25 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
});
const response = await signupClient.post<boolean>(
`${ENDPOINT.USER_SERVICE.USERS}/exists`,
{ email: formData.email }
{ email: formData.email },
);
const exists = response.data;
setEmailAvailable(!exists);
if (exists) {
setErrors(prev => ({ ...prev, email: "이미 사용 중인 이메일입니다." }));
setErrors((prev) => ({
...prev,
email: "이미 사용 중인 이메일입니다.",
}));
} else {
setErrors(prev => ({ ...prev, email: "" }));
setErrors((prev) => ({ ...prev, email: "" }));
}
} catch (error) {
console.error("이메일 중복 체크 오류:", error);
setErrors(prev => ({ ...prev, email: "이메일 중복 체크 중 오류가 발생했습니다." }));
setErrors((prev) => ({
...prev,
email: "이메일 중복 체크 중 오류가 발생했습니다.",
}));
} finally {
setIsCheckingEmail(false);
}
@@ -279,7 +309,7 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
e.preventDefault();
console.log("회원가입 버튼 클릭됨 - handleSubmit");
console.log("현재 폼 데이터:", formData);
if (!validateForm()) {
console.log("폼 검증 실패");
return;
@@ -311,23 +341,23 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
console.log("SignupClient 생성 및 API 호출:", {
baseURL: BASE_URL,
endpoint: ENDPOINT.USER_SERVICE.USER_JOIN,
data: signupData
data: signupData,
});
const signupClient = SignupClient.getInstance({
baseURL: BASE_URL
baseURL: BASE_URL,
});
const response = await signupClient.post(
ENDPOINT.USER_SERVICE.USER_JOIN,
signupData
signupData,
);
console.log("회원가입 성공:", response.data);
// 성공 시 모달 닫기 및 콜백 호출
onSuccess();
onClose();
// 폼 초기화
setFormData({
userId: "",
@@ -351,13 +381,12 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
setErrors({});
setIdAvailable(null);
setEmailAvailable(null);
} catch (error: unknown) {
console.error("회원가입 오류:", error);
if (error instanceof Error) {
setErrors(prev => ({ ...prev, submit: error.message }));
setErrors((prev) => ({ ...prev, submit: error.message }));
} else {
setErrors(prev => ({ ...prev, submit: "회원가입에 실패했습니다." }));
setErrors((prev) => ({ ...prev, submit: "회원가입에 실패했습니다." }));
}
} finally {
setIsLoading(false);
@@ -366,40 +395,56 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
if (!open) return null;
return (
<div className="user-signup-modal-overlay">
<div className="user-signup-modal-content">
return (
<div className="user-signup-modal-overlay">
<div className="user-signup-modal-content">
<div className="user-signup-modal-header">
<h2>{currentStep === 'agreement' ? '개인정보제공동의' : '회원가입'}</h2>
<button className="user-signup-close-button" onClick={onClose}>×</button>
<h2>
{currentStep === "agreement" ? "개인정보제공동의" : "회원가입"}
</h2>
<button className="user-signup-close-button" onClick={onClose}>
×
</button>
</div>
{currentStep === 'agreement' ? (
{currentStep === "agreement" ? (
<div className="user-signup-agreement-content">
<div className="user-signup-agreement-text">
<h3>개인정보 수집 및 이용 동의</h3>
<p>회원가입을 위해 다음과 같이 개인정보를 수집 및 이용합니다.</p>
<h4>1. 수집하는 개인정보 항목</h4>
<ul>
<li>필수항목: 아이디, 이름, 비밀번호, 비밀번호 힌트, 법인구분, 기관구분</li>
<li>선택항목: 이메일, 휴대폰번호, 전화번호, 주소, 기관코드, 상세기관코드, 사업자등록번호</li>
<li>
필수항목: 아이디, 이름, 비밀번호, 비밀번호 힌트, 법인구분,
기관구분
</li>
<li>
선택항목: 이메일, 휴대폰번호, 전화번호, 주소, 기관코드,
상세기관코드, 사업자등록번호
</li>
</ul>
<h4>2. 개인정보의 수집 및 이용목적</h4>
<ul>
<li>회원가입 및 관리</li>
<li>서비스 제공 및 운영</li>
<li>고객상담 및 문의응답</li>
</ul>
<h4>3. 개인정보의 보유 및 이용기간</h4>
<p>회원탈퇴 시까지 (단, 관련 법령에 따라 보존이 필요한 경우 해당 기간까지)</p>
<p>
회원탈퇴 시까지 (단, 관련 법령에 따라 보존이 필요한 경우 해당
기간까지)
</p>
<h4>4. 동의 거부권 및 거부 시 불이익</h4>
<p>개인정보 수집 및 이용에 대한 동의를 거부할 수 있으며, 동의 거부 시 회원가입이 제한됩니다.</p>
<p>
개인정보 수집 및 이용에 대한 동의를 거부할 수 있으며, 동의 거부
시 회원가입이 제한됩니다.
</p>
</div>
<div className="user-signup-agreement-checkbox">
<label>
<input
@@ -410,7 +455,7 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
<span>개인정보 수집 및 이용에 동의합니다.</span>
</label>
</div>
<div className="user-signup-agreement-actions">
<button
type="button"
@@ -433,7 +478,7 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
<form onSubmit={handleSubmit} className="user-signup-form">
<div className="user-signup-form-section">
<h3>기본 정보</h3>
<div className="user-signup-form-row">
<div className="user-signup-form-group">
<label htmlFor="userId">아이디 *</label>
@@ -457,8 +502,16 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
{isCheckingId ? "확인중..." : "중복확인"}
</button>
</div>
{idAvailable === true && <span className="user-signup-success-message">사용 가능한 아이디입니다.</span>}
{errors.userId && <span className="user-signup-error-message">{errors.userId}</span>}
{idAvailable === true && (
<span className="user-signup-success-message">
사용 가능한 아이디입니다.
</span>
)}
{errors.userId && (
<span className="user-signup-error-message">
{errors.userId}
</span>
)}
</div>
</div>
@@ -474,7 +527,11 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
placeholder="이름을 입력하세요"
disabled={isLoading}
/>
{errors.userName && <span className="user-signup-error-message">{errors.userName}</span>}
{errors.userName && (
<span className="user-signup-error-message">
{errors.userName}
</span>
)}
</div>
</div>
@@ -500,8 +557,16 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
{isCheckingEmail ? "확인중..." : "중복확인"}
</button>
</div>
{emailAvailable === true && <span className="user-signup-success-message">사용 가능한 이메일입니다.</span>}
{errors.email && <span className="user-signup-error-message">{errors.email}</span>}
{emailAvailable === true && (
<span className="user-signup-success-message">
사용 가능한 이메일입니다.
</span>
)}
{errors.email && (
<span className="user-signup-error-message">
{errors.email}
</span>
)}
</div>
</div>
@@ -518,7 +583,11 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
maxLength={20}
disabled={isLoading}
/>
{errors.password && <span className="user-signup-error-message">{errors.password}</span>}
{errors.password && (
<span className="user-signup-error-message">
{errors.password}
</span>
)}
</div>
</div>
@@ -535,7 +604,11 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
maxLength={20}
disabled={isLoading}
/>
{errors.confirmPassword && <span className="user-signup-error-message">{errors.confirmPassword}</span>}
{errors.confirmPassword && (
<span className="user-signup-error-message">
{errors.confirmPassword}
</span>
)}
</div>
</div>
@@ -545,11 +618,17 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
<AnonymousCodeSelect
upCd="PSWDHNT"
value={formData.pswdHnt}
onValueChange={(value: string) => setFormData(prev => ({ ...prev, pswdHnt: value }))}
onValueChange={(value: string) =>
setFormData((prev) => ({ ...prev, pswdHnt: value }))
}
disabled={isLoading}
placeholder="비밀번호 힌트를 선택하세요"
/>
{errors.pswdHnt && <span className="user-signup-error-message">{errors.pswdHnt}</span>}
{errors.pswdHnt && (
<span className="user-signup-error-message">
{errors.pswdHnt}
</span>
)}
</div>
</div>
@@ -566,14 +645,18 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
maxLength={100}
disabled={isLoading}
/>
{errors.pswdAns && <span className="user-signup-error-message">{errors.pswdAns}</span>}
{errors.pswdAns && (
<span className="user-signup-error-message">
{errors.pswdAns}
</span>
)}
</div>
</div>
</div>
<div className="user-signup-form-section">
<h3>연락처 정보</h3>
<div className="user-signup-form-row">
<div className="user-signup-form-group">
<label htmlFor="mphn">휴대폰 번호</label>
@@ -587,7 +670,11 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
maxLength={11}
disabled={isLoading}
/>
{errors.mphn && <span className="user-signup-error-message">{errors.mphn}</span>}
{errors.mphn && (
<span className="user-signup-error-message">
{errors.mphn}
</span>
)}
</div>
</div>
@@ -604,14 +691,18 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
maxLength={11}
disabled={isLoading}
/>
{errors.telno && <span className="user-signup-error-message">{errors.telno}</span>}
{errors.telno && (
<span className="user-signup-error-message">
{errors.telno}
</span>
)}
</div>
</div>
</div>
<div className="user-signup-form-section">
<h3>주소 정보</h3>
<div className="user-signup-form-row">
<div className="user-signup-form-group">
<label htmlFor="zip">우편번호</label>
@@ -625,7 +716,11 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
maxLength={5}
disabled={isLoading}
/>
{errors.zip && <span className="user-signup-error-message">{errors.zip}</span>}
{errors.zip && (
<span className="user-signup-error-message">
{errors.zip}
</span>
)}
</div>
</div>
@@ -642,7 +737,11 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
maxLength={200}
disabled={isLoading}
/>
{errors.addr && <span className="user-signup-error-message">{errors.addr}</span>}
{errors.addr && (
<span className="user-signup-error-message">
{errors.addr}
</span>
)}
</div>
</div>
@@ -659,25 +758,35 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
maxLength={200}
disabled={isLoading}
/>
{errors.daddr && <span className="user-signup-error-message">{errors.daddr}</span>}
{errors.daddr && (
<span className="user-signup-error-message">
{errors.daddr}
</span>
)}
</div>
</div>
</div>
<div className="user-signup-form-section">
<h3>기관 정보</h3>
<div className="user-signup-form-row">
<div className="user-signup-form-group">
<label htmlFor="laeSeCd">법인구분 *</label>
<AnonymousCodeSelect
upCd="LAESECD"
value={formData.laeSeCd}
onValueChange={(value: string) => setFormData(prev => ({ ...prev, laeSeCd: value }))}
onValueChange={(value: string) =>
setFormData((prev) => ({ ...prev, laeSeCd: value }))
}
disabled={isLoading}
placeholder="법인구분을 선택하세요"
/>
{errors.laeSeCd && <span className="user-signup-error-message">{errors.laeSeCd}</span>}
{errors.laeSeCd && (
<span className="user-signup-error-message">
{errors.laeSeCd}
</span>
)}
</div>
</div>
@@ -687,11 +796,17 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
<AnonymousCodeSelect
upCd="OGDPSECD"
value={formData.ogdpSeCd}
onValueChange={(value: string) => setFormData(prev => ({ ...prev, ogdpSeCd: value }))}
onValueChange={(value: string) =>
setFormData((prev) => ({ ...prev, ogdpSeCd: value }))
}
disabled={isLoading}
placeholder="기관구분을 선택하세요"
/>
{errors.ogdpSeCd && <span className="user-signup-error-message">{errors.ogdpSeCd}</span>}
{errors.ogdpSeCd && (
<span className="user-signup-error-message">
{errors.ogdpSeCd}
</span>
)}
</div>
</div>
@@ -708,7 +823,11 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
maxLength={10}
disabled={isLoading}
/>
{errors.instSeCd && <span className="user-signup-error-message">{errors.instSeCd}</span>}
{errors.instSeCd && (
<span className="user-signup-error-message">
{errors.instSeCd}
</span>
)}
</div>
</div>
@@ -725,21 +844,27 @@ function UserSignupModal({ open, onClose, onSuccess }: UserSignupModalProps) {
maxLength={10}
disabled={isLoading}
/>
{errors.dtlInstCd && <span className="user-signup-error-message">{errors.dtlInstCd}</span>}
{errors.dtlInstCd && (
<span className="user-signup-error-message">
{errors.dtlInstCd}
</span>
)}
</div>
</div>
</div>
{errors.submit && (
<div className="user-signup-form-row">
<div className="user-signup-error-message user-signup-submit-error">{errors.submit}</div>
<div className="user-signup-error-message user-signup-submit-error">
{errors.submit}
</div>
</div>
)}
<div className="user-signup-form-actions">
<button
type="button"
onClick={() => setCurrentStep('agreement')}
onClick={() => setCurrentStep("agreement")}
className="user-signup-back-button"
disabled={isLoading}
>
+11353
View File
File diff suppressed because it is too large Load Diff