Skip to content

Commit 8d37266

Browse files
authored
Feature/#38 - UT전 수정사항 (#39)
* chore: 사용하지 않는 파일 제거 * feat: 퀴즈 푼 이후 로딩 ui 적용 * refactor: url 상수 적용 * feat: 이미지 다운로드 기능 추가 * fix: 모바일 Toast 중앙 정렬 안되는 이슈 해결
1 parent 9d7730f commit 8d37266

File tree

11 files changed

+117
-56
lines changed

11 files changed

+117
-56
lines changed

apps/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"@vanilla-extract/css": "catalog:",
1515
"@vanilla-extract/recipes": "catalog:",
1616
"es-toolkit": "^1.39.8",
17+
"html2canvas": "^1.4.1",
1718
"react": "catalog:react19",
1819
"react-dom": "catalog:react19",
1920
"react-router-dom": "^7.7.1"

apps/web/src/components/Loading/style.css.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,5 +53,5 @@ export const textOutline = style({
5353
maskPosition: "0% 0px",
5454
WebkitMaskRepeat: "no-repeat",
5555
maskRepeat: "no-repeat",
56-
animation: `${textMaskAnimation} 3s ease-in-out infinite`,
56+
animation: `${textMaskAnimation} 2s ease-in-out infinite`,
5757
});

apps/web/src/components/QuizSubmitButton.tsx

Lines changed: 0 additions & 17 deletions
This file was deleted.

apps/web/src/components/ShareButton.tsx

Lines changed: 0 additions & 14 deletions
This file was deleted.

apps/web/src/constants/urls.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const URLS = {
2+
MAIN: "/",
3+
TEST: "/test",
4+
RESULT: (type: string) => `/result?type=${type}`,
5+
};

apps/web/src/pages/Components/index.tsx

Lines changed: 0 additions & 12 deletions
This file was deleted.

apps/web/src/pages/intro/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
introParticipant,
1212
introTitle,
1313
} from "./style.css";
14+
import { URLS } from "../../constants/urls";
1415

1516
export const IntroPage = () => {
1617
return (
@@ -49,7 +50,7 @@ const IntroContent = () => {
4950
</div>
5051
<div className={introFooter}>
5152
<Text className={introParticipant}>참여자 수 | 435명</Text>
52-
<Button variant="filled" onClick={() => navigate("/test")}>
53+
<Button variant="filled" onClick={() => navigate(URLS.TEST)}>
5354
나는 얼마나 AI를 잘 찾을까?
5455
</Button>
5556
</div>

apps/web/src/pages/result/index.tsx

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { Button, COLOR_VARS, Text, useToast } from "@gotchai/ui";
22
import { useNavigate, useSearchParams } from "react-router-dom";
3+
import { useRef } from "react";
4+
import html2canvas from "html2canvas";
35

46
import { Layout } from "../../components/Layout/Layout";
57
import { ResultCard } from "../../components/ResultCard/ResultCard";
68
import { CardResult } from "../../components/ResultCard/cardConfig";
79
import { container, downloadSection, buttonContainer } from "./style.css";
10+
import { URLS } from "../../constants/urls";
811

912
const getValidResult = (type: string | null): CardResult | null => {
1013
const validTypes = Object.values(CardResult).find((result) =>
@@ -18,30 +21,70 @@ export const ResultPage = () => {
1821
const { showToast } = useToast();
1922
const navigate = useNavigate();
2023
const [searchParams] = useSearchParams();
24+
const resultCardRef = useRef<HTMLDivElement>(null);
2125

2226
const result = getValidResult(searchParams.get("type"));
2327

2428
const handleClickReTry = () => {
25-
navigate("/");
29+
navigate(URLS.TEST);
2630
};
2731

28-
const handleClickDownload = () => {
29-
showToast({
30-
data: {
31-
message: "이미지를 저장했어요.",
32-
},
33-
});
32+
const handleClickDownload = async () => {
33+
if (!resultCardRef.current) return;
34+
35+
try {
36+
const canvas = await html2canvas(resultCardRef.current, {
37+
scale: 2, // 고해상도
38+
useCORS: true, // 외부 이미지 허용
39+
allowTaint: true, // 외부 리소스 허용
40+
backgroundColor: null, // 배경 투명
41+
logging: false, // 로그 비활성화
42+
});
43+
44+
canvas.toBlob(async (blob) => {
45+
if (!blob) {
46+
showToast({
47+
data: {
48+
message: "이미지 변환에 실패했어요.",
49+
},
50+
});
51+
return;
52+
}
53+
54+
try {
55+
// 클립보드에 이미지 저장
56+
const clipboardItem = new ClipboardItem({
57+
"image/png": blob,
58+
});
59+
await navigator.clipboard.write([clipboardItem]);
60+
61+
showToast({
62+
data: {
63+
message: "이미지를 저장했어요.",
64+
},
65+
});
66+
} catch (error) {
67+
console.error("클립보드 저장 실패:", error);
68+
}
69+
}, "image/png");
70+
} catch (error) {
71+
console.error("이미지 변환 실패:", error);
72+
}
3473
};
3574

3675
return (
3776
<Layout>
3877
<div className={container}>
39-
<ResultCard result={result as CardResult} />
78+
<div ref={resultCardRef}>
79+
<ResultCard result={result as CardResult} />
80+
</div>
4081
<div className={downloadSection}>
4182
<Text color={COLOR_VARS.green[600]} size="lg" weight="medium">
4283
앱에서도 계속 퀴즈를 풀어볼까요?
4384
</Text>
44-
<Button variant="filled">1분만에 다운로드하기</Button>
85+
<Button variant="filled" disabled>
86+
1분만에 다운로드하기
87+
</Button>
4588
</div>
4689
<div className={buttonContainer}>
4790
<Button onClick={handleClickReTry}>다시하기</Button>

apps/web/src/pages/test/index.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,19 @@ import { QuizResultModal } from "../../components/QuizResultModal/QuizResultModa
1414
import { useNavigate } from "react-router-dom";
1515
import { CardResult } from "../../components/ResultCard/cardConfig";
1616
import { Layout } from "../../components/Layout/Layout";
17+
import { Loading } from "../../components/Loading/Loading";
18+
import { URLS } from "../../constants/urls";
1719

1820
export const TestPage = () => {
21+
const [isLoading, setIsLoading] = useState(false);
1922
const navigate = useNavigate();
2023

2124
const onTestEnd = (result: CardResult) => {
22-
navigate(`/result?type=${result}`);
25+
setIsLoading(true);
26+
27+
setTimeout(() => {
28+
navigate(URLS.RESULT(result));
29+
}, 4_000);
2330
};
2431

2532
const {
@@ -48,6 +55,14 @@ export const TestPage = () => {
4855
handleNextQuestion();
4956
};
5057

58+
if (isLoading) {
59+
return (
60+
<Layout>
61+
<Loading />
62+
</Layout>
63+
);
64+
}
65+
5166
return (
5267
<Layout hideLogo>
5368
<Chip color="green" className={progressBadge}>

packages/ui/src/components/Toast/style.css.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export const toast = style({
1010
backgroundColor: COLOR_VARS.gray[800],
1111
padding: "16px 20px",
1212
borderRadius: 16,
13-
margin: 0,
13+
margin: "0 auto",
1414

1515
...media.mobile({
1616
borderRadius: 40,

0 commit comments

Comments
 (0)