Signup.js 14.1 KB
Newer Older
한규민's avatar
한규민 committed
1
import styles from "./signup.module.scss";
한규민's avatar
한규민 committed
2
import { useState } from "react";
한규민's avatar
한규민 committed
3
import authApi from "../../apis/auth.api.js";
한규민's avatar
한규민 committed
4
import { Redirect } from "react-router-dom";
한규민's avatar
한규민 committed
5
import catchErrors from "../../utils/catchErrors.js";
한규민's avatar
한규민 committed
6
7

const Signup = () => {
한규민's avatar
한규민 committed
8
    const [user, setUser] = useState({
한규민's avatar
한규민 committed
9
        userId: "",
한규민's avatar
한규민 committed
10
        userEmail: "",
한규민's avatar
한규민 committed
11
12
13
14
15
        userNickName: "",
        userBirthday: "",
        userMbnum: "",
        userPassword: "",
        userRePassword: ""
16
    })
한규민's avatar
한규민 committed
17
18
    
    const [number, setNumber] = useState(null);
한규민's avatar
한규민 committed
19
20
    const [loading, setLoading] = useState(false);
    const [success, setSuccess] = useState(false);
한규민's avatar
한규민 committed
21
    //각 타입별 error 유무 state
한규민's avatar
한규민 committed
22
    const [mbError,setMbError] = useState(false);
한규민's avatar
한규민 committed
23
    const [error, setError] = useState("");
한규민's avatar
한규민 committed
24
    const [errorMsg, setErrorMsg] = useState({
한규민's avatar
한규민 committed
25
        errorId: null,
한규민's avatar
한규민 committed
26
        errorEmail: false,
한규민's avatar
한규민 committed
27
        errorNickName: false,
한규민's avatar
한규민 committed
28
29
30
31
32
        errorBirthday: false,
        errorMbnum: false,
        errorPassword: false,
        errorRePassword: false
    })
한규민's avatar
한규민 committed
33
    // id중복확인 여부 state와 가입하기 누르면 id 임시 저장
한규민's avatar
한규민 committed
34
    const [overlapId, setOverlapId] = useState(false);
한규민's avatar
한규민 committed
35
    const [confirmMb, setConfirmMb] = useState(false);
한규민's avatar
한규민 committed
36
37
38
    const [preId, setPreId] = useState("");

    //입력할때마다 state에 저장
39
    const handleUserOnChange = (e) => {
한규민's avatar
한규민 committed
40
41
        setUser({
            ...user,
42
43
            [e.target.name]: e.target.value
        })
한규민's avatar
한규민 committed
44
        if (e.target.name === "userBirthday" || e.target.name === "userMbum") {
한규민's avatar
한규민 committed
45
46
47
48
49
            setUser({
                ...user,
                [e.target.name]: String(e.target.value)
            })
        }
한규민's avatar
한규민 committed
50
    }
51

한규민's avatar
한규민 committed
52
    //id(중복확인 체크, 형식 에러)
한규민's avatar
한규민 committed
53
54
    const handleOnClickId = async (e) => {
        e.preventDefault();
한규민's avatar
한규민 committed
55
        try {
한규민's avatar
한규민 committed
56
57
58
59
60
61
62
63
64
65
66
67
            setError("");
            if (user.userId.length < 5) {
                setErrorMsg(errorMsg => ({
                    ...errorMsg,
                    [e.target.name]: true
                }));
                if (overlapId === true) {
                    setOverlapId(() => (false));
                };
            } else {
                const userId = user.userId;
                await authApi.compareId(userId);
한규민's avatar
한규민 committed
68
                if (!await authApi.compareId(userId)) {
한규민's avatar
한규민 committed
69
70
71
72
73
                    alert("이 아이디는 사용가능합니다.")
                    setErrorMsg(errorMsg => ({
                        ...errorMsg,
                        [e.target.name]: false
                    }));
한규민's avatar
한규민 committed
74
75
                    setOverlapId(() => (true));
                } else {
한규민's avatar
한규민 committed
76
                    alert("이미 사용중인 아이디입니다.")
한규민's avatar
한규민 committed
77
                    setOverlapId(() => (false));
한규민's avatar
한규민 committed
78
79
                }
            }
한규민's avatar
한규민 committed
80
81
82
        } catch (error) {
            catchErrors(error, setError)
        } finally {
한규민's avatar
한규민 committed
83
            setLoading(false);
한규민's avatar
한규민 committed
84
        }
한규민's avatar
한규민 committed
85
86
87
    }

    const handleOnClickMbnum = async (e) => {
한규민's avatar
한규민 committed
88
        e.preventDefault();
한규민's avatar
한규민 committed
89
        try {
한규민's avatar
한규민 committed
90
91
92
93
94
95
96
97
98
99
            setError("");
            setLoading(true)
            const phone = user.userMbnum;
            console.log("phone : ", phone)
            const message = await authApi.confirmMbnum(phone);
            console.log("message : ", message);
            if(message.isSuccess){
                console.log("mberror: "+mbError);
            setMbError("보냄");
            }
한규민's avatar
한규민 committed
100
        } catch (error) {
한규민's avatar
한규민 committed
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
            console.log('error'+ error)
        }finally {
            setLoading(false);
        }
    }

    const handleOnChangeMb = (e) => {
        setNumber(String(e.target.value));
    }

    const handleOnClickMbConfirm = async (e) => {
        e.preventDefault();
        try {
            setError("");
            setLoading(true)
            const confirmNum = number;
            console.log(confirmNum)
            const message = await authApi.confirmNum(confirmNum);
            console.log(message);
            setMbError(message);
            if(message === "성공"){
                setConfirmMb(true);
                console.log("인증완료");
            }
        } catch (error) {
            catchErrors(error, setError);
        }finally {
            setLoading(false);
한규민's avatar
한규민 committed
129
        }
한규민's avatar
한규민 committed
130
131
132
133
134
    }

    const handleOnSummit = async (e) => {
        e.preventDefault();
        try {
한규민's avatar
한규민 committed
135
            setError(() => (""));
한규민's avatar
한규민 committed
136
            //처리가 될때까지 버튼(가입하기)이 안눌리게 지정
한규민's avatar
한규민 committed
137
            setLoading(() => (true));
한규민's avatar
한규민 committed
138
139
140
141
142
143
144
145
146
147
148
149
            //유효성 검사
            validation();
            const userData = user;
            //서버로 전송
            await authApi.signup(userData)
            alert("가입이 완료되었습니다. 로그인 해주세요.");
            setSuccess(true);
        } catch (error) {
            //에러전송
            catchErrors(error, setError);
        } finally {
            setLoading(false);
한규민's avatar
한규민 committed
150
        }
한규민's avatar
signup    
한규민 committed
151
    }
한규민's avatar
한규민 committed
152

한규민's avatar
한규민 committed
153
154
    //비교하여 error메세지 반환
    const vaildationData = (text, compareValue, error) => {
한규민's avatar
한규민 committed
155
        if (text !== compareValue) {
한규민's avatar
한규민 committed
156
            setErrorMsg(errorMsg => ({ ...errorMsg, [error]: true }));
한규민's avatar
한규민 committed
157
        } else {
한규민's avatar
한규민 committed
158
            setErrorMsg(errorMsg => ({ ...errorMsg, [error]: false }));
한규민's avatar
한규민 committed
159
160
        }
    }
한규민's avatar
한규민 committed
161
162
    //아이디 비번 유효성 검사
    const vaildationIdPw = (text, minValue, error) => {
한규민's avatar
한규민 committed
163
164
165
        if ((text < minValue)) {
            setErrorMsg(errorMsg => ({ ...errorMsg, [error]: true }));
        } else if (text >= minValue) {
한규민's avatar
한규민 committed
166
            setErrorMsg(errorMsg => ({ ...errorMsg, [error]: false }));
한규민's avatar
한규민 committed
167
168
169
            if (overlapId === true) {
                if (preId !== user.userId) {
                    setOverlapId(false);
한규민's avatar
한규민 committed
170
                }
한규민's avatar
한규민 committed
171
            }
한규민's avatar
한규민 committed
172
173
        }
    }
한규민's avatar
한규민 committed
174
175
    //유효성 검사
    const validation = () => {
한규민's avatar
한규민 committed
176
        setPreId(user.userId);
한규민's avatar
한규민 committed
177
        //아이디 유효성 검사
한규민's avatar
한규민 committed
178
        vaildationIdPw(user.userId.length, 5, "errorId");
한규민's avatar
한규민 committed
179
        //별명 유효성 검사
한규민's avatar
한규민 committed
180
        vaildationData((user.userNickName.length === 0), false, "errorNickName");
한규민's avatar
한규민 committed
181
182
183
184
185
        // 생일 유효성 검사
        vaildationData(user.userBirthday.length, 6, "errorBirthday");
        // 휴대폰 유효성 검사
        vaildationData(user.userMbnum.length, 11, "errorMbnum");
        // 비밀번호 유효성 검사
한규민's avatar
한규민 committed
186
        vaildationIdPw(user.userPassword.length, 8, "errorPassword");
한규민's avatar
한규민 committed
187
188
        // 비밀번호 확인 유효성 검사
        vaildationData(user.userRePassword, user.userPassword, "errorRePassword");
한규민's avatar
한규민 committed
189
190
        let validation = false;
        validation = (Object.values(errorMsg).some((element) => (element)) === false);
한규민's avatar
한규민 committed
191

한규민's avatar
한규민 committed
192
        // 최종 유효성 검사
한규민's avatar
한규민 committed
193
194
195
196
197
198
199
200
201
202
203
204
        if (overlapId) {
            if(confirmMb){
                if(!validation){
                    throw new Error("유효하지 않은 데이터입니다.");
                }else{
                        console.log("가입성공");
                        return true
                }
            }else{
                throw new Error("휴대폰 인증도 해주세요");
            }
        }else{
한규민's avatar
한규민 committed
205
            setErrorMsg(errorMsg => ({ ...errorMsg, errorId: false }));
한규민's avatar
한규민 committed
206
            throw new Error("먼저 아이디 중복확인을 해주세요");
한규민's avatar
한규민 committed
207
        }
한규민's avatar
한규민 committed
208
    }
한규민's avatar
한규민 committed
209
210
211
    if (success) {
        return <Redirect to="/login" />;
    }
한규민's avatar
한규민 committed
212

한규민's avatar
한규민 committed
213

한규민's avatar
한규민 committed
214
    return (
한규민's avatar
한규민 committed
215
        // 데이터 입력과 유효성 검사 후 보이는 경고창
한규민's avatar
한규민 committed
216
        <form className={`d-flex col-md-6 col-12 justify-content-center`} onSubmit={handleOnSummit}>
한규민's avatar
한규민 committed
217
            <div className="d-flex flex-column">
한규민's avatar
signup    
한규민 committed
218
219
220
221
222
                <span className={styles.title}>회원가입</span>
                <div className="d-flex flex-column">
                    <div className={styles.inputContent}>
                        <label className={styles.signupLabel}>아이디</label>
                        <div className="d-flex col-md-auto">
한규민's avatar
한규민 committed
223
                            <input className={styles.input} type="text" name="userId" placeholder="5~10자리 사이" onChange={handleUserOnChange} maxLength="10" required />
한규민's avatar
한규민 committed
224
                            <button type="button" disabled={loading} name="errorId" className={`rounded-2 mt-2 ${styles.butterYellowAndBtn} ${styles.btnHover}`} onClick={handleOnClickId}>중복확인</button>
한규민's avatar
signup    
한규민 committed
225
                        </div>
한규민's avatar
한규민 committed
226
                    </div>
한규민's avatar
한규민 committed
227
228
229
                    {(overlapId === false) && errorMsg.errorId && <p className={styles.passwordConfirmError}>5~10자리 사이로 입력해주세요.</p>}
                    {overlapId && (errorMsg.errorId === false) && <p className={styles.passwordConfirmError}>아이디 중복이 확인되었습니다.</p>}
                    {(errorMsg.errorId === false) && (overlapId === false) && <p className={styles.passwordConfirmError}>아이디 중복확인을 해주세요.</p>}
230
                </div>
한규민's avatar
한규민 committed
231
232
233
234
235
236
237
                <div className="d-flex flex-column">
                    <div className={styles.inputContent}>
                        <label className={styles.signupLabel}>이메일</label>
                        <input className={`${styles.input} ${styles.inputSize}`} type="email" name="userEmail" placeholder="이메일을 입력해주세요" onChange={handleUserOnChange} maxlength="20" required />
                    </div>
                    {errorMsg.errorEmail && <p className={styles.passwordConfirmError}>이메일을 입력해주세요</p>}
                </div>
한규민's avatar
한규민 committed
238
239
240
                <div className="d-flex flex-column">
                    <div className={styles.inputContent}>
                        <label className={styles.signupLabel}>별명</label>
한규민's avatar
한규민 committed
241
                        <input className={`${styles.input} ${styles.inputSize}`} type="text" name="userNickName" placeholder="10자리 이내" onChange={handleUserOnChange} maxLength="10" required />
한규민's avatar
한규민 committed
242
                    </div>
한규민's avatar
한규민 committed
243
                    {errorMsg.errorNickName && <p className={styles.passwordConfirmError}>10 이내로 입력해주세요.</p>}
244
                </div>
한규민's avatar
한규민 committed
245
246
247
248

                <div className="d-flex flex-column">
                    <div className={styles.inputContent}>
                        <label className={styles.signupLabel}>생년월일</label>
한규민's avatar
한규민 committed
249
                        <input className={`${styles.input} ${styles.inputSize} ${styles.input.placeholder}`} type="number" name="userBirthday" placeholder="6자리(예시: 991225)" onChange={handleUserOnChange} min="0" max="999999" required />
한규민's avatar
한규민 committed
250
                    </div>
한규민's avatar
한규민 committed
251
                    {errorMsg.errorBirthday && <p className={styles.passwordConfirmError}>숫자 6자리를 입력해주세요.</p>}
252
                </div>
한규민's avatar
한규민 committed
253
254
255
256

                <div className="d-flex flex-column">
                    <div className={styles.inputContent}>
                        <label className={styles.signupLabel}>휴대폰 번호</label>
한규민's avatar
한규민 committed
257
                        <div className="d-flex col-md-auto">
한규민's avatar
한규민 committed
258
259
                            <input className={`${styles.input} ${styles.input2}`} type="number" name="userMbnum" placeholder="-없이 11자리 입력" onChange={handleUserOnChange} min="" max="99999999999" required />
                            <button type="button" disabled={loading} className={`rounded-2 mt-2 ${styles.butterYellowAndBtn} ${styles.btnHover}`} data-bs-toggle="collapse" data-bs-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample" onClick={handleOnClickMbnum}>인증번호받기</button>
한규민's avatar
한규민 committed
260
                        </div>
한규민's avatar
한규민 committed
261
                    </div>
한규민's avatar
한규민 committed
262
                    {errorMsg.errorMbnum && <p className={styles.passwordConfirmError}>-없이 숫자 11자리를 입력해주세요.</p>}
한규민's avatar
한규민 committed
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278

                    <div class="collapse" id="collapseExample">
                        {/* <div className="d-flex col-md-auto justify-content-end"> */}
                        <div className="d-flex justify-content-between mt-3">
                            <label className={`${styles.confirm}`}>인증하기</label>
                            <div>
                                <input className={`${styles.input} ${styles.input2}`} type="number" placeholder="인증번호를 입력" onChange={handleOnChangeMb} require />
                                <button type="button" className={`rounded-2 py-2 ${styles.butterYellowAndBtn} ${styles.btnHover}`} onClick={handleOnClickMbConfirm}>확인</button>
                                <button type="button" className={`rounded-2 py-2 ${styles.butterYellowAndBtn} ${styles.btnHover}`} onClick={handleOnClickMbnum}>재전송</button>
                            </div>
                        </div>
                        {(mbError === "재전송") && <p className={styles.passwordConfirmError}>유효시간이 만료되었습니다. 재전송해주세요.</p>}
                        {(mbError === "보냄") && <p className={styles.passwordConfirmError}>5분이내에 입력해주세요.</p>}
                        {(mbError === "성공") && <p className={styles.passwordConfirmError}>인증되었습니다.</p>}
                        {(mbError === "실패") && <p className={styles.passwordConfirmError}>인증번호를 다시 입력해주세요.</p>}
                    </div>
279
                </div>
한규민's avatar
한규민 committed
280

한규민's avatar
한규민 committed
281
282
283
                <div className="d-flex flex-column">
                    <div className={`${styles.inputContent}`}>
                        <label className={styles.signupLabel}>비밀번호</label>
한규민's avatar
한규민 committed
284
                        <input className={`${styles.input} ${styles.inputSize}`} type="password" name="userPassword" placeholder="8~11자리 사이" onChange={handleUserOnChange} maxLength="11" required />
한규민's avatar
한규민 committed
285
                    </div>
한규민's avatar
한규민 committed
286
                    {errorMsg.errorPassword && <p className={styles.passwordConfirmError}>8~11자리 사이로 입력해주세요.</p>}
287
                </div>
한규민's avatar
한규민 committed
288

289
                <div className="d-flex flex-column">
한규민's avatar
한규민 committed
290
                    <div className={styles.inputContent}>
291
                        <label className={styles.signupLabel}>비밀번호 확인</label>
한규민's avatar
한규민 committed
292
                        <input className={`${styles.input} ${styles.inputSize}`} type="password" name="userRePassword" placeholder="8~11자리 사이" onChange={handleUserOnChange} maxLength="11" required />
한규민's avatar
한규민 committed
293
                    </div>
한규민's avatar
한규민 committed
294
                    {errorMsg.errorRePassword && <p className={styles.passwordConfirmError}>비밀번호가 일치하지 않습니다.</p>}
한규민's avatar
한규민 committed
295
296
                </div>

한규민's avatar
한규민 committed
297
                <button className={`rounded my-3 py-2 fs-5 ${styles.butterYellowAndBtn} ${styles.btnHover}`} type="submit" disabled={loading}>가입하기</button>
298
            </div>
한규민's avatar
한규민 committed
299
        </form>
한규민's avatar
한규민 committed
300
301
302
303
    )
}

export default Signup