Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6d2d252
chore: Auth 모달창 스타일링 변경
hanana1253 Mar 29, 2022
f4700c3
fix: Dim div의 position을 absolute에서 fixed로 변경
hanana1253 Mar 29, 2022
e23384d
chore: Auth Error 배경색 변경
hanana1253 Mar 29, 2022
e30c21f
feat: Auth 토글 버튼 추가 및 스타일링 변경
hanana1253 Mar 29, 2022
0b70350
fix: Auth 컴포넌트 키보드 트래핑 버그 수정
hanana1253 Mar 29, 2022
5ff874f
fix: Dialog onClose 이벤트에 대한 버그 수정
hanana1253 Mar 29, 2022
7ba2627
Merge branch 'develop' of https://github.com/TeamCooks/TwoSpoon into …
hanana1253 Mar 29, 2022
4d8e783
feat: 로그인 시 Toast 등장
hanana1253 Mar 29, 2022
e97736b
fix: Auth 컴포넌트에서 Toast 관련 핸들러를 프롭으로 받도록 추가
hanana1253 Mar 29, 2022
091688c
refactor: 재사용 가능한 useToast 훅 작성
hanana1253 Mar 30, 2022
55e07be
refactor: Global HEADER_HEIGHT 변수 적용 및 Toast 컴포넌트 삽입
hanana1253 Mar 30, 2022
91961e2
refactor: Auth 컴포넌트와 Menu 컴포넌트에 auth 상태 변경 시 Toast핸들러 프롭 전달
hanana1253 Mar 30, 2022
63ba206
chore: Toast 컴포넌트를 index에 추가 및 필요없는 로직 삭제
hanana1253 Mar 30, 2022
109a849
refactor: ErrorBoundary 컴포넌트 내부코드 및 import 구문 순서 수정
hanana1253 Mar 30, 2022
1191a14
refactor: ErrorBoundaryProp수정
hanana1253 Mar 30, 2022
d63ed28
fix: Auth slice의 타입 에러 해결
hanana1253 Mar 30, 2022
cf52a90
chore: Error Test 페이지 레이아웃 스타일링
hanana1253 Mar 30, 2022
41578ca
fix: _error.tsx 페이지의 타입 에러 수정
hanana1253 Mar 30, 2022
3e95701
Merge branch 'develop' into develop
hanana1253 Mar 30, 2022
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
17 changes: 13 additions & 4 deletions src/components/Auth/Auth.styled.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import styled from '@emotion/styled';
import { pxToRem } from 'utils';
import { media, pxToRem } from 'utils';
import { Button } from 'components';
import { StyledInputProps } from './Auth.types';

export const StyledAuthContainer = styled.div`
Expand All @@ -10,7 +11,6 @@ export const StyledAuthContainer = styled.div`

export const StyledForm = styled.form`
margin: ${pxToRem(18)} auto;
min-width: ${pxToRem(280)};
display: flex;
flex-direction: column;
gap: ${pxToRem(4)};
Expand All @@ -25,12 +25,12 @@ export const StyledForm = styled.form`

export const StyledAuthError = styled.div`
border: 2px solid red;
background-color: rgba(255, 0, 0, 0.4);
background-color: rgba(255, 0, 0, 0.7);
border-radius: ${pxToRem(5)};
padding: ${pxToRem(16)} 0;
margin: ${pxToRem(18)} auto;
max-width: ${pxToRem(400)};
min-width: ${pxToRem(280)};
${media.mobile && 'padding: 20px;'}
text-align: center;
color: white;
`;
Expand All @@ -49,4 +49,13 @@ export const StyledInput = styled.input<StyledInputProps>`
border: none;
border-radius: ${pxToRem(5)} ${pxToRem(5)};
${({ $warning, theme }) => $warning && `box-shadow: 0 0 1px 5px ${theme.color.primaryOrange};`}
background-color: ${({ theme }) => theme.color.searchGray};
`;

export const StyledToggleButton = styled(Button)`
text-align: center;
width: 100%;
:hover {
text-decoration: underline;
}
`;
48 changes: 33 additions & 15 deletions src/components/Auth/Auth.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import { actions } from 'store/slices/auth';
import { Button, Heading, Dialog } from 'components';
import { useState, Fragment } from 'react';
import { useDispatch } from 'react-redux';
import { FormikProps, withFormik } from 'formik';
import { FormValues, FormProps, AuthContainerProps } from './Auth.types';
import { StyledForm, StyledInput, StyledAuthError, StyledFieldError, StyledAuthContainer } from './Auth.styled';
import { FormValues, FormProps, AuthContainerProps, Form } from './Auth.types';
import {
StyledForm,
StyledInput,
StyledAuthError,
StyledFieldError,
StyledAuthContainer,
StyledToggleButton,
} from './Auth.styled';
import {
AUTH_STATE,
AUTH_FUNC,
Expand All @@ -11,11 +22,8 @@ import {
PLACEHOLDER,
TYPE,
AUTH_ERROR_MSG,
TOGGLE_MESSAGE,
} from './AuthServices';
import { Button, Heading } from 'components';
import { useState, Fragment } from 'react';
import { useDispatch } from 'react-redux';
import { actions } from 'store/slices/auth';

const AuthForm = (props: FormProps & FormikProps<FormValues>): JSX.Element => {
const { currentForm, values, errors, dirty, touched, isValid, handleChange, handleBlur, handleSubmit } = props;
Expand Down Expand Up @@ -43,7 +51,7 @@ const AuthForm = (props: FormProps & FormikProps<FormValues>): JSX.Element => {
),
)}

<Button variant="filled" round={true} color="primaryGreen" type="submit" disabled={!dirty || !isValid}>
<Button variant="filled" color="primaryGreen" type="submit" disabled={!dirty || !isValid}>
{HEADING[currentForm]}
</Button>
</StyledForm>
Expand All @@ -58,26 +66,36 @@ const Auth = withFormik<FormProps, FormValues>({
},
})(AuthForm);

export const AuthContainer = ({ onClose }: AuthContainerProps) => {
const [currentForm, setCurrentForm] = useState(AUTH_STATE.signin);
export const AuthContainer = ({ onClose, onSignIn }: AuthContainerProps) => {
const [currentForm, setCurrentForm] = useState<Form>(AUTH_STATE.signin);
const [hasAuthError, setAuthError] = useState(false);
const dispatch = useDispatch();

const handleSubmit = async (values) => {
const toggleCurrentForm = () => {
setCurrentForm(currentForm === AUTH_STATE.signin ? AUTH_STATE.signup : AUTH_STATE.signin);
};

const handleSubmit = async (values: FormValues) => {
try {
dispatch(actions.loading(true));
const { uid: userId } = await AUTH_FUNC[currentForm](values);
dispatch(actions.signIn(userId));
onClose();
onSignIn();
} catch (e) {
setAuthError(true);
}
};
return (
<StyledAuthContainer>
<Heading as="h1">{HEADING[currentForm]}</Heading>
{hasAuthError && <StyledAuthError>{AUTH_ERROR_MSG[currentForm]}</StyledAuthError>}
<Auth currentForm={currentForm} onSubmit={handleSubmit} />
</StyledAuthContainer>
<Dialog label={currentForm} onClose={onClose}>
<StyledAuthContainer>
<Heading as="h1">{HEADING[currentForm]}</Heading>
{hasAuthError && <StyledAuthError>{AUTH_ERROR_MSG[currentForm]}</StyledAuthError>}
<Auth key={currentForm} currentForm={currentForm} onSubmit={handleSubmit} />
<StyledToggleButton color="black" variant="transparent" type="button" onClick={toggleCurrentForm}>
{TOGGLE_MESSAGE[currentForm]}
</StyledToggleButton>
</StyledAuthContainer>
</Dialog>
);
};
5 changes: 4 additions & 1 deletion src/components/Auth/Auth.types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export type Form = 'signin' | 'signup';

export interface SignInFormValues {
password: string;
email: string;
Expand All @@ -16,7 +18,7 @@ export interface FormProps {
initialPasswordConfirm?: string;
initialUsername?: string;
currentForm: 'signin' | 'signup';
onSubmit: (values: {}) => void;
onSubmit: (values: FormValues) => void;
}

export interface StyledInputProps {
Expand All @@ -26,4 +28,5 @@ export interface StyledInputProps {

export interface AuthContainerProps {
onClose: () => void;
onSignIn: () => void;
}
6 changes: 0 additions & 6 deletions src/components/Dialog/Dialog.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ComponentMeta, ComponentStory } from '@storybook/react';
import { AuthContainer } from 'components';
import { Dialog } from './Dialog';

export default {
Expand All @@ -16,11 +15,6 @@ export default {
const Template: ComponentStory<typeof Dialog> = (args) => <Dialog {...args} />;

export const DefaultDialog = Template.bind({});

export const AuthDialog = Template.bind({});

AuthDialog.args = { ...DefaultDialog.args, children: <AuthContainer currentForm="signup" /> };

export const LongDialog = Template.bind({});
LongDialog.args = {
...DefaultDialog.args,
Expand Down
16 changes: 8 additions & 8 deletions src/components/Dialog/Dialog.styled.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import styled from '@emotion/styled';
import { IconButton } from 'components';
import { media } from 'utils';
import { media, pxToRem } from 'utils';

export const StyledDialogContainer = styled.div`
z-index: 200;
position: absolute;
position: fixed;
top: 50vh;
left: 50%;
${media.desktop} {
width: 60vw;
width: ${pxToRem(400)};
}
${media.mobile} {
width: 90vw;
width: ${pxToRem(300)};
}
min-height: 50vh;
max-height: 80vh;
transform: translate(-50%, -50%);
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
background-color: rgb(255, 255, 255);
`;

export const StyledDialogContent = styled.div`
Expand All @@ -28,22 +28,22 @@ export const StyledDialogContent = styled.div`

export const StyledCloseButton = styled(IconButton)`
cursor: pointer;
position: absolute;
position: fixed;
z-index: 200;
top: 5px;
right: 5px;
border: 0;
padding: 5px;
background: transparent;
color: #fefefe;
color: ${({theme}) => theme.color.gray400};
svg {
pointer-events: none;
fill: currentColor;
}
`;

export const StyledDim = styled.div`
position: absolute;
position: fixed;
z-index: 100;
top: 0;
left: 0;
Expand Down
8 changes: 4 additions & 4 deletions src/components/Dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function Dialog({ onClose, children, nodeId = 'dialog', label, ...restPro
const lastTabbableElement = tabbableElements[tabbableElements.length - 1];

firstTabbableElement.focus();
let eventType = 'keydown';
const eventType = 'keydown';

const eventListener = (e: KeyboardEvent) => {
const { key, shiftKey, target } = e;
Expand Down Expand Up @@ -69,11 +69,11 @@ export function Dialog({ onClose, children, nodeId = 'dialog', label, ...restPro
variant="transparent"
color="white"
size="large"
onClick={onClose}
onClick={handleClose}
/>
</StyledDialogContainer>
<StyledDim role="presentation" onClick={onClose} />
<StyledDim role="presentation" onClick={handleClose} />
</>,
document.getElementById(nodeId),
document.getElementById(nodeId)!,
);
}
17 changes: 11 additions & 6 deletions src/components/ErrorBoundary/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import React from 'react';
import Link from 'next/link';
import { Heading, Header, EmptyPage } from '..';
import { ErrorBoundaryProps, ErrorBoundaryState } from './ErrorBoundary.types';
import Link from 'next/link';

export class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
public state: ErrorBoundaryState = {
hasError: false,
};
constructor(props: ErrorBoundaryProps) {
super(props);
this.state = {
hasError: false,
};
}

public componentDidCatch(error: Error) {
this.setState({
Expand All @@ -18,7 +21,8 @@ export class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoun
}

public render() {
if (this.state.hasError) {
const { hasError } = this.state;
if (hasError) {
return (
<>
<Header />
Expand All @@ -31,6 +35,7 @@ export class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoun
</>
);
}
return this.props.children;
const { children } = this.props;
return children;
}
}
2 changes: 1 addition & 1 deletion src/components/ErrorBoundary/ErrorBoundary.types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

export interface ErrorBoundaryProps extends WithRouterProps {
export interface ErrorBoundaryProps {
children?: React.ReactNode;
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/Header/Header.styled.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import styled from '@emotion/styled';
import { IconButton } from 'components';
import { StyledHeaderProps } from './Header.types';
import { HEADER_HEIGHT } from 'styles/GlobalStyle';
import { pxToRem } from 'utils';
import { StyledHeaderProps } from './Header.types';

export const StyledHeader = styled.header<StyledHeaderProps>`
background-color: ${({ theme }) => theme.color.white};
Expand Down
30 changes: 16 additions & 14 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { SearchForm, Menu, Button, Logo, AuthContainer, Dialog } from 'components';
import { useState, useEffect, useRef } from 'react';
import lodash from 'lodash';
import { AuthContainer, Button, Logo, Menu, SearchForm, Toast } from 'components';
import { useToast } from 'hooks';
import _ from 'lodash';
import { useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { StyledHeader, StyledDiv, StyledIconButton, headerHeight } from './Header.styled';
import { useSelector } from 'react-redux';
import { RootState } from 'store';
import { AuthState } from 'store/slices/auth';
import { HEADER_HEIGHT } from 'styles/GlobalStyle';
import { StyledDiv, StyledHeader, StyledIconButton } from './Header.styled';

export const Header = (): JSX.Element => {
const [showDialog, setShowDialog] = useState(false);
const { showToast: showSignInToast, displayToast: displaySignInToast } = useToast(2000);
const { showToast: showSignOutToast, displayToast: displaySignOutToast } = useToast(2000);
const [hideHeader, setHideHeader] = useState(false);
const [showScrollToTop, setShowScrollToTop] = useState(false);
const oldScrollTop = useRef(0);
Expand All @@ -27,16 +31,16 @@ export const Header = (): JSX.Element => {
};

const handleBlur = () => {
setHideHeader(window.pageYOffset > headerHeight);
setHideHeader(window.pageYOffset > HEADER_HEIGHT);
};

const controlHeader = lodash.throttle(() => {
const controlHeader = _.throttle(() => {
const currentScrollTop = window.pageYOffset;
setHideHeader(currentScrollTop > headerHeight && currentScrollTop > oldScrollTop.current);
setHideHeader(currentScrollTop > HEADER_HEIGHT && currentScrollTop > oldScrollTop.current);
oldScrollTop.current = currentScrollTop;
}, 300);

const controlScrollToTop = lodash.debounce(() => {
const controlScrollToTop = _.debounce(() => {
const currentScrollTop = window.pageYOffset;
setShowScrollToTop(currentScrollTop > 500);
}, 300);
Expand All @@ -56,7 +60,7 @@ export const Header = (): JSX.Element => {
<Logo />
<SearchForm />
{authUser ? (
<Menu />
<Menu onSignOut={displaySignOutToast} />
) : (
<>
<Button
Expand All @@ -70,11 +74,7 @@ export const Header = (): JSX.Element => {
>
Sign In
</Button>
{showDialog && (
<Dialog label="login" onClose={handleCloseDialog}>
<AuthContainer onClose={handleCloseDialog}/>
</Dialog>
)}
{showDialog && <AuthContainer onClose={handleCloseDialog} onSignIn={displaySignInToast} />}
</>
)}
{showScrollToTop &&
Expand All @@ -97,6 +97,8 @@ export const Header = (): JSX.Element => {
/>,
document.getElementById('__next')!,
)}
{showSignInToast && <Toast message="Signed in successfully!" />}
{showSignOutToast && <Toast message="Signed out" />}
</StyledDiv>
</StyledHeader>
);
Expand Down
Loading