-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Sign up form/#7
- Loading branch information
Showing
38 changed files
with
2,632 additions
and
144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
'use client'; | ||
import useFunnel from '@/app/hooks/useFunnel'; | ||
import SignUpForm from '@/app/ui/user/sign-up-form/sign-up-form'; | ||
import SignUpTerm from './sign-up-terms'; | ||
import SignUpSuccess from './sign-up-success'; | ||
import ContentContainer from '@/app/ui/view/atom/content-container'; | ||
|
||
export default function SignUpContainer() { | ||
const { Funnel, setStep } = useFunnel<'terms' | 'form' | 'success'>('terms'); | ||
|
||
return ( | ||
<div className="p-6"> | ||
<Funnel> | ||
<Funnel.Step name="terms"> | ||
<SignUpTerm | ||
onNext={() => { | ||
setStep('form'); | ||
}} | ||
/> | ||
</Funnel.Step> | ||
<Funnel.Step name="form"> | ||
<SignUpForm | ||
onNext={() => { | ||
setStep('success'); | ||
}} | ||
/> | ||
</Funnel.Step> | ||
<Funnel.Step name="success"> | ||
<SignUpSuccess /> | ||
</Funnel.Step> | ||
</Funnel> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import Button from '@/app/ui/view/atom/button/button'; | ||
import Link from 'next/link'; | ||
|
||
// 내용이랑 스타일은 mock인 상태입니다. | ||
export default function SignUpSuccess() { | ||
return ( | ||
<div className="min-h-screen bg-gray-100 flex items-center justify-center px-4 sm:px-6"> | ||
<div className="max-w-md w-full space-y-8"> | ||
<div className="space-y-2"> | ||
<h2 className="text-3xl font-extrabold tracking-tight">Youre all set.</h2> | ||
<p className="text-gray-500"> | ||
Thanks for signing up! We just need to verify your email address to complete the process. | ||
</p> | ||
</div> | ||
<div className="space-y-4"> | ||
<div className="grid grid-cols-2 gap-4"> | ||
<Link className="inline-block w-full" href="/login"> | ||
<Button className="w-full" label={'로그인 하기'} /> | ||
</Link> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import Button from '@/app/ui/view/atom/button/button'; | ||
|
||
interface SignUpTermProps { | ||
onNext?: () => void; | ||
} | ||
|
||
// 약관 내용이랑 스타일은 mock인 상태입니다. | ||
export default function SignUpTerm({ onNext }: SignUpTermProps) { | ||
const handleAgreeButtonClick = () => { | ||
onNext?.(); | ||
}; | ||
|
||
return ( | ||
<div className="max-w-2xl mx-auto my-8 p-6 bg-white rounded-lg shadow-md"> | ||
<h1 className="text-3xl font-bold text-center mb-6">알림독의 안내문</h1> | ||
<ul className="list-disc space-y-4 text-sm"> | ||
<li> | ||
현재 저희 기능은 한국-한국은 아니라 한국-외국도 가능합니다. 각사별에서 수하인 없더라도 저희가 받는데까지는 | ||
무관합니다만, 꼭 관세사무소와 협의하세요! | ||
<ul className="list-disc ml-6 mt-2"> | ||
<li>대상: 국외발송, 북부발송, 사회복지대상, ICT용품대상, 일반대상, 미래용품대상(확인)</li> | ||
<li>발송: 16 ~ 22시발</li> | ||
</ul> | ||
</li> | ||
<li> | ||
교직, 디자인, 연계개발, 물품, 전자, 자원관리/회계지원에 해당하는 사용자는 각사 기준에 따른 선정되지 않아 각사 | ||
별 관리하는데요. | ||
</li> | ||
<li>검사를 위해서 선적품을 직접 연락드려야만 PC화면에서 진행하는 것을 권장합니다.</li> | ||
<li> | ||
검사 기준은 최신버전 확인내역(2023.07.24) 반영하여 선정되었으며, 학사내역은 매년 개편되므로 자사이 외고 있는 | ||
구버전과 다를 수 있습니다. | ||
<ul className="list-disc ml-6 mt-2"> | ||
<li>문자대항: 학사내역은 확인 클릭</li> | ||
</ul> | ||
</li> | ||
<li> | ||
본 서비스 정보는 공식적인 확인을 전제 않으며, 정확한 증상조사결과를 위해 서류 또는 담당과 교류해야할 사항을 | ||
잊지 않습니다. | ||
</li> | ||
<li> | ||
전자문 서화지 데이터베이스는 의무화되어 저희가 고유축적 및 교육과정 등에서 사용되며, 어떤 다른 용도로 사용 | ||
되지 않습니다. | ||
</li> | ||
<li>특허요건 기준이 전문 선정되었거나, 오류발생 시 우측 하단 채팅창으로 또는 담당 부서로문의합니다.</li> | ||
</ul> | ||
<div className="mt-8 flex justify-center"> | ||
<Button | ||
onClick={handleAgreeButtonClick} | ||
className="ml-4 bg-blue-500 text-white py-2 px-4 rounded-full" | ||
label={'알림독의 안내문'} | ||
/> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import ContentContainer from '@/app/ui/view/atom/content-container'; | ||
import SignUpContainer from './components/sign-up-container'; | ||
import { Suspense } from 'react'; | ||
import LoadingSpinner from '@/app/ui/view/atom/loading-spinner'; | ||
|
||
// Refactor: fallback 스켈레톤으로 대체 | ||
export default function Page() { | ||
return ( | ||
<ContentContainer className="md:w-[768px]"> | ||
<Suspense | ||
fallback={ | ||
<div className="h-96"> | ||
<LoadingSpinner /> | ||
</div> | ||
} | ||
> | ||
<SignUpContainer /> | ||
</Suspense> | ||
</ContentContainer> | ||
); | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
const BASE_URL = process.env.API_MOCKING === 'enable' ? 'http://localhost:9090' : 'http://mock.api.com'; | ||
const BASE_URL = process.env.API_MOCKING === 'enable' ? 'http://localhost:9090' : 'https://mock.api.com'; | ||
|
||
export const API_PATH = { | ||
revenue: `${BASE_URL}/revenue`, | ||
registerUserGrade: `${BASE_URL}/registerUserGrade`, | ||
parsePDFtoText: `${BASE_URL}/parsePDFtoText`, | ||
takenLectures: `${BASE_URL}/taken-lectures`, | ||
user: `${BASE_URL}/users`, | ||
}; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
'use server'; | ||
|
||
import { FormState } from '@/app/ui/view/molecule/form/form-root'; | ||
import { API_PATH } from '../api-path'; | ||
import { SignUpRequestBody } from './user.type'; | ||
import { httpErrorHandler } from '@/app/utils/http/http-error-handler'; | ||
import { BadRequestError } from '@/app/utils/http/http-error'; | ||
import { SignUpFormSchema } from './user.validation'; | ||
|
||
export async function createUser(prevState: FormState, formData: FormData): Promise<FormState> { | ||
const validatedFields = SignUpFormSchema.safeParse({ | ||
authId: formData.get('authId'), | ||
password: formData.get('password'), | ||
confirmPassword: formData.get('confirmPassword'), | ||
studentNumber: formData.get('studentNumber'), | ||
engLv: formData.get('engLv'), | ||
}); | ||
|
||
if (!validatedFields.success) { | ||
return { | ||
isSuccess: false, | ||
isFailure: true, | ||
validationError: validatedFields.error.flatten().fieldErrors, | ||
message: '양식에 맞춰 다시 입력해주세요.', | ||
}; | ||
} | ||
|
||
const { authId, password, studentNumber, engLv } = validatedFields.data; | ||
const body: SignUpRequestBody = { | ||
authId, | ||
password, | ||
studentNumber, | ||
engLv, | ||
}; | ||
|
||
try { | ||
const response = await fetch(`${API_PATH.user}/sign-up`, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify(body), | ||
}); | ||
|
||
const result = await response.json(); | ||
|
||
httpErrorHandler(response, result); | ||
} catch (error) { | ||
if (error instanceof BadRequestError) { | ||
// 잘못된 요청 처리 로직 | ||
return { | ||
isSuccess: false, | ||
isFailure: true, | ||
validationError: {}, | ||
message: error.message, | ||
}; | ||
} else { | ||
// 나머지 에러는 더 상위 수준에서 처리 | ||
throw error; | ||
} | ||
} | ||
|
||
return { | ||
isSuccess: true, | ||
isFailure: false, | ||
validationError: {}, | ||
message: '회원가입이 완료되었습니다.', | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// https://stackoverflow.com/questions/76957592/error-only-async-functions-are-allowed-to-be-exported-in-a-use-server-file | ||
// server action 파일에서는 async function만 export 가능 | ||
|
||
export interface SignUpRequestBody { | ||
authId: string; | ||
password: string; | ||
studentNumber: string; | ||
engLv: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { z } from 'zod'; | ||
|
||
export const SignUpFormSchema = z | ||
.object({ | ||
authId: z | ||
.string() | ||
.min(6, { | ||
message: '아이디는 6자 이상 20자 이하여야 합니다.', | ||
}) | ||
.max(20, { | ||
message: 'User ID must be at most 20 characters', | ||
}), | ||
password: z | ||
.string() | ||
.min(8, { message: '비밀번호는 8자 이상이어야 합니다.' }) | ||
.regex(/^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,}$/, { | ||
message: '비밀번호는 문자, 숫자, 특수문자(!@#$%^&*)를 포함해야 합니다.', | ||
}) | ||
.max(20, { message: '비밀번호는 20자 이하여야 합니다.' }), | ||
confirmPassword: z.string(), | ||
studentNumber: z.string().length(8, { message: '학번은 8자리여야 합니다.' }).startsWith('60', { | ||
message: '학번은 60으로 시작해야 합니다.', | ||
}), | ||
engLv: z.enum(['basic', 'ENG12', 'ENG34', 'bypass'], { | ||
invalid_type_error: '올바른 영어 레벨을 선택해주세요.', | ||
}), | ||
}) | ||
.superRefine(({ confirmPassword, password }, ctx) => { | ||
if (confirmPassword !== password) { | ||
ctx.addIssue({ | ||
code: 'custom', | ||
message: '비밀번호가 일치하지 않습니다.', | ||
path: ['confirmPassword'], | ||
}); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.