diff --git a/public/assets/img/img-graphic-logo.png b/public/assets/img/img-graphic-logo.png deleted file mode 100644 index a1cefb0..0000000 Binary files a/public/assets/img/img-graphic-logo.png and /dev/null differ diff --git a/public/assets/img/img-graphic-logo.webp b/public/assets/img/img-graphic-logo.webp new file mode 100644 index 0000000..72fbd3d Binary files /dev/null and b/public/assets/img/img-graphic-logo.webp differ diff --git a/public/assets/img/img-style-cute.png b/public/assets/img/img-style-cute.png deleted file mode 100644 index 4df9df2..0000000 Binary files a/public/assets/img/img-style-cute.png and /dev/null differ diff --git a/public/assets/img/img-style-cute.webp b/public/assets/img/img-style-cute.webp new file mode 100644 index 0000000..2b33985 Binary files /dev/null and b/public/assets/img/img-style-cute.webp differ diff --git a/public/assets/img/img-style-friendly.png b/public/assets/img/img-style-friendly.png deleted file mode 100644 index c5d6e1b..0000000 Binary files a/public/assets/img/img-style-friendly.png and /dev/null differ diff --git a/public/assets/img/img-style-friendly.webp b/public/assets/img/img-style-friendly.webp new file mode 100644 index 0000000..ed0b950 Binary files /dev/null and b/public/assets/img/img-style-friendly.webp differ diff --git a/public/assets/img/img-style-trust.png b/public/assets/img/img-style-trust.png deleted file mode 100644 index 5c3afa4..0000000 Binary files a/public/assets/img/img-style-trust.png and /dev/null differ diff --git a/public/assets/img/img-style-trust.webp b/public/assets/img/img-style-trust.webp new file mode 100644 index 0000000..4ba7036 Binary files /dev/null and b/public/assets/img/img-style-trust.webp differ diff --git a/src/components/Home/Home.tsx b/src/components/Home/Home.tsx deleted file mode 100644 index 63e2b28..0000000 --- a/src/components/Home/Home.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { useEffect } from "react"; - -import styles from "@/components/Home/Home.module.scss"; -import { AppBridgeMessageType } from "@/components/provider/AppBridgeProvider/AppBridgeMessage.types"; -import { useAppBridge } from "@/components/provider/AppBridgeProvider/AppBridgeProvider"; -import IconButton from "@/components/ui/IconButton/IconButton"; -import Text from "@/components/ui/Text/Text"; - -import { useRoute } from "@/hooks/common/useRoute"; - -import { useScanDataStore } from "@/store/useScanDataStore"; - -const Home = () => { - const { send } = useAppBridge(); - - const { scanData } = useScanDataStore(); - - const { navigateToReceiptEdit, navigateToRecognitionFail } = useRoute(); - - useEffect(() => { - if (scanData === "error") { - navigateToRecognitionFail(); - } - - if (typeof scanData !== "string" && scanData.parsed && scanData.parsed.length > 0) { - navigateToReceiptEdit(); - } - }, [scanData]); - - return ( -
-
-
- - {`영수증으로\nAI 음식 리뷰 남겨요`} - - - 손쉬운 음식 리뷰 작성 - -
-
- mainLogo -
-
- -
- { - send({ type: AppBridgeMessageType.OPEN_GALLERY, payload: "" }); - - send({ type: AppBridgeMessageType.RECEIVE_SCAN_RESULT, payload: { result: "" } }); - }} - /> - { - send({ type: AppBridgeMessageType.OPEN_CAMERA, payload: "" }); - - send({ type: AppBridgeMessageType.RECEIVE_SCAN_RESULT, payload: { result: "" } }); - }} - /> -
-
- ); -}; - -export default Home; diff --git a/src/components/common/Navbar/Navbar.module.scss b/src/components/Navbar/Navbar.module.scss similarity index 100% rename from src/components/common/Navbar/Navbar.module.scss rename to src/components/Navbar/Navbar.module.scss diff --git a/src/components/common/Navbar/Navbar.stories.tsx b/src/components/Navbar/Navbar.stories.tsx similarity index 95% rename from src/components/common/Navbar/Navbar.stories.tsx rename to src/components/Navbar/Navbar.stories.tsx index 237be71..baad3fb 100644 --- a/src/components/common/Navbar/Navbar.stories.tsx +++ b/src/components/Navbar/Navbar.stories.tsx @@ -1,6 +1,6 @@ import { MemoryRouter } from "react-router-dom"; -import Navbar from "@/components/common/Navbar/Navbar"; +import Navbar from "@/components/Navbar/Navbar"; import Icon from "@/components/ui/Icon/Icon"; import Text from "@/components/ui/Text/Text"; diff --git a/src/components/common/Navbar/Navbar.tsx b/src/components/Navbar/Navbar.tsx similarity index 68% rename from src/components/common/Navbar/Navbar.tsx rename to src/components/Navbar/Navbar.tsx index e7b62fd..3d6f651 100644 --- a/src/components/common/Navbar/Navbar.tsx +++ b/src/components/Navbar/Navbar.tsx @@ -2,14 +2,10 @@ import type { ButtonHTMLAttributes, PropsWithChildren } from "react"; import classNames from "classnames"; -import styles from "@/components/common/Navbar/Navbar.module.scss"; +import styles from "@/components/Navbar/Navbar.module.scss"; -interface NavbarProps extends PropsWithChildren { - className?: string; -} - -const Navbar = ({ children, className }: NavbarProps) => { - return
{children}
; +const Navbar = ({ children }: PropsWithChildren) => { + return
{children}
; }; Navbar.LeftButton = ({ diff --git a/src/components/RecognitionFail/RecognitionFail.tsx b/src/components/RecognitionFail/RecognitionFail.tsx deleted file mode 100644 index 5450b5d..0000000 --- a/src/components/RecognitionFail/RecognitionFail.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { AppBridgeMessageType } from "@/components/provider/AppBridgeProvider/AppBridgeMessage.types"; -import { useAppBridge } from "@/components/provider/AppBridgeProvider/AppBridgeProvider"; -import styles from "@/components/RecognitionFail/RecognitionFail.module.scss"; -import Button from "@/components/ui/Button/Button"; -import Text from "@/components/ui/Text/Text"; - -import { useRoute } from "@/hooks/common/useRoute"; - -const RecognitionFail = () => { - const { send } = useAppBridge(); - - const { navgateToReceiptInput } = useRoute(); - - return ( -
-
- - 영수증 인식에 실패했어요 - - - {`깨끗한 배경에 영수증을 놓고\n전체가 잘 나오도록 촬영해 주세요`} - -
-
- recognitionFailImg -
-
-
-
- ); -}; - -export default RecognitionFail; diff --git a/src/components/SelectStyle/SelectStyle.tsx b/src/components/SelectStyle/SelectStyle.tsx deleted file mode 100644 index 16661eb..0000000 --- a/src/components/SelectStyle/SelectStyle.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import { useState } from "react"; - -import classNames from "classnames"; - -import { AppBridgeMessageType } from "@/components/provider/AppBridgeProvider/AppBridgeMessage.types"; -import { useAppBridge } from "@/components/provider/AppBridgeProvider/AppBridgeProvider"; -import styles from "@/components/SelectStyle/SelectStyle.module.scss"; -import StyleExampleModal from "@/components/SelectStyle/StyleExampleModal"; -import Button from "@/components/ui/Button/Button"; -import Icon from "@/components/ui/Icon/Icon"; -import Text from "@/components/ui/Text/Text"; - -import { useOverlay } from "@/hooks/common/useOverlay"; -import { useRoute } from "@/hooks/common/useRoute"; - -import { useCreateReviewStore } from "@/store/useReviewStore"; - -interface StyleProps { - name: string; - image: string; -} - -const IMG_STYLE_DATA = [ - { name: "친근한 말투", image: "/assets/img/img-style-friendly.png" }, - { name: "믿음직한 말투", image: "/assets/img/img-style-trust.png" }, - { name: "귀여운 말투", image: "/assets/img/img-style-cute.png" }, -]; - -const STYLE_NAME_MAPPING: { [key: string]: string } = { - "친근한 말투": "FRIENDLY", - "믿음직한 말투": "PROFESSIONAL", - "귀여운 말투": "CUTE", -}; - -const SelectStyle = () => { - const { send } = useAppBridge(); - - const { createReviewData, setReviewStyle } = useCreateReviewStore(); - - const { navigateToLoading } = useRoute(); - - const { isOpen, handleClose, handleOpen } = useOverlay(); - - const [selectedStyle, setSelectedStyle] = useState(IMG_STYLE_DATA[0]); - - const { ocrText, hashTag } = createReviewData; - - const handleStyleClick = (style: StyleProps) => { - setSelectedStyle((prevStyle) => (prevStyle.name === style.name ? IMG_STYLE_DATA[0] : style)); - }; - - const handleCreateReview = () => { - const mappedStyle = STYLE_NAME_MAPPING[selectedStyle.name]; - - if (mappedStyle) { - setReviewStyle(mappedStyle); - } - - send({ - type: AppBridgeMessageType.CREATE_REVIEW, - payload: { ocrText, hashTag, reviewStyle: mappedStyle }, - }); - - navigateToLoading(); - }; - - return ( -
-
-
- - 어떤 말투로 작성할까요? - - - 선택지에 따라 리뷰 말투가 달라져요 - -
- -
- -
-
- -
- {`${selectedStyle.name}-img`} -
- -
-
- {IMG_STYLE_DATA.map((style) => ( -
handleStyleClick(style)} - > - - {style.name} - - -
- ))} -
- -
- - -
- ); -}; - -export default SelectStyle; diff --git a/src/components/SelectTag/SelectTag.tsx b/src/components/SelectTag/SelectTag.tsx deleted file mode 100644 index a836bfe..0000000 --- a/src/components/SelectTag/SelectTag.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { useEffect, useState } from "react"; - -import styles from "@/components/SelectTag/SelectTag.module.scss"; -import TagSheet from "@/components/SelectTag/TagSheet/TagSheet"; -import Button from "@/components/ui/Button/Button"; -import Tag from "@/components/ui/Tag/Tag"; -import Text from "@/components/ui/Text/Text"; - -import { useRoute } from "@/hooks/common/useRoute"; - -import { useCreateReviewStore } from "@/store/useReviewStore"; - -const SelectTag = () => { - const { navigateToSelectStyle } = useRoute(); - - const { createReviewData, setHashTag, setTagList } = useCreateReviewStore(); - - const { tagList, hashTag } = createReviewData; - - const [isBottomSheetOpen, setIsBottomSheetOpen] = useState(false); - - useEffect(() => { - setHashTag(hashTag); - }, [hashTag, setHashTag]); - - const handleTagClick = (tag: string) => { - const newSelectedTags = hashTag.includes(tag) - ? hashTag.filter((selectedTag) => selectedTag !== tag) - : [...hashTag, tag]; - - setHashTag(newSelectedTags); - }; - - const handleTagAdd = (newTag: string) => { - setIsBottomSheetOpen(false); - setTagList([...tagList, newTag]); - setHashTag([...hashTag, newTag]); - }; - - const handleSheetClose = () => { - setIsBottomSheetOpen(false); - }; - - const handleNextClick = () => { - navigateToSelectStyle(); - }; - - return ( -
-
-
- - 어떠셨나요? - - - 복수 가능 - -
-
- {tagList.map((tag) => ( - handleTagClick(tag)} - isSelect={hashTag.includes(tag)} - /> - ))} - setIsBottomSheetOpen(true)} /> -
-
- -
-
- - -
- ); -}; - -export default SelectTag; diff --git a/src/components/SelectStyle/StyleExampleModal.module.scss b/src/components/StyleExampleModal/StyleExampleModal.module.scss similarity index 100% rename from src/components/SelectStyle/StyleExampleModal.module.scss rename to src/components/StyleExampleModal/StyleExampleModal.module.scss diff --git a/src/components/SelectStyle/StyleExampleModal.tsx b/src/components/StyleExampleModal/StyleExampleModal.tsx similarity index 95% rename from src/components/SelectStyle/StyleExampleModal.tsx rename to src/components/StyleExampleModal/StyleExampleModal.tsx index 923840b..924afc9 100644 --- a/src/components/SelectStyle/StyleExampleModal.tsx +++ b/src/components/StyleExampleModal/StyleExampleModal.tsx @@ -1,5 +1,5 @@ import type { ModalProps } from "@/components/HomeNavigateConfirmModal/HomeNavigateConfirmModal"; -import styles from "@/components/SelectStyle/StyleExampleModal.module.scss"; +import styles from "@/components/StyleExampleModal/StyleExampleModal.module.scss"; import Icon from "@/components/ui/Icon/Icon"; import Modal from "@/components/ui/Modal/Modal"; import Text from "@/components/ui/Text/Text"; diff --git a/src/components/SelectTag/TagSheet/TagSheet.module.scss b/src/components/TagSheet/TagSheet.module.scss similarity index 100% rename from src/components/SelectTag/TagSheet/TagSheet.module.scss rename to src/components/TagSheet/TagSheet.module.scss diff --git a/src/components/SelectTag/TagSheet/TagSheet.tsx b/src/components/TagSheet/TagSheet.tsx similarity index 98% rename from src/components/SelectTag/TagSheet/TagSheet.tsx rename to src/components/TagSheet/TagSheet.tsx index 973ad40..e843bbb 100644 --- a/src/components/SelectTag/TagSheet/TagSheet.tsx +++ b/src/components/TagSheet/TagSheet.tsx @@ -4,7 +4,7 @@ import * as Dialog from "@radix-ui/react-dialog"; import * as VisuallyHidden from "@radix-ui/react-visually-hidden"; import classNames from "classnames"; -import styles from "@/components/SelectTag/TagSheet/TagSheet.module.scss"; +import styles from "@/components/TagSheet/TagSheet.module.scss"; import Button from "@/components/ui/Button/Button"; import Icon from "@/components/ui/Icon/Icon"; import Input from "@/components/ui/Input/Input"; diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx deleted file mode 100644 index 030b081..0000000 --- a/src/pages/HomePage.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import Navbar from "@/components/common/Navbar/Navbar"; -import Home from "@/components/Home/Home"; -import { AppBridgeMessageType } from "@/components/provider/AppBridgeProvider/AppBridgeMessage.types"; -import { useAppBridge } from "@/components/provider/AppBridgeProvider/AppBridgeProvider"; -import Text from "@/components/ui/Text/Text"; - -const SHARE_TEXT = - "영수증을 촬영하면 AI가 자동으로 맛집 리뷰를 생성! 🍽️✨ 간편하게 추억을 남기고, 나만의 미식 기록을 완성하세요. 미식 경험을 더욱 스마트하게, 미식 MISIK!"; - -const HomePage = () => { - const { send } = useAppBridge(); - - return ( - <> - - - send({ type: AppBridgeMessageType.SHARE, payload: { shareText: SHARE_TEXT } }) - } - > - - 앱 공유하기 - - - - - - - ); -}; - -export default HomePage; diff --git a/src/components/Home/Home.module.scss b/src/pages/HomePage/HomePage.module.scss similarity index 62% rename from src/components/Home/Home.module.scss rename to src/pages/HomePage/HomePage.module.scss index 4870aed..bf2e739 100644 --- a/src/components/Home/Home.module.scss +++ b/src/pages/HomePage/HomePage.module.scss @@ -1,3 +1,5 @@ +@use "@/styles/_mixins.scss" as *; + .Home { padding-left: 1.25rem; padding-right: 1.25rem; @@ -24,6 +26,24 @@ } } +.Title { + @include titleLg; + + line-height: 1.5; + + background-image: linear-gradient(90deg, #7953cd 20%, #d444ba 30%, #b544d4 70%, #764ada 80%); + + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; + text-align: center; + white-space: pre-line; + background-size: 200% auto; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + animation: gradient 3s linear infinite; +} + .HomeTop { z-index: 1; } @@ -33,10 +53,6 @@ display: flex; flex-direction: column; gap: 0.625rem; - - & > h1 { - white-space: pre-line; - } } .HomeImage { @@ -59,3 +75,12 @@ gap: 0.875rem; z-index: 1; } + +@keyframes gradient { + 0% { + background-position: 200% center; + } + 100% { + background-position: 0% center; + } +} diff --git a/src/pages/HomePage/HomePage.tsx b/src/pages/HomePage/HomePage.tsx new file mode 100644 index 0000000..eab62dc --- /dev/null +++ b/src/pages/HomePage/HomePage.tsx @@ -0,0 +1,87 @@ +import { useEffect } from "react"; + +import Navbar from "@/components/Navbar/Navbar"; +import { AppBridgeMessageType } from "@/components/provider/AppBridgeProvider/AppBridgeMessage.types"; +import { useAppBridge } from "@/components/provider/AppBridgeProvider/AppBridgeProvider"; +import IconButton from "@/components/ui/IconButton/IconButton"; +import Text from "@/components/ui/Text/Text"; + +import { useRoute } from "@/hooks/common/useRoute"; + +import styles from "@/pages/HomePage/HomePage.module.scss"; + +import { useScanDataStore } from "@/store/useScanDataStore"; + +const SHARE_TEXT = + "영수증을 촬영하면 AI가 자동으로 맛집 리뷰를 생성! 🍽️✨ 간편하게 추억을 남기고, 나만의 미식 기록을 완성하세요. 미식 경험을 더욱 스마트하게, 미식 MISIK!"; + +const HomePage = () => { + const { send } = useAppBridge(); + + const { scanData } = useScanDataStore(); + + const { navigateToReceiptEdit, navigateToRecognitionFail } = useRoute(); + + useEffect(() => { + if (scanData === "error") { + navigateToRecognitionFail(); + } + + if (typeof scanData !== "string" && scanData.parsed && scanData.parsed.length > 0) { + navigateToReceiptEdit(); + } + }, [scanData]); + + return ( + <> + + + send({ type: AppBridgeMessageType.SHARE, payload: { shareText: SHARE_TEXT } }) + } + > + + 앱 공유하기 + + + + +
+
+
+

{`영수증으로\nAI 음식 리뷰 남겨요`}

+ + 손쉬운 음식 리뷰 작성 + +
+
+ mainLogo +
+
+ +
+ { + send({ type: AppBridgeMessageType.OPEN_GALLERY, payload: "" }); + + send({ type: AppBridgeMessageType.RECEIVE_SCAN_RESULT, payload: { result: "" } }); + }} + /> + { + send({ type: AppBridgeMessageType.OPEN_CAMERA, payload: "" }); + + send({ type: AppBridgeMessageType.RECEIVE_SCAN_RESULT, payload: { result: "" } }); + }} + /> +
+
+ + ); +}; + +export default HomePage; diff --git a/src/pages/LoadingPage/LoadingPage.tsx b/src/pages/LoadingPage/LoadingPage.tsx index 85edbfc..3af9c54 100644 --- a/src/pages/LoadingPage/LoadingPage.tsx +++ b/src/pages/LoadingPage/LoadingPage.tsx @@ -1,6 +1,6 @@ import { useEffect } from "react"; -import Navbar from "@/components/common/Navbar/Navbar"; +import Navbar from "@/components/Navbar/Navbar"; import { AppBridgeMessageType } from "@/components/provider/AppBridgeProvider/AppBridgeMessage.types"; import { useAppBridge } from "@/components/provider/AppBridgeProvider/AppBridgeProvider"; import Icon from "@/components/ui/Icon/Icon"; diff --git a/src/pages/ReceiptEditPage/ReceiptEditPage.module.scss b/src/pages/ReceiptEditPage/ReceiptEditPage.module.scss index 77a0cfb..f5e6a72 100644 --- a/src/pages/ReceiptEditPage/ReceiptEditPage.module.scss +++ b/src/pages/ReceiptEditPage/ReceiptEditPage.module.scss @@ -31,15 +31,6 @@ } } -.Navbar { - padding-left: 0; - padding-right: 0; -} - -.Container { - z-index: 1; -} - .Top { z-index: 1; diff --git a/src/pages/ReceiptEditPage/ReceiptEditPage.tsx b/src/pages/ReceiptEditPage/ReceiptEditPage.tsx index fa25e62..9dd054a 100644 --- a/src/pages/ReceiptEditPage/ReceiptEditPage.tsx +++ b/src/pages/ReceiptEditPage/ReceiptEditPage.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from "react"; -import Navbar from "@/components/common/Navbar/Navbar"; +import Navbar from "@/components/Navbar/Navbar"; import Button from "@/components/ui/Button/Button"; import Icon from "@/components/ui/Icon/Icon"; import Input from "@/components/ui/Input/Input"; @@ -79,14 +79,14 @@ const ReceiptEditPage = () => { }; return ( -
-
- - - - - - + <> + + + + + + +
@@ -118,33 +118,33 @@ const ReceiptEditPage = () => { ))}
-
-
- {Object.values(focusState).some((isFocus) => isFocus) ? ( -
-
+ ); }; diff --git a/src/pages/ReceiptInputPage/ReceiptInputPage.tsx b/src/pages/ReceiptInputPage/ReceiptInputPage.tsx index 539a363..15127c3 100644 --- a/src/pages/ReceiptInputPage/ReceiptInputPage.tsx +++ b/src/pages/ReceiptInputPage/ReceiptInputPage.tsx @@ -1,6 +1,6 @@ import { useState, useEffect } from "react"; -import Navbar from "@/components/common/Navbar/Navbar"; +import Navbar from "@/components/Navbar/Navbar"; import Button from "@/components/ui/Button/Button"; import Icon from "@/components/ui/Icon/Icon"; import Input from "@/components/ui/Input/Input"; diff --git a/src/pages/RecognitionFailPage.tsx b/src/pages/RecognitionFailPage.tsx deleted file mode 100644 index d06120b..0000000 --- a/src/pages/RecognitionFailPage.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import Navbar from "@/components/common/Navbar/Navbar"; -import RecognitionFail from "@/components/RecognitionFail/RecognitionFail"; -import Icon from "@/components/ui/Icon/Icon"; - -import { useRoute } from "@/hooks/common/useRoute"; - -import { useScanDataStore } from "@/store/useScanDataStore"; - -const RecognitionFailPage = () => { - const { navigateToHome } = useRoute(); - - const { resetScanData } = useScanDataStore(); - - const handleNavigateToHome = () => { - resetScanData(); - navigateToHome(); - }; - - return ( - <> - - - - - - - - - ); -}; - -export default RecognitionFailPage; diff --git a/src/components/RecognitionFail/RecognitionFail.module.scss b/src/pages/RecognitionFailPage/RecognitionFailPage.module.scss similarity index 100% rename from src/components/RecognitionFail/RecognitionFail.module.scss rename to src/pages/RecognitionFailPage/RecognitionFailPage.module.scss diff --git a/src/pages/RecognitionFailPage/RecognitionFailPage.tsx b/src/pages/RecognitionFailPage/RecognitionFailPage.tsx new file mode 100644 index 0000000..8dfe170 --- /dev/null +++ b/src/pages/RecognitionFailPage/RecognitionFailPage.tsx @@ -0,0 +1,59 @@ +import Navbar from "@/components/Navbar/Navbar"; +import { AppBridgeMessageType } from "@/components/provider/AppBridgeProvider/AppBridgeMessage.types"; +import { useAppBridge } from "@/components/provider/AppBridgeProvider/AppBridgeProvider"; +import Button from "@/components/ui/Button/Button"; +import Icon from "@/components/ui/Icon/Icon"; +import Text from "@/components/ui/Text/Text"; + +import { useRoute } from "@/hooks/common/useRoute"; + +import styles from "@/pages/RecognitionFailPage/RecognitionFailPage.module.scss"; + +import { useScanDataStore } from "@/store/useScanDataStore"; + +const RecognitionFailPage = () => { + const { send } = useAppBridge(); + + const { navigateToHome, navgateToReceiptInput } = useRoute(); + + const { resetScanData } = useScanDataStore(); + + const handleNavigateToHome = () => { + resetScanData(); + navigateToHome(); + }; + + return ( + <> + + + + + + +
+
+ + 영수증 인식에 실패했어요 + + + {`깨끗한 배경에 영수증을 놓고\n전체가 잘 나오도록 촬영해 주세요`} + +
+
+ recognitionFailImg +
+
+
+
+ + ); +}; + +export default RecognitionFailPage; diff --git a/src/pages/SelectStylePage.tsx b/src/pages/SelectStylePage.tsx deleted file mode 100644 index 542a805..0000000 --- a/src/pages/SelectStylePage.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import Navbar from "@/components/common/Navbar/Navbar"; -import SelectStyle from "@/components/SelectStyle/SelectStyle"; -import Icon from "@/components/ui/Icon/Icon"; - -import { useRoute } from "@/hooks/common/useRoute"; - -const SelectStylePage = () => { - const { navigateToBack } = useRoute(); - - return ( - <> - - - - - - - - ); -}; - -export default SelectStylePage; diff --git a/src/components/SelectStyle/SelectStyle.module.scss b/src/pages/SelectStylePage/SelectStylePage.module.scss similarity index 100% rename from src/components/SelectStyle/SelectStyle.module.scss rename to src/pages/SelectStylePage/SelectStylePage.module.scss diff --git a/src/pages/SelectStylePage/SelectStylePage.tsx b/src/pages/SelectStylePage/SelectStylePage.tsx new file mode 100644 index 0000000..7e71b4e --- /dev/null +++ b/src/pages/SelectStylePage/SelectStylePage.tsx @@ -0,0 +1,130 @@ +import { useState } from "react"; + +import classNames from "classnames"; + +import Navbar from "@/components/Navbar/Navbar"; +import { AppBridgeMessageType } from "@/components/provider/AppBridgeProvider/AppBridgeMessage.types"; +import { useAppBridge } from "@/components/provider/AppBridgeProvider/AppBridgeProvider"; +import StyleExampleModal from "@/components/StyleExampleModal/StyleExampleModal"; +import Button from "@/components/ui/Button/Button"; +import Icon from "@/components/ui/Icon/Icon"; +import Text from "@/components/ui/Text/Text"; + +import { useOverlay } from "@/hooks/common/useOverlay"; +import { useRoute } from "@/hooks/common/useRoute"; + +import styles from "@/pages/SelectStylePage/SelectStylePage.module.scss"; + +import { useCreateReviewStore } from "@/store/useReviewStore"; + +interface StyleProps { + name: string; + image: string; +} + +const IMG_STYLE_DATA = [ + { name: "친근한 말투", image: "/assets/img/img-style-friendly.webp" }, + { name: "믿음직한 말투", image: "/assets/img/img-style-trust.webp" }, + { name: "귀여운 말투", image: "/assets/img/img-style-cute.webp" }, +]; + +const STYLE_NAME_MAPPING: { [key: string]: string } = { + "친근한 말투": "FRIENDLY", + "믿음직한 말투": "PROFESSIONAL", + "귀여운 말투": "CUTE", +}; + +const SelectStylePage = () => { + const { navigateToBack, navigateToLoading } = useRoute(); + + const { send } = useAppBridge(); + + const { createReviewData, setReviewStyle } = useCreateReviewStore(); + + const { isOpen, handleClose, handleOpen } = useOverlay(); + + const [selectedStyle, setSelectedStyle] = useState(IMG_STYLE_DATA[0]); + + const { ocrText, hashTag } = createReviewData; + + const handleStyleClick = (style: StyleProps) => { + setSelectedStyle((prevStyle) => (prevStyle.name === style.name ? IMG_STYLE_DATA[0] : style)); + }; + + const handleCreateReview = () => { + const mappedStyle = STYLE_NAME_MAPPING[selectedStyle.name]; + + if (mappedStyle) { + setReviewStyle(mappedStyle); + } + + send({ + type: AppBridgeMessageType.CREATE_REVIEW, + payload: { ocrText, hashTag, reviewStyle: mappedStyle }, + }); + + navigateToLoading(); + }; + + return ( + <> + + + + + +
+
+
+ + 어떤 말투로 작성할까요? + + + 선택지에 따라 리뷰 말투가 달라져요 + +
+ +
+ +
+
+ +
+ {`${selectedStyle.name}-img`} +
+ +
+
+ {IMG_STYLE_DATA.map((style) => ( +
handleStyleClick(style)} + > + + {style.name} + + +
+ ))} +
+ +
+ + +
+ + ); +}; + +export default SelectStylePage; diff --git a/src/pages/SelectTagPage.tsx b/src/pages/SelectTagPage.tsx deleted file mode 100644 index 152e20f..0000000 --- a/src/pages/SelectTagPage.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import Navbar from "@/components/common/Navbar/Navbar"; -import SelectTag from "@/components/SelectTag/SelectTag"; -import Icon from "@/components/ui/Icon/Icon"; - -import { useRoute } from "@/hooks/common/useRoute"; - -const SelectTagPage = () => { - const { navigateToBack } = useRoute(); - - return ( - <> - - - - - - - - ); -}; - -export default SelectTagPage; diff --git a/src/components/SelectTag/SelectTag.module.scss b/src/pages/SelectTagPage/SelectTagPage.module.scss similarity index 100% rename from src/components/SelectTag/SelectTag.module.scss rename to src/pages/SelectTagPage/SelectTagPage.module.scss diff --git a/src/pages/SelectTagPage/SelectTagPage.tsx b/src/pages/SelectTagPage/SelectTagPage.tsx new file mode 100644 index 0000000..4c1eb27 --- /dev/null +++ b/src/pages/SelectTagPage/SelectTagPage.tsx @@ -0,0 +1,97 @@ +import { useEffect, useState } from "react"; + +import Navbar from "@/components/Navbar/Navbar"; +import TagSheet from "@/components/TagSheet/TagSheet"; +import Button from "@/components/ui/Button/Button"; +import Icon from "@/components/ui/Icon/Icon"; +import Tag from "@/components/ui/Tag/Tag"; +import Text from "@/components/ui/Text/Text"; + +import { useRoute } from "@/hooks/common/useRoute"; + +import styles from "@/pages/SelectTagPage/SelectTagPage.module.scss"; + +import { useCreateReviewStore } from "@/store/useReviewStore"; + +const SelectTagPage = () => { + const { navigateToSelectStyle, navigateToBack } = useRoute(); + + const { createReviewData, setHashTag, setTagList } = useCreateReviewStore(); + + const { tagList, hashTag } = createReviewData; + + const [isBottomSheetOpen, setIsBottomSheetOpen] = useState(false); + + useEffect(() => { + setHashTag(hashTag); + }, [hashTag, setHashTag]); + + const handleTagClick = (tag: string) => { + const newSelectedTags = hashTag.includes(tag) + ? hashTag.filter((selectedTag) => selectedTag !== tag) + : [...hashTag, tag]; + + setHashTag(newSelectedTags); + }; + + const handleTagAdd = (newTag: string) => { + setIsBottomSheetOpen(false); + setTagList([...tagList, newTag]); + setHashTag([...hashTag, newTag]); + }; + + const handleSheetClose = () => { + setIsBottomSheetOpen(false); + }; + + const handleNextClick = () => { + navigateToSelectStyle(); + }; + + return ( + <> + + + + + + +
+
+
+ + 어떠셨나요? + + + 복수 가능 + +
+
+ {tagList.map((tag) => ( + handleTagClick(tag)} + isSelect={hashTag.includes(tag)} + /> + ))} + setIsBottomSheetOpen(true)} /> +
+
+ +
+
+ + +
+ + ); +}; + +export default SelectTagPage; diff --git a/src/router/AppRouter.tsx b/src/router/AppRouter.tsx index 772e41a..ab97d7e 100644 --- a/src/router/AppRouter.tsx +++ b/src/router/AppRouter.tsx @@ -5,14 +5,14 @@ import App from "@/App"; import { PATH } from "@/constants/path"; import CreateReviewFailPage from "@/pages/CreateReviewFailPage/CreateReviewFailPage"; -import HomePage from "@/pages/HomePage"; +import HomePage from "@/pages/HomePage/HomePage"; import LoadingPage from "@/pages/LoadingPage/LoadingPage"; import ReceiptEditPage from "@/pages/ReceiptEditPage/ReceiptEditPage"; import ReceiptInputPage from "@/pages/ReceiptInputPage/ReceiptInputPage"; -import RecognitionFailPage from "@/pages/RecognitionFailPage"; +import RecognitionFailPage from "@/pages/RecognitionFailPage/RecognitionFailPage"; import ReviewResultPage from "@/pages/ReviewResultPage/ReviewResultPage"; -import SelectStylePage from "@/pages/SelectStylePage"; -import SelectTagPage from "@/pages/SelectTagPage"; +import SelectStylePage from "@/pages/SelectStylePage/SelectStylePage"; +import SelectTagPage from "@/pages/SelectTagPage/SelectTagPage"; const AppRouter = () => { const router = createBrowserRouter([