From 5419f76450cf9a9872665c41dad00bf40a0f3c7c Mon Sep 17 00:00:00 2001 From: j2an777 Date: Mon, 24 Jun 2024 00:01:51 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EA=B3=B5=EC=9C=A0=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 카카오 제외 나머지 구현 완료 --- index.html | 2 + src/App.tsx | 6 + src/components/icon/index.tsx | 34 +++++- .../components/galleryHeader/index.tsx | 18 ++- src/pages/gallery/components/index.ts | 3 +- .../gallery/components/shareModal/index.tsx | 106 ++++++++++++++++++ .../gallery/components/shareModal/styles.ts | 67 +++++++++++ src/pages/gallery/hooks/shareKakao.ts | 80 +++++++++++++ src/vite-env.d.ts | 2 +- 9 files changed, 314 insertions(+), 4 deletions(-) create mode 100644 src/pages/gallery/components/shareModal/index.tsx create mode 100644 src/pages/gallery/components/shareModal/styles.ts create mode 100644 src/pages/gallery/hooks/shareKakao.ts diff --git a/index.html b/index.html index 1481edc..f6f08f5 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,8 @@ D'art + +
diff --git a/src/App.tsx b/src/App.tsx index c0bd0a6..c27dda9 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,6 +3,12 @@ import { Navbar } from '@/components'; import { routes } from './routes'; import ProtectedRoute from './routes/ProtectedRoute'; +declare global { + interface Window { + Kakao: any; + } +} + function App() { return ( diff --git a/src/components/icon/index.tsx b/src/components/icon/index.tsx index ca3c326..b3792bf 100644 --- a/src/components/icon/index.tsx +++ b/src/components/icon/index.tsx @@ -49,7 +49,10 @@ export type IconValues = | 'template2' | 'template3' | 'template4' - | 'watch'; + | 'watch' + | 'share' + | 'kakaoShare' + | 'naver'; interface IconProps { value: IconValues; @@ -851,6 +854,35 @@ const renderIcon = ( ); + case 'share': + return ( + + + + + + ); + case 'kakaoShare': + return ( + + + + + ); + case 'naver': + return ( + + + + + + + + + + + + ); } }; diff --git a/src/pages/gallery/components/galleryHeader/index.tsx b/src/pages/gallery/components/galleryHeader/index.tsx index ea4a502..9a24d00 100644 --- a/src/pages/gallery/components/galleryHeader/index.tsx +++ b/src/pages/gallery/components/galleryHeader/index.tsx @@ -9,19 +9,23 @@ import { postReview } from '@/apis/review'; import useCustomNavigate from '@/hooks/useCustomNavigate'; import { useStore } from 'zustand'; import { memberStore } from '@/stores/member'; +import ShareModal from '../shareModal'; interface GalleryHeaderProps { galleryId: number; galleryNick: string; chatRoomId: number; + title: string; + thumbnail: string; } -const GalleryHeader = ({ galleryId, galleryNick, chatRoomId }: GalleryHeaderProps) => { +const GalleryHeader = ({ galleryId, galleryNick, chatRoomId, title, thumbnail }: GalleryHeaderProps) => { const { open, close } = useStore(alertStore); const openChat = chatStore((state) => state.open); const navigate = useCustomNavigate(); const queryClient = useQueryClient(); const { auth: { nickname }, accessToken } = memberStore(); + const location = window.location.href; const mutation = useMutation({ mutationKey: ['review'], @@ -78,6 +82,17 @@ const GalleryHeader = ({ galleryId, galleryNick, chatRoomId }: GalleryHeaderProp navigate('/'); }, }); + } else if (name === 'share') { + open({ + title: '전시 공유하기', + description: ( + + ), + buttonLabel: '닫기', + onClickButton: () => { + close(); + }, + }) } else { open({ title: '전시관 나가기', @@ -104,6 +119,7 @@ const GalleryHeader = ({ galleryId, galleryNick, chatRoomId }: GalleryHeaderProp strokeColor="white" /> : null} + onHandleToggle('share')} /> onHandleToggle('chat')} /> onHandleToggle('out')} /> diff --git a/src/pages/gallery/components/index.ts b/src/pages/gallery/components/index.ts index 93a9d2d..89a55e0 100644 --- a/src/pages/gallery/components/index.ts +++ b/src/pages/gallery/components/index.ts @@ -1,3 +1,4 @@ export { default as GalleryHeader } from './galleryHeader'; export { default as GalleryRotate } from './galleryTemplate/rotate'; -export { default as ReviewModal} from './reviewModal'; \ No newline at end of file +export { default as ReviewModal } from './reviewModal'; +export { default as ShareModal } from './shareModal'; \ No newline at end of file diff --git a/src/pages/gallery/components/shareModal/index.tsx b/src/pages/gallery/components/shareModal/index.tsx new file mode 100644 index 0000000..df68258 --- /dev/null +++ b/src/pages/gallery/components/shareModal/index.tsx @@ -0,0 +1,106 @@ +import { useState } from 'react'; +import * as S from './styles'; +import { Icon } from '@/components'; +import { + EmailShareButton, + EmailIcon, + FacebookShareButton, + FacebookIcon, + TwitterShareButton, + TwitterIcon, + InstapaperIcon, + InstapaperShareButton, + PinterestShareButton, + PinterestIcon, + LineShareButton, + LineIcon, + LinkedinShareButton, + LinkedinIcon, + WhatsappShareButton, + WhatsappIcon, + TumblrShareButton, + TumblrIcon, + TelegramShareButton, + TelegramIcon +} from 'react-share'; +import shareKakao from '../../hooks/shareKakao'; + +interface ShareModalProps { + location: string; + title: string; + thumbnail: string; +} + +const ShareModal = ({ location, title, thumbnail }: ShareModalProps) => { + const [copy, setCopy] = useState(false); + + const onHandleCopy = () => { + const input = document.querySelector('#share-url') as HTMLInputElement; + input.select(); + document.execCommand('copy'); + setCopy(true); + }; + + const onHandleSocial = (platform: string, location?: string, title?: string) => { + if (platform === 'kakao') { + shareKakao(); + } else if (platform === 'naver') { + window.open("https://share.naver.com/web/shareView?url=" + location + "&title=" + title); + } + }; + + return ( + + + + URL 복사 + + + + + + + onHandleSocial('kakao')} + id="kakao-sharing-btn"> + + + onHandleSocial('naver', location, title)}> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export default ShareModal \ No newline at end of file diff --git a/src/pages/gallery/components/shareModal/styles.ts b/src/pages/gallery/components/shareModal/styles.ts new file mode 100644 index 0000000..9f442cf --- /dev/null +++ b/src/pages/gallery/components/shareModal/styles.ts @@ -0,0 +1,67 @@ +import { buttonSizeMap, buttonTypeMap } from "@/styles/button"; +import { colors } from "@/styles/colorPalette"; +import { LayoutMap } from "@/styles/layout"; +import { typographyMap } from "@/styles/typography"; +import styled from "@emotion/styled"; + +export const Container = styled.div` + ${LayoutMap.displayFlex}; + flex-direction: column; + gap : 30px; + padding : 20px; +`; + +export const UrlBox = styled.div` + width : 400px; + height : 50px; + background-color : ${colors.gray100}; + ${LayoutMap.displayFlex}; + justify-content : center; + gap : 20px; + padding : 10px; + border-radius : 10px; +`; + +export const UrlText = styled.input` + width : 60%; + height: 100%; + background-color : white; + ${LayoutMap.displayFlex}; + padding-left : 5px; + white-space: nowrap; + overflow : hidden; + text-overflow : ellipsis; + cursor: text; + border-radius : 5px; +`; + +export const CopyBtn = styled.button` + width : 55%; + height : 100%; + ${buttonTypeMap.rectangleWhite}; + ${buttonSizeMap.fit}; + ${typographyMap.t7}; + padding : 5px; + transition : all 0.3s ease; + border-radius : 5px; + + &:hover { + ${buttonTypeMap.rectangleGray}; + } +`; + +export const SocialBox = styled.div` + width : 100%; + height : 100px; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(50px, 1fr)); + grid-gap: 10px; + justify-items: center; + align-items: center; + margin-bottom : 10px; +`; + +export const SocialBtn = styled.button` + width : 50px; + height : 50px; +`; diff --git a/src/pages/gallery/hooks/shareKakao.ts b/src/pages/gallery/hooks/shareKakao.ts new file mode 100644 index 0000000..eff513b --- /dev/null +++ b/src/pages/gallery/hooks/shareKakao.ts @@ -0,0 +1,80 @@ + + + +export const shareKakao = () => { + + if (window.Kakao) { + const kakao = window.Kakao; + + if (!kakao.isInitialized()) { + kakao.init('2de91a34726841d2d47e292877371dbd'); + } + + kakao.Share.sendDefault({ + objectType: 'feed', + content: { + title: '안녕하세요', + description: '아메리카노, 빵, 케익', + imageUrl: 'https://mud-kage.kakao.com/dn/NTmhS/btqfEUdFAUf/FjKzkZsnoeE4o19klTOVI1/openlink_640x640s.jpg', + link: { + mobileWebUrl: 'https://developers.kakao.com', + webUrl: 'https://developers.kakao.com', + }, + }, + itemContent: { + profileText: 'Kakao', + profileImageUrl: 'https://mud-kage.kakao.com/dn/Q2iNx/btqgeRgV54P/VLdBs9cvyn8BJXB3o7N8UK/kakaolink40_original.png', + titleImageUrl: 'https://mud-kage.kakao.com/dn/Q2iNx/btqgeRgV54P/VLdBs9cvyn8BJXB3o7N8UK/kakaolink40_original.png', + titleImageText: 'Cheese cake', + titleImageCategory: 'Cake', + items: [ + { + item: 'Cake1', + itemOp: '1000원', + }, + { + item: 'Cake2', + itemOp: '2000원', + }, + { + item: 'Cake3', + itemOp: '3000원', + }, + { + item: 'Cake4', + itemOp: '4000원', + }, + { + item: 'Cake5', + itemOp: '5000원', + }, + ], + sum: '총 결제금액', + sumOp: '15000원', + }, + social: { + likeCount: 10, + commentCount: 20, + sharedCount: 30, + }, + buttons: [ + { + title: '웹으로 이동', + link: { + mobileWebUrl: 'https://developers.kakao.com', + webUrl: 'https://developers.kakao.com', + }, + }, + { + title: '앱으로 이동', + link: { + mobileWebUrl: 'https://developers.kakao.com', + webUrl: 'https://developers.kakao.com', + }, + }, + ], + }); + } +} + +export default shareKakao \ No newline at end of file diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index 11f02fe..151aa68 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -1 +1 @@ -/// +/// \ No newline at end of file