Skip to content

Commit

Permalink
[공통] v1.1.0 배포
Browse files Browse the repository at this point in the history
[공통] v1.1.0 배포
  • Loading branch information
sihyung92 authored Oct 29, 2021
2 parents 909aad1 + 78a9771 commit 0b032d1
Show file tree
Hide file tree
Showing 18 changed files with 247 additions and 9 deletions.
2 changes: 1 addition & 1 deletion admin/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jujeol-admin",
"version": "1.0.0",
"version": "1.1.0",
"description": "jujeol-admin",
"main": "index.js",
"author": "",
Expand Down
2 changes: 1 addition & 1 deletion backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ ext {
}

group = 'com.jujeol.'
version = '1.0.0'
version = '1.1.0'
sourceCompatibility = '11'

configurations {
Expand Down
8 changes: 6 additions & 2 deletions backend/src/docs/asciidoc/error.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
|코드|타입|메세지
|0001|NOT_FOUND_ERROR_CODE|"발생한 에러의 에러코드를 찾을 수 없습니다."
|0002|NOT_FOUND_API|"해당 경로에 대한 응답 API를 찾을 수 없습니다."
|1001|NOT_ADULT_EXCEPTION|"만 18세 미만 가입 불가합니다."
|1002|KAKAO_ACCESS|"카카오 로그인 서버에 접근 중 예외가 발생했습니다."
|1003|INVALID_TOKEN|"access token이 유효하지 않습니다."
|1004|NO_SUCH_MEMBER|"해당 id의 유저가 없습니다."
Expand All @@ -27,6 +26,11 @@
|2007|CREATE_REVIEW_LIMIT|"동일 상품에 대한 리뷰는 하루에 하나만 작성할 수 있습니다."
|2008|INVALID_CONTENT_LENGTH|"리뷰는 빈 공백이거나 300자를 넘을 수 없습니다."
|2009|NOT_EXIST_CATEGORY|"해당 카테고리가 존재하지 않습니다."
|2010|NOT_EXIST_PREFERENCE|"해당 선호도가 존재하지 않습니다."
|2011|NOT_FOUND_VIEW_COUNT|"해당 주류에 대한 조회수를 찾을 수 없습니다."
|2012|CREATE_REVIEW_NO_PREFERENCE|"리뷰를 생성하려면 선호도를 입력해야합니다."
|2013|INVALID_DESCRIPTION|"유효하지 않은 상세설명입니다."
|2014|INVALID_SORT_BY|"유효하지 않은 정렬 기준입니다."
|2015|IMAGE_RESIZE|"이미지를 리사이징 하는 도중 오류가 발생했습니다."
|2016|IMAGE_IO|"이미지 파일을 다루는 과정에서 오류가 발생했습니다."
|2017|AMAZON_CLIENT_EXCEPTION|"아마존 서버에 업로드하는 과정에서 오류가 발생했습니다."
|===
3 changes: 3 additions & 0 deletions frontend/config.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
declare module 'dotenv';
declare module 'jujeol';

interface Window {
Kakao: any;
}
declare module '*.svg' {
const content: string;
export default content;
Expand Down
3 changes: 3 additions & 0 deletions frontend/env/.env.development
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ SNOWPACK_PUBLIC_LOGIN_REDIRECT_URL=https://dev.jujeol-jujeol.com/oauth
SNOWPACK_PUBLIC_API_URL=https://jujeol.kro.kr
SNOWPACK_PUBLIC_KAKAO_CLIENT_ID=838bcd43c3b007b4ef38c3da555c4806
SNOWPACK_PUBLIC_ENV=DEV
SNOWPACK_PUBLIC_HOST_URL=https://dev.jujeol-jujeol.com
SNOWPACK_PUBLIC_KAKAO_JS_KEY=67ab5f05c77a95d99a10ebba0f22abfb
SNOWPACK_PUBLIC_KAKAO_SHARE_TEMPLATE_ID=64335
3 changes: 3 additions & 0 deletions frontend/env/.env.local
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ SNOWPACK_PUBLIC_LOGIN_REDIRECT_URL=http://localhost:3000/oauth
SNOWPACK_PUBLIC_API_URL=http://localhost:8080
SNOWPACK_PUBLIC_KAKAO_CLIENT_ID=838bcd43c3b007b4ef38c3da555c4806
SNOWPACK_PUBLIC_ENV=LOCAL
SNOWPACK_PUBLIC_HOST_URL=http://localhost:3000
SNOWPACK_PUBLIC_KAKAO_JS_KEY=67ab5f05c77a95d99a10ebba0f22abfb
SNOWPACK_PUBLIC_KAKAO_SHARE_TEMPLATE_ID=64336
3 changes: 3 additions & 0 deletions frontend/env/.env.prod
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ SNOWPACK_PUBLIC_API_URL=https://api.jujeol-jujeol.com
SNOWPACK_PUBLIC_KAKAO_CLIENT_ID=838bcd43c3b007b4ef38c3da555c4806
SNOWPACK_PUBLIC_ENV=PROD
SNOWPACK_PUBLIC_SENTRY_DSN=https://[email protected]/5903219
SNOWPACK_PUBLIC_HOST_URL=https://jujeol-jujeol.com
SNOWPACK_PUBLIC_KAKAO_JS_KEY=67ab5f05c77a95d99a10ebba0f22abfb
SNOWPACK_PUBLIC_KAKAO_SHARE_TEMPLATE_ID=59769
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jujeol-jujeol-frontend",
"version": "1.0.0",
"version": "1.1.0",
"description": "jujeol-jujeol-frontend",
"main": "index.js",
"scripts": {
Expand Down
1 change: 1 addition & 0 deletions frontend/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
<div id="snackbar"></div>

<script type="module" src="%PUBLIC_URL%/dist/index.js"></script>
<script src="https://developers.kakao.com/sdk/js/kakao.js"></script>
</body>

</html>
28 changes: 28 additions & 0 deletions frontend/src/components/@Icons/LinkIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { COLOR } from 'src/constants';

const LinkIcon = ({ width = '32px', height = '32px', color = COLOR.WHITE }: IconProps) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 27.65 27.82"
width={width}
height={height}
fill={color}
>
<path
className="cls-1"
d="M9.2,19.82a1.51,1.51,0,0,1-1.06-.44,1.49,1.49,0,0,1,0-2.12l8.78-8.78A1.5,1.5,0,1,1,19,10.6l-8.78,8.78A1.51,1.51,0,0,1,9.2,19.82Z"
/>
<path
className="cls-1"
d="M7.84,27.82A7.84,7.84,0,0,1,2.29,14.44L6,10.77a1.49,1.49,0,0,1,2.12,0,1.51,1.51,0,0,1,0,2.12L4.41,16.56a4.84,4.84,0,0,0,6.85,6.85l4-4a1.51,1.51,0,0,1,2.12,0,1.49,1.49,0,0,1,0,2.12l-4,4A7.82,7.82,0,0,1,7.84,27.82Z"
/>
<path
className="cls-1"
d="M20.62,17.5a1.5,1.5,0,0,1-1.06-2.56l3.67-3.68a4.84,4.84,0,0,0-6.85-6.84l-4,4A1.5,1.5,0,0,1,10.26,6.3l4-4a7.85,7.85,0,0,1,11.09,11.1l-3.67,3.67A1.51,1.51,0,0,1,20.62,17.5Z"
/>
</svg>
);
};

export default LinkIcon;
1 change: 1 addition & 0 deletions frontend/src/components/@Icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export { default as ExcitedEmojiIcon } from './ExcitedEmojiIcon';
export { default as HomeIcon } from './HomeIcon';
export { default as HumanIcon } from './HumanIcon';
export { default as KakaoIcon } from './KakaoIcon';
export { default as LinkIcon } from './LinkIcon';
export { default as LoginIcon } from './LoginIcon';
export { default as LoveEmojiColorIcon } from './LoveEmojiColorIcon';
export { default as LoveEmojiIcon } from './LoveEmojiIcon';
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/components/Header/MainHeader.styles.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import styled from '@emotion/styled';

import Flex from 'src/styles/Flex';
import Heading from '../@shared/Heading/Heading';

const envContent =
process.env.SNOWPACK_PUBLIC_ENV === 'PROD' ? '' : process.env.SNOWPACK_PUBLIC_ENV?.toLowerCase();

const Logo = styled(Heading.level1)`
position: relative;
${Flex({ flexDirection: 'column', justifyContent: 'center', alignItems: 'center' })}
:after {
content: '${envContent}';
Expand Down
25 changes: 25 additions & 0 deletions frontend/src/components/ShareLinks/CopyLinkButton.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import styled from '@emotion/styled';
import { SerializedStyles } from '@emotion/utils';

import { COLOR } from 'src/constants';
import Flex from 'src/styles/Flex';

export const Container = styled.div<{ css: SerializedStyles }>`
${Flex({ flexDirection: 'column', justifyContent: 'center', alignItems: 'center' })}
font-size: 0.8rem;
color: ${COLOR.BLACK};
> button {
cursor: copy;
}
> input {
// input이 화면에 보이지 않으면 select할 범위를 찾지 못하는 이슈로 인해, 화면 바깥으로 숨김
position: fixed;
top: -20rem;
right: -20rem;
}
${({ css }) => css};
`;
66 changes: 66 additions & 0 deletions frontend/src/components/ShareLinks/CopyLinkButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useContext, useRef } from 'react';
import { useLocation } from 'react-router';
import { css as emotionCss } from '@emotion/react';
import { SerializedStyles } from '@emotion/utils';

import { COLOR, MESSAGE } from 'src/constants';
import { LinkIcon } from '../@Icons';
import IconButton from '../@shared/Button/IconButton';
import { SnackbarContext } from '../@shared/Snackbar/SnackbarProvider';
import { Container } from './CopyLinkButton.styles';

const HOST_URL = process.env.SNOWPACK_PUBLIC_HOST_URL;

const CopyLinkButton = ({ css }: { css: SerializedStyles }) => {
const inputRef = useRef<HTMLInputElement>(null);

const location = useLocation();

const targetLink = HOST_URL + location.pathname;

const { setSnackbarMessage } = useContext(SnackbarContext) ?? {};

const copyLink = async () => {
const clipboard = navigator.clipboard;

try {
await clipboard.writeText(targetLink);

setSnackbarMessage?.({ type: 'CONFIRM', message: MESSAGE.COPY_LINK_SUCCESS });
} catch (error) {
try {
// 카카오톡 인앱 브라우저에서 clipboard 미적용으로 인한 지원 하지 않음 에러 발생
inputRef.current?.select();
inputRef.current?.setSelectionRange(0, targetLink.length);

document.execCommand('Copy');
setSnackbarMessage?.({ type: 'CONFIRM', message: MESSAGE.COPY_LINK_SUCCESS });
} catch (error) {
setSnackbarMessage?.({ type: 'ERROR', message: MESSAGE.COPY_LINK_FAILED });
}
}
};

return (
<Container css={css}>
<IconButton
id="copy-url-button"
size="SMALL"
margin="0 0 0.2rem"
css={emotionCss`
padding: 0.6rem;
background-color: ${COLOR.PURPLE_400};
border-radius: 50%;
`}
onClick={copyLink}
>
<LinkIcon />
</IconButton>
<label htmlFor="copy-url-button">URL 복사</label>
<input ref={inputRef} type="text" value={targetLink} readOnly />
</Container>
);
};

export default CopyLinkButton;
78 changes: 78 additions & 0 deletions frontend/src/components/ShareLinks/KaKaoShareButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { useContext, useEffect } from 'react';
import { useLocation } from 'react-router';
import { css as emotionCss } from '@emotion/react';
import { SerializedStyles } from '@emotion/utils';

import { COLOR, MESSAGE } from 'src/constants';
import { KakaoIcon } from '../@Icons';
import IconButton from '../@shared/Button/IconButton';
import { SnackbarContext } from '../@shared/Snackbar/SnackbarProvider';
import { Container } from './CopyLinkButton.styles';

const JS_KEY = process.env.SNOWPACK_PUBLIC_KAKAO_JS_KEY;
const TEMPLATE_ID = Number(process.env.SNOWPACK_PUBLIC_KAKAO_SHARE_TEMPLATE_ID);

const KakaoShareButton = ({
content,
css,
}: {
content: { title: string; description: string; imageUrl: string };
css: SerializedStyles;
}) => {
const location = useLocation();
const kakao = window.Kakao;

const { setSnackbarMessage } = useContext(SnackbarContext) ?? {};

const shareWithKakao = async () => {
if (!kakao) {
setSnackbarMessage?.({
type: 'ERROR',
message: MESSAGE.KAKAO_SHARE_FAILED,
});
return;
}

kakao.Link.sendCustom({
templateId: TEMPLATE_ID,
templateArgs: {
TITLE: content.title,
DESCRIPTION: content.description,
IMAGE_URL: content.imageUrl,
PATH: location.pathname.substring(1),
},
});
};

useEffect(() => {
if (!kakao?.isInitialized()) {
kakao?.init(JS_KEY);
}
}, [kakao]);

return (
<Container css={css}>
<IconButton
id="kakao-share-button"
size="SMALL"
margin="0 0 0.3rem"
css={emotionCss`
padding: 0.6rem;
background-color: ${COLOR.YELLOW_300};
border-radius: 50%;
`}
onClick={shareWithKakao}
>
<KakaoIcon />
</IconButton>
<label htmlFor="kakao-share-button">
카카오톡
<br />
공유하기
</label>
</Container>
);
};

export default KakaoShareButton;
4 changes: 4 additions & 0 deletions frontend/src/constants/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ const MESSAGE = {

EDIT_PROFILE_SUCCESS: '프로필을 수정하였습니다.',

COPY_LINK_SUCCESS: '클립보드에 복사 되었습니다.',
COPY_LINK_FAILED: '링크를 복사하지 못했습니다.',
KAKAO_SHARE_FAILED: '카카오톡 공유하기를 이용할 수 없습니다. 링크 공유를 이용해 주세요.',

SEARCH_INPUT_CANNOT_EMPTY: '공백이 아닌 검색어를 입력해주세요.',
};

Expand Down
17 changes: 17 additions & 0 deletions frontend/src/pages/DrinksDetailPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { confirmContext } from 'src/components/Confirm/ConfirmProvider';
import Property from 'src/components/Property/Property';
import RangeWithIcons from 'src/components/RangeWithIcons/RangeWithIcons';
import Review from 'src/components/Review/Review';
import CopyLinkButton from 'src/components/ShareLinks/CopyLinkButton';
import KakaoShareButton from 'src/components/ShareLinks/KaKaoShareButton';
import DrinksDetailDescriptionSkeleton from 'src/components/Skeleton/DrinksDetailDescriptionSkeleton';
import {
APPLICATION_ERROR_CODE,
Expand Down Expand Up @@ -258,6 +260,21 @@ const DrinksDetailPage = () => {
/>
</ImageWrapper>
)}
<CopyLinkButton
css={css`
position: absolute;
top: 1rem;
right: 1rem;
`}
/>
<KakaoShareButton
content={{ title: name, description: description, imageUrl: imageResponse?.small ?? '' }}
css={css`
position: absolute;
top: 5.4rem;
right: 1rem;
`}
/>

<Section isShowImageFull={isShowImageFull} id="preference">
<PreferenceSection ref={preferenceRef} isBlinked={isBlinked}>
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/pages/DrinksDetailPage/test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ describe('로그인 된 사용자가 상세페이지를 이용한다.', () => {
pageInfo: drinksReviews.pageInfo,
});

const reviewInput = screen.getByRole('textbox');
const reviewInput = screen.getByRole('textbox', { name: '리뷰 작성' });
const submitButton = screen.getByRole('button', { name: '작성 완료' });

fireEvent.change(reviewInput, { target: { value: review } });
Expand All @@ -130,7 +130,7 @@ describe('로그인 된 사용자가 상세페이지를 이용한다.', () => {

const review = 'good12312341234';

const reviewInput = screen.getByRole('textbox');
const reviewInput = screen.getByRole('textbox', { name: '리뷰 작성' });
const submitButton = screen.getByRole('button', { name: '작성 완료' });

fireEvent.change(reviewInput, { target: { value: review } });
Expand All @@ -144,7 +144,7 @@ describe('로그인 된 사용자가 상세페이지를 이용한다.', () => {

it('로그인 된 사용자는 상세페이지에서 리뷰를 수정할 수 있다.', async () => {
const review = 'good12312341234';
const reviewInput = screen.getByRole('textbox');
const reviewInput = screen.getByRole('textbox', { name: '리뷰 작성' });
const submitButton = screen.getByRole('button', { name: '작성 완료' });

fireEvent.change(reviewInput, { target: { value: review } });
Expand Down Expand Up @@ -188,7 +188,7 @@ describe('로그인 된 사용자가 상세페이지를 이용한다.', () => {

it('로그인 된 사용자는 상세페이지에서 리뷰를 삭제할 수 있다.', async () => {
const review = 'good12312341234';
const reviewInput = screen.getByRole('textbox');
const reviewInput = screen.getByRole('textbox', { name: '리뷰 작성' });
const submitButton = screen.getByRole('button', { name: '작성 완료' });

fireEvent.change(reviewInput, { target: { value: review } });
Expand Down

0 comments on commit 0b032d1

Please sign in to comment.