dh_demo

DreamHanks demo project
git clone git://git.lair.cx/dh_demo
Log | Files | Refs | README

[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 }