diff --git a/package-lock.json b/package-lock.json index 7b1567d2..6aa3335d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -121,6 +121,7 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -4544,6 +4545,7 @@ "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -4680,6 +4682,7 @@ "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.6.tgz", "integrity": "sha512-gB1sljYjcobZKxjPbKSa31FUTyr+ROaBdoH+wSSs9Dk+yDCmMs+TkTV3PybRRVLC7ax7q0erJ9LvRWnMktnRAw==", "license": "MIT", + "peer": true, "dependencies": { "@tanstack/query-core": "5.90.6" }, @@ -4714,7 +4717,6 @@ "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -4735,7 +4737,6 @@ "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "dequal": "^2.0.3" } @@ -4819,8 +4820,7 @@ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -5008,6 +5008,7 @@ "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -5092,6 +5093,7 @@ "integrity": "sha512-6m1I5RmHBGTnUGS113G04DMu3CpSdxCAU/UvtjNWL4Nuf3MW9tQhiJqRlHzChIkhy6kZSAQmc+I1bcGjE3yNKg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.46.3", "@typescript-eslint/types": "8.46.3", @@ -5622,6 +5624,7 @@ "integrity": "sha512-SdrcvwvP6q8n82cS2BthbZuHGFPHeKkjbpeIRhGaeV8hJ8P0swWFx5lUZ/Vnd7G0CsfL6m4/3lOaqd/n12vtZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/mocker": "4.0.6", "@vitest/utils": "4.0.6", @@ -5645,6 +5648,7 @@ "integrity": "sha512-u6DliDabPQYXz8U4ZwnCvr9q2kJnribkenO6FK0qv5Gu/m1X884JOf0IZ71x7rLrmSsoP3YD3hVnNutAbhEX3A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/browser": "4.0.6", "@vitest/mocker": "4.0.6", @@ -5916,6 +5920,7 @@ "integrity": "sha512-trPk5qpd7Jj+AiLZbV/e+KiiaGXZ8ECsRxtnPnCrJr9OW2mLB72Cb824IXgxVz/mVU3Aj4VebY+tDTPn++j1Og==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/utils": "4.0.6", "pathe": "^2.0.3" @@ -6221,6 +6226,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6286,6 +6292,7 @@ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -7280,6 +7287,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.19", "caniuse-lite": "^1.0.30001751", @@ -8326,7 +8334,6 @@ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -8413,8 +8420,7 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/dom-converter": { "version": "0.2.0", @@ -8846,6 +8852,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -8910,6 +8917,7 @@ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -9010,6 +9018,7 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", + "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -9111,6 +9120,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -11693,6 +11703,7 @@ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "dev": true, "license": "MIT", + "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -12208,7 +12219,6 @@ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "lz-string": "bin/bin.js" } @@ -13753,6 +13763,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -14085,6 +14096,7 @@ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -14204,7 +14216,6 @@ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -14220,7 +14231,6 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -14231,7 +14241,6 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -14244,8 +14253,7 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/process": { "version": "0.11.10", @@ -14409,6 +14417,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -14478,6 +14487,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -14490,6 +14500,7 @@ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.66.0.tgz", "integrity": "sha512-xXBqsWGKrY46ZqaHDo+ZUYiMUgi8suYu5kdrS20EG8KiL7VRQitEbNjm+UcrDYrNi1YLyfpmAeGjCZYXLT9YBw==", "license": "MIT", + "peer": true, "engines": { "node": ">=18.0.0" }, @@ -14522,6 +14533,7 @@ "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -15129,6 +15141,7 @@ "integrity": "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -15365,6 +15378,7 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -15831,6 +15845,7 @@ "integrity": "sha512-s3qY17stuSxU9TFdSHWF2VWJiDKrhZsdlM9M9/APBLT+3kbTlfCPuaNONE0UETgz5tiZLIrC9K4RYjJ8c6PHPA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^1.6.0", @@ -16575,6 +16590,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -16766,6 +16782,7 @@ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, "license": "(MIT OR CC0-1.0)", + "peer": true, "engines": { "node": ">=10" }, @@ -16857,6 +16874,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -17163,6 +17181,7 @@ "integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -17256,6 +17275,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -17269,6 +17289,7 @@ "integrity": "sha512-gR7INfiVRwnEOkCk47faros/9McCZMp5LM+OMNWGLaDBSvJxIzwjgNFufkuePBNaesGRnLmNfW+ddbUJRZn0nQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/expect": "4.0.6", "@vitest/mocker": "4.0.6", @@ -17493,6 +17514,7 @@ "integrity": "sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -17571,6 +17593,7 @@ "integrity": "sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ansi-html-community": "0.0.8", "html-entities": "^2.1.0", @@ -17965,6 +17988,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/public/assets/images/img-team.svg b/public/assets/images/img-team.svg index 69d7564e..9ec341c6 100644 --- a/public/assets/images/img-team.svg +++ b/public/assets/images/img-team.svg @@ -1,101 +1,100 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - + + diff --git a/src/app/(routes)/(landing)/page.tsx b/src/app/(routes)/(landing)/page.tsx index b991ea73..0d38fe7d 100644 --- a/src/app/(routes)/(landing)/page.tsx +++ b/src/app/(routes)/(landing)/page.tsx @@ -17,7 +17,7 @@ import { const sectionBackgrounds = [ "var(--gray-900)", "#091014", - "linear-gradient(to bottom, #091014, var(--gray-900))", + "linear-gradient(to bottom, #091014 90%, var(--gray-900))", "var(--gray-900)", "var(--gray-900)", "var(--gray-900)", diff --git a/src/app/(routes)/layout.tsx b/src/app/(routes)/layout.tsx index 49a0e90e..49d1218f 100644 --- a/src/app/(routes)/layout.tsx +++ b/src/app/(routes)/layout.tsx @@ -5,7 +5,7 @@ import { Header } from "@/components/layout"; import { DropdownOption } from "@/types/option"; export default function RoutesLayout({ children }: { children: React.ReactNode }) { - const [group, setGroup] = useState([]); + const [group, setGroup] = useState(null); const user = useAuthStore(state => state.user); @@ -21,6 +21,8 @@ export default function RoutesLayout({ children }: { children: React.ReactNode } return groupInfo; }) || []; setGroup(userGroupInfo); + } else { + setGroup(null); } }, [user]); diff --git a/src/app/(routes)/team/[id]/edit/page.tsx b/src/app/(routes)/team/[id]/edit/page.tsx index 8db817da..60ac4874 100644 --- a/src/app/(routes)/team/[id]/edit/page.tsx +++ b/src/app/(routes)/team/[id]/edit/page.tsx @@ -154,13 +154,14 @@ export default function TeamEditPagae() { - + diff --git a/src/components/features/landing/intro-section.tsx b/src/components/features/landing/intro-section.tsx index d682a575..9e483381 100644 --- a/src/components/features/landing/intro-section.tsx +++ b/src/components/features/landing/intro-section.tsx @@ -4,20 +4,37 @@ import Logo from "@/assets/landing/logo-flat.svg"; import cn from "@/lib/cn"; import { Button } from "@/components/ui"; import { introContainer, introWave, introWaveWrapper } from "./landing.style"; +import { motion } from "motion/react"; +import Link from "next/link"; export default function IntroBanner() { return (
-

함께 계획하고 완성하는 ✨

+

+ 함께 계획하고 완성하는{" "} + + ✨ + +

혼자서는 힘들었던 목표, 이제 친구들과 함께 재밌게!
루틴부터 여행 계획까지, 모두 함께 완성해가는 공간

-
diff --git a/src/components/features/landing/landing.style.ts b/src/components/features/landing/landing.style.ts index 8ec387e4..abb5cd1e 100644 --- a/src/components/features/landing/landing.style.ts +++ b/src/components/features/landing/landing.style.ts @@ -14,7 +14,7 @@ export const introWave = [ "tablet:h-[140px] tablet:bg-[auto_140px] ", "desktop:h-[250px] desktop:bg-[auto_250px] ", ].join(""); -export const sectionWrapper = "py-10 tablet:py-24 px-[1.25rem] tablet:px-6"; +export const sectionWrapper = "py-16 tablet:py-24 px-[1.25rem] tablet:px-6 overflow-hidden"; export const sectionTitle = "text-center text-3xl tablet:text-5xl font-bold break-keep"; export const sectionTitleGradient = cva("bg-gradient-to-r bg-clip-text text-transparent", { variants: { @@ -29,7 +29,7 @@ export const sectionTitleGradient = cva("bg-gradient-to-r bg-clip-text text-tran export const sectionInnerContainer = cva("mx-auto max-w-[760px] flex", { variants: { layout: { - problem: "flex-col items-center gap-10 pt-10 tablet:pt-24", + problem: "flex-col items-center gap-10 tablet:gap-20 pt-10 tablet:pt-24", whyPlango: "flex-col", solution: "flex-col gap-10 pt-10 tablet:gap-20 tablet:pt-24", dailySummary: @@ -54,7 +54,7 @@ export const sectionContentBox = cva("flex flex-col rounded-3xl border p-5 table problem: "w-full tablet:max-w-[360px] gap-2 tablet:gap-4 text-center odd:mr-auto even:ml-auto", solution: "flex flex-1 gap-3 tablet:gap-6 ", - whyPlango: "p-3 rounded-2xl tablet:rounded-3xl", + whyPlango: "rounded-2xl tablet:rounded-3xl", }, }, }); diff --git a/src/components/features/landing/problem-section.tsx b/src/components/features/landing/problem-section.tsx index 60fbcf86..fe55c2e6 100644 --- a/src/components/features/landing/problem-section.tsx +++ b/src/components/features/landing/problem-section.tsx @@ -7,6 +7,7 @@ import { sectionTitleGradient, sectionWrapper, } from "./landing.style"; +import { motion } from "motion/react"; const values = [ { @@ -25,35 +26,68 @@ const values = [ icon: "🤷", title: "일정 공유 누락", description: "친구들과 계획 체크리스트를 공유하고 싶어요", - solution: "“카톡에 흩어져버린 체크리스트, 결국 아무도 기억 못 하죠”", + solution: "“카톡에 흩어진 체크리스트, 결국 아무도 기억 못 하죠”", }, ]; export default function ProblemSection() { return (
-

- 🤔 - - 이런 고민 있으신가요? - -

-
    - {values.map(v => { + + + 🤔 + + 이런 고민 있으신가요? + + + + + {values.map((v, index) => { const { icon, title, description, solution } = v; + const isOdd = index % 2 === 0; return ( -
  • +

    {icon}
    {title}

    {description}

    {solution}

    -
  • + ); })} -
  • -
+
); } diff --git a/src/components/features/landing/solution-section.tsx b/src/components/features/landing/solution-section.tsx index ae715d43..a26501ad 100644 --- a/src/components/features/landing/solution-section.tsx +++ b/src/components/features/landing/solution-section.tsx @@ -10,6 +10,7 @@ import { sectionWrapper, } from "./landing.style"; import IcDone from "@/assets/icons/ic-done.svg"; +import { motion } from "motion/react"; type Color = "orange" | "blue" | "green" | "purple"; type ContentValueType = { @@ -76,24 +77,46 @@ type ChecklistProps = { function SectionH3() { return (

- 🪴
- Plango에서
- + 🪴 + + + Plango에서 + + 친구들과 이런 걸 함께해요 - +

); } function SectionH4() { return (

- 다양한 활동들을 함께해요
- 운동, 여행, 공부, 취미 뭐든지 함께하면 더 즐거워져요 + + 다양한 활동들을 함께해요
+ 운동, 여행, 공부, 취미 뭐든지 함께하면 더 즐거워져요 +

); } @@ -110,15 +133,23 @@ function CheckList({ color, checkList }: ChecklistProps) {
    {checkList.map((v, index) => { return ( -
  • {v} -
  • + ); })}
@@ -127,10 +158,20 @@ function CheckList({ color, checkList }: ChecklistProps) { function SolutionList() { return (
    - {values.map(v => { + {values.map((v, index) => { const { icon, theme, description, solution2, solution, color, percent, checkList } = v; return ( -
  • +
    {icon} {description} @@ -147,7 +188,7 @@ function SolutionList() {
- + ); })} diff --git a/src/components/features/landing/why-plango-section.tsx b/src/components/features/landing/why-plango-section.tsx index 67f28ac0..e8c846f9 100644 --- a/src/components/features/landing/why-plango-section.tsx +++ b/src/components/features/landing/why-plango-section.tsx @@ -7,6 +7,7 @@ import { sectionTitleGradient, sectionWrapper, } from "./landing.style"; +import { motion } from "motion/react"; const values = [ "🧑‍🤝‍🧑 같은 목표를 가진 친구들과", @@ -18,34 +19,62 @@ export default function WhyPlangoSection() { return (
-

- Plango가 준비했어요 ✨ -

+ Plango가 준비했어요 + + ✨ + +
다같이 꾸준히 이어가기 위한 공간
혼자서는 어렵지만,
- 함께라면 달라져요 💪 + 함께라면 달라져요 💪
-
    + {values.map((v, index) => ( -
  • {v} -
  • + ))} -
+
); diff --git a/src/components/features/my/history-list.tsx b/src/components/features/my/history-list.tsx index 0970db01..e98b8646 100644 --- a/src/components/features/my/history-list.tsx +++ b/src/components/features/my/history-list.tsx @@ -46,7 +46,7 @@ export default function HistoryList({ tasksDone }: UserHistoryList) { className="flex items-center gap-2 rounded-lg bg-gray-800 px-3 py-2.5" > - {item.description} + {item.name} ))} diff --git a/src/components/features/tasklist/task-add-modal.tsx b/src/components/features/tasklist/task-add-modal.tsx index aac8eeec..faa40ae0 100644 --- a/src/components/features/tasklist/task-add-modal.tsx +++ b/src/components/features/tasklist/task-add-modal.tsx @@ -70,7 +70,7 @@ function FormField() {
- + diff --git a/src/components/features/tasklist/task-card-field.tsx b/src/components/features/tasklist/task-card-field.tsx index 35d7a685..fc4f08f0 100644 --- a/src/components/features/tasklist/task-card-field.tsx +++ b/src/components/features/tasklist/task-card-field.tsx @@ -310,7 +310,7 @@ export default function TaskCardField({ {isLoadingTaskList ? ( ) : taskListData ? ( -
+
- + {taskDetail.writer.nickname}
- {formatDateToFullStr({ date: taskDetail.date, type: "korean" })} + {formatDateToFullStr({ date: taskDetail.recurring.startDate, type: "korean" })}
@@ -158,7 +158,7 @@ export default function TaskDetailMain({
- {formatDateToFullStr({ date: taskDetail.date, type: "korean" })} + {formatDateToFullStr({ date: taskDetail.recurring.startDate, type: "korean" })}
| @@ -167,7 +167,7 @@ export default function TaskDetailMain({ - {formatTimeToStr({ date: taskDetail.date, type: "meridiem" })} + {formatTimeToStr({ date: taskDetail.recurring.startDate, type: "meridiem" })} | diff --git a/src/components/features/tasklist/task-recurring/task-recurring-add-modal.tsx b/src/components/features/tasklist/task-recurring/task-recurring-add-modal.tsx index 66237dee..1bfb3569 100644 --- a/src/components/features/tasklist/task-recurring/task-recurring-add-modal.tsx +++ b/src/components/features/tasklist/task-recurring/task-recurring-add-modal.tsx @@ -109,7 +109,7 @@ function FormField({ const handleSelectValue = (option: DropdownOption) => { if (!option.value) return; - setValue("frequencyType", option.value, { shouldValidate: true }); + setValue("frequencyType", option.value); if (option.value === FrequencyType.Weekly) { setIsWeekpickerOpen(true); @@ -303,9 +303,21 @@ function FormField({ {isWeekpickerOpen && ( - - - + + ( + <> + + + + + )} + /> )} diff --git a/src/components/features/tasklist/task-recurring/task-recurring-update-modal.tsx b/src/components/features/tasklist/task-recurring/task-recurring-update-modal.tsx index 7edd956a..dbca46fd 100644 --- a/src/components/features/tasklist/task-recurring/task-recurring-update-modal.tsx +++ b/src/components/features/tasklist/task-recurring/task-recurring-update-modal.tsx @@ -83,7 +83,7 @@ function FormField({ type }: { type: FormFieldType }) {
- + diff --git a/src/components/features/team/member-card.tsx b/src/components/features/team/member-card.tsx index 19b15cb7..deeef634 100644 --- a/src/components/features/team/member-card.tsx +++ b/src/components/features/team/member-card.tsx @@ -1,3 +1,4 @@ +"use client"; import { useCallback } from "react"; import cn from "@/lib/cn"; import IcKebab from "@/assets/icons/ic-kebab.svg"; @@ -34,7 +35,6 @@ export default function MemberCard({ member, userRole, userId }: MemberCardProps const useDeleteMember = useMutation({ mutationFn: deleteMember, onSuccess: (res, param) => { - console.log(res); const { groupId } = param; if (isAdmin) { queryClient.invalidateQueries({ @@ -54,6 +54,11 @@ export default function MemberCard({ member, userRole, userId }: MemberCardProps const handlerMemberDelete = useCallback( async (groupId: number, userId: number, message: string) => { + if (isAdmin && mySelf) { + showAlert(`팀장은 스스로 내보내기를 할 수 없습니다.`); + return; + } + const confirmed = await showAlert(message); if (confirmed) { useDeleteMember.mutate({ groupId, userId }); @@ -65,7 +70,10 @@ export default function MemberCard({ member, userRole, userId }: MemberCardProps return (
- +

{member.userName}

{dropdownCheck && ( diff --git a/src/components/features/team/modal/invite-modal.tsx b/src/components/features/team/modal/invite-modal.tsx index f11e3776..e86d1496 100644 --- a/src/components/features/team/modal/invite-modal.tsx +++ b/src/components/features/team/modal/invite-modal.tsx @@ -20,7 +20,7 @@ export const InviteModal = ({ isOpen, groupId, onClose }: TeamModalProps) => { showToast("클립보드에 복사되었습니다.", "success"); onClose(); } catch (err) { - showToast("클립보드 복사 실패:", "error"); + showToast("클립보드 복사 실패", "error"); devConsoleError(err); } }; diff --git a/src/components/features/team/modal/todo-create-modal.tsx b/src/components/features/team/modal/todo-create-modal.tsx index b6271e49..b2b4801c 100644 --- a/src/components/features/team/modal/todo-create-modal.tsx +++ b/src/components/features/team/modal/todo-create-modal.tsx @@ -5,10 +5,12 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import { TeamModalProps } from "../team.props"; import { useToast } from "@/providers/toast-provider"; import { devConsoleError } from "@/lib/error"; +import { useAlert } from "@/providers/alert-provider"; export const TodoListCreateModal = ({ isOpen, groupId, onClose }: TeamModalProps) => { const queryClient = useQueryClient(); const { showToast } = useToast(); + const { showAlert } = useAlert(); const [todoName, setTodoName] = useState(""); @@ -34,6 +36,15 @@ export const TodoListCreateModal = ({ isOpen, groupId, onClose }: TeamModalProps const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); + if (!todoName) { + showAlert("할 일 목록의 이름은 빈칸 일 수 없습니다."); + return; + } + if (todoName.length > 30) { + showAlert("할 일 목록의 제목은 최대 30자 입니다."); + return; + } + mutate({ groupId, param: todoName }); }; @@ -48,6 +59,8 @@ export const TodoListCreateModal = ({ isOpen, groupId, onClose }: TeamModalProps placeholder="목록 명을 입력해주세요." onChange={handleNameChange} value={todoName} + maxLength="30" + autoComplete="off" /> diff --git a/src/components/features/team/modal/todo-edit-modal.tsx b/src/components/features/team/modal/todo-edit-modal.tsx index 28bbc5f3..76bfdae0 100644 --- a/src/components/features/team/modal/todo-edit-modal.tsx +++ b/src/components/features/team/modal/todo-edit-modal.tsx @@ -4,6 +4,7 @@ import patchTodo from "@/api/team/patch-todo"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { TodoEditProps } from "../team.props"; import { useToast } from "@/providers/toast-provider"; +import { useAlert } from "@/providers/alert-provider"; import { devConsoleError } from "@/lib/error"; export const TodoListEditModal = ({ @@ -15,10 +16,11 @@ export const TodoListEditModal = ({ }: TodoEditProps) => { const queryClient = useQueryClient(); const { showToast } = useToast(); + const { showAlert } = useAlert(); const [todoName, setTodoName] = useState(taskListName); - const { mutate, isPending, isSuccess } = useMutation({ + const { mutate, isPending } = useMutation({ mutationFn: patchTodo, onSuccess: () => { queryClient.invalidateQueries({ @@ -41,22 +43,30 @@ export const TodoListEditModal = ({ const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!todoName) { - alert("할 일 목록의 제목은 공란일 수 없습니다."); + showAlert("할 일 목록의 제목은 공란일 수 없습니다."); + return; + } + if (todoName.length > 30) { + showAlert("할 일 목록의 제목은 최대 30자 입니다."); return; } mutate({ groupId, taskListId, name: todoName }); }; - if (isSuccess) onClose(); - return (
- + diff --git a/src/components/features/team/team-report.tsx b/src/components/features/team/team-report.tsx index d71c344b..9c2f233b 100644 --- a/src/components/features/team/team-report.tsx +++ b/src/components/features/team/team-report.tsx @@ -15,7 +15,7 @@ export default function TeamReport({ taskLists = [] }: { taskLists: TaskList[] } 0, ); - const percent = totalTasks > 0 ? (doneTasks / totalTasks) * 100 : 0; + const percent = totalTasks > 0 ? Math.round((doneTasks / totalTasks) * 100) : 0; return (
@@ -24,7 +24,7 @@ export default function TeamReport({ taskLists = [] }: { taskLists: TaskList[] }
-
+

오늘

{percent}%

@@ -39,9 +39,9 @@ export default function TeamReport({ taskLists = [] }: { taskLists: TaskList[] }

오늘의 할 일

-

{totalTasks}개

+

{totalTasks - doneTasks}개

- +
diff --git a/src/components/layout/header/dropdown/group-dropdown.tsx b/src/components/layout/header/dropdown/group-dropdown.tsx index 9ce7aac6..4c2b0132 100644 --- a/src/components/layout/header/dropdown/group-dropdown.tsx +++ b/src/components/layout/header/dropdown/group-dropdown.tsx @@ -55,10 +55,19 @@ export function GroupDropdown({ groups, className }: dropdownProps) { +
+ + + {selectedGroup.name} + +
@@ -72,8 +81,10 @@ export function GroupDropdown({ groups, className }: dropdownProps) { href={`/team/${group.id}`} as="a" > - - {group.name} + + + {group.name} + ); })} diff --git a/src/components/layout/header/dropdown/user-dropdown.tsx b/src/components/layout/header/dropdown/user-dropdown.tsx index df114b3b..4ababb60 100644 --- a/src/components/layout/header/dropdown/user-dropdown.tsx +++ b/src/components/layout/header/dropdown/user-dropdown.tsx @@ -1,5 +1,4 @@ -import IcUser from "@/assets/icons/ic-user.svg"; -import { Dropdown } from "@/components/ui"; +import { Avatar, Dropdown } from "@/components/ui"; import { userOptions } from "../header.props"; import { User } from "@/types/user"; import { useLogout } from "@/hooks"; @@ -10,7 +9,11 @@ export function UserDropdown({ user }: { user: User }) { return ( - + {user.nickname} diff --git a/src/components/layout/header/header-sidebar.tsx b/src/components/layout/header/header-sidebar.tsx index 355947ac..485ab7c0 100644 --- a/src/components/layout/header/header-sidebar.tsx +++ b/src/components/layout/header/header-sidebar.tsx @@ -29,8 +29,14 @@ export function HeaderSidebar({ groups, onClick }: sidebarProps) {
- - {group.name} + + + {group.name} +
diff --git a/src/components/layout/header/header.tsx b/src/components/layout/header/header.tsx index 0e8f9bbb..534ae0d3 100644 --- a/src/components/layout/header/header.tsx +++ b/src/components/layout/header/header.tsx @@ -2,7 +2,7 @@ import Link from "next/link"; import { HeaderSidebar } from "./header-sidebar"; import { useState } from "react"; -import Logo from "@/assets/icons/ic-logo.svg"; +import Logo from "@/assets/landing/logo-flat.svg"; import IcMenu from "@/assets/icons/ic-gnb-menu.svg"; import { GroupDropdown } from "./dropdown/group-dropdown"; import { UserDropdown } from "./dropdown/user-dropdown"; @@ -11,7 +11,7 @@ import { User } from "@/types/user"; interface HeaderProps { isLoginPage: boolean; - groups?: DropdownOption[]; + groups?: DropdownOption[] | null; user?: User | null; } @@ -24,7 +24,7 @@ export default function Header({ isLoginPage, groups, user }: HeaderProps) { if (isLoginPage) { return (
-
+
@@ -38,7 +38,7 @@ export default function Header({ isLoginPage, groups, user }: HeaderProps) { return (
{open && } -
+
- {groups && } + {groups?.length !== 0 && groups && } 자유게시판
-
{user ? : 로그인}
+
+ {user ? : 로그인} +
); diff --git a/src/components/skeleton-ui/team-skeleton.tsx b/src/components/skeleton-ui/team-skeleton.tsx index 26ddf677..9b9380f8 100644 --- a/src/components/skeleton-ui/team-skeleton.tsx +++ b/src/components/skeleton-ui/team-skeleton.tsx @@ -28,10 +28,10 @@ export default function TeamSkeleton() {
-
- - - +
+ + +
diff --git a/src/components/ui/input/input-password.tsx b/src/components/ui/input/input-password.tsx index 82db21d6..3a0a0447 100644 --- a/src/components/ui/input/input-password.tsx +++ b/src/components/ui/input/input-password.tsx @@ -28,6 +28,7 @@ export default function InputPassword({ inputStyle({ intent: "password", disabled, error: Boolean(ctx?.errorMsg) }), className, )} + autoComplete="off" {...props} />
- - {comment.createdAt !== comment.updatedAt && ( - (수정됨) + {variant === "primary" ? ( + <> + + {comment.createdAt !== comment.updatedAt && ( + (수정됨) + )} + + ) : ( +
+ {comment.createdAt !== comment.updatedAt && ( + (수정됨) + )} + +
)}
{isAuthor && } diff --git a/src/types/option.ts b/src/types/option.ts index d277ccb7..9463836c 100644 --- a/src/types/option.ts +++ b/src/types/option.ts @@ -3,5 +3,5 @@ export interface DropdownOption { value?: string; id?: number; name?: string; - image?: string; + image?: string | null; }