Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
40333fe
conf: 스토리북 테스트를 위해 템플릿에 #__next div 요소 추가
hanana1253 Mar 25, 2022
5de4030
refactor: dom 유틸함수에 브라우저환경을 위한 if 문 추가
hanana1253 Mar 25, 2022
d6386c4
Merge branch 'develop' of https://github.com/TeamCooks/TwoSpoon into …
hanana1253 Mar 25, 2022
5b0d90c
feat: AuthError 메시지 추가, 스타일링 완성
hanana1253 Mar 25, 2022
f288601
chore: Dialog 컴포넌트 스타일링 완성
hanana1253 Mar 25, 2022
b438f76
Merge branch 'feature/dialog' into develop
hanana1253 Mar 25, 2022
821edb8
chore: Auth 컴포넌트에 as prop 추가
hanana1253 Mar 26, 2022
b454cc8
fix: CSS 문자열 오타 수정
hanana1253 Mar 26, 2022
a583b6e
fix: dom 유틸함수에 if 문 수정
hanana1253 Mar 26, 2022
a60f927
fix: Search 요청 로직 수정
hanana1253 Mar 26, 2022
d1c26e3
fix: Header 영역 margin-top 등 스타일링 추가
hanana1253 Mar 26, 2022
89ee8c7
chore: headerHeight를 export로 내보내기
hanana1253 Mar 26, 2022
243164c
feat: Auth 컴포넌트에 dispatch 로직 추가
hanana1253 Mar 26, 2022
710e4da
feat: AuthSlice 작성 및 redux 로직 추가
hanana1253 Mar 26, 2022
935a952
chore: Auth 컴포넌트 key prop 추가& 테스트 스토리 파일 decorator 삭제
hanana1253 Mar 26, 2022
7cd4538
conf: StoreProvider를 스토리북 환경에 추가
hanana1253 Mar 26, 2022
04fb181
feat: Store에서 구독한 Auth 상태에 따른 menu / login 버튼 적용
hanana1253 Mar 26, 2022
883d5df
feat: signout 클릭 시 firebase & store auth 상태 변경 로직 추가
hanana1253 Mar 26, 2022
eeae8bd
chore: 변수명 변경 (data => results) 및 타입 정의
hanana1253 Mar 26, 2022
5ef242d
Merge branch 'feature/search' into develop
hanana1253 Mar 26, 2022
33004bd
fix: CSS 속성 오타 수정
hanana1253 Mar 28, 2022
4576797
chore: Transient prop으로 타입 정의 및 prop 이름 변경
hanana1253 Mar 28, 2022
42767a4
conf: Sentry 연동을 위한 패키지 설치 및 configuration
hanana1253 Mar 29, 2022
7069dad
feat: ErrorBoundary 적용 및 에러 페이지 커스텀, 에러 테스트 페이지 제작
hanana1253 Mar 29, 2022
1b357ab
feat: ErrorBoundary 컴포넌트 및 테스트 코드 작성
hanana1253 Mar 29, 2022
56c21ce
conf: Sentry 패키지 설치로 yarn.lock 파일 변경
hanana1253 Mar 29, 2022
40aa007
Merge branch 'feature/ErrorBoundary' into develop
hanana1253 Mar 29, 2022
b877794
chore: 필요없는 CSS 선택자 삭제
hanana1253 Mar 29, 2022
2557ffa
chore: import 경로를 절대경로로 수정
hanana1253 Mar 29, 2022
62c36aa
fix: Signout 후 모달 창 꺼지지 않는 버그 해결
hanana1253 Mar 29, 2022
9d1f6f0
fix: Auth Slice 기본값 수정 및 type 에러 해결
hanana1253 Mar 29, 2022
641e130
conf: @types/react-dom 패키지 설치
hanana1253 Mar 29, 2022
e50721e
Merge branch 'develop' of https://github.com/TeamCooks/TwoSpoon into …
hanana1253 Mar 29, 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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,6 @@ sketch
firebaseConfig.ts
.firebaserc
firebase.json
.firebase
.firebase
# Sentry
.sentryclirc
1 change: 1 addition & 0 deletions .storybook/preview-body.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<div id="__next"></div>
<div id="loading-start" aria-live="assertive"></div>
<div id="loading-end" aria-live="assertive"></div>
<div id="dialog"></div>
8 changes: 7 additions & 1 deletion next.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/** @type {import('next').NextConfig} */
const { withSentryConfig } = require('@sentry/nextjs');

const nextConfig = {
reactStrictMode: true,
webpack(config) {
Expand All @@ -12,4 +14,8 @@ const nextConfig = {
},
};

module.exports = nextConfig;
const sentryWebpackPluginOptions = {
silent: true,
};

module.exports = withSentryConfig(nextConfig, sentryWebpackPluginOptions);
35 changes: 35 additions & 0 deletions next.config.wizardcopy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// This file sets a custom webpack configuration to use your Next.js app
// with Sentry.
// https://nextjs.org/docs/api-reference/next.config.js/introduction
// https://docs.sentry.io/platforms/javascript/guides/nextjs/

const { withSentryConfig } = require('@sentry/nextjs');

const moduleExports = {
reactStrictMode: true,
webpack(config) {
config.module.rules.push({
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
use: ['@svgr/webpack'],
});

return config;
},
};

const sentryWebpackPluginOptions = {
// Additional config options for the Sentry Webpack plugin. Keep in mind that
// the following options are set automatically, and overriding them is not
// recommended:
// release, url, org, project, authToken, configFile, stripPrefix,
// urlPrefix, include, ignore

silent: true, // Suppresses all logs
// For all available options, see:
// https://github.com/getsentry/sentry-webpack-plugin#options.
};

// Make sure adding Sentry options is the last code to run before exporting, to
// ensure that your source maps include changes from all other Webpack plugins
module.exports = withSentryConfig(moduleExports, sentryWebpackPluginOptions);
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@emotion/react": "^11.8.2",
"@emotion/styled": "^11.8.1",
"@reduxjs/toolkit": "^1.8.0",
"@sentry/nextjs": "^6.19.2",
"@svgr/webpack": "^5.5.0",
"@types/react-redux": "^7.1.23",
"@types/yup": "^0.29.13",
Expand Down Expand Up @@ -44,6 +45,7 @@
"@storybook/testing-library": "^0.0.9",
"@types/node": "17.0.21",
"@types/react": "17.0.40",
"@types/react-dom": "^17.0.14",
"@typescript-eslint/eslint-plugin": "^5.15.0",
"@typescript-eslint/parser": "^5.15.0",
"babel-loader": "^8.2.3",
Expand Down
17 changes: 17 additions & 0 deletions sentry.client.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// This file configures the initialization of Sentry on the browser.
// The config you add here will be used whenever a page is visited.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/

import * as Sentry from '@sentry/nextjs';

const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;

Sentry.init({
dsn: SENTRY_DSN || 'https://fc2400a639f64961be0888ef06fb9196@o1128064.ingest.sentry.io/6170372',
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
});
4 changes: 4 additions & 0 deletions sentry.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
defaults.url=https://sentry.io/
defaults.org=teamcooks
defaults.project=teamcooks
cli.executable=../../../.npm/_npx/a8388072043b4cbc/node_modules/@sentry/cli/bin/sentry-cli
17 changes: 17 additions & 0 deletions sentry.server.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// This file configures the initialization of Sentry on the server.
// The config you add here will be used whenever the server handles a request.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/

import * as Sentry from '@sentry/nextjs';

const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;

Sentry.init({
dsn: SENTRY_DSN || 'https://fc2400a639f64961be0888ef06fb9196@o1128064.ingest.sentry.io/6170372',
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1.0,
// ...
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so
// that it will also get attached to your source maps
});
14 changes: 6 additions & 8 deletions src/components/Auth/Auth.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { ComponentMeta, ComponentStory } from '@storybook/react';
import { Auth } from './Auth';
import { StoreProvider } from 'store';
import { AuthContainer } from './Auth';

export default {
title: 'Auth',
component: Auth,
args: { currentForm: 'signin' },
} as ComponentMeta<typeof Auth>;
title: 'AuthContainer',
component: AuthContainer,
} as ComponentMeta<typeof AuthContainer>;

const Template: ComponentStory<typeof Auth> = (args) => <Auth {...args} />;
const Template: ComponentStory<typeof AuthContainer> = () => <AuthContainer />;

export const SignInForm = Template.bind({});
export const SignUpForm = Template.bind({});
SignUpForm.args = { currentForm: 'signup' };
29 changes: 18 additions & 11 deletions src/components/Auth/Auth.styled.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import styled from '@emotion/styled';
import { pxToRem } from 'utils';
import { StyleInputProps } from './Auth.types';
import { StyledInputProps } from './Auth.types';

export const StyledAuthContainer = styled.div`
padding: 15vh 0 0 0;
> * {
max-width: ${pxToRem(400)};
display: block;
width: 40vw;
min-width: ${pxToRem(300)};
margin: 0 auto;
h1 {
text-align: center;
}
`;

Expand All @@ -19,15 +14,27 @@ export const StyledForm = styled.form`
display: flex;
flex-direction: column;
gap: ${pxToRem(4)};
input,
button {
> * {
display: block;
padding: 0 ${pxToRem(24)};
height: ${pxToRem(36)};
border: none;
border-radius: ${pxToRem(5)} ${pxToRem(5)};
}
`;

export const StyledAuthError = styled.div`
border: 2px solid red;
background-color: rgba(255, 0, 0, 0.4);
border-radius: ${pxToRem(5)};
padding: ${pxToRem(16)} 0;
margin: ${pxToRem(18)} auto;
max-width: ${pxToRem(400)};
min-width: ${pxToRem(280)};
text-align: center;
color: white;
`;

export const StyledFieldError = styled.div`
height: ${pxToRem(32)};
line-height: 1.8;
Expand All @@ -36,7 +43,7 @@ export const StyledFieldError = styled.div`
padding: 0 ${pxToRem(20)};
`;

export const StyledInput = styled.input<StyleInputProps>`
export const StyledInput = styled.input<StyledInputProps>`
padding: 0 ${pxToRem(24)};
height: ${pxToRem(36)};
border: none;
Expand Down
104 changes: 70 additions & 34 deletions src/components/Auth/Auth.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,83 @@
import { FormikProps, withFormik } from 'formik';
import { FormValues, FormProps } from './Auth.types';
import { StyledForm, StyledInput, StyledFieldError, StyledAuthContainer } from './Auth.styled';
import { AUTH_FUNC, SCHEMA, INITIAL_VALUES, FIELDS, HEADING, PLACEHOLDER, TYPE } from './AuthServices';
import { Button } from 'components/Button/Button';
import { FormValues, FormProps, AuthContainerProps } from './Auth.types';
import { StyledForm, StyledInput, StyledAuthError, StyledFieldError, StyledAuthContainer } from './Auth.styled';
import {
AUTH_STATE,
AUTH_FUNC,
SCHEMA,
INITIAL_VALUES,
FIELDS,
HEADING,
PLACEHOLDER,
TYPE,
AUTH_ERROR_MSG,
} 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;

return (
<StyledAuthContainer>
<StyledForm onSubmit={handleSubmit}>
{FIELDS[currentForm].map(
(field): JSX.Element => (
<>
<label className="a11yHidden" htmlFor={field}>
{field.toUpperCase()}
</label>
<StyledInput
id={field}
$warning={touched[field] && errors[field]}
name={field}
placeholder={PLACEHOLDER[field]}
type={TYPE[field]}
onChange={handleChange}
onBlur={handleBlur}
value={values[field] || ''}
/>
<StyledFieldError>{touched[field] && errors[field]}</StyledFieldError>
</>
),
)}
<StyledForm onSubmit={handleSubmit}>
{FIELDS[currentForm].map(
(field): JSX.Element => (
<Fragment key={field}>
<label className="a11yHidden" htmlFor={field}>
{field.toUpperCase()}
</label>
<StyledInput
id={field}
$warning={touched[field] && errors[field]}
name={field}
placeholder={PLACEHOLDER[field]}
type={TYPE[field]}
onChange={handleChange}
onBlur={handleBlur}
value={values[field] || ''}
/>
<StyledFieldError>{touched[field] && errors[field]}</StyledFieldError>
</Fragment>
),
)}

<Button variant="filled" round={true} color="primaryGreen" type="submit" disabled={!dirty || !isValid}>
{HEADING[currentForm]}
</Button>
</StyledForm>
</StyledAuthContainer>
<Button variant="filled" round={true} color="primaryGreen" type="submit" disabled={!dirty || !isValid}>
{HEADING[currentForm]}
</Button>
</StyledForm>
);
};

export const Auth = withFormik<FormProps, FormValues>({
const Auth = withFormik<FormProps, FormValues>({
mapPropsToValues: ({ currentForm }) => INITIAL_VALUES[currentForm],
validationSchema: ({ currentForm }: FormProps) => SCHEMA[currentForm],
handleSubmit(values: FormValues, { props: { currentForm } }) {
AUTH_FUNC[currentForm](values);
handleSubmit: async (values: FormValues, { props: { onSubmit } }) => {
onSubmit(values);
},
})(AuthForm);

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

const handleSubmit = async (values) => {
try {
dispatch(actions.loading(true));
const { uid: userId } = await AUTH_FUNC[currentForm](values);
dispatch(actions.signIn(userId));
onClose();
} 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>
);
};
8 changes: 7 additions & 1 deletion src/components/Auth/Auth.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@ export interface FormProps {
initialPasswordConfirm?: string;
initialUsername?: string;
currentForm: 'signin' | 'signup';
onSubmit: (values: {}) => void;
}

export interface StyleInputProps {
export interface StyledInputProps {
$warning: boolean;
}


export interface AuthContainerProps {
onClose: () => void;
}
5 changes: 5 additions & 0 deletions src/components/Auth/AuthServices.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { signIn, signUp } from 'api/requestAuth';
import * as Yup from 'yup';

export const AUTH_STATE = {
signin: 'signin',
signup: 'signup',
} as const;

export const TOGGLE_MESSAGE = {
signin: 'Not registered yet? Sign up here!',
signup: 'Already a member? Sign in here!',
Expand Down
Loading