diff --git a/.eslintrc.json b/.eslintrc.json index 0a9380a..aae14a0 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -62,6 +62,11 @@ "group": "type", "position": "before" }, + { + "pattern": "@/store/**/*", + "group": "type", + "position": "before" + }, { "pattern": "@/styles/**/*", "group": "type", diff --git a/.pnp.cjs b/.pnp.cjs index 89b910a..a20190c 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -77,7 +77,8 @@ const RAW_RUNTIME_STATE = ["typescript-plugin-css-modules", "virtual:bf4b7fdd92a9723d0b8b3c0ad1d9b3bf177b06bda2d8d90eee6bb9b559bcf7f6a4e86d3e1e4088168d00f3b758fa58c40c57bffe4a3e68627cd86f7a3c1c2191#npm:5.1.0"],\ ["vite", "virtual:bf4b7fdd92a9723d0b8b3c0ad1d9b3bf177b06bda2d8d90eee6bb9b559bcf7f6a4e86d3e1e4088168d00f3b758fa58c40c57bffe4a3e68627cd86f7a3c1c2191#npm:6.0.7"],\ ["vite-plugin-svgr", "virtual:bf4b7fdd92a9723d0b8b3c0ad1d9b3bf177b06bda2d8d90eee6bb9b559bcf7f6a4e86d3e1e4088168d00f3b758fa58c40c57bffe4a3e68627cd86f7a3c1c2191#npm:4.3.0"],\ - ["vite-tsconfig-paths", "virtual:bf4b7fdd92a9723d0b8b3c0ad1d9b3bf177b06bda2d8d90eee6bb9b559bcf7f6a4e86d3e1e4088168d00f3b758fa58c40c57bffe4a3e68627cd86f7a3c1c2191#npm:5.1.4"]\ + ["vite-tsconfig-paths", "virtual:bf4b7fdd92a9723d0b8b3c0ad1d9b3bf177b06bda2d8d90eee6bb9b559bcf7f6a4e86d3e1e4088168d00f3b758fa58c40c57bffe4a3e68627cd86f7a3c1c2191#npm:5.1.4"],\ + ["zustand", "virtual:bf4b7fdd92a9723d0b8b3c0ad1d9b3bf177b06bda2d8d90eee6bb9b559bcf7f6a4e86d3e1e4088168d00f3b758fa58c40c57bffe4a3e68627cd86f7a3c1c2191#npm:5.0.3"]\ ],\ "linkType": "SOFT"\ }]\ @@ -10625,7 +10626,8 @@ const RAW_RUNTIME_STATE = ["typescript-plugin-css-modules", "virtual:bf4b7fdd92a9723d0b8b3c0ad1d9b3bf177b06bda2d8d90eee6bb9b559bcf7f6a4e86d3e1e4088168d00f3b758fa58c40c57bffe4a3e68627cd86f7a3c1c2191#npm:5.1.0"],\ ["vite", "virtual:bf4b7fdd92a9723d0b8b3c0ad1d9b3bf177b06bda2d8d90eee6bb9b559bcf7f6a4e86d3e1e4088168d00f3b758fa58c40c57bffe4a3e68627cd86f7a3c1c2191#npm:6.0.7"],\ ["vite-plugin-svgr", "virtual:bf4b7fdd92a9723d0b8b3c0ad1d9b3bf177b06bda2d8d90eee6bb9b559bcf7f6a4e86d3e1e4088168d00f3b758fa58c40c57bffe4a3e68627cd86f7a3c1c2191#npm:4.3.0"],\ - ["vite-tsconfig-paths", "virtual:bf4b7fdd92a9723d0b8b3c0ad1d9b3bf177b06bda2d8d90eee6bb9b559bcf7f6a4e86d3e1e4088168d00f3b758fa58c40c57bffe4a3e68627cd86f7a3c1c2191#npm:5.1.4"]\ + ["vite-tsconfig-paths", "virtual:bf4b7fdd92a9723d0b8b3c0ad1d9b3bf177b06bda2d8d90eee6bb9b559bcf7f6a4e86d3e1e4088168d00f3b758fa58c40c57bffe4a3e68627cd86f7a3c1c2191#npm:5.1.4"],\ + ["zustand", "virtual:bf4b7fdd92a9723d0b8b3c0ad1d9b3bf177b06bda2d8d90eee6bb9b559bcf7f6a4e86d3e1e4088168d00f3b758fa58c40c57bffe4a3e68627cd86f7a3c1c2191#npm:5.0.3"]\ ],\ "linkType": "SOFT"\ }]\ @@ -14166,6 +14168,36 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }]\ + ]],\ + ["zustand", [\ + ["npm:5.0.3", {\ + "packageLocation": "./.yarn/cache/zustand-npm-5.0.3-6b60927ae4-dad96c6c12.zip/node_modules/zustand/",\ + "packageDependencies": [\ + ["zustand", "npm:5.0.3"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:bf4b7fdd92a9723d0b8b3c0ad1d9b3bf177b06bda2d8d90eee6bb9b559bcf7f6a4e86d3e1e4088168d00f3b758fa58c40c57bffe4a3e68627cd86f7a3c1c2191#npm:5.0.3", {\ + "packageLocation": "./.yarn/__virtual__/zustand-virtual-21fdc291ee/0/cache/zustand-npm-5.0.3-6b60927ae4-dad96c6c12.zip/node_modules/zustand/",\ + "packageDependencies": [\ + ["zustand", "virtual:bf4b7fdd92a9723d0b8b3c0ad1d9b3bf177b06bda2d8d90eee6bb9b559bcf7f6a4e86d3e1e4088168d00f3b758fa58c40c57bffe4a3e68627cd86f7a3c1c2191#npm:5.0.3"],\ + ["@types/immer", null],\ + ["@types/react", "npm:18.3.18"],\ + ["@types/use-sync-external-store", null],\ + ["immer", null],\ + ["react", "npm:18.3.1"],\ + ["use-sync-external-store", null]\ + ],\ + "packagePeers": [\ + "@types/immer",\ + "@types/react",\ + "@types/use-sync-external-store",\ + "immer",\ + "react",\ + "use-sync-external-store"\ + ],\ + "linkType": "HARD"\ + }]\ ]]\ ]\ }'; diff --git a/.yarn/cache/zustand-npm-5.0.3-6b60927ae4-dad96c6c12.zip b/.yarn/cache/zustand-npm-5.0.3-6b60927ae4-dad96c6c12.zip new file mode 100644 index 0000000..c2ba236 Binary files /dev/null and b/.yarn/cache/zustand-npm-5.0.3-6b60927ae4-dad96c6c12.zip differ diff --git a/package.json b/package.json index 6fb1e0f..3ebc62c 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "classnames": "^2.5.1", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-router-dom": "^7.1.3" + "react-router-dom": "^7.1.3", + "zustand": "^5.0.3" }, "devDependencies": { "@commitlint/cli": "^19.6.1", diff --git a/src/components/ReceiptEdit/ReceiptEdit.tsx b/src/components/ReceiptEdit/ReceiptEdit.tsx index 86c4e7d..2aaba94 100644 --- a/src/components/ReceiptEdit/ReceiptEdit.tsx +++ b/src/components/ReceiptEdit/ReceiptEdit.tsx @@ -8,9 +8,13 @@ import Text from "@/components/ui/Text/Text"; import { useFocus } from "@/hooks/common/useFocus"; import { useRoute } from "@/hooks/common/useRoute"; +import { useCreateReviewStore } from "@/store/useReviewStore"; + const ReceiptEdit = () => { const { navigateToSelectTag } = useRoute(); + const { setOcrText } = useCreateReviewStore(); + const [placeName, setPlaceName] = useState("청담커피 앤 토스트"); const [foodName, setFoodName] = useState("카야토스트+음료세트"); @@ -21,6 +25,13 @@ const ReceiptEdit = () => { } = useFocus({}); const { isFocus: isFoodFocus, onFocus: handleFoodFocus, onBlur: handleFoodBlur } = useFocus({}); + const handleInfoRightClick = () => { + const ocrText = `${placeName} ${foodName}`; + setOcrText(ocrText); + + navigateToSelectTag(); + }; + return (
@@ -75,7 +86,7 @@ const ReceiptEdit = () => {
); diff --git a/src/components/ReviewResult/ReviewResult.tsx b/src/components/ReviewResult/ReviewResult.tsx index a065e78..39a7fb8 100644 --- a/src/components/ReviewResult/ReviewResult.tsx +++ b/src/components/ReviewResult/ReviewResult.tsx @@ -3,6 +3,8 @@ import { useEffect } from "react"; import confetti from "canvas-confetti"; import HomeNavigateConfirmModal from "@/components/HomeNavigateConfirmModal/HomeNavigateConfirmModal"; +import { AppBridgeMessageType } from "@/components/provider/AppBridgeProvider/AppBridgeMessage.types"; +import { useAppBridge } from "@/components/provider/AppBridgeProvider/AppBridgeProvider"; import styles from "@/components/ReviewResult/ReviewResult.module.scss"; import Button from "@/components/ui/Button/Button"; import IconButton from "@/components/ui/IconButton/IconButton"; @@ -15,16 +17,14 @@ import useToast from "@/hooks/common/useToast"; import type { Options as ConfettiOptions } from "canvas-confetti"; const ReviewResult = () => { + const { send } = useAppBridge(); + const { isOpen, handleClose, handleOpen } = useOverlay(); - const { isToast, showToast } = useToast(1000); + const { isToast } = useToast(1000); const reviewText = `오늘 처음으로 청담커피 앤 토스트에서 주문했어요.. 매장도 깔끔하고 직원들도 친절해요! 음료랑 토스트 세트 시켰는데 가성비가 좋네요… 맛도 좋고 양도 많아요!! 다음에도 또 시켜먹을 거예요.`; - const handleCopy = () => { - showToast(); - }; - const handleConfetti = () => { const setting: ConfettiOptions = { particleCount: 100, @@ -57,7 +57,14 @@ const ReviewResult = () => { {reviewText}
- + + send({ type: AppBridgeMessageType.COPY, payload: { review: reviewText } }) + } + />
diff --git a/src/components/SelectStyle/SelectStyle.tsx b/src/components/SelectStyle/SelectStyle.tsx index c001d72..be18f3f 100644 --- a/src/components/SelectStyle/SelectStyle.tsx +++ b/src/components/SelectStyle/SelectStyle.tsx @@ -2,12 +2,14 @@ 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 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 { useCreateReviewStore } from "@/store/useReviewStore"; interface StyleProps { name: string; @@ -22,14 +24,29 @@ const IMG_STYLE_DATA = [ ]; const SelectStyle = () => { - const { navigateToReviewResult } = useRoute(); + const { send } = useAppBridge(); + + const { createReviewData, setReviewStyle } = useCreateReviewStore(); const [selectedStyle, setSelectedStyle] = useState(IMG_STYLE_DATA[0]); + const { ocrText, hashTag, reviewStyle } = createReviewData; + const handleStyleClick = (style: StyleProps) => { setSelectedStyle((prevStyle) => (prevStyle.name === style.name ? IMG_STYLE_DATA[0] : style)); }; + const handleCreateReview = () => { + if (selectedStyle.name !== "default") { + setReviewStyle(selectedStyle.name); + } + + send({ + type: AppBridgeMessageType.CREATE_REVIEW, + payload: { ocrText, hashTag, reviewStyle }, + }); + }; + return (
@@ -63,7 +80,7 @@ const SelectStyle = () => {
-
); diff --git a/src/components/SelectTag/SelectTag.tsx b/src/components/SelectTag/SelectTag.tsx index 577f653..606cb3f 100644 --- a/src/components/SelectTag/SelectTag.tsx +++ b/src/components/SelectTag/SelectTag.tsx @@ -8,9 +8,13 @@ import Text from "@/components/ui/Text/Text"; import { useRoute } from "@/hooks/common/useRoute"; +import { useCreateReviewStore } from "@/store/useReviewStore"; + const SelectTag = () => { const { navigateToSelectStyle } = useRoute(); + const { setHashTag } = useCreateReviewStore(); + const [selectedTagList, setSelectedTagList] = useState([]); const [isBottomSheetOpen, setIsBottomSheetOpen] = useState(false); const [tagList, setTagList] = useState([ @@ -33,7 +37,7 @@ const SelectTag = () => { setSelectedTagList((prevSelectedTags) => prevSelectedTags.includes(tag) ? prevSelectedTags.filter((selectedTag) => selectedTag !== tag) - : [...prevSelectedTags, tag] + : [...prevSelectedTags, tag], ); }; @@ -48,6 +52,11 @@ const SelectTag = () => { setIsBottomSheetOpen(false); }; + const handleNextClick = () => { + setHashTag(selectedTagList); + navigateToSelectStyle(); + }; + return (
@@ -73,7 +82,7 @@ const SelectTag = () => {
-
{ navigateToHome: () => navigate(PATH.HOME), navigateToBack: () => navigate(-1), navigateToReceiptEdit: () => navigate(PATH.RECEIPT_EDIT), - navigateToRecognitionFail: () => navigate(PATH.RECOGNITION_FAIL), - navigateToReviewResult: () => navigate(PATH.REVIEW_RESULT), navigateToSelectStyle: () => navigate(PATH.SELECT_STYLE), navigateToSelectTag: () => navigate(PATH.SELECT_TAG), }; diff --git a/src/pages/HomePage.tsx b/src/pages/HomePage.tsx index 397e53d..564e883 100644 --- a/src/pages/HomePage.tsx +++ b/src/pages/HomePage.tsx @@ -1,11 +1,15 @@ 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 Icon from "@/components/ui/Icon/Icon"; import Text from "@/components/ui/Text/Text"; import { useRoute } from "@/hooks/common/useRoute"; const HomePage = () => { + const { send } = useAppBridge(); + const { navigateToHome } = useRoute(); return ( @@ -14,7 +18,7 @@ const HomePage = () => { - + send({ type: AppBridgeMessageType.SHARE })}> 앱 공유하기 diff --git a/src/store/useReviewStore.ts b/src/store/useReviewStore.ts new file mode 100644 index 0000000..82197e9 --- /dev/null +++ b/src/store/useReviewStore.ts @@ -0,0 +1,36 @@ +import { create } from "zustand"; + +interface CreateReviewData { + ocrText: string; + hashTag: string[]; + reviewStyle: string; +} + +interface CreateReviewDataStore { + createReviewData: CreateReviewData; + setOcrText: (ocrText: string) => void; + setHashTag: (hashTag: string[]) => void; + setReviewStyle: (reviewStyle: string) => void; +} + +export const CREATE_REVIEW_DATA = { + ocrText: "", + hashTag: [], + reviewStyle: "", +}; + +export const useCreateReviewStore = create((set) => ({ + createReviewData: { ...CREATE_REVIEW_DATA }, + setOcrText: (ocrText: string) => + set((state) => ({ + createReviewData: { ...state.createReviewData, ocrText }, + })), + setHashTag: (hashTag: string[]) => + set((state) => ({ + createReviewData: { ...state.createReviewData, hashTag }, + })), + setReviewStyle: (reviewStyle: string) => + set((state) => ({ + createReviewData: { ...state.createReviewData, reviewStyle }, + })), +})); diff --git a/yarn.lock b/yarn.lock index f9727cc..cecdcbb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8165,6 +8165,7 @@ __metadata: vite: "npm:^6.0.5" vite-plugin-svgr: "npm:^4.3.0" vite-tsconfig-paths: "npm:^5.1.4" + zustand: "npm:^5.0.3" languageName: unknown linkType: soft @@ -11216,3 +11217,24 @@ __metadata: checksum: 10c0/cb287fe5e6acfa82690acb43c283de34e945c571a78a939774f6eaba7c285bacdf6c90fbc16ce530060863984c906d2b4c6ceb069c94d1e0a06d5f2b458e2a92 languageName: node linkType: hard + +"zustand@npm:^5.0.3": + version: 5.0.3 + resolution: "zustand@npm:5.0.3" + peerDependencies: + "@types/react": ">=18.0.0" + immer: ">=9.0.6" + react: ">=18.0.0" + use-sync-external-store: ">=1.2.0" + peerDependenciesMeta: + "@types/react": + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + checksum: 10c0/dad96c6c123fda088c583d5df6692e9245cd207583078dc15f93d255a67b0f346bad4535545c98852ecde93d254812a0c799579dfde2ab595016b99fbe20e4d5 + languageName: node + linkType: hard