Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#9] Add Join Page #14

Merged
merged 9 commits into from
Sep 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"dependencies": {
"@hookform/resolvers": "^3.9.0",
"classnames": "^2.5.1",
"immer": "^10.1.1",
"next": "14.2.9",
"react": "^18",
"react-dom": "^18",
Expand Down
96 changes: 96 additions & 0 deletions src/app/join/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
'use client';

import { memo, useState } from 'react';
import { produce } from 'immer';
import TermsAgreement from '@/components/join/termsAgreement';
import EmailJoinForm from '@/components/join/emailJoinForm';
import PasswordJoinForm from '@/components/join/passwordJoinForm';
import PhoneJoinForm from '@/components/join/phoneJoinForm';
import PersonalInfoForm from '@/components/join/personalInfoForm';
import JoinSuccess from '@/components/join/joinSuccess';
import { StepType, UserDataType } from '@/types/join';

const Join = memo(function Join() {
const [step, setStep] = useState(0);

const [userData, setUserData] = useState<UserDataType>({
term_marketing: false,
term_ad: false,
email: null,
password: null,
phone: null,
name: null,
gender: null,
birth: null,
});

console.log('userData', userData);

const handleUserData = (id: keyof UserDataType, value: boolean | string) => {
setUserData(
produce((draft) => {
(draft[id] as typeof value) = value;
}),
);
};

const StepData: StepType[] = [
{
title: 'eqCM에 이용 약관에\n동의해 주세요',
component: (
<TermsAgreement
onClickNextBtn={setStep}
onChangeData={handleUserData}
/>
),
},
{
title: '로그인에 사용할\n아이디를 입력해 주세요.',
component: (
<EmailJoinForm onClickNextBtn={setStep} onChangeData={handleUserData} />
),
},
{
title: '로그인에 사용할\n비밀번호를 입력해 주세요.',
component: (
<PasswordJoinForm
onClickNextBtn={setStep}
onChangeData={handleUserData}
/>
),
},
{
title: '본인인증을\n진행해 주세요',
subtitle: '이미 가입한 계정이 있다면 알려드릴게요!',
component: (
<PhoneJoinForm onClickNextBtn={setStep} onChangeData={handleUserData} />
),
},
{
title: '이름과 성별, 생년월일을\n입력해 주세요.',
component: (
<PersonalInfoForm
onClickNextBtn={setStep}
onChangeData={handleUserData}
/>
),
},
{
title: '가입 완료!',
subtitle: '가입을 축하해요!',
component: <JoinSuccess />,
},
];

return (
<div className="flex flex-col w-full min-h-[650px] py-[50px] px-[20px] md:w-[400px] mx-auto md:px-0 md:pt-[43px] font-pretendard">
<p className="text-[30px] font-bold whitespace-pre-wrap">
{StepData[step].title}
</p>
{StepData[step].subtitle && <p>{StepData[step].subtitle}</p>}
<div className="h-full">{StepData[step].component}</div>
</div>
);
});

export default Join;
9 changes: 5 additions & 4 deletions src/components/common/input.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { memo } from 'react';
import { memo, InputHTMLAttributes } from 'react';
import { UseFormRegisterReturn } from 'react-hook-form';
import cn from 'classnames';

type Props = {
type?: HTMLInputElement['type'];
placeholder: string;
type Props = InputHTMLAttributes<HTMLInputElement> & {
style?: string;
register: Partial<UseFormRegisterReturn>;
};
Expand All @@ -14,13 +12,16 @@ const Input = memo(function Input({
placeholder,
style = '',
register,
...restProps
}: Props) {
return (
<input
type={type}
placeholder={placeholder}
className={cn('h-[44px] border rounded px-[14px]', style)}
autoComplete="off"
{...register}
{...restProps}
/>
);
});
Expand Down
5 changes: 3 additions & 2 deletions src/components/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@ import { memo } from 'react';
import MyMenu from './myMenu';
import Menu from './menu';
import Category from './category';
import Link from 'next/link';

const Header = memo(function Header() {
return (
<header className="bg-white sticky w-full top-0 left-0 right-0 px-5 py-2 md:px-6 md:pb-4 md:pt-10 lg:px-12 lg:pb-5">
<div className="flex justify-between md:mb-6 h-[18px]">
<div className="h-4">
<Link href={'/'} className="h-4">
<Image
src="/static/images/logo.png"
alt="logo"
width="60"
height="16"
/>
</div>
</Link>
<MyMenu />
</div>
<div className="hidden md:block">
Expand Down
2 changes: 1 addition & 1 deletion src/components/header/myMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { DEFAULT_MENU, USER_STATUS_MENU } from '@/constants/header';
import MyMenuItem from './myMenuItem';

const MyMenu = memo(function MyMenu() {
const isLoggedIn = true;
const isLoggedIn = false;
return (
<ul className="flex gap-4 text-[10px] font-base">
{DEFAULT_MENU.map((menu) => (
Expand Down
49 changes: 32 additions & 17 deletions src/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export const Icons = {
id="vector"
fillRule="evenodd"
clipRule="evenodd"
d="M8 10H19.25C19.6642 10 20 10.3358 20 10.75V21.25C20 21.6642 19.6642 22 19.25 22H4.75C4.33579 22 4 21.6642 4 21.25V10.75C4 10.3358 4.33579 10 4.75 10H6V8C6 4.68629 8.68629 2 12 2C13.9985 2 15.7688 2.97712 16.8593 4.47969L15.307 5.749C14.5869 4.69318 13.3744 4 12 4C9.79086 4 8 5.79086 8 8V10ZM12 12.5C12.5523 12.5 13 12.9477 13 13.5V15.5C13 16.0523 12.5523 16.5 12 16.5C11.4477 16.5 11 16.0523 11 15.5V13.5C11 12.9477 11.4477 12.5 12 12.5Z"
d="M12 2C8.68629 2 6 4.68629 6 8V10H4.75C4.33579 10 4 10.3358 4 10.75V21.25C4 21.6642 4.33579 22 4.75 22H19.25C19.6642 22 20 21.6642 20 21.25V10.75C20 10.3358 19.6642 10 19.25 10H18V8C18 4.68629 15.3137 2 12 2ZM16 10V8C16 5.79086 14.2091 4 12 4C9.79086 4 8 5.79086 8 8V10H16ZM13 13.5C13 12.9477 12.5523 12.5 12 12.5C11.4477 12.5 11 12.9477 11 13.5V15.5C11 16.0523 11.4477 16.5 12 16.5C12.5523 16.5 13 16.0523 13 15.5V13.5Z"
fill="black"
></path>
</g>
Expand Down Expand Up @@ -213,9 +213,9 @@ export const Icons = {
<g>
<path
fill="currentColor"
fill-rule="evenodd"
fillRule="evenodd"
d="M1 .5H.5V3h1V1.5h15V3h1V.5H1zm0 4H.5v13h17v-13H1zm.5 12v-11h15v11h-7v-6h-1v6h-7z"
clip-rule="evenodd"
clipRule="evenodd"
></path>
</g>
</svg>
Expand All @@ -232,9 +232,9 @@ export const Icons = {
<g>
<path
fill="currentColor"
fill-rule="evenodd"
fillRule="evenodd"
d="M1 .5H.5V3h1V1.5h15V3h1V.5H1zm0 4H.5v13h17v-13H1zm.5 12v-11h15v11h-7v-6h-1v6h-7z"
clip-rule="evenodd"
clipRule="evenodd"
></path>
</g>
</svg>
Expand All @@ -251,8 +251,8 @@ export const Icons = {
<g id="weight=light, fill=false">
<path
id="vector"
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
d="M10.9 4C7.08924 4 4 7.08924 4 10.9C4 14.7108 7.08924 17.8 10.9 17.8C12.8012 17.8 14.5219 17.0318 15.7705 15.7876C17.0247 14.5377 17.8 12.8099 17.8 10.9C17.8 7.08924 14.7108 4 10.9 4ZM3 10.9C3 6.53695 6.53695 3 10.9 3C15.2631 3 18.8 6.53695 18.8 10.9C18.8 12.9057 18.052 14.7375 16.8206 16.1305L20.8528 20.1457L20.1472 20.8543L16.1124 16.8365C14.7218 18.0584 12.8971 18.8 10.9 18.8C6.53695 18.8 3 15.2631 3 10.9Z"
fill="black"
></path>
Expand All @@ -272,8 +272,8 @@ export const Icons = {
<g id="weight=light, fill=false">
<path
id="vector"
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
d="M10.9 4C7.08924 4 4 7.08924 4 10.9C4 14.7108 7.08924 17.8 10.9 17.8C12.8012 17.8 14.5219 17.0318 15.7705 15.7876C17.0247 14.5377 17.8 12.8099 17.8 10.9C17.8 7.08924 14.7108 4 10.9 4ZM3 10.9C3 6.53695 6.53695 3 10.9 3C15.2631 3 18.8 6.53695 18.8 10.9C18.8 12.9057 18.052 14.7375 16.8206 16.1305L20.8528 20.1457L20.1472 20.8543L16.1124 16.8365C14.7218 18.0584 12.8971 18.8 10.9 18.8C6.53695 18.8 3 15.2631 3 10.9Z"
fill="black"
></path>
Expand All @@ -292,8 +292,8 @@ export const Icons = {
<g id="weight=light, fill=false">
<path
id="vector"
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
d="M4.5 4.5V19.5H19.5V4.5H15V12H14V4.5H10V12H9V4.5H4.5ZM3.5 4.25C3.5 3.83579 3.83579 3.5 4.25 3.5H19.75C20.1642 3.5 20.5 3.83579 20.5 4.25V19.75C20.5 20.1642 20.1642 20.5 19.75 20.5H4.25C3.83579 20.5 3.5 20.1642 3.5 19.75V4.25Z"
fill="black"
></path>
Expand All @@ -313,8 +313,8 @@ export const Icons = {
<g id="weight=light, fill=false">
<path
id="vector"
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
d="M4.5 4.5V19.5H19.5V4.5H15V12H14V4.5H10V12H9V4.5H4.5ZM3.5 4.25C3.5 3.83579 3.83579 3.5 4.25 3.5H19.75C20.1642 3.5 20.5 3.83579 20.5 4.25V19.75C20.5 20.1642 20.1642 20.5 19.75 20.5H4.25C3.83579 20.5 3.5 20.1642 3.5 19.75V4.25Z"
fill="black"
></path>
Expand All @@ -333,8 +333,8 @@ export const Icons = {
<g id="weight=light, fill=false">
<path
id="vector"
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
d="M12.5 3V2.5H11.5V3V8V8.5H12.5V8V3ZM4.5 17.1225V12H19.5V20.5V21H20.5V20.5V11.75C20.5 11.3358 20.1642 11 19.75 11H4.25C3.83796 11 3.5 11.3328 3.5 11.7492V20.5V21H4.5V20.5V17.1225Z"
fill="black"
></path>
Expand All @@ -354,8 +354,8 @@ export const Icons = {
<g id="weight=light, fill=false">
<path
id="vector"
fill-rule="evenodd"
clip-rule="evenodd"
fillRule="evenodd"
clipRule="evenodd"
d="M12.5 3V2.5H11.5V3V8V8.5H12.5V8V3ZM4.5 17.1225V12H19.5V20.5V21H20.5V20.5V11.75C20.5 11.3358 20.1642 11 19.75 11H4.25C3.83796 11 3.5 11.3328 3.5 11.7492V20.5V21H4.5V20.5V17.1225Z"
fill="black"
></path>
Expand Down Expand Up @@ -402,4 +402,19 @@ export const Icons = {
></path>
</svg>
),
check: ({ color }: { color?: string }) => (
<svg
width="14px"
height="14px"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={`w-[14px] h-[14px] text-[${color ? color : '#dcdfe6'}] peer-checked:text-white`}
>
<path
d="M20.6303 6.49266L10.6975 19.2009L3.43756 12.0235L4.56245 10.8856L10.5439 16.7991L19.3697 5.50735L20.6303 6.49266Z"
fill={color ? color : '#dcdfe6'}
></path>
</svg>
),
};
51 changes: 51 additions & 0 deletions src/components/join/checkbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use client';

import { memo } from 'react';
import { Icons } from '../icons';
import { AGREEMENT_CHECK_IDS_TYPE } from '@/types/join';

type Props = {
id: AGREEMENT_CHECK_IDS_TYPE;
text: string;
check: boolean;
detail?: string;
onClick: (id: AGREEMENT_CHECK_IDS_TYPE) => void;
};

const CheckBox = memo(function CheckBox({
id,
text,
detail,
check,
onClick,
}: Props) {
return (
<label
key={id}
htmlFor={id}
className="flex items-center gap-2 cursor-pointer"
>
<input
type="checkbox"
className="hidden peer"
name={id}
id={id}
onChange={() => onClick(id)}
checked={check}
/>
<div className="flex items-center justify-center w-[18px] h-[18px] border-[1px] border-[#dcdfe6] peer-checked:bg-black">
<Icons.check />
</div>
<div className="flex justify-between w-full">
<p>{text}</p>
{detail && (
<button type="button" className="border-b border-[#000]">
보기
</button>
)}
</div>
</label>
);
});

export default CheckBox;
Loading
Loading