From c41342e18f17152809278e6f28fac0ebf8495cb3 Mon Sep 17 00:00:00 2001 From: JAESEON PARK Date: Wed, 29 Apr 2026 13:39:27 +0900 Subject: [PATCH 1/2] =?UTF-8?q?setting:=20import=20=EC=A0=95=EB=A0=AC=20?= =?UTF-8?q?=EA=B7=9C=EC=B9=99,=20prettier=20=ED=8F=AC=EB=A7=B7=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .prettierrc | 10 +- eslint.config.js | 11 + index.html | 5 +- package.json | 2 + pnpm-lock.yaml | 171 ++++++ src/App.tsx | 34 +- src/api/adapters/store.adapter.ts | 7 +- src/api/api.error.ts | 1 + src/api/auth.ts | 28 +- src/api/axios.ts | 14 +- src/api/bookings.ts | 10 +- src/api/dto/store.dto.ts | 7 +- src/api/endpoints/bookings.ts | 4 +- src/api/endpoints/member.ts | 10 +- src/api/endpoints/menus.ts | 5 +- src/api/endpoints/payments.ts | 10 +- src/api/endpoints/reservations.ts | 4 +- src/api/inquiry.ts | 10 +- src/api/menu.ts | 1 + src/api/owner/menus.ts | 34 +- src/api/owner/reservation.ts | 37 +- src/api/owner/storeLayout.ts | 24 +- src/api/owner/stores.ts | 23 +- src/api/owner/table.ts | 12 +- src/api/store.ts | 8 +- src/components/RouteGuards.tsx | 3 +- src/components/auth/ChangePasswordDiaLog.tsx | 16 +- src/components/auth/LoginDialog.tsx | 51 +- src/components/auth/Signup.schema.ts | 11 +- src/components/auth/SignupDialog.tsx | 79 +-- src/components/auth/WithdrawDialog.tsx | 20 +- .../customer-support/SupportCompleteModal.tsx | 5 +- .../customer-support/SupportFAQ.tsx | 10 +- .../customer-support/SupportHero.tsx | 6 +- .../customer-support/SupportModal.tsx | 53 +- .../customer-support/support.schema.ts | 10 +- src/components/main/CtaSection.tsx | 10 +- src/components/main/FeatureCard.tsx | 17 +- src/components/main/FeatureSection.tsx | 16 +- src/components/main/Footer.tsx | 60 +- src/components/main/ForOwnerSection.tsx | 11 +- src/components/main/ForUserSection.tsx | 11 +- src/components/main/Header.tsx | 54 +- src/components/main/Hero.tsx | 1 + src/components/main/ProblemSection.tsx | 7 +- src/components/main/StateSection.tsx | 12 +- src/components/map/KakaoMap.tsx | 16 +- src/components/owner/AddTableModal.tsx | 17 +- src/components/owner/BreakTimeModal.tsx | 14 +- src/components/owner/MenuManagement.tsx | 54 +- src/components/owner/StoreSettings.tsx | 62 +-- src/components/owner/TableCreateModal.tsx | 22 +- src/components/owner/menuFormModal.tsx | 30 +- src/components/owner/tableDashboard.tsx | 514 +++++++----------- src/components/owner/tableDetailModal.tsx | 164 ++---- .../reservation/modals/PaymentModal.tsx | 52 +- .../modals/ReservationCompleteModal.tsx | 5 +- .../modals/ReservationConfirmModal.tsx | 14 +- .../modals/ReservationMenuModal.tsx | 247 ++++----- .../reservation/modals/ReservationModal.tsx | 85 ++- src/components/reservation/parts/TableMap.tsx | 21 +- src/components/restaurant/RestaurantCard.tsx | 6 +- .../restaurant/RestaurantDetailModal.tsx | 31 +- src/components/restaurant/RestaurantList.tsx | 5 +- .../restaurant/RestaurantListSkeleton.tsx | 6 +- .../store-registration/CompleteModal.tsx | 31 +- .../store-registration/ConfirmModal.tsx | 11 +- .../store-registration/Menu.schema.ts | 4 +- .../store-registration/MenuItemInput.tsx | 55 +- .../RegistrationStepper.tsx | 4 +- .../store-registration/StepBusinessAuth.tsx | 71 +-- .../StepMenuRegistration.tsx | 8 +- .../store-registration/StepStoreInfo.tsx | 97 +--- .../store-registration/StoreInfo.schema.ts | 25 +- .../StoreTransform.utils.ts | 9 +- src/components/ui/button.tsx | 16 +- src/components/ui/calendar.tsx | 66 +-- src/components/ui/checkbox.tsx | 7 +- src/components/ui/dialog.tsx | 33 +- src/components/ui/label.tsx | 7 +- src/components/ui/popover.tsx | 16 +- src/components/ui/separator.tsx | 2 +- src/hooks/common/useConfirmClose.ts | 4 +- src/hooks/queries/useAuth.ts | 13 +- src/hooks/queries/useMenu.ts | 21 +- src/hooks/queries/useStore.ts | 10 +- src/hooks/reservation/useAvailableTables.ts | 8 +- src/hooks/reservation/useAvailableTimes.ts | 3 +- src/hooks/reservation/useCreateBooking.ts | 3 +- src/hooks/reservation/useMenus.ts | 7 +- src/hooks/store/useRestaurantDetail.ts | 3 +- src/hooks/store/useSearchStores.ts | 3 +- src/layouts/PublicLayout.tsx | 17 +- src/layouts/myPageLayout.tsx | 11 +- src/lib/kakao.ts | 4 +- src/lib/utils.ts | 2 +- src/main.tsx | 9 +- src/pages/CustomerSupportPage.tsx | 9 +- src/pages/LoginErrorPage.tsx | 6 +- src/pages/NotFound.tsx | 6 +- src/pages/OAuthCallbackPage.tsx | 7 +- src/pages/ReservationCompletePage.tsx | 5 +- src/pages/SearchPage.tsx | 74 +-- src/pages/myPage/MyInfoPage.tsx | 33 +- src/pages/myPage/StoreRegistrationPage.tsx | 41 +- src/pages/myPage/reservationPage.tsx | 48 +- src/pages/myPage/settingPage.tsx | 34 +- src/pages/myPage/storePage.tsx | 23 +- src/pages/myPage/subscriptionPage.tsx | 39 +- src/pages/ownerPage.tsx | 30 +- src/pages/payment/FailPage.tsx | 18 +- src/pages/payment/SuccessPage.tsx | 3 +- src/query/keys.ts | 24 +- src/stores/useAuthStore.ts | 5 +- src/types/booking.ts | 4 +- src/types/kakao.d.ts | 6 +- src/types/restaurant.ts | 8 +- src/utils/menu.ts | 10 +- src/utils/phoneNumber.ts | 12 +- src/utils/reservation.ts | 4 +- src/utils/time.ts | 7 +- tsconfig.json | 5 +- vite.config.ts | 7 +- 123 files changed, 1270 insertions(+), 2088 deletions(-) diff --git a/.prettierrc b/.prettierrc index cd3cd5c..4079f00 100644 --- a/.prettierrc +++ b/.prettierrc @@ -2,7 +2,13 @@ "semi": true, "singleQuote": false, "trailingComma": "all", - "printWidth": 80, + "printWidth": 100, "tabWidth": 2, - "useTabs": false + "useTabs": false, + "bracketSpacing": true, + "bracketSameLine": false, + "endOfLine": "auto", + "quoteProps": "consistent", + "arrowParens": "always", + "proseWrap": "preserve" } diff --git a/eslint.config.js b/eslint.config.js index 356c51d..8bc4858 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -5,6 +5,9 @@ import prettierConfig from "eslint-config-prettier"; import globals from "globals"; import react from "eslint-plugin-react"; +import importPlugin from "eslint-plugin-import"; +import simpleImportSort from "eslint-plugin-simple-import-sort"; + export default [ { languageOptions: { @@ -28,6 +31,8 @@ export default [ files: ["**/*.{ts,tsx}"], plugins: { "react-hooks": reactHooks, + "import": importPlugin, + "simple-import-sort": simpleImportSort, }, rules: { ...reactHooks.configs.recommended.rules, @@ -40,6 +45,12 @@ export default [ // 추가: 빈 블록({}) 허용 "no-empty": "warn", + + /*import 규칙 추가*/ + "simple-import-sort/imports": "warn", // import 구문 정렬 검사 + "simple-import-sort/exports": "warn", // export 구문 순서 정리 + "import/newline-after-import": "warn", // import 구문 다음에 코드 한줄 띄워줌(빈 줄 추가) + "import/no-duplicates": "warn", // 중복된 import 구문 있으면 하나로 합쳐줌(중복제거) }, }, prettierConfig, diff --git a/index.html b/index.html index ecad331..14f525f 100644 --- a/index.html +++ b/index.html @@ -5,10 +5,7 @@ 잇츠파인(Eatsfine) - + = 0.4'} + array.prototype.findlastindex@1.2.6: + resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==} + engines: {node: '>= 0.4'} + array.prototype.flat@1.3.3: resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} engines: {node: '>= 0.4'} @@ -1291,6 +1307,14 @@ packages: date-fns@4.1.0: resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -1395,6 +1419,40 @@ packages: peerDependencies: eslint: '>=7.0.0' + eslint-import-resolver-node@0.3.10: + resolution: {integrity: sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==} + + eslint-module-utils@2.12.1: + resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-import@2.32.0: + resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint-plugin-prettier@5.5.4: resolution: {integrity: sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==} engines: {node: ^14.18.0 || >=16.0.0} @@ -1426,6 +1484,11 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + eslint-plugin-simple-import-sort@13.0.0: + resolution: {integrity: sha512-McAc+/Nlvcg4byY/CABGH8kqnefWBj8s3JA2okEtz8ixbECQgU46p0HkTUKa4YS7wvgGceimlc34p1nXqbWqtA==} + peerDependencies: + eslint: '>=5.0.0' + eslint-scope@8.4.0: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1786,6 +1849,10 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} @@ -1930,6 +1997,9 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1972,6 +2042,10 @@ packages: resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} engines: {node: '>= 0.4'} + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + object.values@1.2.1: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} @@ -2276,6 +2350,10 @@ packages: resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} engines: {node: '>=12'} + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -2316,6 +2394,9 @@ packages: peerDependencies: typescript: '>=4.8.4' + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -3125,6 +3206,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.54.0': optional: true + '@rtsao/scc@1.1.0': {} + '@standard-schema/utils@0.3.0': {} '@tailwindcss/node@4.1.18': @@ -3237,6 +3320,8 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/json5@0.0.29': {} + '@types/node@24.10.4': dependencies: undici-types: 7.16.0 @@ -3408,6 +3493,16 @@ snapshots: es-object-atoms: 1.1.1 es-shim-unscopables: 1.1.0 + array.prototype.findlastindex@1.2.6: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + array.prototype.flat@1.3.3: dependencies: call-bind: 1.0.8 @@ -3568,6 +3663,10 @@ snapshots: date-fns@4.1.0: {} + debug@3.2.7: + dependencies: + ms: 2.1.3 + debug@4.4.3: dependencies: ms: 2.1.3 @@ -3752,6 +3851,53 @@ snapshots: dependencies: eslint: 9.39.2(jiti@2.6.1) + eslint-import-resolver-node@0.3.10: + dependencies: + debug: 3.2.7 + is-core-module: 2.16.1 + resolve: 2.0.0-next.6 + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint@9.39.2(jiti@2.6.1)): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.2(jiti@2.6.1) + eslint-import-resolver-node: 0.3.10 + transitivePeerDependencies: + - supports-color + + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.9 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.39.2(jiti@2.6.1) + eslint-import-resolver-node: 0.3.10 + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint@9.39.2(jiti@2.6.1)) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + eslint-plugin-prettier@5.5.4(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.7.4): dependencies: eslint: 9.39.2(jiti@2.6.1) @@ -3798,6 +3944,10 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 + eslint-plugin-simple-import-sort@13.0.0(eslint@9.39.2(jiti@2.6.1)): + dependencies: + eslint: 9.39.2(jiti@2.6.1) + eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 @@ -4163,6 +4313,10 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + json5@1.0.2: + dependencies: + minimist: 1.2.8 + json5@2.2.3: {} jsx-ast-utils@3.3.5: @@ -4296,6 +4450,8 @@ snapshots: dependencies: brace-expansion: 2.0.2 + minimist@1.2.8: {} + ms@2.1.3: {} nanoid@3.3.11: {} @@ -4340,6 +4496,12 @@ snapshots: es-abstract: 1.24.1 es-object-atoms: 1.1.1 + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + object.values@1.2.1: dependencies: call-bind: 1.0.8 @@ -4710,6 +4872,8 @@ snapshots: dependencies: ansi-regex: 6.2.2 + strip-bom@3.0.0: {} + strip-json-comments@3.1.1: {} supports-color@7.2.0: @@ -4739,6 +4903,13 @@ snapshots: dependencies: typescript: 5.9.3 + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + tslib@2.8.1: {} tw-animate-css@1.4.0: {} diff --git a/src/App.tsx b/src/App.tsx index cdbb2b8..071cfc2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,29 +1,25 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; -import { - createBrowserRouter, - Navigate, - RouterProvider, - type RouteObject, -} from "react-router-dom"; -import NotFound from "./pages/NotFound"; -import Intro from "./pages/Intro"; -import SearchPage from "./pages/SearchPage"; -import CustomerSupportPage from "./pages/CustomerSupportPage"; -import PublicLayout from "./layouts/PublicLayout"; -import StoreRegistrationPage from "./pages/myPage/StoreRegistrationPage"; +import { createBrowserRouter, Navigate, type RouteObject, RouterProvider } from "react-router-dom"; + +import { PrivateRoute } from "./components/RouteGuards"; import MyPageLayout from "./layouts/myPageLayout"; -import OAuthCallbackPage from "./pages/OAuthCallbackPage"; +import PublicLayout from "./layouts/PublicLayout"; +import CustomerSupportPage from "./pages/CustomerSupportPage"; +import Intro from "./pages/Intro"; import LoginErrorPage from "./pages/LoginErrorPage"; -import SuccessPage from "./pages/payment/SuccessPage"; -import FailPage from "./pages/payment/FailPage"; -import ReservationCompletePage from "./pages/ReservationCompletePage"; -import { PrivateRoute } from "./components/RouteGuards"; +import MyInfoPage from "./pages/myPage/MyInfoPage"; import ReservationPage from "./pages/myPage/reservationPage"; import SettingsPage from "./pages/myPage/settingPage"; -import SubscriptionPage from "./pages/myPage/subscriptionPage"; import StorePage from "./pages/myPage/storePage"; +import StoreRegistrationPage from "./pages/myPage/StoreRegistrationPage"; +import SubscriptionPage from "./pages/myPage/subscriptionPage"; +import NotFound from "./pages/NotFound"; +import OAuthCallbackPage from "./pages/OAuthCallbackPage"; import OwnerPage from "./pages/ownerPage"; -import MyInfoPage from "./pages/myPage/MyInfoPage"; +import FailPage from "./pages/payment/FailPage"; +import SuccessPage from "./pages/payment/SuccessPage"; +import ReservationCompletePage from "./pages/ReservationCompletePage"; +import SearchPage from "./pages/SearchPage"; const myPageRoutes: RouteObject = { path: "/mypage", diff --git a/src/api/adapters/store.adapter.ts b/src/api/adapters/store.adapter.ts index 21d42c6..888b174 100644 --- a/src/api/adapters/store.adapter.ts +++ b/src/api/adapters/store.adapter.ts @@ -1,5 +1,5 @@ -import type { BreakTime, RestaurantDetail } from "@/types/store"; import type { StoreDetailDataDTO } from "@/api/dto/store.dto"; +import type { BreakTime, RestaurantDetail } from "@/types/store"; export function toRestaurantDetail(dto: StoreDetailDataDTO): RestaurantDetail { const breakTime = toBreakTime(dto.breakStartTime, dto.breakEndTime); @@ -26,10 +26,7 @@ export function toRestaurantDetail(dto: StoreDetailDataDTO): RestaurantDetail { }; } -function toBreakTime( - start?: string | null, - end?: string | null, -): BreakTime | undefined { +function toBreakTime(start?: string | null, end?: string | null): BreakTime | undefined { if (!start || !end) return undefined; return { start, end }; } diff --git a/src/api/api.error.ts b/src/api/api.error.ts index b9ed5d5..a11df06 100644 --- a/src/api/api.error.ts +++ b/src/api/api.error.ts @@ -1,4 +1,5 @@ import type { AxiosError } from "axios"; + import type { ApiError, ApiResponse } from "@/types/api"; export function isApiResponse(data: unknown): data is ApiResponse { diff --git a/src/api/auth.ts b/src/api/auth.ts index cd90b3a..1f80ffc 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -1,38 +1,32 @@ +import axios from "axios"; + +import { useAuthStore } from "@/stores/useAuthStore"; import type { ApiResponse } from "@/types/api"; import type { - RequestSignupDto, - ResponseSignupDto, RequestLoginDto, + RequestSignupDto, + RequestVerifyOwnerDto, ResponseLoginDto, ResponseLogoutDto, ResponseRefreshDto, - RequestVerifyOwnerDto, + ResponseSignupDto, ResponseVerifyOwnerDto, } from "@/types/auth"; + import { api } from "./axios"; -import { useAuthStore } from "@/stores/useAuthStore"; -import axios from "axios"; -export const postSignup = async ( - body: RequestSignupDto, -): Promise => { +export const postSignup = async (body: RequestSignupDto): Promise => { const { data } = await api.post("/api/auth/signup", body); return data; }; -export const postLogin = async ( - body: RequestLoginDto, -): Promise => { - const { data } = await api.post>( - "/api/auth/login", - body, - ); +export const postLogin = async (body: RequestLoginDto): Promise => { + const { data } = await api.post>("/api/auth/login", body); return data.result; }; const postLogout = async (): Promise => { - const { data } = - await api.delete>("/api/auth/logout"); + const { data } = await api.delete>("/api/auth/logout"); return data.result; }; diff --git a/src/api/axios.ts b/src/api/axios.ts index 33f52f5..2cfabb6 100644 --- a/src/api/axios.ts +++ b/src/api/axios.ts @@ -1,8 +1,10 @@ import axios, { type AxiosError, type InternalAxiosRequestConfig } from "axios"; -import { isApiResponse, normalizeApiError } from "./api.error"; + +import { useAuthStore } from "@/stores/useAuthStore"; import type { ApiError } from "@/types/api"; + +import { isApiResponse, normalizeApiError } from "./api.error"; import { clearAuth, postRefresh } from "./auth"; -import { useAuthStore } from "@/stores/useAuthStore"; export const api = axios.create({ baseURL: import.meta.env.VITE_API_URL as string | undefined, @@ -48,8 +50,7 @@ api.interceptors.response.use( const data = res.data; if (isApiResponse(data)) { const responseData: ApiResponseWithFlags = data; - const failed = - responseData.success === false || responseData.isSuccess === false; + const failed = responseData.success === false || responseData.isSuccess === false; if (failed) { return Promise.reject({ @@ -86,10 +87,7 @@ api.interceptors.response.use( } // 이미 재시도한 요청이거나, 재발급 요청 자체가 실패인 경우 -> 로그아웃 - if ( - originalRequest._retry || - originalRequest.url?.includes("/api/auth/reissue") - ) { + if (originalRequest._retry || originalRequest.url?.includes("/api/auth/reissue")) { clearAuth(); return Promise.reject(apiError); } diff --git a/src/api/bookings.ts b/src/api/bookings.ts index 80b37cc..024635c 100644 --- a/src/api/bookings.ts +++ b/src/api/bookings.ts @@ -36,17 +36,11 @@ export const getBookings = async ( const params: GetBookingParams = { page }; if (status) params.status = status; - const response = await api.get<{ result: BookingResponse }>( - "/api/v1/users/bookings", - { params }, - ); + const response = await api.get<{ result: BookingResponse }>("/api/v1/users/bookings", { params }); return response.data.result as BookingResponse; }; -export const cancelBooking = async ( - bookingId: number, - reason: string = "사용자 취소", -) => { +export const cancelBooking = async (bookingId: number, reason: string = "사용자 취소") => { const response = await api.patch(`/api/v1/bookings/${bookingId}/cancel`, { reason, }); diff --git a/src/api/dto/store.dto.ts b/src/api/dto/store.dto.ts index 1c962cf..ce40038 100644 --- a/src/api/dto/store.dto.ts +++ b/src/api/dto/store.dto.ts @@ -1,9 +1,4 @@ -export type CategoryDTO = - | "KOREAN" - | "CHINESE" - | "JAPANESE" - | "WESTERN" - | "CAFE"; +export type CategoryDTO = "KOREAN" | "CHINESE" | "JAPANESE" | "WESTERN" | "CAFE"; export type DayDTO = | "MONDAY" diff --git a/src/api/endpoints/bookings.ts b/src/api/endpoints/bookings.ts index 5c89b03..9619b5b 100644 --- a/src/api/endpoints/bookings.ts +++ b/src/api/endpoints/bookings.ts @@ -36,8 +36,6 @@ type UserBookingsResult = { }; export async function getUserBookings(page = 1) { - const res = await api.get>( - `/api/v1/users/bookings?page=${page}`, - ); + const res = await api.get>(`/api/v1/users/bookings?page=${page}`); return res.data.result; } diff --git a/src/api/endpoints/member.ts b/src/api/endpoints/member.ts index b1b57a1..0d5aa08 100644 --- a/src/api/endpoints/member.ts +++ b/src/api/endpoints/member.ts @@ -36,10 +36,7 @@ export async function patchMemberInfo(body: PatchMemberInfo) { export async function putProfileImage(file: File) { const formData = new FormData(); formData.append("profileImage", file); - const res = await api.put>( - "/api/v1/member/profile-image", - formData, - ); + const res = await api.put>("/api/v1/member/profile-image", formData); if (!res.data.isSuccess) { throw new Error(res.data.message ?? "프로필 업로드 실패"); } @@ -58,10 +55,7 @@ type ChangePasswordResponse = { message: string; }; export async function putChangePassword(body: ChangePasswordRequest) { - const res = await api.put>( - "/api/v1/member/password", - body, - ); + const res = await api.put>("/api/v1/member/password", body); return res.data.result; } diff --git a/src/api/endpoints/menus.ts b/src/api/endpoints/menus.ts index 1494818..39a0184 100644 --- a/src/api/endpoints/menus.ts +++ b/src/api/endpoints/menus.ts @@ -1,4 +1,5 @@ import type { MenuCategory, MenuItem } from "@/types/menus"; + import { api } from "../axios"; type ApiResult = { @@ -24,9 +25,7 @@ type MenuListResult = { }; export async function getMenus(storeId: string): Promise { - const { data } = await api.get>( - `/api/v1/stores/${storeId}/menus`, - ); + const { data } = await api.get>(`/api/v1/stores/${storeId}/menus`); if (!data?.isSuccess) { throw { status: 0, diff --git a/src/api/endpoints/payments.ts b/src/api/endpoints/payments.ts index 83296d5..c3d20d2 100644 --- a/src/api/endpoints/payments.ts +++ b/src/api/endpoints/payments.ts @@ -17,10 +17,7 @@ type PaymentRequestResult = { }; export async function requestPayment(body: { bookingId: number }) { - const res = await api.post>( - `/api/v1/payments/request`, - body, - ); + const res = await api.post>(`/api/v1/payments/request`, body); if (!res.data?.isSuccess) { throw { status: 0, @@ -47,9 +44,6 @@ export async function confirmPayment(body: { orderId: string; amount: number; }) { - const res = await api.post>( - "/api/v1/payments/confirm", - body, - ); + const res = await api.post>("/api/v1/payments/confirm", body); return res.data.result; } diff --git a/src/api/endpoints/reservations.ts b/src/api/endpoints/reservations.ts index abe58e7..9ce56c4 100644 --- a/src/api/endpoints/reservations.ts +++ b/src/api/endpoints/reservations.ts @@ -18,9 +18,7 @@ type AvailableTimesResult = { availableTimes: string[]; }; -export async function getAvailableTimes( - params: GetAvailableTimesParams, -): Promise { +export async function getAvailableTimes(params: GetAvailableTimesParams): Promise { const { storeId, ...query } = params; const { data } = await api.get>( diff --git a/src/api/inquiry.ts b/src/api/inquiry.ts index b7c0e81..36c2a08 100644 --- a/src/api/inquiry.ts +++ b/src/api/inquiry.ts @@ -3,14 +3,10 @@ import type { SupportFormValues, } from "@/components/customer-support/support.schema"; import type { ApiResponse } from "@/types/api"; + import { api } from "./axios"; -export const postInquiry = async ( - body: SupportFormValues, -): Promise => { - const { data } = await api.post>( - "/api/v1/inquiries", - body, - ); +export const postInquiry = async (body: SupportFormValues): Promise => { + const { data } = await api.post>("/api/v1/inquiries", body); return data.result; }; diff --git a/src/api/menu.ts b/src/api/menu.ts index 9ba4a2c..f9cc470 100644 --- a/src/api/menu.ts +++ b/src/api/menu.ts @@ -5,6 +5,7 @@ import type { ResponseMenuCreateDto, ResponseMenuImageDto, } from "@/types/menus"; + import { api } from "./axios"; export const postMenuCreate = async ( diff --git a/src/api/owner/menus.ts b/src/api/owner/menus.ts index d0193ed..c00637e 100644 --- a/src/api/owner/menus.ts +++ b/src/api/owner/menus.ts @@ -1,7 +1,9 @@ import axios from "axios"; -import { api } from "../axios"; + import type { ApiResponse } from "@/types/api"; +import { api } from "../axios"; + interface ServerMenu { menuId: number; name: string; @@ -61,20 +63,14 @@ interface DeleteMenusResponse { } export async function getMenus(storeId: string | number) { - const res = await api.get>( - `/api/v1/stores/${storeId}/menus`, - ); + const res = await api.get>(`/api/v1/stores/${storeId}/menus`); return res.data; } -export async function createMenus( - storeId: string | number, - menus: MenuCreateItem[], -) { - const res = await api.post>( - `/api/v1/stores/${storeId}/menus`, - { menus }, - ); +export async function createMenus(storeId: string | number, menus: MenuCreateItem[]) { + const res = await api.post>(`/api/v1/stores/${storeId}/menus`, { + menus, + }); return res.data; } @@ -82,9 +78,10 @@ export async function uploadMenuImage(storeId: string | number, file: File) { const formData = new FormData(); formData.append("image", file); - const res = await api.post< - ApiResponse<{ imageKey: string; imageUrl: string }> - >(`/api/v1/stores/${storeId}/menus/images`, formData); + const res = await api.post>( + `/api/v1/stores/${storeId}/menus/images`, + formData, + ); return res.data; } @@ -145,8 +142,9 @@ export async function updateMenuSoldOut( isSoldOut: boolean, ) { const body = { isSoldOut }; - const res = await api.patch< - ApiResponse<{ menuId: number; isSoldOut: boolean }> - >(`/api/v1/stores/${storeId}/menus/${menuId}/sold-out`, body); + const res = await api.patch>( + `/api/v1/stores/${storeId}/menus/${menuId}/sold-out`, + body, + ); return res.data; } diff --git a/src/api/owner/reservation.ts b/src/api/owner/reservation.ts index 93eabd6..f050b7d 100644 --- a/src/api/owner/reservation.ts +++ b/src/api/owner/reservation.ts @@ -1,6 +1,7 @@ -import { api } from "../axios"; import type { ApiResponse } from "@/types/api"; +import { api } from "../axios"; + export interface Slot { time: string; status: "AVAILABLE" | "BOOKED" | "BLOCKED"; @@ -38,42 +39,24 @@ interface BookingDetailResult { } export const getTableSlots = (storeId: number, tableId: number, date: string) => - api.get>( - `/api/v1/stores/${storeId}/tables/${tableId}/slots`, - { params: { date } }, - ); + api.get>(`/api/v1/stores/${storeId}/tables/${tableId}/slots`, { + params: { date }, + }); -export const updateTableSlotStatus = ( - storeId: number, - tableId: number, - body: UpdateSlotRequest, -) => +export const updateTableSlotStatus = (storeId: number, tableId: number, body: UpdateSlotRequest) => api.patch>( `/api/v1/stores/${storeId}/tables/${tableId}/slots`, body, ); -export const patchBreakTime = ( - storeId: number, - body: PatchBreakTimeRequest, -) => { +export const patchBreakTime = (storeId: number, body: PatchBreakTimeRequest) => { return api.patch(`/api/v1/stores/${storeId}/break-time`, body); }; -export const getBookingDetail = ( - storeId: number, - tableId: number, - bookingId: number, -) => +export const getBookingDetail = (storeId: number, tableId: number, bookingId: number) => api.get>( `/api/v1/stores/${storeId}/tables/${tableId}/slots/${bookingId}`, ); -export const cancelBookingByOwner = ( - storeId: number, - tableId: number, - bookingId: number, -) => - api.patch( - `/api/v1/stores/${storeId}/tables/${tableId}/slots/${bookingId}/cancel`, - ); +export const cancelBookingByOwner = (storeId: number, tableId: number, bookingId: number) => + api.patch(`/api/v1/stores/${storeId}/tables/${tableId}/slots/${bookingId}/cancel`); diff --git a/src/api/owner/storeLayout.ts b/src/api/owner/storeLayout.ts index f22c065..cae1d9e 100644 --- a/src/api/owner/storeLayout.ts +++ b/src/api/owner/storeLayout.ts @@ -1,7 +1,9 @@ +import axios from "axios"; + import type { ApiResponse } from "@/types/api"; -import { api } from "../axios"; import type { SeatsType } from "@/types/table"; -import axios from "axios"; + +import { api } from "../axios"; export interface LayoutTable { tableId: number; @@ -42,9 +44,7 @@ interface CreateTableResponse { tableImageUrl: string | null; } -export const getActiveLayout = async ( - storeId: number, -): Promise => { +export const getActiveLayout = async (storeId: number): Promise => { try { const res = await api.get(`/api/v1/stores/${storeId}/layouts`); if (res.status === 200 && res.data.isSuccess) { @@ -64,16 +64,12 @@ export const getActiveLayout = async ( } }; -export const createLayout = async ( - storeId: number, - gridCol: number, - gridRow: number, -) => { +export const createLayout = async (storeId: number, gridCol: number, gridRow: number) => { try { - const res = await api.post>( - `/api/v1/stores/${storeId}/layouts`, - { gridCol, gridRow }, - ); + const res = await api.post>(`/api/v1/stores/${storeId}/layouts`, { + gridCol, + gridRow, + }); if (res.status === 201 || (res.status === 200 && res.data.isSuccess)) { return res.data.result; } diff --git a/src/api/owner/stores.ts b/src/api/owner/stores.ts index 093b9e4..4d8c6df 100644 --- a/src/api/owner/stores.ts +++ b/src/api/owner/stores.ts @@ -15,14 +15,7 @@ interface StoreDetail { } interface BusinessHour { - day: - | "MONDAY" - | "TUESDAY" - | "WEDNESDAY" - | "THURSDAY" - | "FRIDAY" - | "SATURDAY" - | "SUNDAY"; + day: "MONDAY" | "TUESDAY" | "WEDNESDAY" | "THURSDAY" | "FRIDAY" | "SATURDAY" | "SUNDAY"; openTime: string | null; closeTime: string | null; isClosed: boolean; @@ -71,16 +64,10 @@ export function updateStore( phoneNumber: string; }, ) { - return api.patch>( - `/api/v1/stores/${storeId}`, - body, - ); + return api.patch>(`/api/v1/stores/${storeId}`, body); } -export function updateBusinessHours( - storeId: number | string, - businessHours: BusinessHour[], -) { +export function updateBusinessHours(storeId: number | string, businessHours: BusinessHour[]) { return api.patch>( `/api/v1/stores/${storeId}/business-hours`, { businessHours }, @@ -92,9 +79,7 @@ export const getMyStores = async (): Promise => { return res.data.result.stores ?? []; }; -export const getTableImages = async ( - storeId: number | string, -): Promise => { +export const getTableImages = async (storeId: number | string): Promise => { const res = await api.get>( `/api/v1/stores/${storeId}/table-images`, ); diff --git a/src/api/owner/table.ts b/src/api/owner/table.ts index 88cb415..2cec825 100644 --- a/src/api/owner/table.ts +++ b/src/api/owner/table.ts @@ -1,7 +1,9 @@ -import { api } from "../axios"; -import type { ApiResponse } from "@/types/api"; import type { AxiosProgressEvent } from "axios"; +import type { ApiResponse } from "@/types/api"; + +import { api } from "../axios"; + interface UploadTableImageResult { tableId: number; tableImageUrl: string; @@ -49,11 +51,7 @@ export const deleteTableImage = ( return api.delete(`/api/v1/stores/${storeId}/tables/${tableId}/table-image`); }; -export const patchTableInfo = ( - storeId: number, - tableId: number, - body: PatchTableRequest, -) => +export const patchTableInfo = (storeId: number, tableId: number, body: PatchTableRequest) => api.patch>( `/api/v1/stores/${storeId}/tables/${tableId}`, body, diff --git a/src/api/store.ts b/src/api/store.ts index 365da90..86c15aa 100644 --- a/src/api/store.ts +++ b/src/api/store.ts @@ -1,19 +1,17 @@ +import type { ApiResponse } from "@/types/api"; import type { RequestMainImageDto, RequestStoreCreateDto, ResponseMainImageDto, ResponseStoreCreateDto, } from "@/types/store"; + import { api } from "./axios"; -import type { ApiResponse } from "@/types/api"; export const postRegisterStore = async ( body: RequestStoreCreateDto, ): Promise => { - const { data } = await api.post>( - "/api/v1/stores", - body, - ); + const { data } = await api.post>("/api/v1/stores", body); return data.result; }; diff --git a/src/components/RouteGuards.tsx b/src/components/RouteGuards.tsx index 75f570d..ab3c803 100644 --- a/src/components/RouteGuards.tsx +++ b/src/components/RouteGuards.tsx @@ -1,6 +1,7 @@ -import { useAuthStore } from "@/stores/useAuthStore"; import { Navigate, Outlet } from "react-router-dom"; +import { useAuthStore } from "@/stores/useAuthStore"; + export const PrivateRoute = () => { const isAuthenticated = useAuthStore((state) => state.isAuthenticated); const hasHydrated = useAuthStore((state) => state.hasHydrated); diff --git a/src/components/auth/ChangePasswordDiaLog.tsx b/src/components/auth/ChangePasswordDiaLog.tsx index a2f3834..503a84a 100644 --- a/src/components/auth/ChangePasswordDiaLog.tsx +++ b/src/components/auth/ChangePasswordDiaLog.tsx @@ -1,19 +1,19 @@ -import { putChangePassword } from "@/api/endpoints/member"; import { zodResolver } from "@hookform/resolvers/zod"; import { useMutation } from "@tanstack/react-query"; +import axios from "axios"; +import { X } from "lucide-react"; import { useForm } from "react-hook-form"; import { z } from "zod"; + +import { putChangePassword } from "@/api/endpoints/member"; + import { Button } from "../ui/button"; -import { X } from "lucide-react"; -import axios from "axios"; const schema = z .object({ currentPassword: z.string().min(1, "현재 비밀번호를 입력해주세요"), newPassword: z.string().min(8, "비밀번호는 8자 이상이어야 합니다"), - newPasswordConfirm: z - .string() - .min(1, "변경하실 비밀번호를 한번더 눌러주세요"), + newPasswordConfirm: z.string().min(1, "변경하실 비밀번호를 한번더 눌러주세요"), }) .refine((v) => v.newPassword === v.newPasswordConfirm, { message: "새 비밀번호와 확인이 일치하지 않습니다.", @@ -119,9 +119,7 @@ export function ChangePasswordDialog({ disabled={isPending} /> {form.formState.errors.newPassword && ( -

- {form.formState.errors.newPassword.message} -

+

{form.formState.errors.newPassword.message}

)}
diff --git a/src/components/auth/LoginDialog.tsx b/src/components/auth/LoginDialog.tsx index 71fbaa3..79b6b40 100644 --- a/src/components/auth/LoginDialog.tsx +++ b/src/components/auth/LoginDialog.tsx @@ -1,32 +1,30 @@ +import { zodResolver } from "@hookform/resolvers/zod"; import { useEffect, useState } from "react"; +import { useForm } from "react-hook-form"; + +import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, - DialogTitle, - DialogHeader, DialogDescription, + DialogHeader, + DialogTitle, } from "@/components/ui/dialog"; -import { Button } from "@/components/ui/button"; -import { Separator } from "@/components/ui/separator"; -import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; -import { useForm } from "react-hook-form"; -import { type LoginFormValues, loginSchema } from "./Login.schema"; -import { zodResolver } from "@hookform/resolvers/zod"; +import { Label } from "@/components/ui/label"; +import { Separator } from "@/components/ui/separator"; import { useEmailLogin } from "@/hooks/queries/useAuth"; import { getErrorMessage } from "@/utils/error"; +import { type LoginFormValues, loginSchema } from "./Login.schema"; + interface LoginDialogProps { isOpen: boolean; onClose: () => void; onSwitchToSignup: () => void; } -export function LoginDialog({ - isOpen, - onClose, - onSwitchToSignup, -}: LoginDialogProps) { +export function LoginDialog({ isOpen, onClose, onSwitchToSignup }: LoginDialogProps) { const emailLoginMutation = useEmailLogin(); const [showEmailLogin, setShowEmailLogin] = useState(false); @@ -92,11 +90,7 @@ export function LoginDialog({ className="w-full h-12 text-base cursor-pointer" onClick={() => handleSocialLogin("google")} > - Google Logo + Google Logo 구글로 계속하기 @@ -106,11 +100,7 @@ export function LoginDialog({ className="w-full h-12 text-base bg-[#FEE500] hover:bg-[#E6CF00] border-0 cursor-pointer text-black" onClick={() => handleSocialLogin("kakao")} > - Kakao Logo + Kakao Logo 카카오톡으로 계속하기
@@ -133,10 +123,7 @@ export function LoginDialog({ ) : ( <> -
+
- {errors.email && ( -

- {errors.email.message} -

- )} + {errors.email &&

{errors.email.message}

}
@@ -163,9 +146,7 @@ export function LoginDialog({ {...register("password")} /> {errors.password && ( -

- {errors.password.message} -

+

{errors.password.message}

)}
diff --git a/src/components/auth/Signup.schema.ts b/src/components/auth/Signup.schema.ts index 43d4c55..5b2d887 100644 --- a/src/components/auth/Signup.schema.ts +++ b/src/components/auth/Signup.schema.ts @@ -28,8 +28,7 @@ export const signupSchema = z .min(8, { message: "비밀번호는 8자 이상이어야 합니다." }) .max(20, { message: "비밀번호는 20자 이하여야 합니다." }) .regex(/^[a-zA-Z0-9!@#$%^&*]+$/, { - message: - "비밀번호는 영문, 숫자, 특수문자(! @ # $ % ^ & *)만 사용 가능합니다.", + message: "비밀번호는 영문, 숫자, 특수문자(! @ # $ % ^ & *)만 사용 가능합니다.", }) .refine( (value) => { @@ -37,9 +36,7 @@ export const signupSchema = z const hasNumber = /\d/.test(value); const hasSpecial = /[!@#$%^&*]/.test(value); - const validCount = [hasLetter, hasNumber, hasSpecial].filter( - (v) => v, - ).length; + const validCount = [hasLetter, hasNumber, hasSpecial].filter((v) => v).length; return validCount >= 2; }, @@ -55,9 +52,7 @@ export const signupSchema = z message: "필수 약관에 동의해주세요.", }), - privacyConsent: z - .boolean() - .refine((v) => v === true, { message: "필수 약관에 동의해주세요." }), + privacyConsent: z.boolean().refine((v) => v === true, { message: "필수 약관에 동의해주세요." }), marketingConsent: z.boolean().default(false), }) diff --git a/src/components/auth/SignupDialog.tsx b/src/components/auth/SignupDialog.tsx index 32880b6..0e79645 100644 --- a/src/components/auth/SignupDialog.tsx +++ b/src/components/auth/SignupDialog.tsx @@ -1,22 +1,24 @@ +import { zodResolver } from "@hookform/resolvers/zod"; +import { useEffect } from "react"; +import { Controller, useForm } from "react-hook-form"; + +import { Button } from "@/components/ui/button"; +import { Checkbox } from "@/components/ui/checkbox"; import { Dialog, DialogContent, - DialogTitle, - DialogHeader, DialogDescription, + DialogHeader, + DialogTitle, } from "@/components/ui/dialog"; -import { Button } from "@/components/ui/button"; -import { Separator } from "@/components/ui/separator"; -import { Label } from "@/components/ui/label"; import { Input } from "@/components/ui/input"; -import { Checkbox } from "@/components/ui/checkbox"; -import { useForm, Controller } from "react-hook-form"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { signupSchema, type SignupFormValues } from "./Signup.schema"; -import { useEffect } from "react"; -import { phoneNumber } from "@/utils/phoneNumber"; +import { Label } from "@/components/ui/label"; +import { Separator } from "@/components/ui/separator"; import { useEmailSignup } from "@/hooks/queries/useAuth"; import { getErrorMessage } from "@/utils/error"; +import { phoneNumber } from "@/utils/phoneNumber"; + +import { type SignupFormValues, signupSchema } from "./Signup.schema"; interface SignupDialogProps { isOpen: boolean; @@ -35,11 +37,7 @@ const defaultValues: SignupFormValues = { marketingConsent: false, }; -export function SignupDialog({ - isOpen, - onClose, - onSwitchToLogin, -}: SignupDialogProps) { +export function SignupDialog({ isOpen, onClose, onSwitchToLogin }: SignupDialogProps) { const signupMutation = useEmailSignup(); const { @@ -84,9 +82,7 @@ export function SignupDialog({ !open && onClose()}> - - 회원가입 - + 회원가입 이메일과 소셜 계정으로 회원가입을 할 수 있는 폼 @@ -100,11 +96,7 @@ export function SignupDialog({ className="w-full h-12 text-base cursor-pointer" onClick={() => handleSocialLogin("google")} > - Google Logo + Google Logo 구글로 가입하기 @@ -114,11 +106,7 @@ export function SignupDialog({ className="w-full h-12 text-base bg-[#FEE500] hover:bg-[#E6CF00] border-0 cursor-pointer text-black" onClick={() => handleSocialLogin("kakao")} > - Kakao Logo + Kakao Logo 카카오톡으로 가입하기 @@ -139,9 +127,7 @@ export function SignupDialog({ className="h-12" {...register("name")} /> - {errors.name && ( -

{errors.name.message}

- )} + {errors.name &&

{errors.name.message}

}
@@ -153,9 +139,7 @@ export function SignupDialog({ className="h-12" {...register("email")} /> - {errors.email && ( -

{errors.email.message}

- )} + {errors.email &&

{errors.email.message}

}
@@ -178,9 +162,7 @@ export function SignupDialog({ )} /> {errors.phoneNumber && ( -

- {errors.phoneNumber.message} -

+

{errors.phoneNumber.message}

)}
@@ -193,11 +175,7 @@ export function SignupDialog({ className="h-12" {...register("password")} /> - {errors.password && ( -

- {errors.password.message} -

- )} + {errors.password &&

{errors.password.message}

}
@@ -210,9 +188,7 @@ export function SignupDialog({ {...register("passwordConfirm")} /> {errors.passwordConfirm && ( -

- {errors.passwordConfirm.message} -

+

{errors.passwordConfirm.message}

)}
@@ -235,9 +211,7 @@ export function SignupDialog({ {errors.tosConsent && ( -

- {errors.tosConsent.message} -

+

{errors.tosConsent.message}

)}
@@ -254,14 +228,11 @@ export function SignupDialog({ )} />
{errors.privacyConsent && ( -

- {errors.privacyConsent.message} -

+

{errors.privacyConsent.message}

)}
diff --git a/src/components/auth/WithdrawDialog.tsx b/src/components/auth/WithdrawDialog.tsx index 01df2b1..8ff04ec 100644 --- a/src/components/auth/WithdrawDialog.tsx +++ b/src/components/auth/WithdrawDialog.tsx @@ -1,12 +1,14 @@ -import { deleteWithDraw } from "@/api/endpoints/member"; -import { useAuthStore } from "@/stores/useAuthStore"; import { useMutation } from "@tanstack/react-query"; -import { useNavigate } from "react-router-dom"; -import { Button } from "../ui/button"; +import axios from "axios"; import { X } from "lucide-react"; import { useState } from "react"; +import { useNavigate } from "react-router-dom"; + import { logout as performLogout } from "@/api/auth"; -import axios from "axios"; +import { deleteWithDraw } from "@/api/endpoints/member"; +import { useAuthStore } from "@/stores/useAuthStore"; + +import { Button } from "../ui/button"; function isWithdrawBlockByBookings(e: unknown) { if (!axios.isAxiosError(e)) return false; @@ -105,9 +107,7 @@ export function WithdrawDialog({ > {blocked ? ( <> -

- 예약 내역이 있어 탈퇴가 불가능합니다. -

+

예약 내역이 있어 탈퇴가 불가능합니다.

예약 현황에서 예약을 취소한 후에 다시 시도해주세요.

@@ -117,9 +117,7 @@ export function WithdrawDialog({

탈퇴하면 계정이 비활성화되며 서비스 이용이 불가합니다.

-

- 탈퇴후에는 동일 계정으로 다시 로그인할 수 없습니다. -

+

탈퇴후에는 동일 계정으로 다시 로그인할 수 없습니다.

)}
diff --git a/src/components/customer-support/SupportCompleteModal.tsx b/src/components/customer-support/SupportCompleteModal.tsx index 9de5a29..f4a4301 100644 --- a/src/components/customer-support/SupportCompleteModal.tsx +++ b/src/components/customer-support/SupportCompleteModal.tsx @@ -1,5 +1,6 @@ import { Send, X } from "lucide-react"; import { useEffect } from "react"; + import { Dialog, DialogContent, @@ -46,9 +47,7 @@ export default function SupportCompleteModal({ {/* 스크린 리더용 설명(경고 방지) */} - - 1:1 문의 내용 완료 모달 - + 1:1 문의 내용 완료 모달
diff --git a/src/components/customer-support/SupportFAQ.tsx b/src/components/customer-support/SupportFAQ.tsx index a8021a8..472553a 100644 --- a/src/components/customer-support/SupportFAQ.tsx +++ b/src/components/customer-support/SupportFAQ.tsx @@ -1,5 +1,6 @@ import { ChevronDown, Search, X } from "lucide-react"; import { useState } from "react"; + import { faqData } from "./faqData"; export default function SupportFAQ() { @@ -12,14 +13,12 @@ export default function SupportFAQ() { const filteredFaqs = faqData.filter((item) => { // 카테고리 매칭 여부 - const matchCategory = - selectedCategory === "전체" || item.category === selectedCategory; + const matchCategory = selectedCategory === "전체" || item.category === selectedCategory; // 검색어 매칭 여부 const query = searchTerm.toLowerCase().trim(); const matchSearch = - item.question.toLowerCase().includes(query) || - item.answer.toLowerCase().includes(query); + item.question.toLowerCase().includes(query) || item.answer.toLowerCase().includes(query); // 둘다 매칭되는 항목만 반환 return matchCategory && matchSearch; @@ -135,8 +134,7 @@ export default function SupportFAQ() {
- 총 {filteredFaqs.length}개의 - 질문이 있습니다. + 총 {filteredFaqs.length}개의 질문이 있습니다.
); diff --git a/src/components/customer-support/SupportHero.tsx b/src/components/customer-support/SupportHero.tsx index 310460d..698d996 100644 --- a/src/components/customer-support/SupportHero.tsx +++ b/src/components/customer-support/SupportHero.tsx @@ -1,7 +1,8 @@ import { MessageCircle } from "lucide-react"; import { useState } from "react"; -import SupportModal from "./SupportModal"; + import SupportCompleteModal from "./SupportCompleteModal"; +import SupportModal from "./SupportModal"; export default function SupportHero() { const [isModalOpen, setIsModalOpen] = useState(false); @@ -13,8 +14,7 @@ export default function SupportHero() {

무엇을 도와드릴까요?

- 자주 묻는 질문을 확인하시거나, 1:1 문의를 통해 더 자세한 도움을 - 받으실 수 있습니다. + 자주 묻는 질문을 확인하시거나, 1:1 문의를 통해 더 자세한 도움을 받으실 수 있습니다.

{/* 스크린 리더용 설명(경고 방지) */} - - 1:1 문의 내용을 작성하는 폼 - + 1:1 문의 내용을 작성하는 폼
@@ -120,9 +116,7 @@ export default function SupportModal({ className={inputStyle} {...register("name")} /> - {errors.name && ( -

{errors.name.message}

- )} + {errors.name &&

{errors.name.message}

}
{/* 이메일 */} @@ -138,9 +132,7 @@ export default function SupportModal({ className={inputStyle} {...register("email")} /> - {errors.email && ( -

{errors.email.message}

- )} + {errors.email &&

{errors.email.message}

}
@@ -149,11 +141,7 @@ export default function SupportModal({ - {Object.entries(SUPPORT_TYPE_LABEL).map(([value, label]) => (