Skip to content

Commit

Permalink
[FEAT] 링크 공유 기능 (#252)
Browse files Browse the repository at this point in the history
  • Loading branch information
jhsung23 authored Oct 23, 2024
1 parent 0a70107 commit 6f5a166
Show file tree
Hide file tree
Showing 17 changed files with 202 additions and 47 deletions.
55 changes: 55 additions & 0 deletions .pnp.cjs

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

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
5 changes: 5 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
<link rel="icon" type="image/svg+xml" href="/icons/jjakkak-logo.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>째깍 - 모두의 일정을 한눈에</title>
<script
src="https://t1.kakaocdn.net/kakao_js_sdk/2.7.2/kakao.min.js"
integrity="sha384-TiCUE00h649CAMonG018J2ujOgDKW/kVWlChEuu4jK2vxfAAD0eZxzCKakxg55G4"
crossorigin="anonymous"
></script>
</head>
<body>
<div id="root"></div>
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"react": "^18.3.1",
"react-dom": "^18.2.0",
"react-error-boundary": "^4.0.13",
"react-helmet-async": "^2.0.5",
"react-router-dom": "^6.24.1",
"upgrade": "^1.1.0"
},
Expand Down
Binary file added public/images/kakao-share-thumbnail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* eslint-disable @typescript-eslint/consistent-type-definitions */
/* eslint-disable @typescript-eslint/no-explicit-any */
interface Window {
Kakao: any;
}
11 changes: 11 additions & 0 deletions src/hooks/useKakaoSdk.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { useEffect } from 'react';

import { ENV } from '@/lib/env';

export const useKakaoSdk = () => {
useEffect(() => {
if (!window.Kakao.isInitialized()) {
window.Kakao.init(ENV.KAKAO_JAVASCRIPT_KEY);
}
}, []);
};
3 changes: 1 addition & 2 deletions src/lib/env.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export const ENV = {
IS_PRODUCTION: import.meta.env.PROD,
API_BASE_URL: `${import.meta.env.VITE_API_BASE_URL}`,
KAKAO_REST_API_KEY: `${import.meta.env.VITE_KAKAO_REST_API_KEY}`,
KAKAO_LOGIN_REDIRECT_URI: `${import.meta.env.VITE_KAKAO_LOGIN_REDIRECT_URI}`,
KAKAO_JAVASCRIPT_KEY: `${import.meta.env.VITE_KAKAO_JAVASCRIPT_KEY}`,
} as const;
19 changes: 11 additions & 8 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { Suspense } from 'react';
import { QueryClientProvider } from '@tanstack/react-query';
import dayjs from 'dayjs';
import ReactDOM from 'react-dom/client';
import { HelmetProvider } from 'react-helmet-async';
import { RouterProvider } from 'react-router-dom';
import 'dayjs/locale/ko';

Expand All @@ -13,12 +14,14 @@ import './index.css';
dayjs.locale('ko');

ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<Suspense>
{/* TODO Suspense fallback */}
<RouterProvider router={router} />
</Suspense>
</QueryClientProvider>
</React.StrictMode>
<HelmetProvider>
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<Suspense>
{/* TODO Suspense fallback */}
<RouterProvider router={router} />
</Suspense>
</QueryClientProvider>
</React.StrictMode>
</HelmetProvider>
);
61 changes: 37 additions & 24 deletions src/pages/MeetingDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Suspense } from 'react';
import { Helmet } from 'react-helmet-async';
import { useParams, useNavigate, Navigate } from 'react-router-dom';

import { FlexBox } from '@/components/common/FlexBox';
Expand All @@ -18,29 +19,41 @@ export const MeetingDetail = () => {
}

return (
<ScheduleLayout>
{/* TODO Suspense fallback */}
<Suspense>
<MeetingInfo uuid={uuid} />
</Suspense>
<Suspense>
<MemberScheduleCard uuid={uuid} onNavigate={navigate} />
</Suspense>
<Suspense>
<MemberList uuid={uuid} />
</Suspense>
{!accessToken && (
<FlexBox padding="14px">
<Body3
regularWeight
color="GY4"
onClick={() => navigate(`/${uuid}/edit`)}
style={{ cursor: 'pointer' }}
>
일정 수정하기
</Body3>
</FlexBox>
)}
</ScheduleLayout>
<>
<Helmet>
<meta property="og:type" content="website" />
<meta property="og:site_name" content="jjakkak" />
<meta property="og:title" content="째깍 모임 링크가 도착했어요!" />
<meta
property="og:description"
content="나의 일정을 입력하고 모두가 가능한 시간을 확인해요."
/>
<meta property="og:image" content="https://ifh.cc/g/38gbOb.jpg" />
</Helmet>
<ScheduleLayout>
{/* TODO Suspense fallback */}
<Suspense>
<MeetingInfo uuid={uuid} />
</Suspense>
<Suspense>
<MemberScheduleCard uuid={uuid} onNavigate={navigate} />
</Suspense>
<Suspense>
<MemberList uuid={uuid} />
</Suspense>
{!accessToken && (
<FlexBox padding="14px">
<Body3
regularWeight
color="GY4"
onClick={() => navigate(`/${uuid}/edit`)}
style={{ cursor: 'pointer' }}
>
일정 수정하기
</Body3>
</FlexBox>
)}
</ScheduleLayout>
</>
);
};
40 changes: 29 additions & 11 deletions src/pages/NewMeetingShare.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import { FlexBox } from '@/components/common/FlexBox';
import { FormLayout } from '@/components/common/FormLayout';
import { Icon } from '@/components/common/Icon';
import { IconButton } from '@/components/common/IconButton';
// import { ENV } from '@/lib/env'; // TODO 주석 해제
import { useKakaoSdk } from '@/hooks/useKakaoSdk';
import { ENV } from '@/lib/env';
import { copyToClipboard } from '@/utils/copy';

export const NewMeetingShare = () => {
useKakaoSdk();
const navigate = useNavigate();
const { state } = useLocation();
const meetingUuid = state?.meetingUuid;
Expand All @@ -18,10 +21,9 @@ export const NewMeetingShare = () => {
return <Navigate to="/" />;
}

// TODO 주석 해제 (@typescript-eslint/no-unused-vars 경고때문에 임시 주석처리)
// const shareUrl = ENV.IS_PRODUCTION
// ? `https://jjakkak.com/${meetingUuid}`
// : `http://localhost:5173/${meetingUuid}`;
const shareUrl = ENV.IS_PRODUCTION
? `https://jjakkak.com/${meetingUuid}`
: `http://localhost:5173/${meetingUuid}`;

return (
<>
Expand All @@ -36,17 +38,13 @@ export const NewMeetingShare = () => {
variant="square"
iconName="kakaotalk1"
label="카카오톡"
onClick={() => {
/* TODO */
}}
onClick={() => window.Kakao.Share.sendDefault(templateForShareMeeting(shareUrl))}
/>
<IconButton
variant="square"
iconName="link"
label="링크 복사"
onClick={() => {
/* TODO */
}}
onClick={() => copyToClipboard(shareUrl)}
/>
</FlexBox>
</FlexBox>
Expand All @@ -72,3 +70,23 @@ const BlankSpace = styled.div`
width: 100%;
height: 52px;
`;

const templateForShareMeeting = (shareUrl: string) => ({
objectType: 'feed',
content: {
title: '째깍 모임 링크가 도착했어요!',
description: '나의 일정을 입력하고 모두가 가능한 시간을 확인해요.',
imageUrl: 'https://ifh.cc/g/vK7L4P.jpg',
link: {
webUrl: shareUrl,
},
},
buttons: [
{
title: '가능한 시간 입력하기',
link: {
webUrl: shareUrl,
},
},
],
});
8 changes: 8 additions & 0 deletions src/utils/copy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const copyToClipboard = async (text: string) => {
try {
await navigator.clipboard.writeText(text);
alert('링크가 복사되었습니다');
} catch (e) {
alert('잠시 후 다시 시도해 주세요');
}
};
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@

"jsxImportSource": "@emotion/react"
},
"include": ["src", "svg.d.ts"],
"include": ["src", "svg.d.ts", "global.d.ts"],
"references": [{ "path": "./tsconfig.node.json" }]
}
Loading

0 comments on commit 6f5a166

Please sign in to comment.