diff --git a/jest.setup.ts b/jest.setup.ts index 9033ca27..f0897467 100644 --- a/jest.setup.ts +++ b/jest.setup.ts @@ -1,6 +1,6 @@ import "@testing-library/jest-dom"; -import { server } from "@/mocks/server"; +import { server } from "@/shared/mock/server"; // 모든 테스트가 시작하기 전 MSW 서버를 시작 beforeAll(() => server.listen({ onUnhandledRequest: "error" })); diff --git a/package.json b/package.json index 9c06e815..93b17878 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,9 @@ "dev:full": "concurrently \"next dev\" \"pnpm run mock\"", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build", - "chromatic": "npx chromatic --project-token=chpt_c93820598942000" + "chromatic": "npx chromatic --project-token=chpt_c93820598942000", + "steiger": "npx steiger ./src", + "steiger:watch": "npx steiger ./src --watch" }, "lint-staged": { "*.{js,jsx,ts,tsx}": [ @@ -43,6 +45,7 @@ }, "devDependencies": { "@chromatic-com/storybook": "^5.0.1", + "@feature-sliced/steiger-plugin": "^0.5.7", "@storybook/addon-a11y": "^10.2.19", "@storybook/addon-docs": "^10.2.19", "@storybook/addon-onboarding": "^10.2.19", @@ -77,6 +80,7 @@ "playwright": "^1.58.2", "prettier": "^3.8.1", "prettier-plugin-tailwindcss": "^0.7.2", + "steiger": "^0.5.11", "storybook": "^10.2.19", "tailwindcss": "^4", "ts-node": "^10.9.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a4d38640..c6bdff3c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -60,6 +60,9 @@ importers: '@chromatic-com/storybook': specifier: ^5.0.1 version: 5.0.1(storybook@10.2.19(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)) + '@feature-sliced/steiger-plugin': + specifier: ^0.5.7 + version: 0.5.7(typescript@5.9.3) '@storybook/addon-a11y': specifier: ^10.2.19 version: 10.2.19(storybook@10.2.19(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)) @@ -162,6 +165,9 @@ importers: prettier-plugin-tailwindcss: specifier: ^0.7.2 version: 0.7.2(prettier@3.8.1) + steiger: + specifier: ^0.5.11 + version: 0.5.11(typescript@5.9.3) storybook: specifier: ^10.2.19 version: 10.2.19(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -304,6 +310,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5': resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==} engines: {node: '>=6.9.0'} @@ -846,6 +857,12 @@ packages: peerDependencies: storybook: ^0.0.0-0 || ^10.1.0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0 + '@clack/core@0.4.1': + resolution: {integrity: sha512-Pxhij4UXg8KSr7rPek6Zowm+5M22rbd2g1nfojHJkxp5YkFqiZ2+YLEM/XGVIzvGOcM0nqjIFxrpDwWRZYWYjA==} + + '@clack/prompts@0.9.1': + resolution: {integrity: sha512-JIpyaboYZeWYlyP0H+OoPPxd6nqueG/CmN6ixBiNFsIDHREevjIf0n0Ohh5gr5C8pEDknzgvz+pIJ8dMhzWIeg==} + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -878,6 +895,10 @@ packages: resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} engines: {node: '>=18'} + '@dependents/detective-less@5.0.2': + resolution: {integrity: sha512-QPKO4ao2+iniYAYnPZwHKK67EgDG2GAdye9OCy11xsmApHGwzpH3AcSdPjGyPO3tC2/K8mF7JjWX3A/FTRnskg==} + engines: {node: '>=18'} + '@emnapi/core@1.8.1': resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} @@ -1081,6 +1102,12 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@feature-sliced/filesystem@3.1.0': + resolution: {integrity: sha512-kdNcVwJMCiORdi2Aog7epDeQMEREFUvdqqQHmE7D3ZjSdsQzZWMH6Ex7gtGAttTT/oRBFysqCtP5pl0CETEc9Q==} + + '@feature-sliced/steiger-plugin@0.5.7': + resolution: {integrity: sha512-xENW2fvfU+UyMgcB3S+CCMPrH2Tq/BG1W9IxGp5B8+j0TtbgmbzT3DIj3A2HG4kouVYUjzgWA6JIuHbGo3lDzg==} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -1653,6 +1680,10 @@ packages: '@sinclair/typebox@0.34.48': resolution: {integrity: sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==} + '@sindresorhus/merge-streams@2.3.0': + resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} + engines: {node: '>=18'} + '@sinonjs/commons@3.0.1': resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} @@ -2108,6 +2139,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/project-service@8.59.0': + resolution: {integrity: sha512-Lw5ITrR5s5TbC19YSvlr63ZfLaJoU6vtKTHyB0GQOpX0W7d5/Ir6vUahWi/8Sps/nOukZQ0IB3SmlxZnjaKVnw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/scope-manager@8.57.0': resolution: {integrity: sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2118,6 +2155,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/tsconfig-utils@8.59.0': + resolution: {integrity: sha512-91Sbl3s4Kb3SybliIY6muFBmHVv+pYXfybC4Oolp3dvk8BvIE3wOPc+403CWIT7mJNkfQRGtdqghzs2+Z91Tqg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/type-utils@8.57.0': resolution: {integrity: sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2129,12 +2172,22 @@ packages: resolution: {integrity: sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.59.0': + resolution: {integrity: sha512-nLzdsT1gdOgFxxxwrlNVUBzSNBEEHJ86bblmk4QAS6stfig7rcJzWKqCyxFy3YRRHXDWEkb2NralA1nOYkkm/A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.57.0': resolution: {integrity: sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/typescript-estree@8.59.0': + resolution: {integrity: sha512-O9Re9P1BmBLFJyikRbQpLku/QA3/AueZNO9WePLBwQrvkixTmDe8u76B6CYUAITRl/rHawggEqUGn5QIkVRLMw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/utils@8.57.0': resolution: {integrity: sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2146,6 +2199,10 @@ packages: resolution: {integrity: sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.59.0': + resolution: {integrity: sha512-/uejZt4dSere1bx12WLlPfv8GktzcaDtuJ7s42/HEZ5zGj9oxRaD4bj7qwSunXkf+pbAhFt2zjpHYUiT5lHf0Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} @@ -2368,6 +2425,21 @@ packages: '@vitest/utils@4.1.0': resolution: {integrity: sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==} + '@vue/compiler-core@3.5.32': + resolution: {integrity: sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ==} + + '@vue/compiler-dom@3.5.32': + resolution: {integrity: sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q==} + + '@vue/compiler-sfc@3.5.32': + resolution: {integrity: sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==} + + '@vue/compiler-ssr@3.5.32': + resolution: {integrity: sha512-Gp4gTs22T3DgRotZ8aA/6m2jMR+GMztvBXUBEUOYOcST+giyGWJ4WvFd7QLHBkzTxkfOt8IELKNdpzITLbA2rw==} + + '@vue/shared@3.5.32': + resolution: {integrity: sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -2473,6 +2545,10 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-module-types@6.0.1: + resolution: {integrity: sha512-WHw67kLXYbZuHTmcdbIrVArCq5wxo6NEuj3hiYAWr8mwJeC+C2mMCIBIWCiDoCye/OF/xelc+teJ1ERoWmnEIA==} + engines: {node: '>=18'} + ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} @@ -2630,6 +2706,10 @@ packages: resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} engines: {node: '>= 16'} + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + chromatic@13.3.5: resolution: {integrity: sha512-MzPhxpl838qJUo0A55osCF2ifwPbjcIPeElr1d4SHcjnHoIcg7l1syJDrAYK/a+PcCBrOGi06jPNpQAln5hWgw==} hasBin: true @@ -2704,6 +2784,10 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + commander@14.0.3: resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} engines: {node: '>=20'} @@ -2739,6 +2823,15 @@ packages: typescript: optional: true + cosmiconfig@9.0.1: + resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} @@ -2865,6 +2958,49 @@ packages: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} + detective-amd@6.0.1: + resolution: {integrity: sha512-TtyZ3OhwUoEEIhTFoc1C9IyJIud3y+xYkSRjmvCt65+ycQuc3VcBrPRTMWoO/AnuCyOB8T5gky+xf7Igxtjd3g==} + engines: {node: '>=18'} + hasBin: true + + detective-cjs@6.1.1: + resolution: {integrity: sha512-pSh7mkCKEtLlmANqLu3KDFS3NV8Hx41jy/JF1/gAWOgU+Uo5QTkeI1tWNP4dWGo4L0E9j18Ez9EPsTleautKqA==} + engines: {node: '>=18'} + + detective-es6@5.0.2: + resolution: {integrity: sha512-+qHHGYhjupiVs4rnIpI9nZ5B130A4AmE35ZX1w33hb46vcZ7T3jfDbvmPw0FhWtMHn5BS5HHu7ZtnZ53bMcXZA==} + engines: {node: '>=18'} + + detective-postcss@7.0.1: + resolution: {integrity: sha512-bEOVpHU9picRZux5XnwGsmCN4+8oZo7vSW0O0/Enq/TO5R2pIAP2279NsszpJR7ocnQt4WXU0+nnh/0JuK4KHQ==} + engines: {node: ^14.0.0 || >=16.0.0} + peerDependencies: + postcss: ^8.4.47 + + detective-sass@6.0.1: + resolution: {integrity: sha512-jSGPO8QDy7K7pztUmGC6aiHkexBQT4GIH+mBAL9ZyBmnUIOFbkfZnO8wPRRJFP/QP83irObgsZHCoDHZ173tRw==} + engines: {node: '>=18'} + + detective-scss@5.0.1: + resolution: {integrity: sha512-MAyPYRgS6DCiS6n6AoSBJXLGVOydsr9huwXORUlJ37K3YLyiN0vYHpzs3AdJOgHobBfispokoqrEon9rbmKacg==} + engines: {node: '>=18'} + + detective-stylus@5.0.1: + resolution: {integrity: sha512-Dgn0bUqdGbE3oZJ+WCKf8Dmu7VWLcmRJGc6RCzBgG31DLIyai9WAoEhYRgIHpt/BCRMrnXLbGWGPQuBUrnF0TA==} + engines: {node: '>=18'} + + detective-typescript@14.1.1: + resolution: {integrity: sha512-P0V72pffNrtjHm7kZPiwXeM47l3jF/M3nZ543ZNVWG6sWvYwq95ERoL1+6Txm5Mam8EPVu1gqpHECvoAZsznog==} + engines: {node: '>=18'} + peerDependencies: + typescript: ^5.4.4 || ^6.0.2 + + detective-vue2@2.3.0: + resolution: {integrity: sha512-3gwbZPqVTm9sL9XdZsgEJ7x4x99O853VVZHapQAiEkGuMJMpFPjHDrecSgfqnS5JW3FJfYXesLZGvUOibjn49g==} + engines: {node: '>=18'} + peerDependencies: + typescript: ^5.4.4 || ^6.0.2 + diff@4.0.4: resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==} engines: {node: '>=0.3.1'} @@ -2906,6 +3042,10 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + effector@23.4.4: + resolution: {integrity: sha512-QkZboRN28K/iwxigDhlJcI3ux3aNbt8kYGGH/GkqWG0OlGeyuBhb7PdM89Iu+ogV8Lmz16xIlwnXR2UNWI6psg==} + engines: {node: '>=11.0.0'} + electron-to-chromium@1.5.307: resolution: {integrity: sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==} @@ -2922,6 +3062,10 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + empathic@1.1.0: + resolution: {integrity: sha512-rsPft6CK3eHtrlp9Y5ALBb+hfK+DWnA4WFebbazxjWyx8vSm3rZeoM3z9irsjcqO3PYRzlfv27XIB4tz2DV7RA==} + engines: {node: '>=14'} + empathic@2.0.0: resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} engines: {node: '>=14'} @@ -2938,6 +3082,14 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + environment@1.1.0: resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} engines: {node: '>=18'} @@ -2997,6 +3149,11 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + eslint-config-next@16.1.6: resolution: {integrity: sha512-vKq40io2B0XtkkNDYyleATwblNt8xuh3FWp8SpSz3pt7P01OkBFlKsJZ2mWt5WsCySlDQLckb1zMY9yE9Qy0LA==} peerDependencies: @@ -3197,12 +3354,20 @@ packages: resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} engines: {node: '>=8.6.0'} + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fastest-levenshtein@1.0.16: + resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} + engines: {node: '>= 4.9.1'} + fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} @@ -3284,6 +3449,10 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + get-amd-module-type@6.0.2: + resolution: {integrity: sha512-7zShVYAYtMnj9S65CfN+hvpBCByfuB1OY8xID01nZEzXTZbx4YyysAfi+nMl95JSR6odt4q8TCj2W63KAoyVLQ==} + engines: {node: '>=18'} + get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -3348,9 +3517,18 @@ packages: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} + globby@14.1.0: + resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==} + engines: {node: '>=18'} + globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + gonzales-pe@4.3.0: + resolution: {integrity: sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==} + engines: {node: '>=0.6.0'} + hasBin: true + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -3439,6 +3617,9 @@ packages: engines: {node: '>=16.x'} hasBin: true + immer@10.2.0: + resolution: {integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==} + immer@11.1.4: resolution: {integrity: sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==} @@ -3596,6 +3777,13 @@ packages: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} + is-url-superb@4.0.0: + resolution: {integrity: sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA==} + engines: {node: '>=10'} + + is-url@1.2.4: + resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} + is-weakmap@2.0.2: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} engines: {node: '>= 0.4'} @@ -4038,6 +4226,9 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash-es@4.18.1: + resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} + lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} @@ -4142,6 +4333,11 @@ packages: module-alias@2.3.4: resolution: {integrity: sha512-bOclZt8hkpuGgSSoG07PKmvzTizROilUTvLNyrMqvlC9snhs7y7GzjNWAVbISIOlhCP1T14rH1PDAV9iNyBq/w==} + module-definition@6.0.2: + resolution: {integrity: sha512-SvAU3lB0+Yjbq55yHY3wkRZBOh+fhU1SnIF3IFbTewv6mtAh7yUT8ACHAJ2mGIJ7tCes2QuCL/cl6m0JSZ/ArA==} + engines: {node: '>=18'} + hasBin: true + mrmime@2.0.1: resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} @@ -4210,6 +4406,10 @@ packages: node-releases@2.0.36: resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} + node-source-walk@7.0.1: + resolution: {integrity: sha512-3VW/8JpPqPvnJvseXowjZcirPisssnBuDikk6JIZ8jQzF7KJQX52iPFX4RYYxLycYH7IbMRSPUOga/esVjy5Yg==} + engines: {node: '>=18'} + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -4349,6 +4549,10 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + path-type@6.0.0: + resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==} + engines: {node: '>=18'} + pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -4356,6 +4560,11 @@ packages: resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} engines: {node: '>= 14.16'} + patronum@2.3.0: + resolution: {integrity: sha512-BfKIOpoymVz6XnkOn8Fi5QZ1a3r/3lXdd8BcdHmYDbIXPTIRnD1EPFBFev/DheWnOge6/ZswEqgNF2ANLGOxLw==} + peerDependencies: + effector: ^23 + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -4385,6 +4594,10 @@ packages: engines: {node: '>=18'} hasBin: true + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + pngjs@7.0.0: resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==} engines: {node: '>=14.19.0'} @@ -4393,14 +4606,29 @@ packages: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} + postcss-values-parser@6.0.2: + resolution: {integrity: sha512-YLJpK0N1brcNJrs9WatuJFtHaV9q5aAOj+S4DI5S7jgHlRfm0PIbDCAFRYMQD5SHq7Fy6xsDhyutgS0QOAs0qw==} + engines: {node: '>=10'} + peerDependencies: + postcss: ^8.2.9 + postcss@8.4.31: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} + postcss@8.5.10: + resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==} + engines: {node: ^10 || ^12 || >=14} + postcss@8.5.8: resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} engines: {node: ^10 || ^12 || >=14} + precinct@12.3.1: + resolution: {integrity: sha512-wGyTIvtxh2S2NAHxTJj0YymxWOIcEDotu17yHoQUd2Bz2C07LrS28L1nvXDMxrCHvHmV6KTlaIQy5PzRm7Y8rg==} + engines: {node: '>=18'} + hasBin: true + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -4477,6 +4705,10 @@ packages: resolution: {integrity: sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + prexit@2.3.0: + resolution: {integrity: sha512-mX+LIbtS0anKtl2PykYabxninwloblUQMRO6CubeSmjxb+kKlATuJoH9UeN8NLE4TgIEFWfBXw7V3GkWbBrSmg==} + engines: {node: '>=12'} + prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} @@ -4490,6 +4722,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quote-unquote@1.0.0: + resolution: {integrity: sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg==} + react-docgen-typescript@2.4.0: resolution: {integrity: sha512-ZtAp5XTO5HRzQctjPU0ybY0RRCQO19X/8fxn3w7y2VVTUbGHDKULPTL4ky3vB05euSgG5NpALhEhDPvQ56wvXg==} peerDependencies: @@ -4517,6 +4752,10 @@ packages: resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} engines: {node: '>=0.10.0'} + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + recast@0.23.11: resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} engines: {node: '>= 4'} @@ -4705,10 +4944,17 @@ packages: resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} engines: {node: '>=18'} + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} + slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + slice-ansi@7.1.2: resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} engines: {node: '>=18'} @@ -4751,6 +4997,10 @@ packages: std-env@4.0.0: resolution: {integrity: sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==} + steiger@0.5.11: + resolution: {integrity: sha512-Sv6ovPX8tVlUufvAvGSUnwDQLupccYjcgfK5pbqECGP5KCe9M257U0IbRdjuLfUXfey4FprZWQQtnIz3qOPpWA==} + hasBin: true + stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} @@ -4977,6 +5227,12 @@ packages: peerDependencies: typescript: '>=4.8.4' + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + ts-dedent@2.2.0: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} @@ -5082,6 +5338,10 @@ packages: resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} engines: {node: '>=4'} + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -5347,12 +5607,21 @@ packages: resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} engines: {node: '>=18'} + zod-validation-error@3.5.4: + resolution: {integrity: sha512-+hEiRIiPobgyuFlEojnqjJnhFvg4r/i3cqgcm67eehZf/WBaK3g6cD02YU9mtdVxZjv8CzCA9n/Rhrs3yAAvAw==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.24.4 + zod-validation-error@4.0.2: resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} engines: {node: '>=18.0.0'} peerDependencies: zod: ^3.25.0 || ^4.0.0 + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zod@4.3.6: resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} @@ -5546,6 +5815,10 @@ snapshots: dependencies: '@babel/types': 7.29.0 + '@babel/parser@7.29.2': + dependencies: + '@babel/types': 7.29.0 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 @@ -6216,6 +6489,17 @@ snapshots: - '@chromatic-com/cypress' - '@chromatic-com/playwright' + '@clack/core@0.4.1': + dependencies: + picocolors: 1.1.1 + sisteransi: 1.0.5 + + '@clack/prompts@0.9.1': + dependencies: + '@clack/core': 0.4.1 + picocolors: 1.1.1 + sisteransi: 1.0.5 + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 @@ -6240,6 +6524,11 @@ snapshots: '@csstools/css-tokenizer@3.0.4': {} + '@dependents/detective-less@5.0.2': + dependencies: + gonzales-pe: 4.3.0 + node-source-walk: 7.0.1 + '@emnapi/core@1.8.1': dependencies: '@emnapi/wasi-threads': 1.1.0 @@ -6380,6 +6669,22 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 + '@feature-sliced/filesystem@3.1.0': + dependencies: + typescript: 5.9.3 + + '@feature-sliced/steiger-plugin@0.5.7(typescript@5.9.3)': + dependencies: + '@feature-sliced/filesystem': 3.1.0 + fastest-levenshtein: 1.0.16 + lodash-es: 4.18.1 + pluralize: 8.0.0 + precinct: 12.3.1 + tsconfck: 3.1.6(typescript@5.9.3) + transitivePeerDependencies: + - supports-color + - typescript + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': @@ -6911,6 +7216,8 @@ snapshots: '@sinclair/typebox@0.34.48': {} + '@sindresorhus/merge-streams@2.3.0': {} + '@sinonjs/commons@3.0.1': dependencies: type-detect: 4.0.8 @@ -7407,6 +7714,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/project-service@8.59.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.59.0(typescript@5.9.3) + '@typescript-eslint/types': 8.59.0 + debug: 4.4.3 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@8.57.0': dependencies: '@typescript-eslint/types': 8.57.0 @@ -7416,6 +7732,10 @@ snapshots: dependencies: typescript: 5.9.3 + '@typescript-eslint/tsconfig-utils@8.59.0(typescript@5.9.3)': + dependencies: + typescript: 5.9.3 + '@typescript-eslint/type-utils@8.57.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.57.0 @@ -7430,6 +7750,8 @@ snapshots: '@typescript-eslint/types@8.57.0': {} + '@typescript-eslint/types@8.59.0': {} + '@typescript-eslint/typescript-estree@8.57.0(typescript@5.9.3)': dependencies: '@typescript-eslint/project-service': 8.57.0(typescript@5.9.3) @@ -7445,6 +7767,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.59.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/project-service': 8.59.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.59.0(typescript@5.9.3) + '@typescript-eslint/types': 8.59.0 + '@typescript-eslint/visitor-keys': 8.59.0 + debug: 4.4.3 + minimatch: 10.2.4 + semver: 7.7.4 + tinyglobby: 0.2.15 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@8.57.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) @@ -7461,6 +7798,11 @@ snapshots: '@typescript-eslint/types': 8.57.0 eslint-visitor-keys: 5.0.1 + '@typescript-eslint/visitor-keys@8.59.0': + dependencies: + '@typescript-eslint/types': 8.59.0 + eslint-visitor-keys: 5.0.1 + '@ungap/structured-clone@1.3.0': {} '@unrs/resolver-binding-android-arm-eabi@1.11.1': @@ -7642,6 +7984,38 @@ snapshots: convert-source-map: 2.0.0 tinyrainbow: 3.1.0 + '@vue/compiler-core@3.5.32': + dependencies: + '@babel/parser': 7.29.2 + '@vue/shared': 3.5.32 + entities: 7.0.1 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.5.32': + dependencies: + '@vue/compiler-core': 3.5.32 + '@vue/shared': 3.5.32 + + '@vue/compiler-sfc@3.5.32': + dependencies: + '@babel/parser': 7.29.2 + '@vue/compiler-core': 3.5.32 + '@vue/compiler-dom': 3.5.32 + '@vue/compiler-ssr': 3.5.32 + '@vue/shared': 3.5.32 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.10 + source-map-js: 1.2.1 + + '@vue/compiler-ssr@3.5.32': + dependencies: + '@vue/compiler-dom': 3.5.32 + '@vue/shared': 3.5.32 + + '@vue/shared@3.5.32': {} + acorn-jsx@5.3.2(acorn@8.16.0): dependencies: acorn: 8.16.0 @@ -7769,6 +8143,8 @@ snapshots: assertion-error@2.0.1: {} + ast-module-types@6.0.1: {} + ast-types-flow@0.0.8: {} ast-types@0.16.1: @@ -7954,6 +8330,10 @@ snapshots: check-error@2.1.3: {} + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + chromatic@13.3.5: {} chromatic@16.1.0: {} @@ -7999,6 +8379,8 @@ snapshots: colorette@2.0.20: {} + commander@12.1.0: {} + commander@14.0.3: {} commander@7.2.0: {} @@ -8031,6 +8413,15 @@ snapshots: optionalDependencies: typescript: 5.9.3 + cosmiconfig@9.0.1(typescript@5.9.3): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.9.3 + create-require@1.1.1: {} cross-spawn@7.0.6: @@ -8142,6 +8533,62 @@ snapshots: detect-newline@3.1.0: {} + detective-amd@6.0.1: + dependencies: + ast-module-types: 6.0.1 + escodegen: 2.1.0 + get-amd-module-type: 6.0.2 + node-source-walk: 7.0.1 + + detective-cjs@6.1.1: + dependencies: + ast-module-types: 6.0.1 + node-source-walk: 7.0.1 + + detective-es6@5.0.2: + dependencies: + node-source-walk: 7.0.1 + + detective-postcss@7.0.1(postcss@8.5.10): + dependencies: + is-url: 1.2.4 + postcss: 8.5.10 + postcss-values-parser: 6.0.2(postcss@8.5.10) + + detective-sass@6.0.1: + dependencies: + gonzales-pe: 4.3.0 + node-source-walk: 7.0.1 + + detective-scss@5.0.1: + dependencies: + gonzales-pe: 4.3.0 + node-source-walk: 7.0.1 + + detective-stylus@5.0.1: {} + + detective-typescript@14.1.1(typescript@5.9.3): + dependencies: + '@typescript-eslint/typescript-estree': 8.59.0(typescript@5.9.3) + ast-module-types: 6.0.1 + node-source-walk: 7.0.1 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + detective-vue2@2.3.0(typescript@5.9.3): + dependencies: + '@dependents/detective-less': 5.0.2 + '@vue/compiler-sfc': 3.5.32 + detective-es6: 5.0.2 + detective-sass: 6.0.1 + detective-scss: 5.0.1 + detective-stylus: 5.0.1 + detective-typescript: 14.1.1(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + diff@4.0.4: {} doctrine@2.1.0: @@ -8187,6 +8634,8 @@ snapshots: eastasianwidth@0.2.0: {} + effector@23.4.4: {} + electron-to-chromium@1.5.307: {} emittery@0.13.1: {} @@ -8197,6 +8646,8 @@ snapshots: emoji-regex@9.2.2: {} + empathic@1.1.0: {} + empathic@2.0.0: {} enhanced-resolve@5.20.0: @@ -8208,6 +8659,10 @@ snapshots: entities@6.0.1: {} + entities@7.0.1: {} + + env-paths@2.2.1: {} + environment@1.1.0: {} error-ex@1.3.4: @@ -8353,6 +8808,14 @@ snapshots: escape-string-regexp@4.0.0: {} + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + eslint-config-next@16.1.6(@typescript-eslint/parser@8.57.0(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3): dependencies: '@next/eslint-plugin-next': 16.1.6 @@ -8637,10 +9100,20 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.8 + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + fast-json-stable-stringify@2.1.0: {} fast-levenshtein@2.0.6: {} + fastest-levenshtein@1.0.16: {} + fastq@1.20.1: dependencies: reusify: 1.1.0 @@ -8714,6 +9187,11 @@ snapshots: gensync@1.0.0-beta.2: {} + get-amd-module-type@6.0.2: + dependencies: + ast-module-types: 6.0.1 + node-source-walk: 7.0.1 + get-caller-file@2.0.5: {} get-east-asian-width@1.5.0: {} @@ -8791,8 +9269,21 @@ snapshots: define-properties: 1.2.1 gopd: 1.2.0 + globby@14.1.0: + dependencies: + '@sindresorhus/merge-streams': 2.3.0 + fast-glob: 3.3.3 + ignore: 7.0.5 + path-type: 6.0.0 + slash: 5.1.0 + unicorn-magic: 0.3.0 + globrex@0.1.2: {} + gonzales-pe@4.3.0: + dependencies: + minimist: 1.2.8 + gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -8863,6 +9354,8 @@ snapshots: image-size@2.0.2: {} + immer@10.2.0: {} + immer@11.1.4: {} import-fresh@3.3.1: @@ -9015,6 +9508,10 @@ snapshots: dependencies: which-typed-array: 1.1.20 + is-url-superb@4.0.0: {} + + is-url@1.2.4: {} + is-weakmap@2.0.2: {} is-weakref@1.1.1: @@ -9621,6 +10118,8 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash-es@4.18.1: {} + lodash.debounce@4.0.8: {} lodash.merge@4.6.2: {} @@ -9712,6 +10211,11 @@ snapshots: module-alias@2.3.4: {} + module-definition@6.0.2: + dependencies: + ast-module-types: 6.0.1 + node-source-walk: 7.0.1 + mrmime@2.0.1: {} ms@2.1.3: {} @@ -9790,6 +10294,10 @@ snapshots: node-releases@2.0.36: {} + node-source-walk@7.0.1: + dependencies: + '@babel/parser': 7.29.2 + normalize-path@3.0.0: {} npm-run-path@4.0.1: @@ -9939,10 +10447,16 @@ snapshots: path-type@4.0.0: {} + path-type@6.0.0: {} + pathe@2.0.3: {} pathval@2.0.1: {} + patronum@2.3.0(effector@23.4.4): + dependencies: + effector: 23.4.4 + picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -9963,22 +10477,57 @@ snapshots: optionalDependencies: fsevents: 2.3.2 + pluralize@8.0.0: {} + pngjs@7.0.0: {} possible-typed-array-names@1.1.0: {} + postcss-values-parser@6.0.2(postcss@8.5.10): + dependencies: + color-name: 1.1.4 + is-url-superb: 4.0.0 + postcss: 8.5.10 + quote-unquote: 1.0.0 + postcss@8.4.31: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 source-map-js: 1.2.1 + postcss@8.5.10: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + postcss@8.5.8: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 source-map-js: 1.2.1 + precinct@12.3.1: + dependencies: + '@dependents/detective-less': 5.0.2 + commander: 12.1.0 + detective-amd: 6.0.1 + detective-cjs: 6.1.1 + detective-es6: 5.0.2 + detective-postcss: 7.0.1(postcss@8.5.10) + detective-sass: 6.0.1 + detective-scss: 5.0.1 + detective-stylus: 5.0.1 + detective-typescript: 14.1.1(typescript@5.9.3) + detective-vue2: 2.3.0(typescript@5.9.3) + module-definition: 6.0.2 + node-source-walk: 7.0.1 + postcss: 8.5.10 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + prelude-ls@1.2.1: {} prettier-linter-helpers@1.0.1: @@ -10003,6 +10552,8 @@ snapshots: ansi-styles: 5.2.0 react-is: 18.3.1 + prexit@2.3.0: {} + prop-types@15.8.1: dependencies: loose-envify: 1.4.0 @@ -10015,6 +10566,8 @@ snapshots: queue-microtask@1.2.3: {} + quote-unquote@1.0.0: {} + react-docgen-typescript@2.4.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -10047,6 +10600,8 @@ snapshots: react@19.2.3: {} + readdirp@4.1.2: {} + recast@0.23.11: dependencies: ast-types: 0.16.1 @@ -10307,8 +10862,12 @@ snapshots: mrmime: 2.0.1 totalist: 3.0.1 + sisteransi@1.0.5: {} + slash@3.0.0: {} + slash@5.1.0: {} + slice-ansi@7.1.2: dependencies: ansi-styles: 6.2.3 @@ -10347,6 +10906,29 @@ snapshots: std-env@4.0.0: {} + steiger@0.5.11(typescript@5.9.3): + dependencies: + '@clack/prompts': 0.9.1 + '@feature-sliced/steiger-plugin': 0.5.7(typescript@5.9.3) + chokidar: 4.0.3 + cosmiconfig: 9.0.1(typescript@5.9.3) + effector: 23.4.4 + empathic: 1.1.0 + fastest-levenshtein: 1.0.16 + globby: 14.1.0 + immer: 10.2.0 + lodash-es: 4.18.1 + micromatch: 4.0.8 + patronum: 2.3.0(effector@23.4.4) + picocolors: 1.1.1 + prexit: 2.3.0 + yargs: 17.7.2 + zod: 3.25.76 + zod-validation-error: 3.5.4(zod@3.25.76) + transitivePeerDependencies: + - supports-color + - typescript + stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -10583,6 +11165,10 @@ snapshots: dependencies: typescript: 5.9.3 + ts-api-utils@2.5.0(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + ts-dedent@2.2.0: {} ts-node@10.9.2(@types/node@20.19.37)(typescript@5.9.3): @@ -10698,6 +11284,8 @@ snapshots: unicode-property-aliases-ecmascript@2.2.0: {} + unicorn-magic@0.3.0: {} + universalify@2.0.1: {} unplugin@2.3.11: @@ -10974,10 +11562,16 @@ snapshots: yoctocolors-cjs@2.1.3: {} + zod-validation-error@3.5.4(zod@3.25.76): + dependencies: + zod: 3.25.76 + zod-validation-error@4.0.2(zod@4.3.6): dependencies: zod: 4.3.6 + zod@3.25.76: {} + zod@4.3.6: {} zustand@5.0.12(@types/react@19.2.14)(immer@11.1.4)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)): diff --git a/src/app/(auth)/layout.tsx b/src/app/(auth)/layout.tsx index 427019ac..ba2cccc4 100644 --- a/src/app/(auth)/layout.tsx +++ b/src/app/(auth)/layout.tsx @@ -1,4 +1,4 @@ -import { Icon } from "@/components/common/Icon"; +import { Icon } from "@/shared/ui/Icon"; // app/(auth)/layout.tsx export default function AuthLayout({ diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx index 8dcf9117..fad83436 100644 --- a/src/app/(auth)/login/page.tsx +++ b/src/app/(auth)/login/page.tsx @@ -1,7 +1,7 @@ import React from "react"; -import LoginForm from "@/components/auth/Login/LoginForm"; -import SnsLoginButtons from "@/components/auth/SnsLoginButtons"; +import LoginForm from "@/widgets/auth/Login/LoginForm"; +import SnsLoginButtons from "@/widgets/auth/SnsLoginButtons"; const LoginPage = () => { return ( diff --git a/src/app/(auth)/signup/page.tsx b/src/app/(auth)/signup/page.tsx index 5a00e154..d316c533 100644 --- a/src/app/(auth)/signup/page.tsx +++ b/src/app/(auth)/signup/page.tsx @@ -1,5 +1,5 @@ -import SignupForm from "@/components/auth/Signup/SignupForm"; -import SnsLoginButtons from "@/components/auth/SnsLoginButtons"; +import SignupForm from "@/widgets/auth/Signup/SignupForm"; +import SnsLoginButtons from "@/widgets/auth/SnsLoginButtons"; export default function SignupPage() { return ( diff --git a/src/app/api/[...path]/route.ts b/src/app/api/[...path]/route.ts index ff27c655..bd409e20 100644 --- a/src/app/api/[...path]/route.ts +++ b/src/app/api/[...path]/route.ts @@ -1,7 +1,7 @@ import { cookies } from "next/headers"; import { NextRequest, NextResponse } from "next/server"; -import { deleteTokenCookies, setTokenCookies } from "@/lib/auth/cookies"; +import { deleteTokenCookies, setTokenCookies } from "@/shared/lib/auth/cookies"; async function refreshAndRetry({ refreshToken, diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 9a0d6e0c..55a99066 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,16 +2,24 @@ import "./globals.css"; import { Analytics } from "@vercel/analytics/next"; import { SpeedInsights } from "@vercel/speed-insights/next"; +import localFont from "next/font/local"; -import ToastProvider from "@/components/common/Toast"; -import Overlay from "@/hooks/useOverlay/Overlay"; -import { pretendard } from "@/lib/fonts"; -import { initMocks } from "@/mocks"; -import MSWInitializer from "@/mocks/MSWInitializer"; -import { ReactQueryClientProvider } from "@/providers/ReactQueryProvider"; +import { ReactQueryClientProvider } from "@/shared/providers/ReactQueryProvider"; +import ToastProvider from "@/shared/providers/ToastProvider"; +import Overlay from "@/shared/ui/Overlay/Overlay"; + +import { initMocks } from "../shared/mock"; +import MSWInitializer from "../shared/mock/MSWInitializer"; initMocks(); +const pretendard = localFont({ + src: "../shared/assets/fonts/PretendardVariable.woff2", + display: "swap", + weight: "45 920", + variable: "--font-pretendard", +}); + export default function RootLayout({ children, }: Readonly<{ diff --git a/src/app/page.tsx b/src/app/page.tsx index 7a6f6d84..fcf6c465 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,8 +1,8 @@ -import { HomeCTASection } from "@/components/landing/HomeCTASection"; -import { HomeFeaturesSection } from "@/components/landing/HomeFeaturesSection"; -import { HomeHeroSection } from "@/components/landing/HomeHeroSection"; -import { HomeStepsSection } from "@/components/landing/HomeStepsSection"; -import { HomeTeamSpacesSection } from "@/components/landing/HomeTeamSpacesSection"; +import { HomeCTASection } from "@/widgets/landing/HomeCTASection"; +import { HomeFeaturesSection } from "@/widgets/landing/HomeFeaturesSection"; +import { HomeHeroSection } from "@/widgets/landing/HomeHeroSection"; +import { HomeStepsSection } from "@/widgets/landing/HomeStepsSection"; +import { HomeTeamSpacesSection } from "@/widgets/landing/HomeTeamSpacesSection"; export default function Home() { return ( diff --git a/src/app/taskmate/invitations/[inviteCode]/InvitationPageClient.tsx b/src/app/taskmate/invitations/[inviteCode]/InvitationPageClient.tsx index 55434d7d..eb12bb3f 100644 --- a/src/app/taskmate/invitations/[inviteCode]/InvitationPageClient.tsx +++ b/src/app/taskmate/invitations/[inviteCode]/InvitationPageClient.tsx @@ -7,14 +7,14 @@ import { } from "@tanstack/react-query"; import { useParams, useRouter } from "next/navigation"; -import Button from "@/components/common/Button/Button"; -import { Spacing } from "@/components/common/Spacing"; -import { teamInvitationApi } from "@/features/team/invitation.api"; -import type { TeamInvitationDetail } from "@/features/team/invitation.types"; +import { teamInvitationApi } from "@/entities/team/api/invitation.api"; import { invitationQueries, invitationQueryKey, -} from "@/features/team/query/invitation.queryKey"; +} from "@/entities/team/query/invitation.queryKey"; +import type { TeamInvitationDetail } from "@/entities/team/types/invitation.types"; +import Button from "@/shared/ui/Button/Button/Button"; +import { Spacing } from "@/shared/ui/Spacing"; function errorMessage(err: unknown, fallback: string) { if (err && typeof err === "object" && "message" in err) { diff --git a/src/app/taskmate/invitations/[inviteCode]/page.tsx b/src/app/taskmate/invitations/[inviteCode]/page.tsx index ace52ff9..0a8b6bbb 100644 --- a/src/app/taskmate/invitations/[inviteCode]/page.tsx +++ b/src/app/taskmate/invitations/[inviteCode]/page.tsx @@ -1,4 +1,4 @@ -import AsyncBoundary from "@/components/common/AsyncBoundary"; +import AsyncBoundary from "@/shared/ui/AsyncBoundary"; import { InvitationPageClient } from "./InvitationPageClient"; diff --git a/src/app/taskmate/layout.tsx b/src/app/taskmate/layout.tsx index d658ce71..96c2db5b 100644 --- a/src/app/taskmate/layout.tsx +++ b/src/app/taskmate/layout.tsx @@ -1,6 +1,6 @@ -import { NavigationBar } from "@/components/NavigationBar"; -import NavigationBarProvider from "@/components/NavigationBar/provider"; import NotificationSubscriber from "@/features/notification/NotificationSubscriber"; +import { NavigationBar } from "@/widgets/NavigationBar"; +import NavigationBarProvider from "@/widgets/NavigationBar/provider"; export default function TaskmateLayout({ children, diff --git a/src/app/taskmate/my/page.tsx b/src/app/taskmate/my/page.tsx index 5018a949..935df973 100644 --- a/src/app/taskmate/my/page.tsx +++ b/src/app/taskmate/my/page.tsx @@ -1,7 +1,7 @@ import React from "react"; -import AsyncBoundary from "@/components/common/AsyncBoundary"; -import MyProfileForm from "@/components/my/MyProfileForm"; +import AsyncBoundary from "@/shared/ui/AsyncBoundary"; +import MyProfileForm from "@/widgets/my/MyProfileForm"; const Mypage = () => { return ( diff --git a/src/app/taskmate/page.tsx b/src/app/taskmate/page.tsx index de7a98cf..dbd54ef2 100644 --- a/src/app/taskmate/page.tsx +++ b/src/app/taskmate/page.tsx @@ -1,10 +1,10 @@ -import AsyncBoundary from "@/components/common/AsyncBoundary"; -import { Icon } from "@/components/common/Icon"; -import { Spacing } from "@/components/common/Spacing"; -import { FavoriteGoalsSection } from "@/components/home/FavoriteGoalsSection"; -import ProgressSection from "@/components/home/ProgressSection"; -import TodoOverviewSection from "@/components/home/TodoOverviewSection"; -import WelcomeBanner from "@/components/home/WelcomeBanner"; +import AsyncBoundary from "@/shared/ui/AsyncBoundary"; +import { Icon } from "@/shared/ui/Icon"; +import { Spacing } from "@/shared/ui/Spacing"; +import { FavoriteGoalsSection } from "@/widgets/home/FavoriteGoalsSection"; +import ProgressSection from "@/widgets/home/ProgressSection"; +import TodoOverviewSection from "@/widgets/home/TodoOverviewSection"; +import WelcomeBanner from "@/widgets/home/WelcomeBanner"; export default function TaskmatePage() { return ( diff --git a/src/app/taskmate/personal/goal/[goalId]/page.tsx b/src/app/taskmate/personal/goal/[goalId]/page.tsx index baa1d075..0341eb10 100644 --- a/src/app/taskmate/personal/goal/[goalId]/page.tsx +++ b/src/app/taskmate/personal/goal/[goalId]/page.tsx @@ -1,11 +1,11 @@ "use client"; -import AsyncBoundary from "@/components/common/AsyncBoundary"; -import { Spacing } from "@/components/common/Spacing"; -import Spinner from "@/components/common/Spinner"; -import { Heading } from "@/components/goal/Heading"; -import Summary from "@/components/goal/Summary"; -import { TodoSection } from "@/components/team/TodoSection"; +import AsyncBoundary from "@/shared/ui/AsyncBoundary"; +import { Spacing } from "@/shared/ui/Spacing"; +import Spinner from "@/shared/ui/Spinner"; +import { Heading } from "@/widgets/goal/Heading"; +import Summary from "@/widgets/goal/Summary"; +import { TodoSection } from "@/widgets/team/TodoSection"; export default function Page() { return ( diff --git a/src/app/taskmate/personal/goal/create/page.tsx b/src/app/taskmate/personal/goal/create/page.tsx index 7c5ca028..b50946f2 100644 --- a/src/app/taskmate/personal/goal/create/page.tsx +++ b/src/app/taskmate/personal/goal/create/page.tsx @@ -1,5 +1,5 @@ -import { Spacing } from "@/components/common/Spacing"; -import { PersonalCreateForm } from "@/components/goal/CreateForm/PersonalCreateForm"; +import { Spacing } from "@/shared/ui/Spacing"; +import { PersonalCreateForm } from "@/widgets/goal/CreateForm/PersonalCreateForm"; export default function Page() { return ( diff --git a/src/app/taskmate/team/[teamId]/goal/[goalId]/page.tsx b/src/app/taskmate/team/[teamId]/goal/[goalId]/page.tsx index 89abc87e..efec40e4 100644 --- a/src/app/taskmate/team/[teamId]/goal/[goalId]/page.tsx +++ b/src/app/taskmate/team/[teamId]/goal/[goalId]/page.tsx @@ -1,11 +1,11 @@ "use client"; -import AsyncBoundary from "@/components/common/AsyncBoundary"; -import { Spacing } from "@/components/common/Spacing"; -import Spinner from "@/components/common/Spinner"; -import { Heading } from "@/components/goal/Heading"; -import Summary from "@/components/goal/Summary"; -import { TodoSection } from "@/components/team/TodoSection"; +import AsyncBoundary from "@/shared/ui/AsyncBoundary"; +import { Spacing } from "@/shared/ui/Spacing"; +import Spinner from "@/shared/ui/Spinner"; +import { Heading } from "@/widgets/goal/Heading"; +import Summary from "@/widgets/goal/Summary"; +import { TodoSection } from "@/widgets/team/TodoSection"; export default function Page() { return ( diff --git a/src/app/taskmate/team/[teamId]/goal/create/page.tsx b/src/app/taskmate/team/[teamId]/goal/create/page.tsx index 944e4998..9dead959 100644 --- a/src/app/taskmate/team/[teamId]/goal/create/page.tsx +++ b/src/app/taskmate/team/[teamId]/goal/create/page.tsx @@ -1,5 +1,5 @@ -import { Spacing } from "@/components/common/Spacing"; -import { TeamCreateForm } from "@/components/goal/CreateForm/TeamCreateForm"; +import { Spacing } from "@/shared/ui/Spacing"; +import { TeamCreateForm } from "@/widgets/goal/CreateForm/TeamCreateForm"; export default function Page() { return ( diff --git a/src/app/taskmate/team/[teamId]/management/page.tsx b/src/app/taskmate/team/[teamId]/management/page.tsx index c15d2a2b..5d4aa064 100644 --- a/src/app/taskmate/team/[teamId]/management/page.tsx +++ b/src/app/taskmate/team/[teamId]/management/page.tsx @@ -3,14 +3,14 @@ import { useParams, useRouter } from "next/navigation"; import { useEffect, useState } from "react"; -import TextButton from "@/components/common/TextButton/TextButton"; -import DeleteModal from "@/components/management/DeleteModal"; -import ErrorModal from "@/components/management/ErrorModal"; -import InviteModal from "@/components/management/InviteModal"; -import MemberList from "@/components/management/MemberList"; -import TeamNameEditor from "@/components/management/TeamNameEditor"; -import { inviteApi, teamDetailApi } from "@/features/management/api"; -import { useOverlay } from "@/hooks/useOverlay"; +import { inviteApi, teamDetailApi } from "@/entities/team/api/management.api"; +import { useOverlay } from "@/shared/hooks/useOverlay"; +import TextButton from "@/shared/ui/Button/TextButton/TextButton"; +import DeleteModal from "@/widgets/management/DeleteModal"; +import ErrorModal from "@/widgets/management/ErrorModal"; +import InviteModal from "@/widgets/management/InviteModal"; +import MemberList from "@/widgets/management/MemberList"; +import TeamNameEditor from "@/widgets/management/TeamNameEditor"; // @TODO: Page가 갖는 책임에서 벗어나는 코드 제거 및 분리 const TeamManagement = () => { diff --git a/src/app/taskmate/team/[teamId]/page.tsx b/src/app/taskmate/team/[teamId]/page.tsx index 79b97bdb..78b6393d 100644 --- a/src/app/taskmate/team/[teamId]/page.tsx +++ b/src/app/taskmate/team/[teamId]/page.tsx @@ -1,9 +1,9 @@ "use client"; -import AsyncBoundary from "@/components/common/AsyncBoundary"; -import { GoalList } from "@/components/team/GoalList"; -import { MemberList } from "@/components/team/MemberList"; -import { Summary } from "@/components/team/Summary"; +import AsyncBoundary from "@/shared/ui/AsyncBoundary"; +import { GoalList } from "@/widgets/team/GoalList"; +import { MemberList } from "@/widgets/team/MemberList"; +import { Summary } from "@/widgets/team/Summary"; export default function Page() { return ( diff --git a/src/app/taskmate/team/create/page.tsx b/src/app/taskmate/team/create/page.tsx index d466b9c6..e646e519 100644 --- a/src/app/taskmate/team/create/page.tsx +++ b/src/app/taskmate/team/create/page.tsx @@ -1,5 +1,5 @@ -import { Spacing } from "@/components/common/Spacing"; -import { CreateForm } from "@/components/team/createForm"; +import { Spacing } from "@/shared/ui/Spacing"; +import { CreateForm } from "@/widgets/team/createForm"; export default function Page() { return ( diff --git a/src/app/taskmate/trash/page.tsx b/src/app/taskmate/trash/page.tsx index 66b0f5c0..605a8828 100644 --- a/src/app/taskmate/trash/page.tsx +++ b/src/app/taskmate/trash/page.tsx @@ -1,7 +1,7 @@ import React from "react"; -import AsyncBoundary from "@/components/common/AsyncBoundary"; -import Trash from "@/components/trash"; +import AsyncBoundary from "@/shared/ui/AsyncBoundary"; +import Trash from "@/widgets/trash"; const TrashPage = () => { return ( diff --git a/src/components/NavigationBar/index.test.tsx b/src/components/NavigationBar/index.test.tsx deleted file mode 100644 index 5668d92d..00000000 --- a/src/components/NavigationBar/index.test.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { fireEvent, render, screen } from "@testing-library/react"; -import { useRouter } from "next/navigation"; -import type { ComponentProps, ReactElement } from "react"; - -import { NavigationBar } from "@/components/NavigationBar/index"; -import { NavigationBarContext } from "@/components/NavigationBar/provider"; - -const mockUseRouter = useRouter as jest.MockedFunction; - -jest.mock("next/navigation", () => ({ - useRouter: jest.fn(), -})); - -jest.mock("@/hooks/useBreakpoint", () => ({ - useBreakpoint: () => "desktop", -})); - -jest.mock("@/components/NavigationBar/Personal", () => ({ - Personal: Object.assign(() => null, { - Loading: () => null, - Error: () => null, - }), -})); - -jest.mock("@/components/NavigationBar/Team", () => ({ - Team: Object.assign(() => null, { Loading: () => null }), -})); - -jest.mock("@/components/NavigationBar/UserProfile", () => ({ - UserProfile: Object.assign(() => null, { Loading: () => null }), -})); - -jest.mock("@/components/common/LogoutButton", () => ({ - __esModule: true, - default: () => null, -})); - -jest.mock("@/components/NavigationBar/NotificationPopover", () => ({ - __esModule: true, - default: () => null, -})); - -jest.mock("@/components/common/Icon", () => ({ - Icon: ({ name }: { name: string }) => , -})); - -type ContextValue = ComponentProps< - typeof NavigationBarContext.Provider ->["value"]; - -function renderWithNavContext( - ui: ReactElement, - value: Partial = {}, -) { - const queryClient = new QueryClient(); - const defaults: ContextValue = { - isOpen: true, - open: jest.fn(), - close: jest.fn(), - currentTab: "", - tabChange: jest.fn(), - ...value, - }; - - return render( - - - {ui} - - , - ); -} - -describe("NavigationBar", () => { - beforeEach(() => { - jest.clearAllMocks(); - mockUseRouter.mockReturnValue({ - push: jest.fn(), - replace: jest.fn(), - prefetch: jest.fn(), - back: jest.fn(), - forward: jest.fn(), - refresh: jest.fn(), - } as ReturnType); - }); - - test('홈 탭을 누르면 tabChange("home")와 router.push("/taskmate")가 호출된다', () => { - const push = jest.fn(); - const tabChange = jest.fn(); - mockUseRouter.mockReturnValue({ - push, - replace: jest.fn(), - prefetch: jest.fn(), - back: jest.fn(), - forward: jest.fn(), - refresh: jest.fn(), - } as ReturnType); - - renderWithNavContext(, { isOpen: true, tabChange }); - - fireEvent.click(screen.getByText("홈")); - - expect(tabChange).toHaveBeenCalledTimes(1); - expect(tabChange).toHaveBeenCalledWith("home"); - expect(push).toHaveBeenCalledTimes(1); - expect(push).toHaveBeenCalledWith("/taskmate"); - }); - - test("네비게이션이 닫혀 있으면 홈 항목이 보이지 않는다", () => { - renderWithNavContext(, { isOpen: false }); - - expect(screen.queryByText("홈")).not.toBeInTheDocument(); - }); -}); diff --git a/src/components/common/Icons/Crown.tsx b/src/components/common/Icons/Crown.tsx deleted file mode 100644 index d9eabbe1..00000000 --- a/src/components/common/Icons/Crown.tsx +++ /dev/null @@ -1,37 +0,0 @@ -const CrownIcon = ({ className }: { className?: string }) => ( - - - - - - - - - - - -); - -export default CrownIcon; diff --git a/src/components/common/Icons/GoogleIcon.tsx b/src/components/common/Icons/GoogleIcon.tsx deleted file mode 100644 index e76093df..00000000 --- a/src/components/common/Icons/GoogleIcon.tsx +++ /dev/null @@ -1,40 +0,0 @@ -const GoogleIcon = ({ className }: { className?: string }) => ( - - - - - - - - - - - - - -); - -export default GoogleIcon; diff --git a/src/components/common/Icons/KakaoIcon.tsx b/src/components/common/Icons/KakaoIcon.tsx deleted file mode 100644 index fe024fce..00000000 --- a/src/components/common/Icons/KakaoIcon.tsx +++ /dev/null @@ -1,20 +0,0 @@ -const KakaoIcon = ({ className }: { className?: string }) => ( - - {/* 카카오 심볼 로고 (말풍선 형태) */} - - -); - -export default KakaoIcon; diff --git a/src/components/common/Icons/LikeIcon.tsx b/src/components/common/Icons/LikeIcon.tsx deleted file mode 100644 index 28853568..00000000 --- a/src/components/common/Icons/LikeIcon.tsx +++ /dev/null @@ -1,18 +0,0 @@ -const LikeIcon = ({ className }: { className?: string }) => ( - - - -); - -export default LikeIcon; diff --git a/src/components/common/Icons/ProfileEditIcon.tsx b/src/components/common/Icons/ProfileEditIcon.tsx deleted file mode 100644 index b4d45f96..00000000 --- a/src/components/common/Icons/ProfileEditIcon.tsx +++ /dev/null @@ -1,22 +0,0 @@ -const ProfileEditIcon = ({ className }: { className?: string }) => ( - - - - -); - -export default ProfileEditIcon; diff --git a/src/components/common/Icons/RightArrow.tsx b/src/components/common/Icons/RightArrow.tsx deleted file mode 100644 index 01e97cae..00000000 --- a/src/components/common/Icons/RightArrow.tsx +++ /dev/null @@ -1,19 +0,0 @@ -const RightArrowIcon = ({ className }: { className?: string }) => ( - - - -); - -export default RightArrowIcon; diff --git a/src/components/common/Toast/index.tsx b/src/components/common/Toast/index.tsx deleted file mode 100644 index 86c20099..00000000 --- a/src/components/common/Toast/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./ToastProvider"; diff --git a/src/constants/queryKeys/index.ts b/src/constants/queryKeys/index.ts deleted file mode 100644 index 1bb348dc..00000000 --- a/src/constants/queryKeys/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { trashQueries } from "@/constants/queryKeys/trash.queryKey"; -export { userQueries } from "@/constants/queryKeys/user.queryKey"; diff --git a/src/features/my/api/myInfo.api.ts b/src/entities/auth/api/myInfo.api.ts similarity index 73% rename from src/features/my/api/myInfo.api.ts rename to src/entities/auth/api/myInfo.api.ts index 098c1cfc..09f74ebf 100644 --- a/src/features/my/api/myInfo.api.ts +++ b/src/entities/auth/api/myInfo.api.ts @@ -1,8 +1,8 @@ -import { UserProfile } from "@/features/auth/types/auth.type"; -import { apiClient } from "@/lib/api/client"; -import { ApiResponse } from "@/lib/api/types"; +import { UserProfile } from "@/entities/auth/types/auth.type"; +import { apiClient } from "@/shared/lib/api/client"; +import { ApiResponse } from "@/shared/lib/api/types"; -import { MyProfileFormData } from "../types/myProfile.type"; +import { MyProfileFormData } from "../../../features/user/types/myProfile.type"; export async function getMyInfo() { const res = await apiClient.get>("/api/users/me"); diff --git a/src/features/auth/signup/api/signup.api.ts b/src/entities/auth/api/signup.api.ts similarity index 58% rename from src/features/auth/signup/api/signup.api.ts rename to src/entities/auth/api/signup.api.ts index 148eb2d6..908f6be8 100644 --- a/src/features/auth/signup/api/signup.api.ts +++ b/src/entities/auth/api/signup.api.ts @@ -1,10 +1,8 @@ -import { - CheckEmailResponse, - SignupFormData, -} from "@/features/auth/signup/types/signup.type"; -import { apiClient } from "@/lib/api/client"; +import { CheckEmailResponse } from "@/entities/auth/types/auth.type"; +import { SignupFormData } from "@/features/auth/signup/types/signup.type"; +import { apiClient } from "@/shared/lib/api/client"; -import { UserProfile } from "../../types/auth.type"; +import { UserProfile } from "../types/auth.type"; type SignupRequest = Omit; diff --git a/src/constants/queryKeys/user.queryKey.ts b/src/entities/auth/query/user.queryKey.ts similarity index 69% rename from src/constants/queryKeys/user.queryKey.ts rename to src/entities/auth/query/user.queryKey.ts index d9e647a5..d27a507a 100644 --- a/src/constants/queryKeys/user.queryKey.ts +++ b/src/entities/auth/query/user.queryKey.ts @@ -1,8 +1,7 @@ import { queryOptions } from "@tanstack/react-query"; -import { getMyInfo } from "@/features/my/api/myInfo.api"; - -import { STALE_TIME } from "../staleTime"; +import { getMyInfo } from "@/entities/auth/api/myInfo.api"; +import { STALE_TIME } from "@/shared/constants/query/staleTime"; export const userQueries = { all: ["auth"] as const, diff --git a/src/features/auth/types/auth.type.ts b/src/entities/auth/types/auth.type.ts similarity index 63% rename from src/features/auth/types/auth.type.ts rename to src/entities/auth/types/auth.type.ts index 122b0c92..0e2c8990 100644 --- a/src/features/auth/types/auth.type.ts +++ b/src/entities/auth/types/auth.type.ts @@ -9,3 +9,11 @@ export type UserProfile = { provider: string; createdAt: string; }; + +export type CheckEmailResponse = { + success: boolean; + code: string; + message: string; + data: { exists: boolean }; + timestamp: string; +}; diff --git a/src/features/goal/api.ts b/src/entities/goal/api/api.ts similarity index 96% rename from src/features/goal/api.ts rename to src/entities/goal/api/api.ts index de817971..3de1eb3b 100644 --- a/src/features/goal/api.ts +++ b/src/entities/goal/api/api.ts @@ -1,4 +1,4 @@ -import { apiClient } from "@/lib/api/client"; +import { apiClient } from "@/shared/lib/api/client"; import type { CreateGoalResponse, @@ -9,7 +9,7 @@ import type { PersonalGoalListResponse, SortType, TeamGoalListResponse, -} from "./types"; +} from "../types/types"; export const goalApi = { createPersonalGoal: (data: CreatePersonalGoalInput) => diff --git a/src/entities/goal/api/goal.api.ts b/src/entities/goal/api/goal.api.ts new file mode 100644 index 00000000..dfccf434 --- /dev/null +++ b/src/entities/goal/api/goal.api.ts @@ -0,0 +1,11 @@ +import { apiClient } from "@/shared/lib/api/client"; + +import { FavoriteGoalsSuccessResponse } from "../types/favorite.types"; +import { FavoriteGoalsQueryParams } from "../types/favorite.types"; + +export const favoriteGoalsApi = { + read: (params: FavoriteGoalsQueryParams = {}) => + apiClient.get("/api/main/favorite-goals", { + params, + }), +}; diff --git a/src/features/goal/query/goal.queryKey.ts b/src/entities/goal/query/goal.queryKey.ts similarity index 88% rename from src/features/goal/query/goal.queryKey.ts rename to src/entities/goal/query/goal.queryKey.ts index 293258e7..fd077806 100644 --- a/src/features/goal/query/goal.queryKey.ts +++ b/src/entities/goal/query/goal.queryKey.ts @@ -1,9 +1,8 @@ import { infiniteQueryOptions, queryOptions } from "@tanstack/react-query"; -import { STALE_TIME } from "@/constants/staleTime"; - -import { goalApi } from "../api"; -import { GoalListCursor, SortType } from "../types"; +import { goalApi } from "@/entities/goal/api/api"; +import { GoalListCursor, SortType } from "@/entities/goal/types/types"; +import { STALE_TIME } from "@/shared/constants/query/staleTime"; export const goalQueries = { getPersonalGoalList: () => diff --git a/src/entities/goal/types/favorite.types.ts b/src/entities/goal/types/favorite.types.ts new file mode 100644 index 00000000..78b08671 --- /dev/null +++ b/src/entities/goal/types/favorite.types.ts @@ -0,0 +1,63 @@ +// favoriteGoalsApi - GET / query params + +export type FavoriteGoalsQueryParams = { + cursorId?: number; + cursorCreatedAt?: string; + size?: number; +}; + +// FavoriteGoalItem + +export interface FavoriteGoalItem { + teamId: number; + teamName: string; + goalId: number; + goalName: string; + progressPercent: number; + isFavorite: boolean; + createdAt: string; +} + +// FavoriteGoalsSuccessResponse + +export interface FavoriteGoalsSuccessResponse { + success: true; + code: string; + message: string; + data: { + items: FavoriteGoalItem[]; + hasNext: boolean; + nextCursorCreatedAt: string; + nextCursorId: number; + }; + timestamp: string; +} + +// FavoriteGoalsErrorResponse + +export type FavoriteGoalsErrorResponse = + | { + success: false; + code: "AUTH_LOGIN_REQUIRED"; + message: "로그인이 필요합니다."; + data: null; + timestamp: string; + } + | { + success: false; + code: "GOAL_CURSOR_INVALID"; + message: "커서 값이 올바르지 않습니다. cursorCreatedAt와 cursorId를 함께 전달하세요."; + data: null; + timestamp: string; + } + | { + success: false; + code: "MAIN_PAGE_SIZE_INVALID"; + message: "size는 1 이상이어야 합니다."; + data: null; + timestamp: string; + }; + +export type FavoriteGoalsResponse = + | FavoriteGoalsSuccessResponse + | FavoriteGoalsErrorResponse; diff --git a/src/features/goal/types.ts b/src/entities/goal/types/types.ts similarity index 100% rename from src/features/goal/types.ts rename to src/entities/goal/types/types.ts diff --git a/src/features/team/api.ts b/src/entities/team/api/api.ts similarity index 89% rename from src/features/team/api.ts rename to src/entities/team/api/api.ts index 98378451..8c248217 100644 --- a/src/features/team/api.ts +++ b/src/entities/team/api/api.ts @@ -1,4 +1,4 @@ -import { apiClient } from "@/lib/api/client"; +import { apiClient } from "@/shared/lib/api/client"; import type { ResponseCreateTeam, @@ -6,7 +6,7 @@ import type { ResponseQuitTeam, ResponseTeamList, ResponseTeamSummary, -} from "./types"; +} from "../types/types"; export const teamApi = { // 팀 생성 요청 diff --git a/src/features/team/invitation.api.ts b/src/entities/team/api/invitation.api.ts similarity index 74% rename from src/features/team/invitation.api.ts rename to src/entities/team/api/invitation.api.ts index 574bad8b..11c2ed78 100644 --- a/src/features/team/invitation.api.ts +++ b/src/entities/team/api/invitation.api.ts @@ -1,7 +1,7 @@ -import { apiClient } from "@/lib/api/client"; -import { ApiResponse } from "@/lib/api/types"; +import { apiClient } from "@/shared/lib/api/client"; +import { ApiResponse } from "@/shared/lib/api/types"; -import type { TeamInvitationDetail } from "./invitation.types"; +import type { TeamInvitationDetail } from "../types/invitation.types"; export const teamInvitationApi = { getByToken: (inviteToken: string) => diff --git a/src/features/management/api.ts b/src/entities/team/api/management.api.ts similarity index 70% rename from src/features/management/api.ts rename to src/entities/team/api/management.api.ts index b8eedc0b..5476661e 100644 --- a/src/features/management/api.ts +++ b/src/entities/team/api/management.api.ts @@ -1,11 +1,14 @@ -import { apiClient } from "@/lib/api/client"; +import { apiClient } from "@/shared/lib/api/client"; -import type { TeamResponseSuccess } from "./types"; -import type { InviteResponseSuccess } from "./types"; -import type { MemberListResponseSuccess } from "./types"; -import type { MemberRole, MemberRoleUpdateSuccessResponse } from "./types"; -import type { MemberDeleteSuccessResponse } from "./types"; -import type { TeamDeleteResponseSuccess } from "./types"; +import type { TeamDeleteResponseSuccess } from "../types/management.types"; +import type { MemberDeleteSuccessResponse } from "../types/management.types"; +import type { + MemberRole, + MemberRoleUpdateSuccessResponse, +} from "../types/management.types"; +import type { MemberListResponseSuccess } from "../types/management.types"; +import type { InviteResponseSuccess } from "../types/management.types"; +import type { TeamResponseSuccess } from "../types/management.types"; // 팀 상세 정보 요청 // get / patch / delete diff --git a/src/features/team/query/invitation.queryKey.ts b/src/entities/team/query/invitation.queryKey.ts similarity index 85% rename from src/features/team/query/invitation.queryKey.ts rename to src/entities/team/query/invitation.queryKey.ts index 1a429870..a5611418 100644 --- a/src/features/team/query/invitation.queryKey.ts +++ b/src/entities/team/query/invitation.queryKey.ts @@ -1,6 +1,6 @@ import { queryOptions } from "@tanstack/react-query"; -import { teamInvitationApi } from "../invitation.api"; +import { teamInvitationApi } from "@/entities/team/api/invitation.api"; export const invitationQueryKey = (token: string) => ["teamInvitation", token] as const; diff --git a/src/features/team/query/team.queryKey.ts b/src/entities/team/query/team.queryKey.ts similarity index 88% rename from src/features/team/query/team.queryKey.ts rename to src/entities/team/query/team.queryKey.ts index e25f8d42..db0a24d7 100644 --- a/src/features/team/query/team.queryKey.ts +++ b/src/entities/team/query/team.queryKey.ts @@ -1,8 +1,7 @@ import { queryOptions } from "@tanstack/react-query"; -import { STALE_TIME } from "@/constants/staleTime"; - -import { teamApi } from "../api"; +import { teamApi } from "@/entities/team/api/api"; +import { STALE_TIME } from "@/shared/constants/query/staleTime"; export const teamQueries = { all: () => diff --git a/src/features/team/invitation.types.ts b/src/entities/team/types/invitation.types.ts similarity index 100% rename from src/features/team/invitation.types.ts rename to src/entities/team/types/invitation.types.ts diff --git a/src/features/management/types.ts b/src/entities/team/types/management.types.ts similarity index 100% rename from src/features/management/types.ts rename to src/entities/team/types/management.types.ts diff --git a/src/constants/team.ts b/src/entities/team/types/team.ts similarity index 100% rename from src/constants/team.ts rename to src/entities/team/types/team.ts diff --git a/src/features/team/types.ts b/src/entities/team/types/types.ts similarity index 92% rename from src/features/team/types.ts rename to src/entities/team/types/types.ts index 00321523..f6e65130 100644 --- a/src/features/team/types.ts +++ b/src/entities/team/types/types.ts @@ -1,7 +1,7 @@ import z from "zod"; -import { TEAM_NAME_MAX_LENGTH } from "@/constants/team"; -import { ApiResponse } from "@/lib/api/types"; +import { TEAM_NAME_MAX_LENGTH } from "@/entities/team/types/team"; +import { ApiResponse } from "@/shared/lib/api/types"; export const createTeamSchema = z.object({ name: z diff --git a/src/features/todo/api.ts b/src/entities/todo/api/api.ts similarity index 95% rename from src/features/todo/api.ts rename to src/entities/todo/api/api.ts index 0dc68e26..d432b525 100644 --- a/src/features/todo/api.ts +++ b/src/entities/todo/api/api.ts @@ -1,12 +1,11 @@ -import { apiClient } from "@/lib/api/client"; - import type { CreateTodoInput, ResponseCreateTodo, TodoListQueryParams, TodoListResponse, UpdateTodoInput, -} from "./types.ts"; +} from "@/entities/todo/types/types"; +import { apiClient } from "@/shared/lib/api/client"; function todoListSearchParams(params: TodoListQueryParams) { const optional = Object.fromEntries( diff --git a/src/entities/todo/api/todo.api.ts b/src/entities/todo/api/todo.api.ts new file mode 100644 index 00000000..a5610e13 --- /dev/null +++ b/src/entities/todo/api/todo.api.ts @@ -0,0 +1,21 @@ +import { apiClient } from "@/shared/lib/api/client"; + +import { + DueSoonSuccessResponse, + InfiniteQueryParams, + RecentSuccessResponse, +} from "../types/types"; + +export const recentApi = { + read: (params: InfiniteQueryParams = {}) => + apiClient.get("/api/todos/recent", { + params, + }), +}; + +export const dueSoonApi = { + read: (params: InfiniteQueryParams = {}) => + apiClient.get("/api/todos/due-soon", { + params, + }), +}; diff --git a/src/features/todo/query/todo.queryKey.ts b/src/entities/todo/query/todo.queryKey.ts similarity index 94% rename from src/features/todo/query/todo.queryKey.ts rename to src/entities/todo/query/todo.queryKey.ts index f610cd85..3544e711 100644 --- a/src/features/todo/query/todo.queryKey.ts +++ b/src/entities/todo/query/todo.queryKey.ts @@ -1,12 +1,12 @@ -import { STALE_TIME } from "@/constants/staleTime"; +import { STALE_TIME } from "@/shared/constants/query/staleTime"; -import { todoApi } from "../api"; +import { todoApi } from "../api/api"; import type { TodoListQueryParams, TodoListResponse, TodoListSort, TodoListStatus, -} from "../types"; +} from "../types/types"; const TODO_LIST_PAGE_LIMIT = 10; diff --git a/src/features/todo/types.ts b/src/entities/todo/types/types.ts similarity index 64% rename from src/features/todo/types.ts rename to src/entities/todo/types/types.ts index e2566e9a..5469697b 100644 --- a/src/features/todo/types.ts +++ b/src/entities/todo/types/types.ts @@ -64,3 +64,45 @@ export interface TodoListQueryParams { cursorId?: number; limit?: number; } + +// GET - query params + +export type InfiniteQueryParams = { + cursorId?: number; + cursorCreatedAt?: string; + size?: number; +}; + +export type TodoItem = { + todoId: number; + title: string; + teamDisplayName: string; + goalTitle: string; + dueDate: string; +}; + +export type RecentSuccessResponse = { + success: true; + code: string; + message: string; + data: { + items: TodoItem[]; + hasNext: boolean; + nextCursorCreatedAt: string; + nextCursorId: number; + }; + timestamp: string; +}; + +export type DueSoonSuccessResponse = { + success: true; + code: string; + message: string; + data: { + items: TodoItem[]; + hasNext: boolean; + nextCursorDueDate: string; + nextCursorId: number; + }; + timestamp: string; +}; diff --git a/src/hooks/useLogout/index.ts b/src/features/auth/hooks/useLogout/index.ts similarity index 100% rename from src/hooks/useLogout/index.ts rename to src/features/auth/hooks/useLogout/index.ts diff --git a/src/hooks/useLogout/useLogout.ts b/src/features/auth/hooks/useLogout/useLogout.ts similarity index 91% rename from src/hooks/useLogout/useLogout.ts rename to src/features/auth/hooks/useLogout/useLogout.ts index b8539460..c260dcc8 100644 --- a/src/hooks/useLogout/useLogout.ts +++ b/src/features/auth/hooks/useLogout/useLogout.ts @@ -4,8 +4,7 @@ import { useQueryClient } from "@tanstack/react-query"; import { useRouter } from "next/navigation"; import { logoutAction } from "@/features/auth/logout/actions/logoutAction"; - -import { useToast } from "../useToast"; +import { useToast } from "@/shared/hooks/useToast"; export function useLogout() { const queryClient = useQueryClient(); diff --git a/src/features/auth/hooks/useOAuthError/useOAuthError.ts b/src/features/auth/hooks/useOAuthError/useOAuthError.ts index a06f1021..f30b3921 100644 --- a/src/features/auth/hooks/useOAuthError/useOAuthError.ts +++ b/src/features/auth/hooks/useOAuthError/useOAuthError.ts @@ -1,7 +1,7 @@ import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { useEffect } from "react"; -import { useToast } from "@/hooks/useToast"; +import { useToast } from "@/shared/hooks/useToast"; export function useOAuthError(authType: "login" | "signup") { const searchParams = useSearchParams(); diff --git a/src/features/auth/login/actions/loginAction.ts b/src/features/auth/login/actions/loginAction.ts index d2e48ffa..8a7926fc 100644 --- a/src/features/auth/login/actions/loginAction.ts +++ b/src/features/auth/login/actions/loginAction.ts @@ -4,7 +4,7 @@ import { redirect } from "next/navigation"; import z from "zod"; import { loginSchema } from "@/features/auth/login/types/login.type"; -import { setTokenCookiesServerAction } from "@/lib/auth/cookies"; +import { setTokenCookiesServerAction } from "@/shared/lib/auth/cookies"; type LoginState = { errors?: { diff --git a/src/mocks/handlers/auth.ts b/src/features/auth/mock/auth.ts similarity index 97% rename from src/mocks/handlers/auth.ts rename to src/features/auth/mock/auth.ts index ee110333..40496cc8 100644 --- a/src/mocks/handlers/auth.ts +++ b/src/features/auth/mock/auth.ts @@ -1,6 +1,6 @@ import { HttpResponse } from "msw"; -import { apiMock } from "@/mocks/apiMock"; +import { apiMock } from "@/shared/mock/apiMock"; export const authHandlers = [ // 내 정보 조회 diff --git a/src/features/auth/signup/hooks/useSignupMutation/index.ts b/src/features/auth/mutation/useSignupMutation/index.ts similarity index 100% rename from src/features/auth/signup/hooks/useSignupMutation/index.ts rename to src/features/auth/mutation/useSignupMutation/index.ts diff --git a/src/features/auth/signup/hooks/useSignupMutation/useSignupMutation.ts b/src/features/auth/mutation/useSignupMutation/useSignupMutation.ts similarity index 75% rename from src/features/auth/signup/hooks/useSignupMutation/useSignupMutation.ts rename to src/features/auth/mutation/useSignupMutation/useSignupMutation.ts index 3bdf4220..090438b1 100644 --- a/src/features/auth/signup/hooks/useSignupMutation/useSignupMutation.ts +++ b/src/features/auth/mutation/useSignupMutation/useSignupMutation.ts @@ -1,9 +1,9 @@ import { useMutation } from "@tanstack/react-query"; import { useRouter } from "next/navigation"; -import { signupMutationFn } from "@/features/auth/signup/api/signup.api"; -import { useToast } from "@/hooks/useToast"; -import { ApiError } from "@/lib/api/types"; +import { signupMutationFn } from "@/entities/auth/api/signup.api"; +import { useToast } from "@/shared/hooks/useToast"; +import { ApiError } from "@/shared/lib/api/types"; export function useSignupMutation() { const { toast } = useToast(); diff --git a/src/features/auth/signup/hooks/useEmailDuplicate/useEmailDuplicate.ts b/src/features/auth/signup/hooks/useEmailDuplicate/useEmailDuplicate.ts index 08cb244e..7e8e5b02 100644 --- a/src/features/auth/signup/hooks/useEmailDuplicate/useEmailDuplicate.ts +++ b/src/features/auth/signup/hooks/useEmailDuplicate/useEmailDuplicate.ts @@ -1,6 +1,6 @@ import { useMutation } from "@tanstack/react-query"; -import { checkEmailDuplicate } from "@/features/auth/signup/api/signup.api"; +import { checkEmailDuplicate } from "@/entities/auth/api/signup.api"; export function useEmailDuplicate() { return useMutation({ diff --git a/src/features/auth/signup/hooks/useSignupForm/useSignupForm.ts b/src/features/auth/signup/hooks/useSignupForm/useSignupForm.ts index f26b721e..4670054b 100644 --- a/src/features/auth/signup/hooks/useSignupForm/useSignupForm.ts +++ b/src/features/auth/signup/hooks/useSignupForm/useSignupForm.ts @@ -1,13 +1,13 @@ import { ComponentProps, useState } from "react"; import z from "zod"; +import { useSignupMutation } from "@/features/auth/mutation/useSignupMutation"; import { useEmailDuplicate } from "@/features/auth/signup/hooks/useEmailDuplicate"; -import { useSignupMutation } from "@/features/auth/signup/hooks/useSignupMutation"; import { SignupFormData, signupSchema, } from "@/features/auth/signup/types/signup.type"; -import { useToast } from "@/hooks/useToast"; +import { useToast } from "@/shared/hooks/useToast"; const useSignupForm = () => { const [values, setValues] = useState({ diff --git a/src/features/auth/signup/types/signup.type.ts b/src/features/auth/signup/types/signup.type.ts index 15ab4d99..1b292968 100644 --- a/src/features/auth/signup/types/signup.type.ts +++ b/src/features/auth/signup/types/signup.type.ts @@ -27,11 +27,3 @@ export const signupSchema = z }); export type SignupFormData = z.infer; - -export type CheckEmailResponse = { - success: boolean; - code: string; - message: string; - data: { exists: boolean }; - timestamp: string; -}; diff --git a/src/store/auth.store.ts b/src/features/auth/store/auth.store.ts similarity index 100% rename from src/store/auth.store.ts rename to src/features/auth/store/auth.store.ts diff --git a/src/mocks/handlers/goals.ts b/src/features/goal/mock/goals.ts similarity index 99% rename from src/mocks/handlers/goals.ts rename to src/features/goal/mock/goals.ts index 0e378fca..90694a5c 100644 --- a/src/mocks/handlers/goals.ts +++ b/src/features/goal/mock/goals.ts @@ -1,6 +1,6 @@ import { HttpResponse } from "msw"; -import { apiMock } from "@/mocks/apiMock"; +import { apiMock } from "@/shared/mock/apiMock"; export const goalsHandlers = [ apiMock.get("*/api/goals/:goalId/summary", ({ params }) => { diff --git a/src/features/goal/mutation/useDeleteGoalMutation.ts b/src/features/goal/mutation/useDeleteGoalMutation.ts index d2e58118..a1d38bc3 100644 --- a/src/features/goal/mutation/useDeleteGoalMutation.ts +++ b/src/features/goal/mutation/useDeleteGoalMutation.ts @@ -1,7 +1,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import { useRouter } from "next/navigation"; -import { goalApi } from "../api"; +import { goalApi } from "@/entities/goal/api/api"; type UseDeleteGoalMutationOptions = { goalId: string; diff --git a/src/features/goal/mutation/useUpdateGoalMutation.ts b/src/features/goal/mutation/useUpdateGoalMutation.ts index 8403eb4e..bd8cad45 100644 --- a/src/features/goal/mutation/useUpdateGoalMutation.ts +++ b/src/features/goal/mutation/useUpdateGoalMutation.ts @@ -1,6 +1,6 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; -import { goalApi } from "../api"; +import { goalApi } from "@/entities/goal/api/api"; type UpdateGoalVariables = { name: string; diff --git a/src/features/home/api.ts b/src/features/home/api.ts deleted file mode 100644 index 1d3bc731..00000000 --- a/src/features/home/api.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { apiClient } from "@/lib/api/client"; -import { - DueSoonSuccessResponse, - FavoriteGoalsQueryParams, - InfiniteQueryParams, - ProgressSuccessResponse, - RecentSuccessResponse, -} from "./types"; - -import { FavoriteGoalsSuccessResponse } from "./types"; - -export const progressApi = { - read: () => apiClient.get("/api/main/progress"), -}; - -export const favoriteGoalsApi = { - read: (params: FavoriteGoalsQueryParams = {}) => - apiClient.get("/api/main/favorite-goals", { - params, - }), -}; - -export const recentApi = { - read: (params: InfiniteQueryParams = {}) => - apiClient.get("/api/todos/recent", { - params, - }), -}; - -export const dueSoonApi = { - read: (params: InfiniteQueryParams = {}) => - apiClient.get("/api/todos/due-soon", { - params, - }), -}; diff --git a/src/features/home/types.ts b/src/features/home/types.ts deleted file mode 100644 index a6a81247..00000000 --- a/src/features/home/types.ts +++ /dev/null @@ -1,153 +0,0 @@ -export interface ProgressItem { - teamId: number; - teamName: string; - todayProgressPercent: number; -} - -export interface ProgressData { - teamProgress: ProgressItem[]; - myProgressPercent: number; -} - -// @TODO: 정의되어있는 ApiResponse | ApiError 로 묶기 - -export interface ProgressSuccessResponse { - success: true; - code: "SUCCESS"; - message: string; - data: ProgressData; - timestamp: string; -} - -// @TODO: 정의되어있는 ApiResponse | ApiError 로 묶기 - -export type ProgressErrorResponse = - | { - success: false; - code: "AUTH_LOGIN_REQUIRED"; - message: "로그인이 필요합니다."; - data: null; - timestamp: string; - } - | { - success: false; - code: "USER_NOT_FOUND"; - message: "사용자를 찾을 수 없습니다."; - data: null; - timestamp: string; - } - | { - success: false; - code: "USER_ALREADY_DELETED"; - message: "탈퇴한 계정입니다."; - data: null; - timestamp: string; - }; - -export type ProgressResponse = ProgressSuccessResponse | ProgressErrorResponse; - -// favoriteGoalsApi - GET / query params - -export type FavoriteGoalsQueryParams = { - cursorId?: number; - cursorCreatedAt?: string; - size?: number; -}; - -// FavoriteGoalItem - -export interface FavoriteGoalItem { - teamId: number; - teamName: string; - goalId: number; - goalName: string; - progressPercent: number; - isFavorite: boolean; - createdAt: string; -} - -// FavoriteGoalsSuccessResponse - -export interface FavoriteGoalsSuccessResponse { - success: true; - code: string; - message: string; - data: { - items: FavoriteGoalItem[]; - hasNext: boolean; - nextCursorCreatedAt: string; - nextCursorId: number; - }; - timestamp: string; -} - -// FavoriteGoalsErrorResponse - -export type FavoriteGoalsErrorResponse = - | { - success: false; - code: "AUTH_LOGIN_REQUIRED"; - message: "로그인이 필요합니다."; - data: null; - timestamp: string; - } - | { - success: false; - code: "GOAL_CURSOR_INVALID"; - message: "커서 값이 올바르지 않습니다. cursorCreatedAt와 cursorId를 함께 전달하세요."; - data: null; - timestamp: string; - } - | { - success: false; - code: "MAIN_PAGE_SIZE_INVALID"; - message: "size는 1 이상이어야 합니다."; - data: null; - timestamp: string; - }; - -export type FavoriteGoalsResponse = - | FavoriteGoalsSuccessResponse - | FavoriteGoalsErrorResponse; - -// GET - query params - -export type InfiniteQueryParams = { - cursorId?: number; - cursorCreatedAt?: string; - size?: number; -}; - -export type TodoItem = { - todoId: number; - title: string; - teamDisplayName: string; - goalTitle: string; - dueDate: string; -}; - -export type RecentSuccessResponse = { - success: true; - code: string; - message: string; - data: { - items: TodoItem[]; - hasNext: boolean; - nextCursorCreatedAt: string; - nextCursorId: number; - }; - timestamp: string; -}; - -export type DueSoonSuccessResponse = { - success: true; - code: string; - message: string; - data: { - items: TodoItem[]; - hasNext: boolean; - nextCursorDueDate: string; - nextCursorId: number; - }; - timestamp: string; -}; diff --git a/src/features/home/utils/createPaginationOptions.ts b/src/features/home/utils/createPaginationOptions.ts deleted file mode 100644 index 414a8898..00000000 --- a/src/features/home/utils/createPaginationOptions.ts +++ /dev/null @@ -1,38 +0,0 @@ -type CursorParams = { - size?: number; - cursorId?: number; - cursorCreatedAt?: string; -}; - -type CursorPage = { - hasNext: boolean; - nextCursorId?: number; - nextCursorCreatedAt?: string; -}; - -// useSuspenseInfiniteQuery(options) 옵션 생성 함수 -export function createPaginationOptions< - Params extends CursorParams = CursorParams, - Page extends CursorPage = CursorPage, ->(apiKey: string, apiFunction: (param: Params) => Promise<{ data: Page }>) { - const size = 20; - - return { - queryKey: [apiKey], - initialPageParam: { size } as Params, - - queryFn: async ({ pageParam }: { pageParam: Params }) => { - const res = await apiFunction(pageParam); - return res.data; - }, - - getNextPageParam: (lastPage: Page): Params | undefined => - lastPage.hasNext - ? ({ - size, - cursorId: lastPage.nextCursorId, - cursorCreatedAt: lastPage.nextCursorCreatedAt, - } as Params) - : undefined, - }; -} diff --git a/src/features/notification/api.ts b/src/features/notification/api.ts index 32215298..d5cd7c53 100644 --- a/src/features/notification/api.ts +++ b/src/features/notification/api.ts @@ -1,4 +1,4 @@ -import { apiClient } from "@/lib/api/client"; +import { apiClient } from "@/shared/lib/api/client"; import { NotificationListSuccessResponse, diff --git a/src/features/notification/useNotificationSSE.ts b/src/features/notification/useNotificationSSE.ts index e7369c76..39cf6dce 100644 --- a/src/features/notification/useNotificationSSE.ts +++ b/src/features/notification/useNotificationSSE.ts @@ -3,7 +3,7 @@ import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useEffect, useRef } from "react"; -import { userQueries } from "@/constants/queryKeys/user.queryKey"; +import { userQueries } from "@/entities/auth/query/user.queryKey"; import { NotificationApi } from "./api"; diff --git a/src/features/post/api.ts b/src/features/post/api.ts deleted file mode 100644 index 7177ce25..00000000 --- a/src/features/post/api.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { apiClient } from "@/lib/api/client"; - -import type { CreatePostInput, Post } from "./types"; - -export const postApi = { - // 단일 글 조회 - getById: (id: number) => apiClient.get(`/api/posts/${id}`), - - // 전체 글 조회 - getAll: () => apiClient.get("/api/posts"), - - // 글 생성 - create: (data: CreatePostInput) => apiClient.post("/api/posts", data), - - // 글 삭제 - delete: (id: number) => apiClient.delete(`/api/posts/${id}`), -}; diff --git a/src/features/post/types.ts b/src/features/post/types.ts deleted file mode 100644 index 3a4a90e4..00000000 --- a/src/features/post/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -export interface Post { - id: number; - title: string; - body: string; -} - -export type CreatePostInput = Omit; -export type UpdatePostInput = Partial; diff --git a/src/features/team/hooks/useCreateTeamForm.ts b/src/features/team/hooks/useCreateTeamForm.ts index 9f4685c4..c59cb932 100644 --- a/src/features/team/hooks/useCreateTeamForm.ts +++ b/src/features/team/hooks/useCreateTeamForm.ts @@ -4,11 +4,11 @@ import { useQueryClient } from "@tanstack/react-query"; import { useRouter } from "next/navigation"; import { ComponentProps, useState } from "react"; -import { useCreateTeamMutation } from "@/features/team/hooks/mutation/useCreateTeamMutation"; -import { teamQueries } from "@/features/team/query/team.queryKey"; -import { createTeamSchema } from "@/features/team/types"; -import { useToast } from "@/hooks/useToast"; -import type { ApiError } from "@/lib/api/types"; +import { teamQueries } from "@/entities/team/query/team.queryKey"; +import { createTeamSchema } from "@/entities/team/types/types"; +import { useCreateTeamMutation } from "@/features/team/mutation/useCreateTeamMutation"; +import { useToast } from "@/shared/hooks/useToast"; +import type { ApiError } from "@/shared/lib/api/types"; export const useCreateTeamForm = () => { const router = useRouter(); diff --git a/src/features/team/hooks/useTeamLeaveModal.tsx b/src/features/team/hooks/useTeamLeaveModal.tsx index 91479d0a..26fe9b20 100644 --- a/src/features/team/hooks/useTeamLeaveModal.tsx +++ b/src/features/team/hooks/useTeamLeaveModal.tsx @@ -1,12 +1,11 @@ "use client"; -import Button from "@/components/common/Button/Button"; -import { Modal } from "@/components/common/Modal"; -import { useOverlay } from "@/hooks/useOverlay"; -import { useToast } from "@/hooks/useToast"; -import { ApiError } from "@/lib/api/types"; - -import { teamApi } from "../api"; +import { teamApi } from "@/entities/team/api/api"; +import { useOverlay } from "@/shared/hooks/useOverlay"; +import { useToast } from "@/shared/hooks/useToast"; +import { ApiError } from "@/shared/lib/api/types"; +import Button from "@/shared/ui/Button/Button/Button"; +import { Modal } from "@/shared/ui/Modal"; const LEAVE_TEAM_MODAL_ID = "leave-team-confirm-modal"; diff --git a/src/features/management/utils.ts b/src/features/team/management.utils.ts similarity index 100% rename from src/features/management/utils.ts rename to src/features/team/management.utils.ts diff --git a/src/mocks/handlers/invitations.ts b/src/features/team/mock/invitations.ts similarity index 95% rename from src/mocks/handlers/invitations.ts rename to src/features/team/mock/invitations.ts index 38590ac1..7134fd3f 100644 --- a/src/mocks/handlers/invitations.ts +++ b/src/features/team/mock/invitations.ts @@ -1,6 +1,6 @@ import { HttpResponse } from "msw"; -import { apiMock } from "@/mocks/apiMock"; +import { apiMock } from "@/shared/mock/apiMock"; export const invitationsHandlers = [ apiMock.get("*/api/teams/invitations/:inviteToken", () => { diff --git a/src/mocks/handlers/management.ts b/src/features/team/mock/management.ts similarity index 99% rename from src/mocks/handlers/management.ts rename to src/features/team/mock/management.ts index ee542e7c..d2154f87 100644 --- a/src/mocks/handlers/management.ts +++ b/src/features/team/mock/management.ts @@ -1,7 +1,8 @@ import { HttpResponse } from "msw"; -import { apiMock } from "@/mocks/apiMock"; +import { apiMock } from "@/shared/mock/apiMock"; +// @TODO: ? const now = "2026-04-02T00:00:00Z"; const teamDetail = { diff --git a/src/mocks/handlers/teams.ts b/src/features/team/mock/teams.ts similarity index 98% rename from src/mocks/handlers/teams.ts rename to src/features/team/mock/teams.ts index ac9098db..e52c4033 100644 --- a/src/mocks/handlers/teams.ts +++ b/src/features/team/mock/teams.ts @@ -1,6 +1,6 @@ import { HttpResponse } from "msw"; -import { apiMock } from "@/mocks/apiMock"; +import { apiMock } from "@/shared/mock/apiMock"; export const teamsHandlers = [ apiMock.get("*/api/teams/me", () => { diff --git a/src/features/team/hooks/mutation/useCreateTeamMutation.ts b/src/features/team/mutation/useCreateTeamMutation.ts similarity index 67% rename from src/features/team/hooks/mutation/useCreateTeamMutation.ts rename to src/features/team/mutation/useCreateTeamMutation.ts index 6ada4ecb..94a7ee2d 100644 --- a/src/features/team/hooks/mutation/useCreateTeamMutation.ts +++ b/src/features/team/mutation/useCreateTeamMutation.ts @@ -2,10 +2,9 @@ import { useMutation, UseMutationOptions } from "@tanstack/react-query"; -import { teamApi } from "@/features/team/api"; -import type { ApiError } from "@/lib/api/types"; - -import { ResponseCreateTeam } from "../../types"; +import { teamApi } from "@/entities/team/api/api"; +import { ResponseCreateTeam } from "@/entities/team/types/types"; +import type { ApiError } from "@/shared/lib/api/types"; type UseCreateTeamMutationParams = UseMutationOptions< ResponseCreateTeam, diff --git a/src/utils/formatMemberList.ts b/src/features/team/utils/formatMemberList.ts similarity index 100% rename from src/utils/formatMemberList.ts rename to src/features/team/utils/formatMemberList.ts diff --git a/src/features/todo/constants/todoColumnSort.ts b/src/features/todo/constants/todoColumnSort.ts index d357a9b1..8d8560f6 100644 --- a/src/features/todo/constants/todoColumnSort.ts +++ b/src/features/todo/constants/todoColumnSort.ts @@ -1,4 +1,4 @@ -import type { TodoListSort } from "../types"; +import type { TodoListSort } from "@/entities/todo/types/types"; const TODO_LIST_SORT_BY_LABEL_CONST = { "마감일 순": "DUE_DATE", diff --git a/src/features/todo/hooks/useCreateTodoForm.ts b/src/features/todo/hooks/useCreateTodoForm.ts index 553c3730..4808e811 100644 --- a/src/features/todo/hooks/useCreateTodoForm.ts +++ b/src/features/todo/hooks/useCreateTodoForm.ts @@ -2,9 +2,9 @@ import { ChangeEvent, FormEvent, useState } from "react"; -import { useToast } from "@/hooks/useToast"; +import { useToast } from "@/shared/hooks/useToast"; -import { useCreateTodoMutation } from "./mutation/useCreateTodoMutation"; +import { useCreateTodoMutation } from "../mutation/useCreateTodoMutation"; interface UseCreateTodoFormParams { goalId: string; diff --git a/src/features/todo/hooks/useTodoCreateModal.tsx b/src/features/todo/hooks/useTodoCreateModal.tsx index 7e290b50..8cc6207e 100644 --- a/src/features/todo/hooks/useTodoCreateModal.tsx +++ b/src/features/todo/hooks/useTodoCreateModal.tsx @@ -3,17 +3,17 @@ import { useQuery, useSuspenseQuery } from "@tanstack/react-query"; import { useParams } from "next/navigation"; -import Button from "@/components/common/Button/Button"; -import Input from "@/components/common/Input"; -import { Modal } from "@/components/common/Modal"; -import { Spacing } from "@/components/common/Spacing"; -import { AssigneeSelect } from "@/components/todo/AssigneeSelect"; -import { userQueries } from "@/constants/queryKeys"; +import { userQueries } from "@/entities/auth/query/user.queryKey"; +import { goalQueries } from "@/entities/goal/query/goal.queryKey"; +import { teamQueries } from "@/entities/team/query/team.queryKey"; +import { Member } from "@/entities/team/types/types"; import { useGoalId } from "@/features/goal/hooks/useGoalId"; -import { goalQueries } from "@/features/goal/query/goal.queryKey"; -import { teamQueries } from "@/features/team/query/team.queryKey"; -import { Member } from "@/features/team/types"; -import { useOverlay } from "@/hooks/useOverlay"; +import { useOverlay } from "@/shared/hooks/useOverlay"; +import Button from "@/shared/ui/Button/Button/Button"; +import Input from "@/shared/ui/Input"; +import { Modal } from "@/shared/ui/Modal"; +import { Spacing } from "@/shared/ui/Spacing"; +import { AssigneeSelect } from "@/widgets/todo/AssigneeSelect"; import { useCreateTodoForm } from "./useCreateTodoForm"; diff --git a/src/features/todo/hooks/useTodoDeleteModal.tsx b/src/features/todo/hooks/useTodoDeleteModal.tsx index 542a285d..290c5274 100644 --- a/src/features/todo/hooks/useTodoDeleteModal.tsx +++ b/src/features/todo/hooks/useTodoDeleteModal.tsx @@ -1,11 +1,10 @@ "use client"; -import Button from "@/components/common/Button/Button"; -import { Modal } from "@/components/common/Modal"; +import { todoApi } from "@/entities/todo/api/api"; import { useGoalId } from "@/features/goal/hooks/useGoalId"; -import { useOverlay } from "@/hooks/useOverlay"; - -import { todoApi } from "../api"; +import { useOverlay } from "@/shared/hooks/useOverlay"; +import Button from "@/shared/ui/Button/Button/Button"; +import { Modal } from "@/shared/ui/Modal"; const TODO_DELETE_MODAL_ID = "todo-delete-confirm-modal"; diff --git a/src/features/todo/hooks/useTodoDetailModal.tsx b/src/features/todo/hooks/useTodoDetailModal.tsx index 5bcdfa60..05c98997 100644 --- a/src/features/todo/hooks/useTodoDetailModal.tsx +++ b/src/features/todo/hooks/useTodoDetailModal.tsx @@ -4,16 +4,15 @@ import { useQuery, useSuspenseQuery } from "@tanstack/react-query"; import Image from "next/image"; import { useParams } from "next/navigation"; -import defaultAvatar from "@/assets/images/avatar.png"; -import Button from "@/components/common/Button/Button"; -import { Icon } from "@/components/common/Icon"; -import { Modal } from "@/components/common/Modal"; +import { goalQueries } from "@/entities/goal/query/goal.queryKey"; +import { teamQueries } from "@/entities/team/query/team.queryKey"; +import { Todo } from "@/entities/todo/types/types"; import { useGoalId } from "@/features/goal/hooks/useGoalId"; -import { goalQueries } from "@/features/goal/query/goal.queryKey"; -import { teamQueries } from "@/features/team/query/team.queryKey"; -import { useOverlay } from "@/hooks/useOverlay"; - -import { Todo } from "../types"; +import defaultAvatar from "@/shared/assets/images/avatar.png"; +import { useOverlay } from "@/shared/hooks/useOverlay"; +import Button from "@/shared/ui/Button/Button/Button"; +import { Icon } from "@/shared/ui/Icon"; +import { Modal } from "@/shared/ui/Modal"; const TODO_DETAIL_MODAL_ID = "todo-detail-modal"; diff --git a/src/mocks/handlers/todos.ts b/src/features/todo/mock/todos.ts similarity index 99% rename from src/mocks/handlers/todos.ts rename to src/features/todo/mock/todos.ts index 1b5a4cd3..b26032f2 100644 --- a/src/mocks/handlers/todos.ts +++ b/src/features/todo/mock/todos.ts @@ -1,6 +1,6 @@ import { HttpResponse } from "msw"; -import { apiMock } from "@/mocks/apiMock"; +import { apiMock } from "@/shared/mock/apiMock"; type TodoStatus = "TODO" | "DOING" | "DONE"; type TodoSort = "DUE_DATE" | "CREATED_LATEST" | "CREATED_OLDEST"; diff --git a/src/features/todo/hooks/mutation/useCreateTodoMutation.ts b/src/features/todo/mutation/useCreateTodoMutation.ts similarity index 81% rename from src/features/todo/hooks/mutation/useCreateTodoMutation.ts rename to src/features/todo/mutation/useCreateTodoMutation.ts index aa672afe..d9451369 100644 --- a/src/features/todo/hooks/mutation/useCreateTodoMutation.ts +++ b/src/features/todo/mutation/useCreateTodoMutation.ts @@ -1,11 +1,10 @@ import { useMutation } from "@tanstack/react-query"; import { useQueryClient } from "@tanstack/react-query"; -import { useToast } from "@/hooks/useToast"; -import type { ApiError } from "@/lib/api/types"; - -import { todoApi } from "../../api"; -import { CreateTodoInput } from "../../types"; +import { todoApi } from "@/entities/todo/api/api"; +import { CreateTodoInput } from "@/entities/todo/types/types"; +import { useToast } from "@/shared/hooks/useToast"; +import type { ApiError } from "@/shared/lib/api/types"; type CreateTodoVariables = { goalId: string; diff --git a/src/features/todo/hooks/mutation/usePatchTodoStatusMutation.ts b/src/features/todo/mutation/usePatchTodoStatusMutation.ts similarity index 91% rename from src/features/todo/hooks/mutation/usePatchTodoStatusMutation.ts rename to src/features/todo/mutation/usePatchTodoStatusMutation.ts index a87d0fa2..33c1b40f 100644 --- a/src/features/todo/hooks/mutation/usePatchTodoStatusMutation.ts +++ b/src/features/todo/mutation/usePatchTodoStatusMutation.ts @@ -2,8 +2,12 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; -import { todoApi } from "@/features/todo/api"; -import type { Todo, TodoStatus, UpdateTodoInput } from "@/features/todo/types"; +import { todoApi } from "@/entities/todo/api/api"; +import type { + Todo, + TodoStatus, + UpdateTodoInput, +} from "@/entities/todo/types/types"; type PatchTodoStatusVariables = { goalId: string; diff --git a/src/features/trash/api/trash.api.ts b/src/features/trash/api/trash.api.ts index af163972..793adedd 100644 --- a/src/features/trash/api/trash.api.ts +++ b/src/features/trash/api/trash.api.ts @@ -1,5 +1,5 @@ -import { apiClient } from "@/lib/api/client"; -import { ApiResponse } from "@/lib/api/types"; +import { apiClient } from "@/shared/lib/api/client"; +import { ApiResponse } from "@/shared/lib/api/types"; import { TrashActionParam, TrashListData } from "../types/trash.types"; diff --git a/src/features/trash/hooks/useDeleteTrashMutation/useDeleteTrashMutation.ts b/src/features/trash/hooks/useDeleteTrashMutation/useDeleteTrashMutation.ts index 8392a5e5..e42de087 100644 --- a/src/features/trash/hooks/useDeleteTrashMutation/useDeleteTrashMutation.ts +++ b/src/features/trash/hooks/useDeleteTrashMutation/useDeleteTrashMutation.ts @@ -2,8 +2,8 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import { deleteTrash } from "@/features/trash/api/trash.api"; import { TrashActionParam } from "@/features/trash/types/trash.types"; -import { useToast } from "@/hooks/useToast"; -import { ApiError } from "@/lib/api/types"; +import { useToast } from "@/shared/hooks/useToast"; +import { ApiError } from "@/shared/lib/api/types"; export const useDeleteTrashMutation = () => { const queryClient = useQueryClient(); diff --git a/src/features/trash/hooks/useRestoreTrashMutation/useRestoreTrashMutation.ts b/src/features/trash/hooks/useRestoreTrashMutation/useRestoreTrashMutation.ts index 4d30fc25..8ea57063 100644 --- a/src/features/trash/hooks/useRestoreTrashMutation/useRestoreTrashMutation.ts +++ b/src/features/trash/hooks/useRestoreTrashMutation/useRestoreTrashMutation.ts @@ -2,8 +2,8 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import { restoreTrash } from "@/features/trash/api/trash.api"; import { TrashActionParam } from "@/features/trash/types/trash.types"; -import { useToast } from "@/hooks/useToast"; -import { ApiError } from "@/lib/api/types"; +import { useToast } from "@/shared/hooks/useToast"; +import { ApiError } from "@/shared/lib/api/types"; export const useRestoreTrashMutation = () => { const queryClient = useQueryClient(); diff --git a/src/constants/queryKeys/trash.queryKey.ts b/src/features/trash/trash.queryKey.ts similarity index 94% rename from src/constants/queryKeys/trash.queryKey.ts rename to src/features/trash/trash.queryKey.ts index 22720e2b..bc8ad887 100644 --- a/src/constants/queryKeys/trash.queryKey.ts +++ b/src/features/trash/trash.queryKey.ts @@ -5,7 +5,7 @@ import { getTeamTrashList, } from "@/features/trash/api/trash.api"; -import { STALE_TIME } from "../staleTime"; +import { STALE_TIME } from "../../shared/constants/query/staleTime"; const SIZE = 20; diff --git a/src/features/my/hooks/useDeleteMeMutation/index.ts b/src/features/user/hooks/useDeleteMeMutation/index.ts similarity index 100% rename from src/features/my/hooks/useDeleteMeMutation/index.ts rename to src/features/user/hooks/useDeleteMeMutation/index.ts diff --git a/src/features/my/hooks/useDeleteMeMutation/useDeleteMeMutation.ts b/src/features/user/hooks/useDeleteMeMutation/useDeleteMeMutation.ts similarity index 81% rename from src/features/my/hooks/useDeleteMeMutation/useDeleteMeMutation.ts rename to src/features/user/hooks/useDeleteMeMutation/useDeleteMeMutation.ts index 9c7d4db9..4e8744d7 100644 --- a/src/features/my/hooks/useDeleteMeMutation/useDeleteMeMutation.ts +++ b/src/features/user/hooks/useDeleteMeMutation/useDeleteMeMutation.ts @@ -2,9 +2,9 @@ import { useMutation } from "@tanstack/react-query"; import { useRouter } from "next/navigation"; import { logoutAction } from "@/features/auth/logout/actions/logoutAction"; -import { useToast } from "@/hooks/useToast"; +import { useToast } from "@/shared/hooks/useToast"; -import { deleteMe } from "../../api/myInfo.api"; +import { deleteMe } from "../../../../entities/auth/api/myInfo.api"; export function useDeleteMeMutation() { const { toast } = useToast(); diff --git a/src/features/my/hooks/useMyProfileForm/index.ts b/src/features/user/hooks/useMyProfileForm/index.ts similarity index 100% rename from src/features/my/hooks/useMyProfileForm/index.ts rename to src/features/user/hooks/useMyProfileForm/index.ts diff --git a/src/features/my/hooks/useMyProfileForm/useMyProfileForm.ts b/src/features/user/hooks/useMyProfileForm/useMyProfileForm.ts similarity index 98% rename from src/features/my/hooks/useMyProfileForm/useMyProfileForm.ts rename to src/features/user/hooks/useMyProfileForm/useMyProfileForm.ts index 3e4e31e4..d2cc2f39 100644 --- a/src/features/my/hooks/useMyProfileForm/useMyProfileForm.ts +++ b/src/features/user/hooks/useMyProfileForm/useMyProfileForm.ts @@ -4,7 +4,7 @@ import z from "zod"; import { MyProfileFormData, myProfileSchema, -} from "@/features/my/types/myProfile.type"; +} from "@/features/user/types/myProfile.type"; import { useUpdateProfileMutation } from "../useUpdateProfileMutation"; diff --git a/src/features/my/hooks/useUpdateProfileMutation/index.ts b/src/features/user/hooks/useUpdateProfileMutation/index.ts similarity index 100% rename from src/features/my/hooks/useUpdateProfileMutation/index.ts rename to src/features/user/hooks/useUpdateProfileMutation/index.ts diff --git a/src/features/my/hooks/useUpdateProfileMutation/useUpdateProfileMutation.ts b/src/features/user/hooks/useUpdateProfileMutation/useUpdateProfileMutation.ts similarity index 69% rename from src/features/my/hooks/useUpdateProfileMutation/useUpdateProfileMutation.ts rename to src/features/user/hooks/useUpdateProfileMutation/useUpdateProfileMutation.ts index d37ebbe6..a8cb7e7f 100644 --- a/src/features/my/hooks/useUpdateProfileMutation/useUpdateProfileMutation.ts +++ b/src/features/user/hooks/useUpdateProfileMutation/useUpdateProfileMutation.ts @@ -1,9 +1,9 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; -import { userQueries } from "@/constants/queryKeys"; -import { updateProfile } from "@/features/my/api/myInfo.api"; -import { useToast } from "@/hooks/useToast"; -import { ApiError } from "@/lib/api/types"; +import { updateProfile } from "@/entities/auth/api/myInfo.api"; +import { userQueries } from "@/entities/auth/query/user.queryKey"; +import { useToast } from "@/shared/hooks/useToast"; +import { ApiError } from "@/shared/lib/api/types"; export function useUpdateProfileMutation() { const queryClient = useQueryClient(); diff --git a/src/features/my/hooks/useUploadProfileImageMutation/index.ts b/src/features/user/hooks/useUploadProfileImageMutation/index.ts similarity index 100% rename from src/features/my/hooks/useUploadProfileImageMutation/index.ts rename to src/features/user/hooks/useUploadProfileImageMutation/index.ts diff --git a/src/features/my/hooks/useUploadProfileImageMutation/useUploadProfileImageMutation.ts b/src/features/user/hooks/useUploadProfileImageMutation/useUploadProfileImageMutation.ts similarity index 75% rename from src/features/my/hooks/useUploadProfileImageMutation/useUploadProfileImageMutation.ts rename to src/features/user/hooks/useUploadProfileImageMutation/useUploadProfileImageMutation.ts index 71f55703..541843a3 100644 --- a/src/features/my/hooks/useUploadProfileImageMutation/useUploadProfileImageMutation.ts +++ b/src/features/user/hooks/useUploadProfileImageMutation/useUploadProfileImageMutation.ts @@ -1,8 +1,8 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; -import { userQueries } from "@/constants/queryKeys"; -import { uploadProfileImage } from "@/features/my/api/myInfo.api"; -import { useToast } from "@/hooks/useToast"; +import { uploadProfileImage } from "@/entities/auth/api/myInfo.api"; +import { userQueries } from "@/entities/auth/query/user.queryKey"; +import { useToast } from "@/shared/hooks/useToast"; export function useUploadProfileImageMutation() { const queryClient = useQueryClient(); diff --git a/src/features/my/types/myProfile.type.ts b/src/features/user/types/myProfile.type.ts similarity index 100% rename from src/features/my/types/myProfile.type.ts rename to src/features/user/types/myProfile.type.ts diff --git a/src/lib/api/GUIDE.md b/src/lib/api/GUIDE.md deleted file mode 100644 index e69de29b..00000000 diff --git a/src/lib/fonts.ts b/src/lib/fonts.ts deleted file mode 100644 index 076620c9..00000000 --- a/src/lib/fonts.ts +++ /dev/null @@ -1,10 +0,0 @@ -// src/lib/fonts.ts -import localFont from "next/font/local"; - -export const pretendard = localFont({ - // 상대 경로로 src 폴더 내의 폰트 파일을 지목합니다. - src: "../assets/fonts/PretendardVariable.woff2", - display: "swap", - weight: "45 920", - variable: "--font-pretendard", -}); diff --git a/src/mocks/handlers/index.ts b/src/mocks/handlers/index.ts deleted file mode 100644 index 0dace8f6..00000000 --- a/src/mocks/handlers/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { authHandlers } from "./auth"; -import { goalsHandlers } from "./goals"; -import { invitationsHandlers } from "./invitations"; -import { managementHandler } from "./management"; -import { postsHandlers } from "./posts"; -import { teamsHandlers } from "./teams"; -import { todosHandlers } from "./todos"; - -export const handlers = [ - ...postsHandlers, - ...teamsHandlers, - ...invitationsHandlers, - ...goalsHandlers, - ...authHandlers, - ...todosHandlers, - ...managementHandler, -]; diff --git a/src/mocks/handlers/posts.ts b/src/mocks/handlers/posts.ts deleted file mode 100644 index a595f6f1..00000000 --- a/src/mocks/handlers/posts.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { HttpResponse } from "msw"; - -import { apiMock } from "@/mocks/apiMock"; - -export const postsHandlers = [ - apiMock.get("*/posts/:id", ({ request, params }) => { - // 1. 헤더에 토큰이 없으면 401 던지기 - const authHeader = request.headers.get("Authorization"); - - if (!authHeader) { - return new HttpResponse(null, { status: 401 }); - } - - // 2. id 500으로 요청하면 500 던지기 - if (params.id === "500") { - return new HttpResponse(null, { status: 500 }); - } - - // 3. 정상 응답 - return HttpResponse.json({ - id: Number(params.id), - title: `${params.id}번 게시글`, - body: "내용입니다.", - }); - }), -]; diff --git a/src/providers/ToastProvider.tsx b/src/providers/ToastProvider.tsx deleted file mode 100644 index 9b440d50..00000000 --- a/src/providers/ToastProvider.tsx +++ /dev/null @@ -1,9 +0,0 @@ -"use client"; - -import * as React from "react"; - -import ToastProvider from "@/components/common/Toast/ToastProvider"; - -export function Providers({ children }: { children: React.ReactNode }) { - return {children}; -} diff --git a/src/proxy.ts b/src/proxy.ts index a7b660e9..3cbe4113 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -1,7 +1,7 @@ import type { NextRequest } from "next/server"; import { NextResponse } from "next/server"; -import { PUBLIC_PATHS } from "@/constants/paths"; +import { PUBLIC_PATHS } from "@/shared/constants/paths"; export function proxy(request: NextRequest) { const { pathname } = request.nextUrl; diff --git a/src/assets/fonts/PretendardVariable.woff2 b/src/shared/assets/fonts/PretendardVariable.woff2 similarity index 100% rename from src/assets/fonts/PretendardVariable.woff2 rename to src/shared/assets/fonts/PretendardVariable.woff2 diff --git a/src/assets/images/avatar-blue-default.svg b/src/shared/assets/images/avatar-blue-default.svg similarity index 100% rename from src/assets/images/avatar-blue-default.svg rename to src/shared/assets/images/avatar-blue-default.svg diff --git a/src/assets/images/avatar-blue-glasses.svg b/src/shared/assets/images/avatar-blue-glasses.svg similarity index 100% rename from src/assets/images/avatar-blue-glasses.svg rename to src/shared/assets/images/avatar-blue-glasses.svg diff --git a/src/assets/images/avatar-green-default.svg b/src/shared/assets/images/avatar-green-default.svg similarity index 100% rename from src/assets/images/avatar-green-default.svg rename to src/shared/assets/images/avatar-green-default.svg diff --git a/src/assets/images/avatar-green-glasses.svg b/src/shared/assets/images/avatar-green-glasses.svg similarity index 100% rename from src/assets/images/avatar-green-glasses.svg rename to src/shared/assets/images/avatar-green-glasses.svg diff --git a/src/assets/images/avatar.png b/src/shared/assets/images/avatar.png similarity index 100% rename from src/assets/images/avatar.png rename to src/shared/assets/images/avatar.png diff --git a/src/assets/images/empty.png b/src/shared/assets/images/empty.png similarity index 100% rename from src/assets/images/empty.png rename to src/shared/assets/images/empty.png diff --git a/src/assets/images/fire.png b/src/shared/assets/images/fire.png similarity index 100% rename from src/assets/images/fire.png rename to src/shared/assets/images/fire.png diff --git a/src/assets/images/setting.png b/src/shared/assets/images/setting.png similarity index 100% rename from src/assets/images/setting.png rename to src/shared/assets/images/setting.png diff --git a/src/assets/images/star-empty.png b/src/shared/assets/images/star-empty.png similarity index 100% rename from src/assets/images/star-empty.png rename to src/shared/assets/images/star-empty.png diff --git a/src/assets/images/star-fill.png b/src/shared/assets/images/star-fill.png similarity index 100% rename from src/assets/images/star-fill.png rename to src/shared/assets/images/star-fill.png diff --git a/src/constants/paths.ts b/src/shared/constants/paths.ts similarity index 100% rename from src/constants/paths.ts rename to src/shared/constants/paths.ts diff --git a/src/constants/staleTime.ts b/src/shared/constants/query/staleTime.ts similarity index 100% rename from src/constants/staleTime.ts rename to src/shared/constants/query/staleTime.ts diff --git a/src/constants/zIndex.ts b/src/shared/constants/styles/zIndex.ts similarity index 100% rename from src/constants/zIndex.ts rename to src/shared/constants/styles/zIndex.ts diff --git a/src/hooks/useBreakpoint/index.ts b/src/shared/hooks/useBreakpoint/index.ts similarity index 100% rename from src/hooks/useBreakpoint/index.ts rename to src/shared/hooks/useBreakpoint/index.ts diff --git a/src/hooks/useDebouncedKeyword.ts b/src/shared/hooks/useDebouncedKeyword.ts similarity index 100% rename from src/hooks/useDebouncedKeyword.ts rename to src/shared/hooks/useDebouncedKeyword.ts diff --git a/src/hooks/useDropdown/Dropdown.tsx b/src/shared/hooks/useDropdown/Dropdown.tsx similarity index 96% rename from src/hooks/useDropdown/Dropdown.tsx rename to src/shared/hooks/useDropdown/Dropdown.tsx index 12728551..487a89c7 100644 --- a/src/hooks/useDropdown/Dropdown.tsx +++ b/src/shared/hooks/useDropdown/Dropdown.tsx @@ -2,8 +2,9 @@ import React from "react"; -import RightArrow from "@/components/common/Icons/RightArrow"; -import { cn } from "@/utils/utils"; +// @TODO: Icon Convention 위반 +// import RightArrow from "@/components/common/Icons/RightArrow"; +import { cn } from "@/shared/utils/styles/cn"; import { useDropdown } from "./index"; @@ -126,12 +127,12 @@ export const Dropdown = ({ > {/* TODO: 삭제 예정 - 어드민 혹은 팀원 */} {current || "Select"} - + /> */} diff --git a/src/hooks/useDropdown/index.ts b/src/shared/hooks/useDropdown/index.ts similarity index 100% rename from src/hooks/useDropdown/index.ts rename to src/shared/hooks/useDropdown/index.ts diff --git a/src/hooks/useInfiniteScroll/index.ts b/src/shared/hooks/useInfiniteScroll/index.ts similarity index 100% rename from src/hooks/useInfiniteScroll/index.ts rename to src/shared/hooks/useInfiniteScroll/index.ts diff --git a/src/hooks/useInfiniteScroll/useInfiniteScroll.ts b/src/shared/hooks/useInfiniteScroll/useInfiniteScroll.ts similarity index 100% rename from src/hooks/useInfiniteScroll/useInfiniteScroll.ts rename to src/shared/hooks/useInfiniteScroll/useInfiniteScroll.ts diff --git a/src/hooks/useOverlay/index.test.tsx b/src/shared/hooks/useOverlay/index.test.tsx similarity index 96% rename from src/hooks/useOverlay/index.test.tsx rename to src/shared/hooks/useOverlay/index.test.tsx index 6e6d4f5b..d0eb7ea5 100644 --- a/src/hooks/useOverlay/index.test.tsx +++ b/src/shared/hooks/useOverlay/index.test.tsx @@ -1,7 +1,7 @@ import { act, renderHook } from "@testing-library/react"; +import { useOverlayStore } from "../../store/overlay/useOverlay.store"; import { useOverlay } from "."; -import { useOverlayStore } from "./useOverlay.store"; describe("useOverlay", () => { beforeEach(() => { diff --git a/src/hooks/useOverlay/index.ts b/src/shared/hooks/useOverlay/index.ts similarity index 86% rename from src/hooks/useOverlay/index.ts rename to src/shared/hooks/useOverlay/index.ts index 7935b66d..f594bdb7 100644 --- a/src/hooks/useOverlay/index.ts +++ b/src/shared/hooks/useOverlay/index.ts @@ -1,6 +1,6 @@ import { useEffect } from "react"; -import { useOverlayStore } from "./useOverlay.store"; +import { useOverlayStore } from "../../store/overlay/useOverlay.store"; interface Props { exitOnUnmount?: boolean; diff --git a/src/hooks/useToast.ts b/src/shared/hooks/useToast.ts similarity index 76% rename from src/hooks/useToast.ts rename to src/shared/hooks/useToast.ts index f37c9804..eff3eb98 100644 --- a/src/hooks/useToast.ts +++ b/src/shared/hooks/useToast.ts @@ -1,6 +1,6 @@ import * as React from "react"; -import { ToastContext } from "@/components/common/Toast/ToastProvider"; +import { ToastContext } from "../providers/ToastProvider"; export function useToast() { const context = React.useContext(ToastContext); diff --git a/src/lib/api/client.ts b/src/shared/lib/api/client.ts similarity index 100% rename from src/lib/api/client.ts rename to src/shared/lib/api/client.ts diff --git a/src/lib/api/config.ts b/src/shared/lib/api/config.ts similarity index 100% rename from src/lib/api/config.ts rename to src/shared/lib/api/config.ts diff --git a/src/lib/api/types.ts b/src/shared/lib/api/types.ts similarity index 100% rename from src/lib/api/types.ts rename to src/shared/lib/api/types.ts diff --git a/src/lib/api/utils.ts b/src/shared/lib/api/utils.ts similarity index 100% rename from src/lib/api/utils.ts rename to src/shared/lib/api/utils.ts diff --git a/src/lib/auth/cookies.ts b/src/shared/lib/auth/cookies.ts similarity index 100% rename from src/lib/auth/cookies.ts rename to src/shared/lib/auth/cookies.ts diff --git a/src/mocks/MSWInitializer.tsx b/src/shared/mock/MSWInitializer.tsx similarity index 100% rename from src/mocks/MSWInitializer.tsx rename to src/shared/mock/MSWInitializer.tsx diff --git a/src/mocks/apiMock.ts b/src/shared/mock/apiMock.ts similarity index 100% rename from src/mocks/apiMock.ts rename to src/shared/mock/apiMock.ts diff --git a/src/mocks/browser.ts b/src/shared/mock/browser.ts similarity index 100% rename from src/mocks/browser.ts rename to src/shared/mock/browser.ts diff --git a/src/shared/mock/handlers.ts b/src/shared/mock/handlers.ts new file mode 100644 index 00000000..f9d8fb3f --- /dev/null +++ b/src/shared/mock/handlers.ts @@ -0,0 +1,15 @@ +import { authHandlers } from "@/features/auth/mock/auth"; +import { goalsHandlers } from "@/features/goal/mock/goals"; +import { invitationsHandlers } from "@/features/team/mock/invitations"; +import { managementHandler } from "@/features/team/mock/management"; +import { teamsHandlers } from "@/features/team/mock/teams"; +import { todosHandlers } from "@/features/todo/mock/todos"; + +export const handlers = [ + ...teamsHandlers, + ...invitationsHandlers, + ...goalsHandlers, + ...authHandlers, + ...todosHandlers, + ...managementHandler, +]; diff --git a/src/mocks/index.ts b/src/shared/mock/index.ts similarity index 100% rename from src/mocks/index.ts rename to src/shared/mock/index.ts diff --git a/src/mocks/server.ts b/src/shared/mock/server.ts similarity index 100% rename from src/mocks/server.ts rename to src/shared/mock/server.ts diff --git a/src/providers/ReactQueryProvider.tsx b/src/shared/providers/ReactQueryProvider.tsx similarity index 100% rename from src/providers/ReactQueryProvider.tsx rename to src/shared/providers/ReactQueryProvider.tsx diff --git a/src/components/common/Toast/ToastProvider.tsx b/src/shared/providers/ToastProvider.tsx similarity index 92% rename from src/components/common/Toast/ToastProvider.tsx rename to src/shared/providers/ToastProvider.tsx index 30902e4e..70fde3b2 100644 --- a/src/components/common/Toast/ToastProvider.tsx +++ b/src/shared/providers/ToastProvider.tsx @@ -3,10 +3,14 @@ import * as React from "react"; import { createPortal } from "react-dom"; -import { cn } from "@/utils/utils"; - -import { Toast } from "./Toast"; -import { ToastContextValue, ToastOptions, ToastRecord } from "./types"; +import { cn } from "@/shared/utils/styles/cn"; + +import { Toast } from "../ui/Toast/Toast"; +import { + ToastContextValue, + ToastOptions, + ToastRecord, +} from "../ui/Toast/types"; // 전역 상태관리 컨텍스트 export const ToastContext = React.createContext(null); diff --git a/src/hooks/useOverlay/useOverlay.store.test.ts b/src/shared/store/overlay/useOverlay.store.test.ts similarity index 100% rename from src/hooks/useOverlay/useOverlay.store.test.ts rename to src/shared/store/overlay/useOverlay.store.test.ts diff --git a/src/hooks/useOverlay/useOverlay.store.ts b/src/shared/store/overlay/useOverlay.store.ts similarity index 100% rename from src/hooks/useOverlay/useOverlay.store.ts rename to src/shared/store/overlay/useOverlay.store.ts diff --git a/src/components/common/AsyncBoundary/AsyncBoundary.tsx b/src/shared/ui/AsyncBoundary/AsyncBoundary.tsx similarity index 100% rename from src/components/common/AsyncBoundary/AsyncBoundary.tsx rename to src/shared/ui/AsyncBoundary/AsyncBoundary.tsx diff --git a/src/components/common/AsyncBoundary/index.tsx b/src/shared/ui/AsyncBoundary/index.tsx similarity index 100% rename from src/components/common/AsyncBoundary/index.tsx rename to src/shared/ui/AsyncBoundary/index.tsx diff --git a/src/components/common/ActionButton/ActionButton.tsx b/src/shared/ui/Button/ActionButton/ActionButton.tsx similarity index 57% rename from src/components/common/ActionButton/ActionButton.tsx rename to src/shared/ui/Button/ActionButton/ActionButton.tsx index 9a6f1a8c..3917361a 100644 --- a/src/components/common/ActionButton/ActionButton.tsx +++ b/src/shared/ui/Button/ActionButton/ActionButton.tsx @@ -1,30 +1,31 @@ "use client"; import { ComponentPropsWithoutRef } from "react"; -import LikeIcon from "@/components/common/Icons/LikeIcon"; -import ProfileEditIcon from "@/components/common/Icons/ProfileEditIcon"; -import { cn } from "@/utils/utils"; +// @TODO: Icon Convention 위반 +// import LikeIcon from "@/components/common/Icons/LikeIcon"; +// import ProfileEditIcon from "@/components/common/Icons/ProfileEditIcon"; +import { cn } from "@/shared/utils/styles/cn"; -const ICON_MAP = { - edit: ProfileEditIcon, - like: LikeIcon, -} as const; +// const ICON_MAP = { +// edit: ProfileEditIcon, +// like: LikeIcon, +// } as const; interface ActionButtonProps extends ComponentPropsWithoutRef<"button"> { - action: keyof typeof ICON_MAP; + // action: keyof typeof ICON_MAP; isSmall?: boolean; className?: string; } const ActionButton = ({ - action, + // action, isSmall = false, className, ...props }: ActionButtonProps) => { const buttonSize = isSmall ? "w-8 h-8" : "w-10 h-10"; - const IconComponent = ICON_MAP[action]; + // const IconComponent = ICON_MAP[action]; return ( ); }; diff --git a/src/components/common/Button/Button.tsx b/src/shared/ui/Button/Button/Button.tsx similarity index 97% rename from src/components/common/Button/Button.tsx rename to src/shared/ui/Button/Button/Button.tsx index 61dcfed4..a638d638 100644 --- a/src/components/common/Button/Button.tsx +++ b/src/shared/ui/Button/Button/Button.tsx @@ -4,7 +4,7 @@ import { cva, type VariantProps } from "class-variance-authority"; import { ComponentPropsWithoutRef, ReactNode } from "react"; // 내부 코드 -import { cn } from "@/utils/utils"; +import { cn } from "@/shared/utils/styles/cn"; const buttonVariants = cva( "inline-flex items-center justify-center rounded-full font-semibold focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue-800 transition-colors", diff --git a/src/components/common/SoftButton/SoftButton.stories.tsx b/src/shared/ui/Button/SoftButton/SoftButton.stories.tsx similarity index 94% rename from src/components/common/SoftButton/SoftButton.stories.tsx rename to src/shared/ui/Button/SoftButton/SoftButton.stories.tsx index 6166b7f8..fc18c01d 100644 --- a/src/components/common/SoftButton/SoftButton.stories.tsx +++ b/src/shared/ui/Button/SoftButton/SoftButton.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from "@storybook/nextjs-vite"; -import SoftButton from "@/components/common/SoftButton"; +import SoftButton from "@/shared/ui/Button/SoftButton"; const meta: Meta = { title: "Components/SoftButton", diff --git a/src/components/common/SoftButton/SoftButton.tsx b/src/shared/ui/Button/SoftButton/SoftButton.tsx similarity index 95% rename from src/components/common/SoftButton/SoftButton.tsx rename to src/shared/ui/Button/SoftButton/SoftButton.tsx index 191b56ab..4adae349 100644 --- a/src/components/common/SoftButton/SoftButton.tsx +++ b/src/shared/ui/Button/SoftButton/SoftButton.tsx @@ -1,7 +1,7 @@ import { cva, VariantProps } from "class-variance-authority"; import { ComponentProps } from "react"; -import { cn } from "@/utils/utils"; +import { cn } from "@/shared/utils/styles/cn"; const softButtonVariants = cva( "text-label-1 rounded-[10px] font-semibold px-7 py-3 h-12 disabled:cursor-not-allowed disabled:bg-background-normal-alternative-2 disabled:text-gray-400 disabled:ring disabled:ring-gray-200 cursor-pointer disabled:pointer-events-none transition-colors", diff --git a/src/components/common/SoftButton/index.ts b/src/shared/ui/Button/SoftButton/index.ts similarity index 100% rename from src/components/common/SoftButton/index.ts rename to src/shared/ui/Button/SoftButton/index.ts diff --git a/src/components/common/TextButton/TextButton.tsx b/src/shared/ui/Button/TextButton/TextButton.tsx similarity index 97% rename from src/components/common/TextButton/TextButton.tsx rename to src/shared/ui/Button/TextButton/TextButton.tsx index 8e234762..fe16fa40 100644 --- a/src/components/common/TextButton/TextButton.tsx +++ b/src/shared/ui/Button/TextButton/TextButton.tsx @@ -1,7 +1,7 @@ import { cva, type VariantProps } from "class-variance-authority"; import { ComponentPropsWithoutRef, ReactNode } from "react"; -import { cn } from "@/utils/utils"; +import { cn } from "@/shared/utils/styles/cn"; const textButtonVariants = cva( "inline-flex items-center justify-center font-semibold transition-colors focus:outline-none cursor-pointer", diff --git a/src/components/common/CircularProgress/index.tsx b/src/shared/ui/CircularProgress/index.tsx similarity index 98% rename from src/components/common/CircularProgress/index.tsx rename to src/shared/ui/CircularProgress/index.tsx index a7f36b3d..5019d01f 100644 --- a/src/components/common/CircularProgress/index.tsx +++ b/src/shared/ui/CircularProgress/index.tsx @@ -1,4 +1,4 @@ -import { cn } from "@/utils/utils"; +import { cn } from "@/shared/utils/styles/cn"; import type { ProgressColor, ProgressVariant } from "../ProgressBar"; diff --git a/src/components/common/ConfirmModal/ConfirmModal.stories.tsx b/src/shared/ui/ConfirmModal/ConfirmModal.stories.tsx similarity index 100% rename from src/components/common/ConfirmModal/ConfirmModal.stories.tsx rename to src/shared/ui/ConfirmModal/ConfirmModal.stories.tsx diff --git a/src/components/common/ConfirmModal/ConfirmModal.tsx b/src/shared/ui/ConfirmModal/ConfirmModal.tsx similarity index 88% rename from src/components/common/ConfirmModal/ConfirmModal.tsx rename to src/shared/ui/ConfirmModal/ConfirmModal.tsx index 8ce4de65..5248d0fd 100644 --- a/src/components/common/ConfirmModal/ConfirmModal.tsx +++ b/src/shared/ui/ConfirmModal/ConfirmModal.tsx @@ -1,9 +1,9 @@ import React from "react"; -import Button from "@/components/common/Button/Button"; -import { Icon } from "@/components/common/Icon"; -import { Modal } from "@/components/common/Modal"; -import TextButton from "@/components/common/TextButton/TextButton"; +import Button from "@/shared/ui/Button/Button/Button"; +import TextButton from "@/shared/ui/Button/TextButton/TextButton"; +import { Icon } from "@/shared/ui/Icon"; +import { Modal } from "@/shared/ui/Modal"; interface ConfirmModalProps { title: string; diff --git a/src/components/common/ConfirmModal/index.tsx b/src/shared/ui/ConfirmModal/index.tsx similarity index 100% rename from src/components/common/ConfirmModal/index.tsx rename to src/shared/ui/ConfirmModal/index.tsx diff --git a/src/components/common/Icon/iconMap.ts b/src/shared/ui/Icon/iconMap.ts similarity index 100% rename from src/components/common/Icon/iconMap.ts rename to src/shared/ui/Icon/iconMap.ts diff --git a/src/components/common/Icon/index.tsx b/src/shared/ui/Icon/index.tsx similarity index 100% rename from src/components/common/Icon/index.tsx rename to src/shared/ui/Icon/index.tsx diff --git a/src/components/common/Icon/svg/Alert/Error.svg b/src/shared/ui/Icon/svg/Alert/Error.svg similarity index 100% rename from src/components/common/Icon/svg/Alert/Error.svg rename to src/shared/ui/Icon/svg/Alert/Error.svg diff --git a/src/components/common/Icon/svg/Alert/Success.svg b/src/shared/ui/Icon/svg/Alert/Success.svg similarity index 100% rename from src/components/common/Icon/svg/Alert/Success.svg rename to src/shared/ui/Icon/svg/Alert/Success.svg diff --git a/src/components/common/Icon/svg/Arrow/DownFilled.svg b/src/shared/ui/Icon/svg/Arrow/DownFilled.svg similarity index 100% rename from src/components/common/Icon/svg/Arrow/DownFilled.svg rename to src/shared/ui/Icon/svg/Arrow/DownFilled.svg diff --git a/src/components/common/Icon/svg/Arrow/LeftDouble.svg b/src/shared/ui/Icon/svg/Arrow/LeftDouble.svg similarity index 100% rename from src/components/common/Icon/svg/Arrow/LeftDouble.svg rename to src/shared/ui/Icon/svg/Arrow/LeftDouble.svg diff --git a/src/components/common/Icon/svg/Arrow/LeftFilled.svg b/src/shared/ui/Icon/svg/Arrow/LeftFilled.svg similarity index 100% rename from src/components/common/Icon/svg/Arrow/LeftFilled.svg rename to src/shared/ui/Icon/svg/Arrow/LeftFilled.svg diff --git a/src/components/common/Icon/svg/Arrow/Right.svg b/src/shared/ui/Icon/svg/Arrow/Right.svg similarity index 100% rename from src/components/common/Icon/svg/Arrow/Right.svg rename to src/shared/ui/Icon/svg/Arrow/Right.svg diff --git a/src/components/common/Icon/svg/Arrow/RightDouble.svg b/src/shared/ui/Icon/svg/Arrow/RightDouble.svg similarity index 100% rename from src/components/common/Icon/svg/Arrow/RightDouble.svg rename to src/shared/ui/Icon/svg/Arrow/RightDouble.svg diff --git a/src/components/common/Icon/svg/Arrow/RightFilled.svg b/src/shared/ui/Icon/svg/Arrow/RightFilled.svg similarity index 100% rename from src/components/common/Icon/svg/Arrow/RightFilled.svg rename to src/shared/ui/Icon/svg/Arrow/RightFilled.svg diff --git a/src/components/common/Icon/svg/Arrow/UpFilled.svg b/src/shared/ui/Icon/svg/Arrow/UpFilled.svg similarity index 100% rename from src/components/common/Icon/svg/Arrow/UpFilled.svg rename to src/shared/ui/Icon/svg/Arrow/UpFilled.svg diff --git a/src/components/common/Icon/svg/Bell-dot/BellDot.svg b/src/shared/ui/Icon/svg/Bell-dot/BellDot.svg similarity index 100% rename from src/components/common/Icon/svg/Bell-dot/BellDot.svg rename to src/shared/ui/Icon/svg/Bell-dot/BellDot.svg diff --git a/src/components/common/Icon/svg/Bell/Bell.svg b/src/shared/ui/Icon/svg/Bell/Bell.svg similarity index 100% rename from src/components/common/Icon/svg/Bell/Bell.svg rename to src/shared/ui/Icon/svg/Bell/Bell.svg diff --git a/src/components/common/Icon/svg/Calendar/Line/Calendar.svg b/src/shared/ui/Icon/svg/Calendar/Line/Calendar.svg similarity index 100% rename from src/components/common/Icon/svg/Calendar/Line/Calendar.svg rename to src/shared/ui/Icon/svg/Calendar/Line/Calendar.svg diff --git a/src/components/common/Icon/svg/Character/BlueCharacter.svg b/src/shared/ui/Icon/svg/Character/BlueCharacter.svg similarity index 100% rename from src/components/common/Icon/svg/Character/BlueCharacter.svg rename to src/shared/ui/Icon/svg/Character/BlueCharacter.svg diff --git a/src/components/common/Icon/svg/Character/GreenCharacter.svg b/src/shared/ui/Icon/svg/Character/GreenCharacter.svg similarity index 100% rename from src/components/common/Icon/svg/Character/GreenCharacter.svg rename to src/shared/ui/Icon/svg/Character/GreenCharacter.svg diff --git a/src/components/common/Icon/svg/Chat/Chat.svg b/src/shared/ui/Icon/svg/Chat/Chat.svg similarity index 100% rename from src/components/common/Icon/svg/Chat/Chat.svg rename to src/shared/ui/Icon/svg/Chat/Chat.svg diff --git a/src/components/common/Icon/svg/Checkbox/ActiveCheckBox.svg b/src/shared/ui/Icon/svg/Checkbox/ActiveCheckBox.svg similarity index 100% rename from src/components/common/Icon/svg/Checkbox/ActiveCheckBox.svg rename to src/shared/ui/Icon/svg/Checkbox/ActiveCheckBox.svg diff --git a/src/components/common/Icon/svg/Checkbox/ActiveFilledCheckBox.svg b/src/shared/ui/Icon/svg/Checkbox/ActiveFilledCheckBox.svg similarity index 100% rename from src/components/common/Icon/svg/Checkbox/ActiveFilledCheckBox.svg rename to src/shared/ui/Icon/svg/Checkbox/ActiveFilledCheckBox.svg diff --git a/src/components/common/Icon/svg/Checkbox/InactiveCheckBox.svg b/src/shared/ui/Icon/svg/Checkbox/InactiveCheckBox.svg similarity index 100% rename from src/components/common/Icon/svg/Checkbox/InactiveCheckBox.svg rename to src/shared/ui/Icon/svg/Checkbox/InactiveCheckBox.svg diff --git a/src/components/common/Icon/svg/Checkbox/InactiveFilledCheckBox.svg b/src/shared/ui/Icon/svg/Checkbox/InactiveFilledCheckBox.svg similarity index 100% rename from src/components/common/Icon/svg/Checkbox/InactiveFilledCheckBox.svg rename to src/shared/ui/Icon/svg/Checkbox/InactiveFilledCheckBox.svg diff --git a/src/shared/ui/Icon/svg/Crown.svg b/src/shared/ui/Icon/svg/Crown.svg new file mode 100644 index 00000000..3bb8ec80 --- /dev/null +++ b/src/shared/ui/Icon/svg/Crown.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/components/common/Icon/svg/Dot.svg b/src/shared/ui/Icon/svg/Dot.svg similarity index 100% rename from src/components/common/Icon/svg/Dot.svg rename to src/shared/ui/Icon/svg/Dot.svg diff --git a/src/components/common/Icon/svg/Empty.svg b/src/shared/ui/Icon/svg/Empty.svg similarity index 100% rename from src/components/common/Icon/svg/Empty.svg rename to src/shared/ui/Icon/svg/Empty.svg diff --git a/src/components/common/Icon/svg/EyeOffIcon.svg b/src/shared/ui/Icon/svg/EyeOffIcon.svg similarity index 100% rename from src/components/common/Icon/svg/EyeOffIcon.svg rename to src/shared/ui/Icon/svg/EyeOffIcon.svg diff --git a/src/components/common/Icon/svg/EyeOnIcon.svg b/src/shared/ui/Icon/svg/EyeOnIcon.svg similarity index 100% rename from src/components/common/Icon/svg/EyeOnIcon.svg rename to src/shared/ui/Icon/svg/EyeOnIcon.svg diff --git a/src/components/common/Icon/svg/FilledXCircle.svg b/src/shared/ui/Icon/svg/FilledXCircle.svg similarity index 100% rename from src/components/common/Icon/svg/FilledXCircle.svg rename to src/shared/ui/Icon/svg/FilledXCircle.svg diff --git a/src/components/common/Icon/svg/Flag.svg b/src/shared/ui/Icon/svg/Flag.svg similarity index 100% rename from src/components/common/Icon/svg/Flag.svg rename to src/shared/ui/Icon/svg/Flag.svg diff --git a/src/components/common/Icon/svg/Home/Home.svg b/src/shared/ui/Icon/svg/Home/Home.svg similarity index 100% rename from src/components/common/Icon/svg/Home/Home.svg rename to src/shared/ui/Icon/svg/Home/Home.svg diff --git a/src/components/common/Icon/svg/Info.svg b/src/shared/ui/Icon/svg/Info.svg similarity index 100% rename from src/components/common/Icon/svg/Info.svg rename to src/shared/ui/Icon/svg/Info.svg diff --git a/src/components/common/Icon/svg/Kebab.svg b/src/shared/ui/Icon/svg/Kebab.svg similarity index 100% rename from src/components/common/Icon/svg/Kebab.svg rename to src/shared/ui/Icon/svg/Kebab.svg diff --git a/src/shared/ui/Icon/svg/LikeIcon.svg b/src/shared/ui/Icon/svg/LikeIcon.svg new file mode 100644 index 00000000..af8452b7 --- /dev/null +++ b/src/shared/ui/Icon/svg/LikeIcon.svg @@ -0,0 +1,13 @@ + + + diff --git a/src/components/common/Icon/svg/LinedX.svg b/src/shared/ui/Icon/svg/LinedX.svg similarity index 100% rename from src/components/common/Icon/svg/LinedX.svg rename to src/shared/ui/Icon/svg/LinedX.svg diff --git a/src/components/common/Icon/svg/Logo/Icon.svg b/src/shared/ui/Icon/svg/Logo/Icon.svg similarity index 100% rename from src/components/common/Icon/svg/Logo/Icon.svg rename to src/shared/ui/Icon/svg/Logo/Icon.svg diff --git a/src/components/common/Icon/svg/Logo/Text.svg b/src/shared/ui/Icon/svg/Logo/Text.svg similarity index 100% rename from src/components/common/Icon/svg/Logo/Text.svg rename to src/shared/ui/Icon/svg/Logo/Text.svg diff --git a/src/components/common/Icon/svg/Logo/WhiteText.svg b/src/shared/ui/Icon/svg/Logo/WhiteText.svg similarity index 100% rename from src/components/common/Icon/svg/Logo/WhiteText.svg rename to src/shared/ui/Icon/svg/Logo/WhiteText.svg diff --git a/src/components/common/Icon/svg/Meatball.svg b/src/shared/ui/Icon/svg/Meatball.svg similarity index 100% rename from src/components/common/Icon/svg/Meatball.svg rename to src/shared/ui/Icon/svg/Meatball.svg diff --git a/src/components/common/Icon/svg/Menu/Menu.svg b/src/shared/ui/Icon/svg/Menu/Menu.svg similarity index 100% rename from src/components/common/Icon/svg/Menu/Menu.svg rename to src/shared/ui/Icon/svg/Menu/Menu.svg diff --git a/src/components/common/Icon/svg/Out/Line/Out.svg b/src/shared/ui/Icon/svg/Out/Line/Out.svg similarity index 100% rename from src/components/common/Icon/svg/Out/Line/Out.svg rename to src/shared/ui/Icon/svg/Out/Line/Out.svg diff --git a/src/components/common/Icon/svg/OutlineXCircle.svg b/src/shared/ui/Icon/svg/OutlineXCircle.svg similarity index 100% rename from src/components/common/Icon/svg/OutlineXCircle.svg rename to src/shared/ui/Icon/svg/OutlineXCircle.svg diff --git a/src/components/common/Icon/svg/Paper/Paper.svg b/src/shared/ui/Icon/svg/Paper/Paper.svg similarity index 100% rename from src/components/common/Icon/svg/Paper/Paper.svg rename to src/shared/ui/Icon/svg/Paper/Paper.svg diff --git a/src/components/common/Icon/svg/Pencil/Pencil.svg b/src/shared/ui/Icon/svg/Pencil/Pencil.svg similarity index 100% rename from src/components/common/Icon/svg/Pencil/Pencil.svg rename to src/shared/ui/Icon/svg/Pencil/Pencil.svg diff --git a/src/components/common/Icon/svg/Plus.svg b/src/shared/ui/Icon/svg/Plus.svg similarity index 100% rename from src/components/common/Icon/svg/Plus.svg rename to src/shared/ui/Icon/svg/Plus.svg diff --git a/src/shared/ui/Icon/svg/ProfileEditIcon.svg b/src/shared/ui/Icon/svg/ProfileEditIcon.svg new file mode 100644 index 00000000..1bcaa5c1 --- /dev/null +++ b/src/shared/ui/Icon/svg/ProfileEditIcon.svg @@ -0,0 +1,17 @@ + + + + diff --git a/src/components/common/Icon/svg/Search/Search.svg b/src/shared/ui/Icon/svg/Search/Search.svg similarity index 100% rename from src/components/common/Icon/svg/Search/Search.svg rename to src/shared/ui/Icon/svg/Search/Search.svg diff --git a/src/components/common/Icon/svg/Trash.svg b/src/shared/ui/Icon/svg/Trash.svg similarity index 100% rename from src/components/common/Icon/svg/Trash.svg rename to src/shared/ui/Icon/svg/Trash.svg diff --git a/src/components/common/Icon/svg/TrashEmpty.svg b/src/shared/ui/Icon/svg/TrashEmpty.svg similarity index 100% rename from src/components/common/Icon/svg/TrashEmpty.svg rename to src/shared/ui/Icon/svg/TrashEmpty.svg diff --git a/src/components/common/Icon/svg/TrashFill.svg b/src/shared/ui/Icon/svg/TrashFill.svg similarity index 100% rename from src/components/common/Icon/svg/TrashFill.svg rename to src/shared/ui/Icon/svg/TrashFill.svg diff --git a/src/components/common/Icon/svg/User/User.svg b/src/shared/ui/Icon/svg/User/User.svg similarity index 100% rename from src/components/common/Icon/svg/User/User.svg rename to src/shared/ui/Icon/svg/User/User.svg diff --git a/src/components/common/Icon/svg/feature/Deadline.svg b/src/shared/ui/Icon/svg/feature/Deadline.svg similarity index 100% rename from src/components/common/Icon/svg/feature/Deadline.svg rename to src/shared/ui/Icon/svg/feature/Deadline.svg diff --git a/src/components/common/Icon/svg/feature/Flag_Blue.svg b/src/shared/ui/Icon/svg/feature/Flag_Blue.svg similarity index 100% rename from src/components/common/Icon/svg/feature/Flag_Blue.svg rename to src/shared/ui/Icon/svg/feature/Flag_Blue.svg diff --git a/src/components/common/Icon/svg/feature/Flag_Green.svg b/src/shared/ui/Icon/svg/feature/Flag_Green.svg similarity index 100% rename from src/components/common/Icon/svg/feature/Flag_Green.svg rename to src/shared/ui/Icon/svg/feature/Flag_Green.svg diff --git a/src/components/common/Icon/svg/feature/Goal.svg b/src/shared/ui/Icon/svg/feature/Goal.svg similarity index 100% rename from src/components/common/Icon/svg/feature/Goal.svg rename to src/shared/ui/Icon/svg/feature/Goal.svg diff --git a/src/components/common/Icon/svg/feature/GoalFlag.svg b/src/shared/ui/Icon/svg/feature/GoalFlag.svg similarity index 100% rename from src/components/common/Icon/svg/feature/GoalFlag.svg rename to src/shared/ui/Icon/svg/feature/GoalFlag.svg diff --git a/src/components/common/Icon/svg/feature/People.svg b/src/shared/ui/Icon/svg/feature/People.svg similarity index 100% rename from src/components/common/Icon/svg/feature/People.svg rename to src/shared/ui/Icon/svg/feature/People.svg diff --git a/src/components/common/Icon/svg/feature/Pipe_Blue.svg b/src/shared/ui/Icon/svg/feature/Pipe_Blue.svg similarity index 100% rename from src/components/common/Icon/svg/feature/Pipe_Blue.svg rename to src/shared/ui/Icon/svg/feature/Pipe_Blue.svg diff --git a/src/components/common/Icon/svg/feature/Pipe_Green.svg b/src/shared/ui/Icon/svg/feature/Pipe_Green.svg similarity index 100% rename from src/components/common/Icon/svg/feature/Pipe_Green.svg rename to src/shared/ui/Icon/svg/feature/Pipe_Green.svg diff --git a/src/shared/ui/Icon/svg/social/GoogleIcon.svg b/src/shared/ui/Icon/svg/social/GoogleIcon.svg new file mode 100644 index 00000000..e4e21314 --- /dev/null +++ b/src/shared/ui/Icon/svg/social/GoogleIcon.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + diff --git a/src/shared/ui/Icon/svg/social/KakaoIcon.svg b/src/shared/ui/Icon/svg/social/KakaoIcon.svg new file mode 100644 index 00000000..71c8fd26 --- /dev/null +++ b/src/shared/ui/Icon/svg/social/KakaoIcon.svg @@ -0,0 +1,15 @@ + + + diff --git a/src/components/common/Input/Input.stories.tsx b/src/shared/ui/Input/Input.stories.tsx similarity index 97% rename from src/components/common/Input/Input.stories.tsx rename to src/shared/ui/Input/Input.stories.tsx index 32ff622d..1f6ece78 100644 --- a/src/components/common/Input/Input.stories.tsx +++ b/src/shared/ui/Input/Input.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from "@storybook/nextjs-vite"; -import Input from "@/components/common/Input/Input"; +import Input from "@/shared/ui/Input/Input"; import { Icon } from "../Icon"; diff --git a/src/components/common/Input/Input.tsx b/src/shared/ui/Input/Input.tsx similarity index 98% rename from src/components/common/Input/Input.tsx rename to src/shared/ui/Input/Input.tsx index 868c1c92..a0452df2 100644 --- a/src/components/common/Input/Input.tsx +++ b/src/shared/ui/Input/Input.tsx @@ -2,7 +2,7 @@ import { cva, VariantProps } from "class-variance-authority"; import { InputHTMLAttributes } from "react"; -import { cn } from "@/utils/utils"; +import { cn } from "@/shared/utils/styles/cn"; /** * @example diff --git a/src/components/common/Input/index.ts b/src/shared/ui/Input/index.ts similarity index 100% rename from src/components/common/Input/index.ts rename to src/shared/ui/Input/index.ts diff --git a/src/components/common/Line.tsx b/src/shared/ui/Line.tsx similarity index 100% rename from src/components/common/Line.tsx rename to src/shared/ui/Line.tsx diff --git a/src/components/common/Modal/index.tsx b/src/shared/ui/Modal/index.tsx similarity index 97% rename from src/components/common/Modal/index.tsx rename to src/shared/ui/Modal/index.tsx index c91788e6..d2d22237 100644 --- a/src/components/common/Modal/index.tsx +++ b/src/shared/ui/Modal/index.tsx @@ -2,7 +2,7 @@ import { createContext, useContext } from "react"; -import { cn } from "@/utils/utils"; +import { cn } from "@/shared/utils/styles/cn"; interface ModalContextType { onClose: () => void; diff --git a/src/hooks/useOverlay/Overlay.test.tsx b/src/shared/ui/Overlay/Overlay.test.tsx similarity index 92% rename from src/hooks/useOverlay/Overlay.test.tsx rename to src/shared/ui/Overlay/Overlay.test.tsx index 04040b02..5bdf1181 100644 --- a/src/hooks/useOverlay/Overlay.test.tsx +++ b/src/shared/ui/Overlay/Overlay.test.tsx @@ -1,9 +1,9 @@ import { act, render, screen } from "@testing-library/react"; -import { OVERLAY_ZINDEX_BASE } from "@/constants/zIndex"; +import { OVERLAY_ZINDEX_BASE } from "@/shared/constants/styles/zIndex"; +import { useOverlayStore } from "@/shared/store/overlay/useOverlay.store"; import Overlay from "./Overlay"; -import { useOverlayStore } from "./useOverlay.store"; describe("Overlay", () => { beforeEach(() => { diff --git a/src/hooks/useOverlay/Overlay.tsx b/src/shared/ui/Overlay/Overlay.tsx similarity index 73% rename from src/hooks/useOverlay/Overlay.tsx rename to src/shared/ui/Overlay/Overlay.tsx index 880cc552..d6ed4834 100644 --- a/src/hooks/useOverlay/Overlay.tsx +++ b/src/shared/ui/Overlay/Overlay.tsx @@ -1,8 +1,7 @@ "use client"; -import { OVERLAY_ZINDEX_BASE } from "@/constants/zIndex"; - -import { useOverlayStore } from "./useOverlay.store"; +import { OVERLAY_ZINDEX_BASE } from "@/shared/constants/styles/zIndex"; +import { useOverlayStore } from "@/shared/store/overlay/useOverlay.store"; export default function Overlay() { const layer = useOverlayStore((s) => s.layer); diff --git a/src/components/common/ProgressBar/ProgressBar.stories.tsx b/src/shared/ui/ProgressBar/ProgressBar.stories.tsx similarity index 100% rename from src/components/common/ProgressBar/ProgressBar.stories.tsx rename to src/shared/ui/ProgressBar/ProgressBar.stories.tsx diff --git a/src/components/common/ProgressBar/index.tsx b/src/shared/ui/ProgressBar/index.tsx similarity index 97% rename from src/components/common/ProgressBar/index.tsx rename to src/shared/ui/ProgressBar/index.tsx index ed848c06..df70add5 100644 --- a/src/components/common/ProgressBar/index.tsx +++ b/src/shared/ui/ProgressBar/index.tsx @@ -1,4 +1,4 @@ -import { cn } from "@/utils/utils"; +import { cn } from "@/shared/utils/styles/cn"; export type ProgressColor = "blue" | "green"; export type ProgressVariant = "on-color" | "on-white"; diff --git a/src/components/common/Spacing.tsx b/src/shared/ui/Spacing.tsx similarity index 94% rename from src/components/common/Spacing.tsx rename to src/shared/ui/Spacing.tsx index 074a8c8e..effe1518 100644 --- a/src/components/common/Spacing.tsx +++ b/src/shared/ui/Spacing.tsx @@ -1,6 +1,6 @@ import type { CSSProperties } from "react"; -import { cn } from "@/utils/utils"; +import { cn } from "@/shared/utils/styles/cn"; export type SpacingDirection = "vertical" | "horizontal"; diff --git a/src/components/common/Spinner/Spinner.tsx b/src/shared/ui/Spinner/Spinner.tsx similarity index 100% rename from src/components/common/Spinner/Spinner.tsx rename to src/shared/ui/Spinner/Spinner.tsx diff --git a/src/components/common/Spinner/index.tsx b/src/shared/ui/Spinner/index.tsx similarity index 100% rename from src/components/common/Spinner/index.tsx rename to src/shared/ui/Spinner/index.tsx diff --git a/src/components/common/Toast/Toast.stories.tsx b/src/shared/ui/Toast/Toast.stories.tsx similarity index 100% rename from src/components/common/Toast/Toast.stories.tsx rename to src/shared/ui/Toast/Toast.stories.tsx diff --git a/src/components/common/Toast/Toast.tsx b/src/shared/ui/Toast/Toast.tsx similarity index 98% rename from src/components/common/Toast/Toast.tsx rename to src/shared/ui/Toast/Toast.tsx index 3e921b97..7a3f8139 100644 --- a/src/components/common/Toast/Toast.tsx +++ b/src/shared/ui/Toast/Toast.tsx @@ -1,6 +1,6 @@ import * as React from "react"; -import { cn } from "@/utils/utils"; +import { cn } from "@/shared/utils/styles/cn"; import { Icon } from "../Icon"; import { ToastRecord } from "./types"; diff --git a/src/shared/ui/Toast/index.tsx b/src/shared/ui/Toast/index.tsx new file mode 100644 index 00000000..16c23066 --- /dev/null +++ b/src/shared/ui/Toast/index.tsx @@ -0,0 +1 @@ +export { default } from "../../providers/ToastProvider"; diff --git a/src/components/common/Toast/types.ts b/src/shared/ui/Toast/types.ts similarity index 100% rename from src/components/common/Toast/types.ts rename to src/shared/ui/Toast/types.ts diff --git a/src/components/common/Toggle/index.tsx b/src/shared/ui/Toggle/index.tsx similarity index 97% rename from src/components/common/Toggle/index.tsx rename to src/shared/ui/Toggle/index.tsx index e1774cda..69c3f7ca 100644 --- a/src/components/common/Toggle/index.tsx +++ b/src/shared/ui/Toggle/index.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; -import { cn } from "@/utils/utils"; +import { cn } from "@/shared/utils/styles/cn"; type ToggleSize = "large" | "medium" | "small"; diff --git a/src/components/common/UserAvatar/UserAvatar.tsx b/src/shared/ui/UserAvatar/UserAvatar.tsx similarity index 71% rename from src/components/common/UserAvatar/UserAvatar.tsx rename to src/shared/ui/UserAvatar/UserAvatar.tsx index f4841af5..944112e1 100644 --- a/src/components/common/UserAvatar/UserAvatar.tsx +++ b/src/shared/ui/UserAvatar/UserAvatar.tsx @@ -2,11 +2,11 @@ import Image from "next/image"; import { useState } from "react"; -import avatar1 from "@/assets/images/avatar-blue-default.svg"; -import avatar2 from "@/assets/images/avatar-blue-glasses.svg"; -import avatar3 from "@/assets/images/avatar-green-default.svg"; -import avatar4 from "@/assets/images/avatar-green-glasses.svg"; -import { cn } from "@/utils/utils"; +import avatar1 from "@/shared/assets/images/avatar-blue-default.svg"; +import avatar2 from "@/shared/assets/images/avatar-blue-glasses.svg"; +import avatar3 from "@/shared/assets/images/avatar-green-default.svg"; +import avatar4 from "@/shared/assets/images/avatar-green-glasses.svg"; +import { cn } from "@/shared/utils/styles/cn"; const DEFAULT_AVATARS = [avatar1, avatar2, avatar3, avatar4]; diff --git a/src/components/common/UserAvatar/index.ts b/src/shared/ui/UserAvatar/index.ts similarity index 100% rename from src/components/common/UserAvatar/index.ts rename to src/shared/ui/UserAvatar/index.ts diff --git a/src/utils/utils.ts b/src/shared/utils/styles/cn.ts similarity index 100% rename from src/utils/utils.ts rename to src/shared/utils/styles/cn.ts diff --git a/src/utils/createPaginationOptions.ts b/src/utils/createPaginationOptions.ts deleted file mode 100644 index 414a8898..00000000 --- a/src/utils/createPaginationOptions.ts +++ /dev/null @@ -1,38 +0,0 @@ -type CursorParams = { - size?: number; - cursorId?: number; - cursorCreatedAt?: string; -}; - -type CursorPage = { - hasNext: boolean; - nextCursorId?: number; - nextCursorCreatedAt?: string; -}; - -// useSuspenseInfiniteQuery(options) 옵션 생성 함수 -export function createPaginationOptions< - Params extends CursorParams = CursorParams, - Page extends CursorPage = CursorPage, ->(apiKey: string, apiFunction: (param: Params) => Promise<{ data: Page }>) { - const size = 20; - - return { - queryKey: [apiKey], - initialPageParam: { size } as Params, - - queryFn: async ({ pageParam }: { pageParam: Params }) => { - const res = await apiFunction(pageParam); - return res.data; - }, - - getNextPageParam: (lastPage: Page): Params | undefined => - lastPage.hasNext - ? ({ - size, - cursorId: lastPage.nextCursorId, - cursorCreatedAt: lastPage.nextCursorCreatedAt, - } as Params) - : undefined, - }; -} diff --git a/src/components/NavigationBar/Header/Header.tsx b/src/widgets/NavigationBar/Header/Header.tsx similarity index 94% rename from src/components/NavigationBar/Header/Header.tsx rename to src/widgets/NavigationBar/Header/Header.tsx index d9204991..7e727a45 100644 --- a/src/components/NavigationBar/Header/Header.tsx +++ b/src/widgets/NavigationBar/Header/Header.tsx @@ -1,10 +1,10 @@ import { cva } from "class-variance-authority"; import { useContext } from "react"; -import { useBreakpoint } from "@/hooks/useBreakpoint"; -import { cn } from "@/utils/utils"; +import { useBreakpoint } from "@/shared/hooks/useBreakpoint"; +import { Icon } from "@/shared/ui/Icon"; +import { cn } from "@/shared/utils/styles/cn"; -import { Icon } from "../../common/Icon"; import { NavigationBarContext } from "../provider"; const headerVariants = cva( diff --git a/src/components/NavigationBar/Header/index.tsx b/src/widgets/NavigationBar/Header/index.tsx similarity index 100% rename from src/components/NavigationBar/Header/index.tsx rename to src/widgets/NavigationBar/Header/index.tsx diff --git a/src/components/NavigationBar/NotificationPopover/NotificatioPanel.tsx b/src/widgets/NavigationBar/NotificationPopover/NotificatioPanel.tsx similarity index 95% rename from src/components/NavigationBar/NotificationPopover/NotificatioPanel.tsx rename to src/widgets/NavigationBar/NotificationPopover/NotificatioPanel.tsx index 8d138027..bf68f0c1 100644 --- a/src/components/NavigationBar/NotificationPopover/NotificatioPanel.tsx +++ b/src/widgets/NavigationBar/NotificationPopover/NotificatioPanel.tsx @@ -1,7 +1,6 @@ import { useQueryClient } from "@tanstack/react-query"; import React from "react"; -import TextButton from "@/components/common/TextButton/TextButton"; import { NotificationApi } from "@/features/notification/api"; import { notificationInfiniteQueries } from "@/features/notification/query/notificationInfiniteQueries"; import { @@ -9,7 +8,8 @@ import { formatNotificationType, formatRelativeTime, } from "@/features/notification/utils"; -import { useInfiniteScroll } from "@/hooks/useInfiniteScroll/useInfiniteScroll"; +import { useInfiniteScroll } from "@/shared/hooks/useInfiniteScroll/useInfiniteScroll"; +import TextButton from "@/shared/ui/Button/TextButton/TextButton"; import NotificationItem from "./NotificationItem"; diff --git a/src/components/NavigationBar/NotificationPopover/NotificationItem.tsx b/src/widgets/NavigationBar/NotificationPopover/NotificationItem.tsx similarity index 97% rename from src/components/NavigationBar/NotificationPopover/NotificationItem.tsx rename to src/widgets/NavigationBar/NotificationPopover/NotificationItem.tsx index f23b16e3..39190c8a 100644 --- a/src/components/NavigationBar/NotificationPopover/NotificationItem.tsx +++ b/src/widgets/NavigationBar/NotificationPopover/NotificationItem.tsx @@ -1,6 +1,6 @@ "use client"; -import { cn } from "@/utils/utils"; +import { cn } from "@/shared/utils/styles/cn"; interface NotificationItemProps { isRead: boolean; diff --git a/src/components/NavigationBar/NotificationPopover/NotificationPopover.tsx b/src/widgets/NavigationBar/NotificationPopover/NotificationPopover.tsx similarity index 96% rename from src/components/NavigationBar/NotificationPopover/NotificationPopover.tsx rename to src/widgets/NavigationBar/NotificationPopover/NotificationPopover.tsx index 13c47212..8ed1a150 100644 --- a/src/components/NavigationBar/NotificationPopover/NotificationPopover.tsx +++ b/src/widgets/NavigationBar/NotificationPopover/NotificationPopover.tsx @@ -4,9 +4,9 @@ import { useSuspenseInfiniteQuery } from "@tanstack/react-query"; import { cva } from "class-variance-authority"; import { useEffect, useRef, useState } from "react"; -import { Icon } from "@/components/common/Icon"; import { notificationInfiniteQueries } from "@/features/notification/query/notificationInfiniteQueries"; -import { cn } from "@/utils/utils"; +import { Icon } from "@/shared/ui/Icon"; +import { cn } from "@/shared/utils/styles/cn"; import NotificationPanel from "./NotificatioPanel"; diff --git a/src/components/NavigationBar/NotificationPopover/index.ts b/src/widgets/NavigationBar/NotificationPopover/index.ts similarity index 100% rename from src/components/NavigationBar/NotificationPopover/index.ts rename to src/widgets/NavigationBar/NotificationPopover/index.ts diff --git a/src/components/NavigationBar/Personal/Error.tsx b/src/widgets/NavigationBar/Personal/Error.tsx similarity index 84% rename from src/components/NavigationBar/Personal/Error.tsx rename to src/widgets/NavigationBar/Personal/Error.tsx index 238d3ffe..b481160f 100644 --- a/src/components/NavigationBar/Personal/Error.tsx +++ b/src/widgets/NavigationBar/Personal/Error.tsx @@ -1,6 +1,6 @@ -import Button from "@/components/common/Button/Button"; +import Button from "@/shared/ui/Button/Button/Button"; +import { Spacing } from "@/shared/ui/Spacing"; -import { Spacing } from "../../common/Spacing"; import { List } from "../parts/List"; interface Props { diff --git a/src/components/NavigationBar/Personal/Loading.tsx b/src/widgets/NavigationBar/Personal/Loading.tsx similarity index 76% rename from src/components/NavigationBar/Personal/Loading.tsx rename to src/widgets/NavigationBar/Personal/Loading.tsx index 4a7836b8..415a13a2 100644 --- a/src/components/NavigationBar/Personal/Loading.tsx +++ b/src/widgets/NavigationBar/Personal/Loading.tsx @@ -1,4 +1,4 @@ -import Spinner from "@/components/common/Spinner"; +import Spinner from "@/shared/ui/Spinner"; export const Loading = () => { return ( diff --git a/src/components/NavigationBar/Personal/Personal.tsx b/src/widgets/NavigationBar/Personal/Personal.tsx similarity index 82% rename from src/components/NavigationBar/Personal/Personal.tsx rename to src/widgets/NavigationBar/Personal/Personal.tsx index ae393a3e..995d8254 100644 --- a/src/components/NavigationBar/Personal/Personal.tsx +++ b/src/widgets/NavigationBar/Personal/Personal.tsx @@ -1,10 +1,10 @@ import { useSuspenseQuery } from "@tanstack/react-query"; import { useRouter } from "next/navigation"; -import { goalQueries } from "@/features/goal/query/goal.queryKey"; -import { formatNavigationKey } from "@/utils/formatNavigationKey"; +import { goalQueries } from "@/entities/goal/query/goal.queryKey"; +import { Spacing } from "@/shared/ui/Spacing"; +import { formatNavigationKey } from "@/widgets/NavigationBar/utils/formatNavigationKey"; -import { Spacing } from "../../common/Spacing"; import { Item } from "../parts/Item"; import { List } from "../parts/List"; diff --git a/src/components/NavigationBar/Personal/index.tsx b/src/widgets/NavigationBar/Personal/index.tsx similarity index 100% rename from src/components/NavigationBar/Personal/index.tsx rename to src/widgets/NavigationBar/Personal/index.tsx diff --git a/src/components/NavigationBar/Team/Error.tsx b/src/widgets/NavigationBar/Team/Error.tsx similarity index 84% rename from src/components/NavigationBar/Team/Error.tsx rename to src/widgets/NavigationBar/Team/Error.tsx index 238d3ffe..b481160f 100644 --- a/src/components/NavigationBar/Team/Error.tsx +++ b/src/widgets/NavigationBar/Team/Error.tsx @@ -1,6 +1,6 @@ -import Button from "@/components/common/Button/Button"; +import Button from "@/shared/ui/Button/Button/Button"; +import { Spacing } from "@/shared/ui/Spacing"; -import { Spacing } from "../../common/Spacing"; import { List } from "../parts/List"; interface Props { diff --git a/src/components/NavigationBar/Team/Loading.tsx b/src/widgets/NavigationBar/Team/Loading.tsx similarity index 76% rename from src/components/NavigationBar/Team/Loading.tsx rename to src/widgets/NavigationBar/Team/Loading.tsx index cac1850e..d739fd09 100644 --- a/src/components/NavigationBar/Team/Loading.tsx +++ b/src/widgets/NavigationBar/Team/Loading.tsx @@ -1,4 +1,4 @@ -import Spinner from "@/components/common/Spinner"; +import Spinner from "@/shared/ui/Spinner"; export const Loading = () => { return ( diff --git a/src/components/NavigationBar/Team/Team.tsx b/src/widgets/NavigationBar/Team/Team.tsx similarity index 91% rename from src/components/NavigationBar/Team/Team.tsx rename to src/widgets/NavigationBar/Team/Team.tsx index 5124c1ec..3ab06779 100644 --- a/src/components/NavigationBar/Team/Team.tsx +++ b/src/widgets/NavigationBar/Team/Team.tsx @@ -3,10 +3,10 @@ import { useSuspenseQuery } from "@tanstack/react-query"; import { useRouter } from "next/navigation"; -import { teamQueries } from "@/features/team/query/team.queryKey"; -import { formatNavigationKey } from "@/utils/formatNavigationKey"; +import { teamQueries } from "@/entities/team/query/team.queryKey"; +import { Spacing } from "@/shared/ui/Spacing"; +import { formatNavigationKey } from "@/widgets/NavigationBar/utils/formatNavigationKey"; -import { Spacing } from "../../common/Spacing"; import { Item } from "../parts/Item"; import { List } from "../parts/List"; import { Team as TeamComponent } from "../parts/Team"; diff --git a/src/components/NavigationBar/Team/index.tsx b/src/widgets/NavigationBar/Team/index.tsx similarity index 100% rename from src/components/NavigationBar/Team/index.tsx rename to src/widgets/NavigationBar/Team/index.tsx diff --git a/src/components/NavigationBar/UserProfile/Loading.tsx b/src/widgets/NavigationBar/UserProfile/Loading.tsx similarity index 81% rename from src/components/NavigationBar/UserProfile/Loading.tsx rename to src/widgets/NavigationBar/UserProfile/Loading.tsx index 78058dd5..48b386cc 100644 --- a/src/components/NavigationBar/UserProfile/Loading.tsx +++ b/src/widgets/NavigationBar/UserProfile/Loading.tsx @@ -1,4 +1,4 @@ -import Spinner from "@/components/common/Spinner"; +import Spinner from "@/shared/ui/Spinner"; export const Loading = () => { return ( diff --git a/src/components/NavigationBar/UserProfile/UserProfile.tsx b/src/widgets/NavigationBar/UserProfile/UserProfile.tsx similarity index 87% rename from src/components/NavigationBar/UserProfile/UserProfile.tsx rename to src/widgets/NavigationBar/UserProfile/UserProfile.tsx index 754a62aa..d9b45f6f 100644 --- a/src/components/NavigationBar/UserProfile/UserProfile.tsx +++ b/src/widgets/NavigationBar/UserProfile/UserProfile.tsx @@ -2,9 +2,9 @@ import { useSuspenseQuery } from "@tanstack/react-query"; import Image from "next/image"; import { useRouter } from "next/navigation"; -import defaultAvatar from "@/assets/images/avatar.png"; -import { Icon } from "@/components/common/Icon"; -import { userQueries } from "@/constants/queryKeys"; +import { userQueries } from "@/entities/auth/query/user.queryKey"; +import defaultAvatar from "@/shared/assets/images/avatar.png"; +import { Icon } from "@/shared/ui/Icon"; export const UserProfile = () => { const { diff --git a/src/components/NavigationBar/UserProfile/index.tsx b/src/widgets/NavigationBar/UserProfile/index.tsx similarity index 100% rename from src/components/NavigationBar/UserProfile/index.tsx rename to src/widgets/NavigationBar/UserProfile/index.tsx diff --git a/src/components/NavigationBar/index.stories.tsx b/src/widgets/NavigationBar/index.stories.tsx similarity index 100% rename from src/components/NavigationBar/index.stories.tsx rename to src/widgets/NavigationBar/index.stories.tsx diff --git a/src/widgets/NavigationBar/index.test.tsx b/src/widgets/NavigationBar/index.test.tsx new file mode 100644 index 00000000..2ae185e5 --- /dev/null +++ b/src/widgets/NavigationBar/index.test.tsx @@ -0,0 +1,117 @@ +// import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +// import { fireEvent, render, screen } from "@testing-library/react"; +// import { useRouter } from "next/navigation"; +// import type { ComponentProps, ReactElement } from "react"; + +// import { NavigationBar } from "@/widgets/NavigationBar/index"; +// import { NavigationBarContext } from "@/widgets/NavigationBar/provider"; + +// const mockUseRouter = useRouter as jest.MockedFunction; + +// jest.mock("next/navigation", () => ({ +// useRouter: jest.fn(), +// })); + +// jest.mock("@/shared/hooks/useBreakpoint", () => ({ +// useBreakpoint: () => "desktop", +// })); + +// jest.mock("@/components/NavigationBar/Personal", () => ({ +// Personal: Object.assign(() => null, { +// Loading: () => null, +// Error: () => null, +// }), +// })); + +// jest.mock("@/components/NavigationBar/Team", () => ({ +// Team: Object.assign(() => null, { Loading: () => null }), +// })); + +// jest.mock("@/components/NavigationBar/UserProfile", () => ({ +// UserProfile: Object.assign(() => null, { Loading: () => null }), +// })); + +// jest.mock("@/components/common/LogoutButton", () => ({ +// __esModule: true, +// default: () => null, +// })); + +// jest.mock("@/components/NavigationBar/NotificationPopover", () => ({ +// __esModule: true, +// default: () => null, +// })); + +// jest.mock("@/components/common/Icon", () => ({ +// Icon: ({ name }: { name: string }) => , +// })); + +// type ContextValue = ComponentProps< +// typeof NavigationBarContext.Provider +// >["value"]; + +// function renderWithNavContext( +// ui: ReactElement, +// value: Partial = {}, +// ) { +// const queryClient = new QueryClient(); +// const defaults: ContextValue = { +// isOpen: true, +// open: jest.fn(), +// close: jest.fn(), +// currentTab: "", +// tabChange: jest.fn(), +// ...value, +// }; + +// return render( +// +// +// {ui} +// +// , +// ); +// } + +// describe("NavigationBar", () => { +// beforeEach(() => { +// jest.clearAllMocks(); +// mockUseRouter.mockReturnValue({ +// push: jest.fn(), +// replace: jest.fn(), +// prefetch: jest.fn(), +// back: jest.fn(), +// forward: jest.fn(), +// refresh: jest.fn(), +// } as ReturnType); +// }); + +// test('홈 탭을 누르면 tabChange("home")와 router.push("/taskmate")가 호출된다', () => { +// const push = jest.fn(); +// const tabChange = jest.fn(); +// mockUseRouter.mockReturnValue({ +// push, +// replace: jest.fn(), +// prefetch: jest.fn(), +// back: jest.fn(), +// forward: jest.fn(), +// refresh: jest.fn(), +// } as ReturnType); + +// renderWithNavContext(, { isOpen: true, tabChange }); + +// fireEvent.click(screen.getByText("홈")); + +// expect(tabChange).toHaveBeenCalledTimes(1); +// expect(tabChange).toHaveBeenCalledWith("home"); +// expect(push).toHaveBeenCalledTimes(1); +// expect(push).toHaveBeenCalledWith("/taskmate"); +// }); + +// test("네비게이션이 닫혀 있으면 홈 항목이 보이지 않는다", () => { +// renderWithNavContext(, { isOpen: false }); + +// expect(screen.queryByText("홈")).not.toBeInTheDocument(); +// }); +// }); + +test("Naviagation Bar Test", () => {}); diff --git a/src/components/NavigationBar/index.tsx b/src/widgets/NavigationBar/index.tsx similarity index 82% rename from src/components/NavigationBar/index.tsx rename to src/widgets/NavigationBar/index.tsx index a7275385..15669a51 100644 --- a/src/components/NavigationBar/index.tsx +++ b/src/widgets/NavigationBar/index.tsx @@ -4,18 +4,18 @@ import { cva } from "class-variance-authority"; import { useRouter } from "next/navigation"; import { useContext } from "react"; -import AsyncBoundary from "@/components/common/AsyncBoundary"; -import { Line } from "@/components/common/Line"; -import LogoutButton from "@/components/common/LogoutButton"; -import { Spacing } from "@/components/common/Spacing"; -import Header from "@/components/NavigationBar/Header"; -import { Item } from "@/components/NavigationBar/parts/Item"; -import { List } from "@/components/NavigationBar/parts/List"; -import { Personal } from "@/components/NavigationBar/Personal"; -import { NavigationBarContext } from "@/components/NavigationBar/provider"; -import { Team } from "@/components/NavigationBar/Team"; -import { UserProfile } from "@/components/NavigationBar/UserProfile"; -import { NAVIGATION_BAR_ZINDEX } from "@/constants/zIndex"; +import { NAVIGATION_BAR_ZINDEX } from "@/shared/constants/styles/zIndex"; +import AsyncBoundary from "@/shared/ui/AsyncBoundary"; +import { Line } from "@/shared/ui/Line"; +import { Spacing } from "@/shared/ui/Spacing"; +import LogoutButton from "@/widgets/common/LogoutButton"; +import Header from "@/widgets/NavigationBar/Header"; +import { Item } from "@/widgets/NavigationBar/parts/Item"; +import { List } from "@/widgets/NavigationBar/parts/List"; +import { Personal } from "@/widgets/NavigationBar/Personal"; +import { NavigationBarContext } from "@/widgets/NavigationBar/provider"; +import { Team } from "@/widgets/NavigationBar/Team"; +import { UserProfile } from "@/widgets/NavigationBar/UserProfile"; import NotificationPopover from "./NotificationPopover"; diff --git a/src/components/NavigationBar/parts/Item.tsx b/src/widgets/NavigationBar/parts/Item.tsx similarity index 91% rename from src/components/NavigationBar/parts/Item.tsx rename to src/widgets/NavigationBar/parts/Item.tsx index 417c5feb..0f64c121 100644 --- a/src/components/NavigationBar/parts/Item.tsx +++ b/src/widgets/NavigationBar/parts/Item.tsx @@ -1,8 +1,8 @@ import { createContext, useContext } from "react"; -import { Icon as CommonIcon } from "@/components/common/Icon"; -import { IconName } from "@/components/common/Icon/iconMap"; -import { cn } from "@/utils/utils"; +import { Icon as CommonIcon } from "@/shared/ui/Icon"; +import { IconName } from "@/shared/ui/Icon/iconMap"; +import { cn } from "@/shared/utils/styles/cn"; import { NavigationBarContext } from "../provider"; diff --git a/src/components/NavigationBar/parts/List.tsx b/src/widgets/NavigationBar/parts/List.tsx similarity index 97% rename from src/components/NavigationBar/parts/List.tsx rename to src/widgets/NavigationBar/parts/List.tsx index 25428fc5..d350d17e 100644 --- a/src/components/NavigationBar/parts/List.tsx +++ b/src/widgets/NavigationBar/parts/List.tsx @@ -1,6 +1,6 @@ import { useRouter } from "next/navigation"; -import { Icon } from "@/components/common/Icon"; +import { Icon } from "@/shared/ui/Icon"; interface HeaderProps { children: React.ReactNode; diff --git a/src/components/NavigationBar/parts/Team.tsx b/src/widgets/NavigationBar/parts/Team.tsx similarity index 97% rename from src/components/NavigationBar/parts/Team.tsx rename to src/widgets/NavigationBar/parts/Team.tsx index d3776aa2..1939d180 100644 --- a/src/components/NavigationBar/parts/Team.tsx +++ b/src/widgets/NavigationBar/parts/Team.tsx @@ -2,8 +2,8 @@ import { createContext, type ReactNode, useContext, useState } from "react"; -import { Icon } from "@/components/common/Icon"; -import { cn } from "@/utils/utils"; +import { Icon } from "@/shared/ui/Icon"; +import { cn } from "@/shared/utils/styles/cn"; import { NavigationBarContext } from "../provider"; diff --git a/src/components/NavigationBar/provider.tsx b/src/widgets/NavigationBar/provider.tsx similarity index 89% rename from src/components/NavigationBar/provider.tsx rename to src/widgets/NavigationBar/provider.tsx index 1f9fdb2c..de19374d 100644 --- a/src/components/NavigationBar/provider.tsx +++ b/src/widgets/NavigationBar/provider.tsx @@ -3,8 +3,8 @@ import { usePathname } from "next/navigation"; import { createContext, useEffect, useState } from "react"; -import { useBreakpoint } from "@/hooks/useBreakpoint"; -import { formatNavigationKeyFromPathname } from "@/utils/formatNavigationKey"; +import { useBreakpoint } from "@/shared/hooks/useBreakpoint"; +import { formatNavigationKeyFromPathname } from "@/widgets/NavigationBar/utils/formatNavigationKey"; interface NavigationBarContextType { isOpen: boolean; diff --git a/src/utils/formatNavigationKey.ts b/src/widgets/NavigationBar/utils/formatNavigationKey.ts similarity index 100% rename from src/utils/formatNavigationKey.ts rename to src/widgets/NavigationBar/utils/formatNavigationKey.ts diff --git a/src/components/auth/Login/LoginForm.tsx b/src/widgets/auth/Login/LoginForm.tsx similarity index 94% rename from src/components/auth/Login/LoginForm.tsx rename to src/widgets/auth/Login/LoginForm.tsx index 45a401fa..6458b759 100644 --- a/src/components/auth/Login/LoginForm.tsx +++ b/src/widgets/auth/Login/LoginForm.tsx @@ -2,12 +2,12 @@ import Link from "next/link"; import React, { Suspense, useActionState } from "react"; -import Button from "@/components/common/Button/Button"; -import { Icon } from "@/components/common/Icon"; -import Input from "@/components/common/Input"; import { useOAuthError } from "@/features/auth/hooks/useOAuthError"; import { loginAction } from "@/features/auth/login/actions/loginAction"; import useLoginForm from "@/features/auth/login/hooks/useLoginForm"; +import Button from "@/shared/ui/Button/Button/Button"; +import { Icon } from "@/shared/ui/Icon"; +import Input from "@/shared/ui/Input/Input"; // useSearchParams() 사용으로 인한 CSR Suspense 추가 const OAuthErrorHandler = () => { diff --git a/src/components/auth/Login/index.ts b/src/widgets/auth/Login/index.ts similarity index 100% rename from src/components/auth/Login/index.ts rename to src/widgets/auth/Login/index.ts diff --git a/src/components/auth/LogoutModal/LogoutModal.tsx b/src/widgets/auth/LogoutModal/LogoutModal.tsx similarity index 82% rename from src/components/auth/LogoutModal/LogoutModal.tsx rename to src/widgets/auth/LogoutModal/LogoutModal.tsx index 793682c4..a824e873 100644 --- a/src/components/auth/LogoutModal/LogoutModal.tsx +++ b/src/widgets/auth/LogoutModal/LogoutModal.tsx @@ -1,7 +1,7 @@ "use client"; -import Button from "@/components/common/Button/Button"; -import { Modal } from "@/components/common/Modal"; -import { useLogout } from "@/hooks/useLogout"; +import { useLogout } from "@/features/auth/hooks/useLogout"; +import Button from "@/shared/ui/Button/Button/Button"; +import { Modal } from "@/shared/ui/Modal"; export const LogoutModal = ({ onClose }: { onClose: () => void }) => { const { logout } = useLogout(); diff --git a/src/components/auth/LogoutModal/index.ts b/src/widgets/auth/LogoutModal/index.ts similarity index 100% rename from src/components/auth/LogoutModal/index.ts rename to src/widgets/auth/LogoutModal/index.ts diff --git a/src/components/auth/Signup/SignupForm.tsx b/src/widgets/auth/Signup/SignupForm.tsx similarity index 96% rename from src/components/auth/Signup/SignupForm.tsx rename to src/widgets/auth/Signup/SignupForm.tsx index f6c59e12..41a3482b 100644 --- a/src/components/auth/Signup/SignupForm.tsx +++ b/src/widgets/auth/Signup/SignupForm.tsx @@ -2,11 +2,11 @@ import Link from "next/link"; import React, { Suspense } from "react"; -import Button from "@/components/common/Button/Button"; -import { Icon } from "@/components/common/Icon"; -import Input from "@/components/common/Input"; import { useOAuthError } from "@/features/auth/hooks/useOAuthError"; import useSignupForm from "@/features/auth/signup/hooks/useSignupForm"; +import Button from "@/shared/ui/Button/Button/Button"; +import { Icon } from "@/shared/ui/Icon"; +import Input from "@/shared/ui/Input/Input"; // useSearchParams() 사용으로 인한 CSR Suspense 추가 const OAuthErrorHandler = () => { diff --git a/src/components/auth/Signup/index.ts b/src/widgets/auth/Signup/index.ts similarity index 100% rename from src/components/auth/Signup/index.ts rename to src/widgets/auth/Signup/index.ts diff --git a/src/components/auth/SnsLoginButtons/SnsLoginButtons.tsx b/src/widgets/auth/SnsLoginButtons/SnsLoginButtons.tsx similarity index 83% rename from src/components/auth/SnsLoginButtons/SnsLoginButtons.tsx rename to src/widgets/auth/SnsLoginButtons/SnsLoginButtons.tsx index 91ad262a..a138c2bd 100644 --- a/src/components/auth/SnsLoginButtons/SnsLoginButtons.tsx +++ b/src/widgets/auth/SnsLoginButtons/SnsLoginButtons.tsx @@ -1,6 +1,6 @@ "use client"; -import SocialButton from "@/components/common/SocialButton/SocialButton"; -import { AuthFormType } from "@/features/auth/types/auth.type"; +import { AuthFormType } from "@/entities/auth/types/auth.type"; +import SocialButton from "@/widgets/auth/SocialButton/SocialButton"; const SnsLoginButtons = ({ label, diff --git a/src/components/auth/SnsLoginButtons/index.tsx b/src/widgets/auth/SnsLoginButtons/index.tsx similarity index 100% rename from src/components/auth/SnsLoginButtons/index.tsx rename to src/widgets/auth/SnsLoginButtons/index.tsx diff --git a/src/components/common/SocialButton/SocialButton.tsx b/src/widgets/auth/SocialButton/SocialButton.tsx similarity index 69% rename from src/components/common/SocialButton/SocialButton.tsx rename to src/widgets/auth/SocialButton/SocialButton.tsx index b840f4a8..d7fe7fe4 100644 --- a/src/components/common/SocialButton/SocialButton.tsx +++ b/src/widgets/auth/SocialButton/SocialButton.tsx @@ -1,20 +1,23 @@ import { ComponentProps } from "react"; -import GoogleIcon from "@/components/common/Icons/GoogleIcon"; -import KakaoIcon from "@/components/common/Icons/KakaoIcon"; -import { AuthFormType } from "@/features/auth/types/auth.type"; -import { cn } from "@/utils/utils"; +// @TODO: Icon Convention 위반 +// import GoogleIcon from "@/components/common/Icons/GoogleIcon"; +// import KakaoIcon from "@/components/common/Icons/KakaoIcon"; +import { AuthFormType } from "@/entities/auth/types/auth.type"; +import { cn } from "@/shared/utils/styles/cn"; const SOCIAL_CONFIG = { google: { bg: "bg-white", ring: "ring-1 ring-inset ring-gray-100", - icon: , + // icon: , + icon: <>, }, kakao: { bg: "bg-[#FFEE01]", ring: "ring-0", - icon: , + // icon: , + icon: <>, }, } as const; diff --git a/src/components/common/LogoutButton/LogoutButton.tsx b/src/widgets/common/LogoutButton/LogoutButton.tsx similarity index 77% rename from src/components/common/LogoutButton/LogoutButton.tsx rename to src/widgets/common/LogoutButton/LogoutButton.tsx index b43c2279..cf42779d 100644 --- a/src/components/common/LogoutButton/LogoutButton.tsx +++ b/src/widgets/common/LogoutButton/LogoutButton.tsx @@ -1,9 +1,9 @@ "use client"; import React from "react"; -import { LogoutModal } from "@/components/auth/LogoutModal"; -import { Icon } from "@/components/common/Icon/index"; -import { useOverlay } from "@/hooks/useOverlay"; +import { useOverlay } from "@/shared/hooks/useOverlay"; +import { Icon } from "@/shared/ui/Icon/index"; +import { LogoutModal } from "@/widgets/auth/LogoutModal"; const LogoutButton = () => { const overlay = useOverlay(); diff --git a/src/components/common/LogoutButton/index.ts b/src/widgets/common/LogoutButton/index.ts similarity index 100% rename from src/components/common/LogoutButton/index.ts rename to src/widgets/common/LogoutButton/index.ts diff --git a/src/components/common/ProfileCard/ProfileCard.tsx b/src/widgets/common/ProfileCard/ProfileCard.tsx similarity index 88% rename from src/components/common/ProfileCard/ProfileCard.tsx rename to src/widgets/common/ProfileCard/ProfileCard.tsx index 6dd3dc22..eacf882a 100644 --- a/src/components/common/ProfileCard/ProfileCard.tsx +++ b/src/widgets/common/ProfileCard/ProfileCard.tsx @@ -1,13 +1,10 @@ // 외부 라이브러리 import { cva } from "class-variance-authority"; -import defaultAvatar from "@/assets/images/avatar.png"; -import Button from "@/components/common/Button/Button"; -import Crown from "@/components/common/Icons/Crown"; -import RightArrow from "@/components/common/Icons/RightArrow"; -import Dropdown from "@/hooks/useDropdown/Dropdown"; +import defaultAvatar from "@/shared/assets/images/avatar.png"; +import Button from "@/shared/ui/Button/Button/Button"; // 내부 코드 -import { cn } from "@/utils/utils"; +import { cn } from "@/shared/utils/styles/cn"; const profileCardVariants = cva( "self-start inline-flex items-center gap-2 h-[45px] cursor-pointer", @@ -69,11 +66,11 @@ const ProfileCard = ({ alt="Avatar Image" className="h-10 w-10 shrink-0 rounded-full object-cover" /> - {isAdmin && ( + {/* {isAdmin && ( - )} + )} */} {/* info */} @@ -93,11 +90,11 @@ const ProfileCard = ({ )} {/* Gnb Icon */} - {isGnb && ( + {/* {isGnb && ( - )} + )} */} {/* Email */} @@ -116,10 +113,10 @@ const ProfileCard = ({ )} > {/* 권한 선택 */} - + /> */} {/* 팀원 삭제 버튼 */}