Skip to content

Commit 9618153

Browse files
authored
Merge pull request #42 from Nexters/feat/#32
[ Feat/#32 ] Tarot reading page 기능 및 라우팅 구현 & 바텀시트 공유하기 기능 적용
2 parents c521617 + a6b2504 commit 9618153

File tree

9 files changed

+270
-138
lines changed

9 files changed

+270
-138
lines changed

package-lock.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"@tanstack/react-query": "^5.63.0",
1919
"@tanstack/react-query-devtools": "^5.63.0",
2020
"axios": "^1.7.9",
21+
"ismobilejs": "^1.1.1",
2122
"motion": "^12.0.5",
2223
"next": "14.2.23",
2324
"react": "^18",

src/app/chats/[chatId]/tarot-reading/[resultId]/page.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
"use client";
22

33
import MainContent from "@/shared/components/MainContent";
4-
import TarotInteraction from "./components/TarotInteraction";
5-
import TarotResult from "./components/TarotResult";
4+
import TarotInteraction from "../../../../../tarot/components/TarotInteraction";
5+
import TarotResult from "../../../../../tarot/components/TarotResult";
66
import { useState } from "react";
77
import ChatHeader from "@/chat/components/ChatHeader";
88

@@ -11,18 +11,17 @@ import { useParams } from "next/navigation";
1111
export default function TarotReadingResultPage() {
1212
const { resultId } = useParams();
1313
const [tarotInteractation, setTarotInteractation] = useState(true);
14-
15-
console.log(resultId);
1614
const { data, isLoading } = useTarotReadingResult(Number(resultId));
1715

18-
console.log(data);
19-
2016
return (
2117
<>
2218
{!tarotInteractation && <ChatHeader />}
2319
<MainContent>
2420
{tarotInteractation || isLoading ? (
25-
<TarotInteraction setTarotInteractation={setTarotInteractation} />
21+
<TarotInteraction
22+
setTarotInteractation={setTarotInteractation}
23+
tarotId={data?.tarot}
24+
/>
2625
) : (
2726
<TarotResult />
2827
)}

src/chat/components/ChatHeader.tsx

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,20 @@ import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
77
import { useRouter } from "next/navigation";
88
import { css } from "styled-components";
99
import { useCreateChatRoom } from "../hooks/useCreateChatRoom";
10+
import { checkBrowserForWebShare } from "@/shared/utils/checkBrowserForWebShare";
11+
import shareLink from "@/shared/utils/shareLink";
12+
import Toast from "@/shared/components/Toast";
13+
import { useState } from "react";
1014

1115
export default function ChatHeader() {
1216
const { mutate: createChatRoom } = useCreateChatRoom();
1317
const router = useRouter();
1418

19+
const tarotNyangUrl = window.location.hostname;
20+
21+
const { handleWebShare, handleCopyToClipboard } = shareLink(tarotNyangUrl);
22+
const [toastOpen, setToastOpen] = useState(false);
23+
1524
const handleResetChatClick = () => {
1625
createChatRoom(undefined, {
1726
onSuccess: (data) => {
@@ -20,6 +29,17 @@ export default function ChatHeader() {
2029
});
2130
};
2231

32+
const handleShare = async () => {
33+
if (checkBrowserForWebShare()) {
34+
handleWebShare();
35+
} else {
36+
const shareSuccess = await handleCopyToClipboard();
37+
if (shareSuccess) {
38+
setToastOpen(true);
39+
}
40+
}
41+
};
42+
2343
return (
2444
<HeaderContent
2545
/**
@@ -40,13 +60,17 @@ export default function ChatHeader() {
4060
/>
4161
</button>
4262
</BottomSheet.Trigger>
63+
4364
<BottomSheet.Portal>
4465
<BottomSheet.Overlay />
4566
<BottomSheet.Content>
4667
<VisuallyHidden>
4768
<BottomSheet.Title>메뉴</BottomSheet.Title>
48-
<BottomSheet.Description>외부를 클릭하면 닫힙니다. 원하는 작업을 선택하세요.</BottomSheet.Description>
69+
<BottomSheet.Description>
70+
외부를 클릭하면 닫힙니다. 원하는 작업을 선택하세요.
71+
</BottomSheet.Description>
4972
</VisuallyHidden>
73+
5074
<ul
5175
css={css`
5276
& > li > button {
@@ -60,7 +84,10 @@ export default function ChatHeader() {
6084
>
6185
<li>
6286
{/* TODO: 메뉴 버튼 액션 추가 */}
63-
<button type="button">친구에게 타로냥 알리기</button>
87+
88+
<button type="button" onClick={handleShare}>
89+
친구에게 타로냥 알리기
90+
</button>
6491
</li>
6592
<li>
6693
<button type="button" onClick={handleResetChatClick}>
@@ -80,25 +107,38 @@ export default function ChatHeader() {
80107
gap: 4px;
81108
`}
82109
>
83-
<span
84-
css={css`
85-
${({ theme }) => theme.fonts.subHead3}
86-
color: ${({ theme }) => theme.colors.grey90};
87-
`}
88-
>
89-
타로냥
90-
</span>
91-
<span
92-
css={css`
93-
padding-inline: 8px;
94-
${({ theme }) => theme.fonts.subHead1}
95-
color: ${({ theme }) => theme.colors.primary03};
96-
background-color: ${({ theme }) => theme.colors.primary00};
97-
border-radius: 40px;
98-
`}
99-
>
100-
AI
101-
</span>
110+
<Toast.Provider>
111+
<Toast.Root
112+
open={toastOpen}
113+
onOpenChange={setToastOpen}
114+
duration={3000}
115+
>
116+
<Toast.Title>
117+
링크 복사 완료! 타로냥을 알리고 싶은 친구에게 링크를 전송해
118+
주세요.
119+
</Toast.Title>
120+
</Toast.Root>
121+
<Toast.Viewport />
122+
<span
123+
css={css`
124+
${({ theme }) => theme.fonts.subHead3}
125+
color: ${({ theme }) => theme.colors.grey90};
126+
`}
127+
>
128+
타로냥
129+
</span>
130+
<span
131+
css={css`
132+
padding-inline: 8px;
133+
${({ theme }) => theme.fonts.subHead1}
134+
color: ${({ theme }) => theme.colors.primary03};
135+
background-color: ${({ theme }) => theme.colors.primary00};
136+
border-radius: 40px;
137+
`}
138+
>
139+
AI
140+
</span>
141+
</Toast.Provider>
102142
</h1>
103143
</HeaderContent>
104144
);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import isMobile from "ismobilejs";
2+
3+
export const checkBrowserForWebShare = () => {
4+
const isFirefoxForAndroid = /Android.*Firefor/.test(navigator.userAgent);
5+
6+
const isAndroidWebView = /wv|WebView/.test(navigator.userAgent);
7+
8+
const checkMobile = isMobile().phone;
9+
const checkTablet = isMobile().tablet;
10+
return !(
11+
isFirefoxForAndroid ||
12+
isAndroidWebView ||
13+
!(checkMobile || checkTablet)
14+
);
15+
};

src/shared/utils/shareLink.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
const shareLink = () => {
2-
const inviteURL = window.location.href;
1+
const shareLink = (shareUrl: string) => {
2+
// const inviteURL = window.location.href;
33

4-
console.log(inviteURL);
4+
// console.log(inviteURL);
55
const handleWebShare = async () => {
66
const shareData = {
77
meet: {
8-
title: "타로냥이",
9-
text: "귀여운 타로냥이가 봐주는 타로 보러 보러가기 \n",
10-
url: inviteURL,
8+
title: "타로냥 - 고양이 타로술사 \n",
9+
text: "고양이 타로술사 타로냥이 당신의 질문에 답해주는 AI 타로 서비스입니다. \n",
10+
url: shareUrl,
1111
},
1212
};
1313

@@ -22,14 +22,14 @@ const shareLink = () => {
2222
const handleCopyToClipboard = async () => {
2323
try {
2424
console.log("복사성공");
25-
await navigator.clipboard.writeText(inviteURL);
25+
await navigator.clipboard.writeText(shareUrl);
2626
return true;
2727
} catch {
2828
alert("링크복사에 실패했습니다. \n 다시 시도해주세요.");
2929
return false;
3030
}
3131
};
32-
return { handleWebShare };
32+
return { handleWebShare, handleCopyToClipboard };
3333
};
3434

3535
export default shareLink;
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import * as motion from "motion/react-client";
44
import Image from "next/image";
55
import catHand from "@/shared/assets/images/catHand.png";
66
import cardBack from "@/shared/assets/images/cardBack.webp";
7-
import cardFront from "@/shared/assets/images/Card1.jpg";
87
import styled from "styled-components";
98
import { easeInOut } from "motion";
109
import { SetStateAction, useState, Dispatch } from "react";
10+
import { TarotCardIdType } from "@/tarot/models/tarotCardId";
11+
import findCardById from "@/tarot/utils/findCardById";
1112

1213
type PropTypes = {
1314
setTarotInteractation: Dispatch<SetStateAction<boolean>>;
15+
tarotId: TarotCardIdType | undefined;
1416
};
1517

1618
const putCardtransition = {
@@ -29,7 +31,7 @@ const cardRotateTransition = {
2931
duration: 0.6,
3032
};
3133

32-
const TarotInteraction = ({ setTarotInteractation }: PropTypes) => {
34+
const TarotInteraction = ({ setTarotInteractation, tarotId }: PropTypes) => {
3335
const [isVisible, setIsVisible] = useState(true);
3436

3537
const routingTarotResult = () => {
@@ -38,6 +40,11 @@ const TarotInteraction = ({ setTarotInteractation }: PropTypes) => {
3840
}, 1000);
3941
};
4042

43+
if (!tarotId) {
44+
return null;
45+
}
46+
47+
const card = findCardById(tarotId);
4148
return (
4249
<TarotWaitingWrapper>
4350
<Center>
@@ -56,7 +63,7 @@ const TarotInteraction = ({ setTarotInteractation }: PropTypes) => {
5663
transition={cardRotateTransition}
5764
onAnimationComplete={routingTarotResult}
5865
>
59-
<CardFront alt="카드 앞면" src={cardFront} />
66+
<CardFront alt="카드 앞면" src={card.imgSrc} />
6067
<CardBack alt="카드 뒷면" src={cardBack} />
6168
</CardInner>
6269

0 commit comments

Comments
 (0)