Skip to content

Commit

Permalink
회원가입 - 뷰 #122
Browse files Browse the repository at this point in the history
  • Loading branch information
ddarkr committed May 7, 2022
2 parents 4e4129f + 1b4f25a commit d881f84
Show file tree
Hide file tree
Showing 8 changed files with 374 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/components/common/Button/FilledButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const filledButtonCss = (theme: Theme, colorType: ColorType) => css`
width: 100%;
height: 37px;
font-size: 14px;
font-weight: ${theme.font.weight.semiBold};
color: ${colorType === 'dark' ? theme.color.background : theme.color.gray05};
background-color: ${colorType === 'dark' ? theme.color.gray05 : theme.color.gray02};
`;
115 changes: 115 additions & 0 deletions src/components/common/Dialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { PropsWithChildren, ReactNode, useEffect, useState } from 'react';
import { css, Theme } from '@emotion/react';
import { motion, Variants } from 'framer-motion';

import PortalWrapper from '~/components/common/PortalWrapper';
import { defaultEasing, defaultFadeInUpVariants } from '~/constants/motions';

export interface DialogProps {
isShowing?: boolean;
actionButtons: ReactNode;
}

export default function Dialog({
isShowing,
children,
actionButtons,
}: PropsWithChildren<DialogProps>) {
const [isSSR, setIsSSR] = useState(true);

useEffect(() => {
setIsSSR(false);
}, []);

// NOTE: https://github.com/vercel/next.js/discussions/35773
if (!isSSR && isShowing) {
return (
<PortalWrapper isShowing={true}>
<motion.div
css={dimBackdropCss}
variants={backgroundFadeInOutVariants}
initial="initial"
animate="animate"
exit="exit"
>
<motion.div css={dialogCss} variants={defaultFadeInUpVariants}>
<div css={dialogContentWrapperCss}>{children}</div>
<div css={dialogButtonWrapperCss}>{actionButtons}</div>
</motion.div>
</motion.div>
</PortalWrapper>
);
}

return <></>;
}

const dimBackdropCss = (theme: Theme) => css`
display: flex;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: ${theme.color.dim03};
z-index: 10;
overflow: hidden;
`;

const dialogCss = (theme: Theme) => css`
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
min-width: 300px;
min-height: 200px;
background-color: ${theme.color.background};
border-radius: ${theme.borderRadius.default};
`;

const dialogContentWrapperCss = (theme: Theme) => css`
white-space: pre;
font-weight: ${theme.font.weight.bold};
font-style: normal;
color: ${theme.color.gray05};
font-size: 16px;
line-height: 150%;
text-align: center;
margin: 24px 16px;
`;

const dialogButtonWrapperCss = css`
display: flex;
flex-direction: row;
gap: 16px;
width: 100%;
padding: 16px;
`;

export const backgroundFadeInOutVariants: Variants = {
initial: {
opacity: 0,
transition: { duration: 0.2, ease: defaultEasing },
willChange: 'opacity',
},
animate: {
opacity: 1,
transition: { duration: 0.2, ease: defaultEasing },
willChange: 'opacity',
},
exit: {
opacity: 0,
transition: { duration: 0.2, ease: defaultEasing },
willChange: 'opacity',
},
};
2 changes: 1 addition & 1 deletion src/constants/motions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Variants } from 'framer-motion';

const defaultEasing = [0.6, -0.05, 0.01, 0.99];
export const defaultEasing = [0.6, -0.05, 0.01, 0.99];

export const staggerOne: Variants = {
animate: { transition: { staggerChildren: 0.1 } },
Expand Down
1 change: 1 addition & 0 deletions src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const layoutCss = (theme: Theme) => css`
background: ${theme.color.background};
max-width: ${theme.size.maxWidth};
width: 100%;
height: 100%;
margin: 0 auto;
padding: ${theme.size.layoutPadding};
`;
94 changes: 94 additions & 0 deletions src/pages/signup/email-verified.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { css, Theme } from '@emotion/react';

import { CTAButton } from '~/components/common/Button';
import CheckList from '~/components/common/CheckList';
import NavigationBar from '~/components/common/NavigationBar';
import TextField from '~/components/common/TextField';
import useInput from '~/hooks/common/useInput';

export default function SignUpEmailVerified() {
const nickname = useInput({ useDebounce: true });
const password = useInput({ useDebounce: true });
const passwordRepeat = useInput({ useDebounce: true });

return (
<article css={containerCss}>
<NavigationBar title={'회원가입'} />
<p css={introTextWrapper}>마지막 단계입니다!</p>
<form css={formCss}>
<fieldset css={fieldSetCss}>
<TextField
label={'닉네임'}
placeholder={'닉네임을 입력해주세요'}
feedback={<>&nbsp;</>}
value={nickname.value}
onChange={nickname.onChange}
required
/>
<TextField
label={'비밀번호'}
placeholder={'영문, 숫자 포함 6자 이상의 비밀번호'}
feedback={<>&nbsp;</>}
value={password.value}
onChange={password.onChange}
required
/>
<TextField
label={'비밀번호 확인'}
placeholder={'영문, 숫자 포함 6자 이상의 비밀번호'}
feedback={<>&nbsp;</>}
value={passwordRepeat.value}
onChange={passwordRepeat.onChange}
required
/>
<div css={checkListWrapperCss}>
<CheckList isChecked={false} onToggle={() => {}}>
(필수) 서비스 이용약관에 동의
</CheckList>
<CheckList isChecked={false} onToggle={() => {}}>
(필수) 개인정보 수집 이용에 동의
</CheckList>
</div>
</fieldset>
<CTAButton type={'submit'}>Start Tang!</CTAButton>
</form>
</article>
);
}

const containerCss = css`
display: flex;
flex-direction: column;
height: 100%;
`;

const introTextWrapper = (theme: Theme) => css`
white-space: pre;
font-weight: ${theme.font.weight.bold};
color: ${theme.color.gray05};
font-size: 18px;
line-height: 150%;
margin-top: 40px;
margin-bottom: 32px;
`;

const formCss = css`
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
`;

const fieldSetCss = css`
display: flex;
flex-direction: column;
gap: 16px; // (original 36px) - (label height 20px)
margin-bottom: 52px;
`;

const checkListWrapperCss = css`
display: flex;
flex-direction: column;
`;
75 changes: 72 additions & 3 deletions src/pages/signup/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,76 @@
import { css } from '@emotion/react';
import { css, Theme } from '@emotion/react';

import { CTAButton } from '~/components/common/Button';
import NavigationBar from '~/components/common/NavigationBar';
import TextField from '~/components/common/TextField';
import useInput from '~/hooks/common/useInput';

export default function Signup() {
return <article css={signupCss}>회원가입</article>;
const email = useInput({ useDebounce: true });

return (
<article css={loginCss}>
<NavigationBar title={'회원가입'} />
<div css={introCardCss}>
<p css={introTextWrapper}>
자주쓰는 이메일을
<br />딱 한번만 인증하면,
<br />
영감을 차곡차곡 쌓아갈 수 있어요.
</p>
</div>
<form css={fieldSetCss}>
<TextField
placeholder={'이메일을 입력해주세요'}
feedback={<>&nbsp;</>}
value={email.value}
onChange={email.onChange}
required
/>
<CTAButton type={'submit'}>로그인</CTAButton>
</form>
<div css={signUpTextWrapperCss}>
입력한 이메일은 홍보/마케팅 용으로 사용되지 않고,
<br />
로그인과 회원가입, 비밀번호 찾기에만 사용되니 안심하세요.
</div>
</article>
);
}

const signupCss = css``;
const loginCss = css`
display: flex;
flex-direction: column;
`;

const introCardCss = css`
position: relative;
width: 100%;
height: 136px;
margin-bottom: 36px;
`;

const introTextWrapper = (theme: Theme) => css`
position: absolute;
left: 12px;
bottom: 17px;
color: ${theme.color.gray05};
font-size: 15px;
font-weight: 600;
line-height: 150%;
`;

const fieldSetCss = css`
display: flex;
flex-direction: column;
gap: 36px;
margin-bottom: 52px;
`;

const signUpTextWrapperCss = (theme: Theme) => css`
color: ${theme.color.gray03};
font-weight: ${theme.font.weight.regular};
font-size: 10px;
line-height: 150%;
text-align: center;
`;
Loading

0 comments on commit d881f84

Please sign in to comment.