Skip to content

Commit

Permalink
Merge pull request #129 from boostcamp-2020/dev
Browse files Browse the repository at this point in the history
Dev -> master 배포
  • Loading branch information
rnjshippo authored Dec 16, 2020
2 parents 6ef3fc6 + c7febc5 commit 1d5be62
Show file tree
Hide file tree
Showing 28 changed files with 454 additions and 77 deletions.
16 changes: 11 additions & 5 deletions client/package-lock.json

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

1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"react": "^17.0.1",
"react-custom-scroll": "^4.2.1",
"react-dom": "^17.0.1",
"react-google-login": "^5.1.25",
"react-redux": "^7.2.2",
"react-router-dom": "^5.2.0",
"redux": "^4.0.5",
Expand Down
3 changes: 2 additions & 1 deletion client/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ instance.interceptors.response.use(
console.log('요청 취소', err);
} else {
if (err.response.status === 401) {
if (err.response.config.url !== '/api/auth/login') {
const { url } = err.response.config;
if (url !== '/api/auth/login' || url !== '/api/oauth/google/signup') {
window.location.href = '/login';
}
}
Expand Down
93 changes: 89 additions & 4 deletions client/src/components/LoginBox/LoginBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ import { useDispatch } from 'react-redux';
import { darken } from 'polished';
import { Link } from 'react-router-dom';
import isEmail from 'validator/es/lib/isEmail';
import { loginRequest } from '@/store/modules/auth.slice';
import { loginRequest, loginSuccess } from '@/store/modules/auth.slice';
import { FormButton, FormInput as Input, FormLabel as Label } from '@/styles/shared/form';
import { WarningIcon } from '@/components';
import { WarningIcon, GoogleLogoIcon } from '@/components';
import { IconBox, WarningText } from '@/components/EmailBox/EmailBox';
import { flex } from '@/styles/mixin';
import { useAuthState } from '@/hooks';
import LoadingSvg from '@/public/icon/loading.svg';
import { GoogleLogin } from 'react-google-login';
import config from '@/config';
import { authService } from '@/services';

const Container = styled.div`
width: 100%;
height: 100%;
${flex('center', 'flex-start', 'column')};
`;

const Title = styled.div`
Expand All @@ -25,9 +29,15 @@ const Title = styled.div`
color: #453841;
`;

const DescText = styled.div`
color: ${(props) => props.theme.color.black4};
font-size: 1rem;
margin-bottom: 2rem;
`;

const Form = styled.form`
width: 25rem;
margin: 1.5rem auto;
margin: 0 auto 1.5rem auto;
`;

const SignupButton = styled(FormButton)`
Expand Down Expand Up @@ -62,6 +72,46 @@ const LoadingButton = styled(FormButton)`
${flex()}
`;

const LineWithText = styled.div`
width: 25rem;
${flex()};
position: relative;
margin: 1rem 0;
`;

const LineText = styled.div`
padding: 0 20px;
padding-bottom: 3px;
margin-top: 0.5rem;
flex-shrink: 0;
font-weight: bold;
font-size: 0.9rem;
color: ${(props) => props.theme.color.black8};
`;

const Line = styled.hr`
border: none;
border-top: 1px solid ${(props) => props.theme.color.lightGray1};
flex: 1;
`;

const GoogleLoginBox = styled.div`
${flex()};
flex-shrink: 0;
border: 2px solid ${(props) => props.theme.color.googleColor};
border-radius: 5px;
width: 25rem;
height: 50px;
cursor: pointer;
`;

const GoogleText = styled.span`
color: ${(props) => props.theme.color.googleColor};
font-weight: 800;
font-size: 1.2rem;
margin-left: 0.8rem;
`;

const LoginBox: React.FC = () => {
const dispatch = useDispatch();

Expand Down Expand Up @@ -91,6 +141,21 @@ const LoginBox: React.FC = () => {
dispatch(loginRequest({ email, pw }));
};

const handleGoogleOAuthSuccess = async (res: any) => {
const { data, status } = await authService.signupWithGoogleOAuth({
accessToken: res.accessToken,
});
const { accessToken, refreshToken, user } = data;
if (status === 200) {
localStorage.setItem('accessToken', accessToken);
localStorage.setItem('refreshToken', refreshToken);
localStorage.setItem('userId', user.id);
dispatch(
loginSuccess({ accessToken, refreshToken, userId: user.id ? Number(user.id) : null }),
);
}
};

useEffect(() => {
if (loginState.err?.response?.status === 401) {
setLoginFailed(true);
Expand All @@ -99,8 +164,28 @@ const LoginBox: React.FC = () => {

return (
<Container>
<Title>로그인</Title>
<DescText>로그인하려면 사용하는 Google 계정이나 이메일 주소로 계속해 주세요.</DescText>
<GoogleLogin
clientId={config.GOOGLE_CLIENT_ID}
buttonText="Google로 계속"
render={(renderProps) => (
<GoogleLoginBox onClick={renderProps.onClick}>
<GoogleLogoIcon size="18px" />
<GoogleText>Google로 계속</GoogleText>
</GoogleLoginBox>
)}
onSuccess={handleGoogleOAuthSuccess}
onFailure={(res: any) => {
alert('로그인 실패');
}}
/>
<LineWithText>
<Line />
<LineText>또는</LineText>
<Line />
</LineWithText>
<Form onSubmit={handleSubmit}>
<Title>로그인</Title>
<Label>
이메일 주소
<Input
Expand Down
6 changes: 6 additions & 0 deletions client/src/components/common/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useAuthState, useUserState } from '@/hooks';
import { logoutRequest } from '@/store/modules/auth.slice';
import { DimModal, UserStateIcon, ClockIcon, Popover } from '@/components';
import theme from '@/styles/theme';
import { useHistory } from 'react-router-dom';
import { UserProfileModalHeader, UserProfileModalBody } from './UserProfileBox';

const Container = styled.div`
Expand Down Expand Up @@ -126,6 +127,7 @@ const TitleClockIcon = styled.div`
const Header: React.FC = () => {
const dispatch = useDispatch();

const history = useHistory();
const { userId } = useAuthState();
const { userInfo } = useUserState();

Expand All @@ -144,7 +146,11 @@ const Header: React.FC = () => {
useEffect(() => {
if (userId) {
dispatch(getUserRequest({ userId: Number(userId) }));
return;
}
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
history.push('/login');
}, [dispatch, userId]);

const workspaceName = '부스트캠프 2020 멤버십';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React, { PropsWithChildren } from 'react';

const GoogleLogoIcon = ({ size }: PropsWithChildren<{ size?: string }>) => {
return (
<svg width={size ?? '16px'} height={size ?? '16px'} viewBox="0 0 48 48">
<g>
<path
fill="#EA4335"
d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"
/>
<path
fill="#4285F4"
d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"
/>
<path
fill="#FBBC05"
d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"
/>
<path
fill="#34A853"
d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"
/>
<path fill="none" d="M0 0h48v48H0z" />
</g>
</svg>
);
};

export default GoogleLogoIcon;
1 change: 1 addition & 0 deletions client/src/components/common/Icon/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ export { default as CommentIcon } from './CommentIcon/CommentIcon';
export { default as PaperPlaneIcon } from './PaperPlaneIcon/PaperPlaneIcon';
export { default as RightIcon } from './RightIcon/RightIcon';
export { default as RightArrowLineIcon } from './RightArrowLineIcon/RightArrowLineIcon';
export { default as GoogleLogoIcon } from './GoogleLogoIcon/GoogleLogoIcon';
4 changes: 2 additions & 2 deletions client/src/components/common/LogoBox/LogoBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const Container = styled.div`
width: 100%;
height: 5rem;
${flex()};
margin-top: 3rem;
margin-top: 2rem;
user-select: none;
`;

Expand All @@ -20,7 +20,7 @@ const SlackLogo = styled.img`
const LogoBox: React.FC = () => {
return (
<Container>
<Link to="/">
<Link to="/login">
<SlackLogo src={slackLogo} />
</Link>
</Container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,16 @@ const ThreadPopup: React.FC<ThreadPopupProps> = ({
const reactionBoxRef = useRef<HTMLDivElement>(null);

const clickDeleteMessage = () => {
dispatch(
sendMessageRequest({
type: SOCKET_MESSAGE_TYPE.THREAD,
room: current?.name as string,
subType: THREAD_SUBTYPE.DELETE_THREAD,
thread,
}),
);
if (confirm('해당 스레드를 삭제 하시겠습니까?')) {
dispatch(
sendMessageRequest({
type: SOCKET_MESSAGE_TYPE.THREAD,
room: current?.name as string,
subType: THREAD_SUBTYPE.DELETE_THREAD,
thread,
}),
);
}
};

return (
Expand Down
1 change: 1 addition & 0 deletions client/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const config = {
jwtSecret: process.env.JWT_SECRET as string,
jwtRefreshSecret: process.env.JWT_REFRESH_SECRET as string,
GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID as string,
};

export default config;
8 changes: 0 additions & 8 deletions client/src/hooks/useChannelState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import { RootState } from '@/store/modules';
const selectChannelState = (state: RootState) => state.channel;
const selectChannel = createSelector(selectChannelState, (channels) => channels);

const selectChannelListState = (state: RootState) => state.channel.channelList;
const selectChannelList = (idx: number) =>
createSelector(selectChannelListState, (channelList) => channelList[idx]);

const selectJoinChannelListState = (state: RootState) => state.channel.myChannelList;
const selectJoinChannelList = (idx: number) =>
createSelector(selectJoinChannelListState, (joinChannelList) => joinChannelList[idx]);
Expand All @@ -17,10 +13,6 @@ export const useChannelState = () => {
return useSelector(selectChannel);
};

export const useChannelList = (idx: number) => {
return useSelector(selectChannelList(idx));
};

export const useJoinChannelListState = (idx: number) => {
return useSelector(selectJoinChannelList(idx));
};
15 changes: 7 additions & 8 deletions client/src/pages/LoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ import { useAuthState } from '@/hooks';

const LoginPage: React.FC = () => {
const { accessToken } = useAuthState();

if (accessToken) {
return <Redirect to="/" />;
}

return (
<>
{accessToken ? (
<Redirect to="/" />
) : (
<>
<LogoBox />
<LoginBox />
</>
)}
<LogoBox />
<LoginBox />
</>
);
};
Expand Down
4 changes: 4 additions & 0 deletions client/src/services/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import API from '@/api';
import { Service } from '@/types';
import axios from 'axios';

interface LoginParam {
email: string;
Expand Down Expand Up @@ -29,4 +30,7 @@ export const authService: Service = {
checkExistEmail({ email }: { email: string }) {
return API.post('/api/auth/email/check', { email });
},
signupWithGoogleOAuth({ accessToken }: { accessToken: string }) {
return axios.post('/api/oauth/google/signup', { accessToken });
},
};
Loading

0 comments on commit 1d5be62

Please sign in to comment.