[id].tsx (4659B)
1 import { Button, SubmitButton } from '@/components/elements/Button' 2 import Title from '@/components/elements/Title' 3 import Field from '@/components/form/Field' 4 import Fields from '@/components/form/Fields' 5 import Form from '@/components/form/Form' 6 import Container from '@/components/layout/Container' 7 import Hero from '@/components/layout/Hero' 8 import Section from '@/components/layout/Section' 9 import { isApiError } from '@/lib/apierror' 10 import { useForm } from '@/lib/hooks/use_form' 11 import { getUnconfirmedSignupRequest } from '@/lib/models/signup_request' 12 import { GetServerSideProps } from 'next' 13 import { useRouter } from 'next/router' 14 import { useCallback, useEffect, useState } from 'react' 15 16 interface PageProps { 17 id: number 18 email: string 19 } 20 21 export const getServerSideProps: GetServerSideProps<PageProps> = async (context) => { 22 let id: number 23 try { 24 id = parseInt(context.query.id as string, 10) 25 } catch (e) { 26 return { 27 notFound: true, 28 } 29 } 30 31 const signUpRequest = await getUnconfirmedSignupRequest([id]) 32 if (signUpRequest == null) { 33 return { 34 notFound: true, 35 } 36 } 37 38 return { 39 props: { 40 id, 41 email: signUpRequest.email, 42 }, 43 } 44 } 45 46 export default function SignUpCompletePage (props: PageProps) { 47 const router = useRouter() 48 const requestId = router.query.id as string 49 50 const [passwordRepeat, setPasswordRepeat] = useState('') 51 52 const [passwordError, setPasswordError] = useState<string | null>(null) 53 const [passwordRepeatError, setPasswordRepeatError] = useState<string | null>(null) 54 const [nicknameError, setNicknameError] = useState<string | null>(null) 55 56 const [fields, updateFields, submit, isLoading] = useForm( 57 { method: 'POST', url: `/api/users/signup/${requestId}` }, 58 { 59 password: '', 60 nickname: '', 61 }, 62 () => { 63 router.push('/users/login') 64 .catch(console.error) 65 }, 66 (status, err) => { 67 if (!isApiError(err)) { 68 setPasswordError('알 수 없는 오류가 발생했습니다.') 69 return 70 } 71 72 switch (status) { 73 case 400: 74 switch (err.code) { 75 case 'invalid_password': 76 setPasswordError('비밀번호가 비어있거나 유효하지 않습니다.') 77 return 78 79 case 'invalid_nickname': 80 setNicknameError('닉네임이 비어있거나 유효하지 않습니다.') 81 return 82 } 83 break 84 85 case 409: 86 switch (err.code) { 87 case 'nickname_duplicated': 88 setNicknameError('이미 사용중인 닉네임입니다.') 89 return 90 } 91 break 92 } 93 94 setPasswordError('알 수 없는 오류가 발생했습니다.') 95 } 96 ) 97 98 99 // 비밀번호 확인 오류 표시 100 useEffect(() => { 101 if (passwordRepeat?.length === 0) { 102 return 103 } 104 setPasswordRepeatError( 105 fields.password !== passwordRepeat 106 ? '비밀번호가 일치하지 않습니다.' 107 : null, 108 ) 109 }, [fields.password, passwordRepeat]) 110 111 return ( 112 <Form onSubmit={submit}> 113 <Hero> 114 <Title kind="headline">Sign up</Title> 115 </Hero> 116 117 <Container> 118 <Section> 119 <Fields> 120 <Field 121 type="text" 122 placeholder="Email" 123 disabled={isLoading} 124 readOnly 125 value={props.email} 126 /> 127 <Field 128 type="password" 129 placeholder="Password" 130 disabled={isLoading} 131 color={passwordError ? 'error' : undefined} 132 message={passwordError ?? undefined} 133 value={fields.password} 134 onValueChange={updateFields.bind(null, 'password')} 135 /> 136 <Field 137 type="password" 138 placeholder="Password (Repeat)" 139 disabled={isLoading} 140 color={passwordRepeatError ? 'error' : undefined} 141 message={passwordRepeatError ?? undefined} 142 value={passwordRepeat} 143 onValueChange={setPasswordRepeat} 144 /> 145 <Field 146 type="text" 147 placeholder="Nickname" 148 disabled={isLoading} 149 color={nicknameError ? 'error' : undefined} 150 message={nicknameError ?? undefined} 151 value={fields.nickname} 152 onValueChange={updateFields.bind(null, 'nickname')} 153 /> 154 </Fields> 155 156 <SubmitButton 157 color="primary" 158 disabled={isLoading} 159 value="Sign up" 160 /> 161 </Section> 162 </Container> 163 </Form> 164 ) 165 }