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

페이지 UI: 회원가입 #62

Merged
merged 3 commits into from
Jan 10, 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
7 changes: 7 additions & 0 deletions src/app/signup/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
function Signuplayout({ children }: { children: React.ReactNode }) {
return (
<div style={{ padding: '0 24px' }}>{children}</div>
);
}

export default Signuplayout;
5 changes: 5 additions & 0 deletions src/app/signup/page.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.ageGroupContainer {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 18px;
}
60 changes: 60 additions & 0 deletions src/app/signup/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* eslint-disable @typescript-eslint/no-misused-promises */

'use client';

import { useForm } from 'react-hook-form';

import classNames from 'classnames/bind';

import Button from '@components/shared/button/Button';
import Flex from '@components/shared/flex/Flex';
import Header from '@components/shared/header/Header';
import Radio from '@components/shared/radio/Radio';
import Spacing from '@components/shared/spacing/Spacing';
import Text from '@components/shared/text/Text';
import TextField from '@components/shared/text-field/TextField';
import Title from '@components/shared/title/Title';

import styles from './page.module.scss';

const cx = classNames.bind(styles);

function SignupPage() {
const { register, handleSubmit } = useForm();
// eslint-disable-next-line @typescript-eslint/require-await
const onSubmit = async () => {
// console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Header displayLogo={false} />
<Spacing size={20} />
<Title title="회원가입" />
<TextField label="아이디" required placeholder="아이디" {...register('id')} />
<TextField label="비밀번호" required placeholder="비밀번호" {...register('password')} />
<TextField label="비밀번호 확인" required placeholder="비밀번호 확인" {...register('confirmedPassword')} />
<TextField label="이메일" required placeholder="이메일" {...register('email')} />
<Text typography="t6"> 성별</Text>
<Spacing size={20} />
<Flex justify="space-between" gap={10}>
<Radio type="gender" label="남성" value="male" {...register('gender')} />
<Radio type="gender" label="여성" value="female" {...register('gender')} />
</Flex>
<Spacing size={20} />
<Text typography="t6">연령층</Text>
<Spacing size={20} />
<div className={cx('ageGroupContainer')}>
<Radio type="ageGroup" label="20대 이상" value="20" {...register('age')} />
<Radio type="ageGroup" label="30대" value="30" {...register('age')} />
<Radio type="ageGroup" label="40대" value="40" {...register('age')} />
<Radio type="ageGroup" label="50대" value="50" {...register('age')} />
<Radio type="ageGroup" label="60대 이상" value="60" {...register('age')} />
</div>
<Spacing size={50} />
<Button size="medium" full>약관 동의하러 가기</Button>
<Spacing size={20} />
</form>
);
}

export default SignupPage;
6 changes: 5 additions & 1 deletion src/components/shared/Input/Input.module.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
input {
.input {
box-sizing: border-box;
width: 100%;
height: 48px;
Expand All @@ -16,4 +16,8 @@ input {
&[aria-invaild="true"] {
border-color: var(--red);
}

&::placeholder {
color: var(--gray-100);
}
}
8 changes: 6 additions & 2 deletions src/components/shared/Input/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { forwardRef, InputHTMLAttributes } from 'react';
import './Input.module.scss';

import classNames from 'classnames/bind';

import styles from './Input.module.scss';

const cx = classNames.bind(styles);
// eslint-disable-next-line prefer-arrow-callback
const Input = forwardRef<HTMLInputElement, InputHTMLAttributes<HTMLInputElement>>((props, ref) => {
return <input {...props} ref={ref} />;
return <input className={cx('input')} {...props} ref={ref} />;
});

export default Input;
7 changes: 4 additions & 3 deletions src/components/shared/flex/Flex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ interface FlexProps {
justify?: CSSProperties['justifyContent']
direction?: CSSProperties['flexDirection']
children: React.ReactNode
gap?: number
className?: string
}

function Flex({
align, justify, direction, children, className,
align, justify, direction, children, className, gap = 0,
}: FlexProps) {
const styles = useMemo(() => {
return {
display: 'flex', alignItems: align, justifyContent: justify, flexDirection: direction,
display: 'flex', alignItems: align, justifyContent: justify, flexDirection: direction, gap: `${gap}px`,
};
}, [align, justify, direction]);
}, [align, justify, direction, gap]);

return (
<div style={styles} className={className}>
Expand Down
22 changes: 11 additions & 11 deletions src/components/shared/radio/Radio.module.scss
Original file line number Diff line number Diff line change
@@ -1,48 +1,48 @@
input[type="radio"] {
.input[type="radio"] {
display: none;
}

label {
.label {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}

label.gender {
.label.gender {
height: 48px;
border-radius: 8px;
}

input[type="radio"] + label.gender {
.input[type="radio"] + .label.gender {
border: 1px solid var(--gray-100);
background-color: var(--white);
color: var(--gray-300);
}

input[type="radio"]:checked + label.gender {
.input[type="radio"]:checked + .label.gender {
background-color: var(--primary);
color: var(--white);
}

label.ageGroup {
.label.ageGroup {
height: 47px;
border-radius: 30px;
}

label.additionalInfo {
.label.additionalInfo {
height: 60px;
border-radius: 10px;
}

input[type="radio"] + label.ageGroup,
input[type="radio"] + label.additionalInfo {
.input[type="radio"] + .label.ageGroup,
.input[type="radio"] + .label.additionalInfo {
background-color: var(--white-100);
color: var(--gray-300);
}

input[type="radio"]:checked + label.ageGroup,
input[type="radio"]:checked + label.additionalInfo {
.input[type="radio"]:checked + .label.ageGroup,
.input[type="radio"]:checked + .label.additionalInfo {
background-color: var(--primary);
color: var(--white-100);
}
6 changes: 3 additions & 3 deletions src/components/shared/radio/Radio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ interface RadioProps extends InputHTMLAttributes<HTMLInputElement> {
const cx = classNames.bind(styles);

const Radio = forwardRef<HTMLInputElement, RadioProps>(({
type, label, value,
type, label, value, ...props
}, ref) => {
return (
<>
<input id={label} type="radio" ref={ref} value={value} />
<label className={cx({ [type]: true })} htmlFor={label}>
<input className={cx('input')} id={label} type="radio" ref={ref} value={value} {...props} />
<label className={cx('label', { [type]: true })} htmlFor={label}>
{label}
</label>
</>
Expand Down
6 changes: 2 additions & 4 deletions src/components/shared/text-field/TextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@ const TextField = forwardRef<HTMLInputElement, TextFieldProps>(function TextFiel
{required && <Text typography="t6" display="inline-block" color="red">*</Text>}
<Spacing size={12} />
<Input ref={ref} aria-vaild={hasError} onFocus={handleFocus} onBlur={handleBlur} {...props} />
<Spacing size={12} />
{hasError && (
<>
<Spacing size={12} />
<Text typography="t7" color={labelColor} display="inline-block">{helpMessage}</Text>
</>
<Text typography="t7" color={labelColor} display="inline-block">{helpMessage}</Text>
)}
</div>
);
Expand Down
Loading