From 416076dde3b75163e707779e1e05f1f38ef67059 Mon Sep 17 00:00:00 2001 From: minh0518 Date: Thu, 21 Dec 2023 13:39:20 +0900 Subject: [PATCH 01/65] ESLint,Prettier setting --- .eslintrc.json | 38 ++- .prettierrc | 19 ++ package-lock.json | 634 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 12 +- 4 files changed, 698 insertions(+), 5 deletions(-) create mode 100644 .prettierrc diff --git a/.eslintrc.json b/.eslintrc.json index bffb357..8859900 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,3 +1,39 @@ { - "extends": "next/core-web-vitals" + "env": { + "browser": true, + "es2021": true, + "node": true + }, + "parser": "@typescript-eslint/parser", + "extends": ["next/core-web-vitals", "plugin:prettier/recommended", "plugin:@typescript-eslint/recommended"], + + "overrides": [], + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module", + "project": ["./tsconfig.json"] + }, + "plugins": ["@typescript-eslint", "prettier"], + "rules": { + "@typescript-eslint/consistent-type-imports": "off", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/space-before-function-paren": "off", + "@typescript-eslint/triple-slash-reference": "off", + "@typescript-eslint/restrict-template-expressions": "error", + "@typescript-eslint/no-floating-promises": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/no-unused-vars": "warn", + "@typescript-eslint/no-misused-promises": [ + "error", + { + "checksVoidReturn": false + } + ], + "prettier/prettier": [ + "error", + { + "endOfLine": "auto" + } + ] + } } diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..f1d1b18 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,19 @@ +{ + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "useTabs": false, + "trailingComma": "all", + "printWidth": 100, + "arrowParens": "always", + "bracketSpacing": true, + "jsxBracketSameLine": false, + "overrides": [ + { + "files": "*.json", + "options": { + "printWidth": 150 + } + } + ] +} diff --git a/package-lock.json b/package-lock.json index 5f69ccc..552f60d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,8 +16,12 @@ "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "@typescript-eslint/eslint-plugin": "^6.15.0", + "@typescript-eslint/parser": "^6.15.0", "eslint": "^8", "eslint-config-next": "14.0.4", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.0", "typescript": "^5" } }, @@ -315,6 +319,26 @@ "node": ">= 8" } }, + "node_modules/@pkgr/utils": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", + "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "fast-glob": "^3.3.0", + "is-glob": "^4.0.3", + "open": "^9.1.0", + "picocolors": "^1.0.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/@rushstack/eslint-patch": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.6.1.tgz", @@ -329,6 +353,12 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -376,6 +406,47 @@ "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.15.0.tgz", + "integrity": "sha512-j5qoikQqPccq9QoBAupOP+CBu8BaJ8BLjaXSioDISeTZkVO3ig7oSIKh3H+rEpee7xCXtWwSB4KIL5l6hWZzpg==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/type-utils": "6.15.0", + "@typescript-eslint/utils": "6.15.0", + "@typescript-eslint/visitor-keys": "6.15.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/@typescript-eslint/parser": { "version": "6.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.15.0.tgz", @@ -421,6 +492,33 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.15.0.tgz", + "integrity": "sha512-CnmHKTfX6450Bo49hPg2OkIm/D/TVYV7jO1MCfPYGwf6x3GO0VU8YMO5AYMn+u3X05lRRxA4fWCz87GFQV6yVQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.15.0", + "@typescript-eslint/utils": "6.15.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/@typescript-eslint/types": { "version": "6.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.15.0.tgz", @@ -461,6 +559,31 @@ } } }, + "node_modules/@typescript-eslint/utils": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.15.0.tgz", + "integrity": "sha512-eF82p0Wrrlt8fQSRL0bGXzK5nWPRV2dYQZdajcfzOD9+cQz9O7ugifrJxclB+xVOvWvagXfqS4Es7vpLP4augw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.15.0", + "@typescript-eslint/types": "6.15.0", + "@typescript-eslint/typescript-estree": "6.15.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, "node_modules/@typescript-eslint/visitor-keys": { "version": "6.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.15.0.tgz", @@ -741,6 +864,27 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.44" + }, + "engines": { + "node": ">= 5.10.0" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -763,6 +907,21 @@ "node": ">=8" } }, + "node_modules/bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "dependencies": { + "run-applescript": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -910,6 +1069,40 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/default-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "dev": true, + "dependencies": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^7.1.1", + "titleize": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", + "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", + "dev": true, + "dependencies": { + "bplist-parser": "^0.2.0", + "untildify": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/define-data-property": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", @@ -924,6 +1117,18 @@ "node": ">= 0.4" } }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/define-properties": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", @@ -1201,6 +1406,18 @@ } } }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "node_modules/eslint-import-resolver-node": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", @@ -1363,6 +1580,36 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, + "node_modules/eslint-plugin-prettier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.0.tgz", + "integrity": "sha512-hQc+2zbnMeXcIkg+pKZtVa+3Yqx4WY7SMkn1PLZ4VbBEU7jJIpVn9347P8BBhTbz6ne85aXvQf30kvexcqBeWw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.5" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, "node_modules/eslint-plugin-react": { "version": "7.33.2", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", @@ -1530,12 +1777,41 @@ "node": ">=0.10.0" } }, + "node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -1711,6 +1987,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -1930,6 +2218,15 @@ "node": ">= 0.4" } }, + "node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "engines": { + "node": ">=14.18.0" + } + }, "node_modules/ignore": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", @@ -2090,6 +2387,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2138,6 +2450,24 @@ "node": ">=0.10.0" } }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", @@ -2229,6 +2559,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -2308,6 +2650,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-wsl/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -2479,6 +2848,12 @@ "node": ">=10" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -2501,6 +2876,18 @@ "node": ">=8.6" } }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2597,6 +2984,33 @@ } } }, + "node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2724,6 +3138,39 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "dev": true, + "dependencies": { + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -2878,6 +3325,34 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", + "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", + "dev": true, + "peer": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -3050,6 +3525,110 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-applescript/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/run-applescript/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/run-applescript/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-applescript/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/run-applescript/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/run-applescript/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-applescript/node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -3192,6 +3771,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -3303,6 +3888,18 @@ "node": ">=4" } }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3361,6 +3958,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/synckit": { + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.6.tgz", + "integrity": "sha512-laHF2savN6sMeHCjLRkheIU4wo3Zg9Ln5YOjOo7sZ5dVQW8yF5pPE5SIw1dsPhq3TRp1jisKRCdPhfs/1WMqDA==", + "dev": true, + "dependencies": { + "@pkgr/utils": "^2.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -3376,6 +3989,18 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/titleize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3540,6 +4165,15 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", diff --git a/package.json b/package.json index 1d5cd4e..e08e08b 100644 --- a/package.json +++ b/package.json @@ -9,16 +9,20 @@ "lint": "next lint" }, "dependencies": { + "next": "14.0.4", "react": "^18", - "react-dom": "^18", - "next": "14.0.4" + "react-dom": "^18" }, "devDependencies": { - "typescript": "^5", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", + "@typescript-eslint/eslint-plugin": "^6.15.0", + "@typescript-eslint/parser": "^6.15.0", "eslint": "^8", - "eslint-config-next": "14.0.4" + "eslint-config-next": "14.0.4", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.0", + "typescript": "^5" } } From 546a5ad77db2ed6764ca2f2994426709a6fda105 Mon Sep 17 00:00:00 2001 From: minh0518 Date: Thu, 21 Dec 2023 13:46:26 +0900 Subject: [PATCH 02/65] add templates and labels --- .github/ISSUE_TEMPLATE.md | 18 ++++++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 29 +++++++++++++++++++++++++++++ .github/labels.yml | 21 +++++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/labels.yml diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..8997b36 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,18 @@ +## 개요 + +{ 업무에 대한 요약 및 설명 } + +
+ +## 체크리스트 + +{ 작업 체크리스트 } + +- [ ] 리스트 1 +- [ ] 리스트 2 + +
+ +## 비고 + +{ 기타 내용, 의존성있는 작업 } diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..ba2581a --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,29 @@ +### 💁‍♂️ PR 개요 + +- 어떤 이유로 코드를 변경했는지 +- #{issue number} + +
+ +### 📝 변경 사항 + +- 어떤 부분이 수정되었는지 + +
+ +### 📷 스크린 샷 (선택) + +- 관련 스크린샷 첨부 + +
+ +### 🗣 리뷰어한테 할 말 (선택) + +- 집중적으로 리뷰해주었으면 하는 부분 설명 + +
+ +### 🧪 테스트 범위 (선택) + +- 테스트 계획 +- 테스트 완료 사항 diff --git a/.github/labels.yml b/.github/labels.yml new file mode 100644 index 0000000..9df3a31 --- /dev/null +++ b/.github/labels.yml @@ -0,0 +1,21 @@ +- color: D4C5F9 + description: '패키지 매니저 수정, 그 외 기타 수정' + name: '⚙️CHORE' +- color: C5DEF5 + description: '문서(주석) 수정' + name: '📝DOCS' +- color: FEF2C0 + description: '기능 구현 관련' + name: '✨FEAT' +- color: F9D0C4 + description: '기능에 대한 버그 수정' + name: '🐛FIX' +- color: C2E0C6 + description: '기능의 변화가 아닌 코드 리팩터링 ex) 변수명 변경' + name: '♻️REFACTOR' +- color: E99695 + description: '코드 스타일, 포맷팅에 대한 수정' + name: '🎨STYLE' +- color: 66ff99 + description: 'test 관련' + name: '✅TEST' From 3cd476336a86bcf178cb3d4a75c784dddc2c7171 Mon Sep 17 00:00:00 2001 From: minh0518 Date: Thu, 21 Dec 2023 14:04:09 +0900 Subject: [PATCH 03/65] change labels file --- .github/labels.json | 37 +++++++++++++++++++++++++++++++++++++ .github/labels.yml | 21 --------------------- 2 files changed, 37 insertions(+), 21 deletions(-) create mode 100644 .github/labels.json delete mode 100644 .github/labels.yml diff --git a/.github/labels.json b/.github/labels.json new file mode 100644 index 0000000..7966030 --- /dev/null +++ b/.github/labels.json @@ -0,0 +1,37 @@ +[ + { + "color": "D4C5F9", + "description": "패키지 매니저 수정, 그 외 기타 수정", + "name": "⚙️CHORE" + }, + { + "color": "C5DEF5", + "description": "문서(주석) 수정", + "name": "📝DOCS" + }, + { + "color": "FEF2C0", + "description": "기능 구현 관련", + "name": "✨FEAT" + }, + { + "color": "F9D0C4", + "description": "기능에 대한 버그 수정", + "name": "🐛FIX" + }, + { + "color": "C2E0C6", + "description": "기능의 변화가 아닌 코드 리팩터링 ex) 변수명 변경", + "name": "♻️REFACTOR" + }, + { + "color": "E99695", + "description": "코드 스타일, 포맷팅에 대한 수정", + "name": "🎨STYLE" + }, + { + "color": "66ff99", + "description": "test 관련", + "name": "✅TEST" + } +] diff --git a/.github/labels.yml b/.github/labels.yml deleted file mode 100644 index 9df3a31..0000000 --- a/.github/labels.yml +++ /dev/null @@ -1,21 +0,0 @@ -- color: D4C5F9 - description: '패키지 매니저 수정, 그 외 기타 수정' - name: '⚙️CHORE' -- color: C5DEF5 - description: '문서(주석) 수정' - name: '📝DOCS' -- color: FEF2C0 - description: '기능 구현 관련' - name: '✨FEAT' -- color: F9D0C4 - description: '기능에 대한 버그 수정' - name: '🐛FIX' -- color: C2E0C6 - description: '기능의 변화가 아닌 코드 리팩터링 ex) 변수명 변경' - name: '♻️REFACTOR' -- color: E99695 - description: '코드 스타일, 포맷팅에 대한 수정' - name: '🎨STYLE' -- color: 66ff99 - description: 'test 관련' - name: '✅TEST' From aaa964fee885c1ea9c06982b90915818cc4a33b6 Mon Sep 17 00:00:00 2001 From: Joie-Kim Date: Wed, 3 Jan 2024 15:11:08 +0900 Subject: [PATCH 04/65] chore: stylelint setting --- .stylelintrc.json | 60 ++ package-lock.json | 1629 +++++++++++++++++++++++++++++++++++++++++++-- package.json | 5 + 3 files changed, 1652 insertions(+), 42 deletions(-) create mode 100644 .stylelintrc.json diff --git a/.stylelintrc.json b/.stylelintrc.json new file mode 100644 index 0000000..4054c7b --- /dev/null +++ b/.stylelintrc.json @@ -0,0 +1,60 @@ +{ + "extends": ["stylelint-config-standard-scss"], + "plugins": ["stylelint-order", "stylelint-prettier"], + "overrides": [ + { + "files": ["**/*.scss"], + "customSyntax": "postcss-scss" + } + ], + "rules": { + "prettier/prettier": [true, { "printWidth": 100 }], + "media-feature-range-notation": "prefix", + "order/properties-order": [ + "display", + "align-items", + "justify-content", + "clear", + "float", + "overflow", + "position", + "top", + "right", + "bottom", + "left", + "z-index", + "width", + "height", + "margin", + "padding", + "background", + "background-size", + "border", + "color", + "font-size", + "font-weight", + "text-overflow", + "text-align", + "line-height", + "text-indent", + "transform", + "transition", + "box-sizing", + "white-space" + ], + "selector-class-pattern": null, + "selector-pseudo-class-no-unknown": [ + true, + { + "ignorePseudoClasses": ["deep"] + } + ], + "no-descending-specificity": null, + "font-family-no-missing-generic-family-keyword": [ + true, + { + "ignoreFontFamilies": ["Font Awesome 5 Free"] + } + ] + } +} diff --git a/package-lock.json b/package-lock.json index 552f60d..1eaf758 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,11 @@ "eslint-config-next": "14.0.4", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.0", + "sass": "^1.69.7", + "stylelint": "^16.1.0", + "stylelint-config-standard-scss": "^12.0.0", + "stylelint-order": "^6.0.4", + "stylelint-prettier": "^5.0.0", "typescript": "^5" } }, @@ -34,6 +39,184 @@ "node": ">=0.10.0" } }, + "node_modules/@babel/code-frame": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.23.4", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/runtime": { "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz", @@ -46,6 +229,92 @@ "node": ">=6.9.0" } }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.5.0.tgz", + "integrity": "sha512-abypo6m9re3clXA00eu5syw+oaPHbJTPapu9C4pzNsJ4hdZDzushT50Zhu+iIYXgEe1CxnRMn7ngsbV+MLrlpQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^2.2.3" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.3.tgz", + "integrity": "sha512-pp//EvZ9dUmGuGtG1p+n17gTHEOqu9jO+FiCUjNN3BDmyhdA2Jq9QsVeR7K8/2QCK17HSsioPlTW9ZkzoWb3Lg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.7.tgz", + "integrity": "sha512-lHPKJDkPUECsyAvD60joYfDmp8UERYxHGkFfyLJFTVK/ERJe0sVlIFLXU5XFxdjNDTerp5L4KeaKG+Z5S94qxQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.5.0", + "@csstools/css-tokenizer": "^2.2.3" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.1.tgz", + "integrity": "sha512-NPljRHkq4a14YzZ3YD406uaxh7s0g6eAq3L9aLOWywoqe8PkYamAvtsh7KNX6c++ihDrJ0RiU+/z7rGnhlZ5ww==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.13" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -135,6 +404,67 @@ "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@next/env": { "version": "14.0.4", "resolved": "https://registry.npmjs.org/@next/env/-/env-14.0.4.tgz", @@ -319,6 +649,16 @@ "node": ">= 8" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@pkgr/utils": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", @@ -668,6 +1008,19 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "devOptional": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -819,6 +1172,15 @@ "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", "dev": true }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/asynciterator.prototype": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", @@ -873,6 +1235,15 @@ "node": ">=0.6" } }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/bplist-parser": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", @@ -899,7 +1270,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, + "devOptional": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -991,6 +1362,45 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "devOptional": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -1014,31 +1424,97 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-functions-list": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.1.tgz", + "integrity": "sha512-Nj5YcaGgBtuUmn1D7oHqPW0c9iui7xsTsj5lIX8ZgevdfhmjFfKB3r8moHJtNJnctnYXJyYX5I1pp90HM4TPgQ==", + "dev": true, + "engines": { + "node": ">=12 || >=16" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true }, "node_modules/damerau-levenshtein": { "version": "1.0.8", @@ -1179,6 +1655,12 @@ "node": ">=6.0.0" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -1198,6 +1680,24 @@ "node": ">=10.13.0" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-abstract": { "version": "1.22.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", @@ -1852,6 +2352,15 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, "node_modules/fastq": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", @@ -1877,7 +2386,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, + "devOptional": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1930,12 +2439,54 @@ "is-callable": "^1.1.3" } }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -2064,6 +2615,44 @@ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -2114,6 +2703,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -2218,6 +2813,18 @@ "node": ">= 0.4" } }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/human-signals": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", @@ -2236,6 +2843,12 @@ "node": ">= 4" } }, + "node_modules/immutable": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", + "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", + "devOptional": true + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -2277,6 +2890,12 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, "node_modules/internal-slot": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", @@ -2305,6 +2924,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, "node_modules/is-async-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", @@ -2332,6 +2957,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "devOptional": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -2406,7 +3043,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -2423,6 +3060,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-generator-function": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", @@ -2442,7 +3088,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, + "devOptional": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -2493,7 +3139,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.12.0" } @@ -2522,6 +3168,15 @@ "node": ">=8" } }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -2702,6 +3357,24 @@ "set-function-name": "^2.0.1" } }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2725,6 +3398,12 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -2773,6 +3452,21 @@ "json-buffer": "3.0.1" } }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/known-css-properties": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.29.0.tgz", + "integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==", + "dev": true + }, "node_modules/language-subtag-registry": { "version": "0.3.22", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", @@ -2804,6 +3498,12 @@ "node": ">= 0.8.0" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2825,6 +3525,12 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -2848,6 +3554,34 @@ "node": ">=10" } }, + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/meow": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.0.0.tgz", + "integrity": "sha512-4Hu+75Vo7EOR+8C9RmkabfLijuwd9SrzQ8f0SyC4qZZwU6BlxeOt5ulF3PGCpcMJX4hI+ktpJhea0P6PN1RiWw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -2909,6 +3643,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -2984,6 +3727,15 @@ } } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm-run-path": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", @@ -3230,6 +3982,24 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3263,6 +4033,31 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -3281,7 +4076,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8.6" }, @@ -3316,28 +4111,94 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true }, - "node_modules/prettier": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", - "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", + "dev": true + }, + "node_modules/postcss-scss": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", + "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", "dev": true, - "peer": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-scss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.4.29" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-sorting": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-8.0.2.tgz", + "integrity": "sha512-M9dkSrmU00t/jK7rF6BZSZauA5MAaBW4i5EnJXspMwt4iqTh/L9j6fgMnbElEOfyRyfLfVbIHj/R52zHzAPe1Q==", + "dev": true, + "peerDependencies": { + "postcss": "^8.4.20" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", + "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", + "dev": true, + "peer": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" } }, @@ -3422,6 +4283,18 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "devOptional": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", @@ -3465,6 +4338,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -3684,6 +4566,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sass": { + "version": "1.69.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.7.tgz", + "integrity": "sha512-rzj2soDeZ8wtE2egyLXgOOHQvaC2iosZrkF6v3EUG+tBwEvhqUCzm0VP3k9gHF9LXbSrRhT5SksoI56Iw8NPnQ==", + "devOptional": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/scheduler": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", @@ -3786,6 +4685,23 @@ "node": ">=8" } }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -3802,6 +4718,47 @@ "node": ">=10.0.0" } }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "node_modules/string.prototype.matchall": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", @@ -3879,6 +4836,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -3934,6 +4904,402 @@ } } }, + "node_modules/stylelint": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.1.0.tgz", + "integrity": "sha512-Sh1rRV0lN1qxz/QsuuooLWsIZ/ona7NKw/fRZd6y6PyXYdD2W0EAzJ8yJcwSx4Iw/muz0CF09VZ+z4EiTAcKmg==", + "dev": true, + "dependencies": { + "@csstools/css-parser-algorithms": "^2.4.0", + "@csstools/css-tokenizer": "^2.2.2", + "@csstools/media-query-list-parser": "^2.1.6", + "@csstools/selector-specificity": "^3.0.1", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^9.0.0", + "css-functions-list": "^3.2.1", + "css-tree": "^2.3.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^8.0.0", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.3.1", + "ignore": "^5.3.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.29.0", + "mathml-tag-names": "^2.1.3", + "meow": "^13.0.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.32", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^7.0.0", + "postcss-selector-parser": "^6.0.13", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^7.1.0", + "supports-hyperlinks": "^3.0.0", + "svg-tags": "^1.0.0", + "table": "^6.8.1", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "stylelint": "bin/stylelint.mjs" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.0.tgz", + "integrity": "sha512-jSkx290CglS8StmrLp2TxAppIajzIBZKYm3IxT89Kg6fGlxbPiTiyH9PS5YUuVAFwaJLl1ikiXX0QWjI0jmgZQ==", + "dev": true, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.0.0" + } + }, + "node_modules/stylelint-config-recommended-scss": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.0.0.tgz", + "integrity": "sha512-HDvpoOAQ1RpF+sPbDOT2Q2/YrBDEJDnUymmVmZ7mMCeNiFSdhRdyGEimBkz06wsN+HaFwUh249gDR+I9JR7Onw==", + "dev": true, + "dependencies": { + "postcss-scss": "^4.0.9", + "stylelint-config-recommended": "^14.0.0", + "stylelint-scss": "^6.0.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "postcss": "^8.3.3", + "stylelint": "^16.0.2" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + } + } + }, + "node_modules/stylelint-config-standard": { + "version": "35.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-35.0.0.tgz", + "integrity": "sha512-JyQrNZk2BZwVKFauGGxW2U6RuhIfQ4XoHHo+rBzMHcAkLnwI/knpszwXjzxiMgSfcxbZBckM7Vq4LHoANTR85g==", + "dev": true, + "dependencies": { + "stylelint-config-recommended": "^14.0.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.0.0" + } + }, + "node_modules/stylelint-config-standard-scss": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-12.0.0.tgz", + "integrity": "sha512-ATh3EcEOLZq0iwlFaBdIsSavrla0lNtJ7mO7hdE7DgVT6imozRggFSqd4cFcjzVnOLKv/uJT63MmqA1acIflbw==", + "dev": true, + "dependencies": { + "stylelint-config-recommended-scss": "^14.0.0", + "stylelint-config-standard": "^35.0.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "postcss": "^8.3.3", + "stylelint": "^16.0.2" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + } + } + }, + "node_modules/stylelint-order": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-6.0.4.tgz", + "integrity": "sha512-0UuKo4+s1hgQ/uAxlYU4h0o0HS4NiQDud0NAUNI0aa8FJdmYHA5ZZTFHiV5FpmE3071e9pZx5j0QpVJW5zOCUA==", + "dev": true, + "dependencies": { + "postcss": "^8.4.32", + "postcss-sorting": "^8.0.2" + }, + "peerDependencies": { + "stylelint": "^14.0.0 || ^15.0.0 || ^16.0.1" + } + }, + "node_modules/stylelint-order/node_modules/postcss": { + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/stylelint-prettier": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/stylelint-prettier/-/stylelint-prettier-5.0.0.tgz", + "integrity": "sha512-RHfSlRJIsaVg5Br94gZVdWlz/rBTyQzZflNE6dXvSxt/GthWMY3gEHsWZEBaVGg7GM+XrtVSp4RznFlB7i0oyw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "prettier": ">=3.0.0", + "stylelint": ">=16.0.0" + } + }, + "node_modules/stylelint-scss": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.0.0.tgz", + "integrity": "sha512-N1xV/Ef5PNRQQt9E45unzGvBUN1KZxCI8B4FgN/pMfmyRYbZGVN4y9qWlvOMdScU17c8VVCnjIHTVn38Bb6qSA==", + "dev": true, + "dependencies": { + "known-css-properties": "^0.29.0", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-selector-parser": "^6.0.13", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.0.2" + } + }, + "node_modules/stylelint/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/stylelint/node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true + }, + "node_modules/stylelint/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/stylelint/node_modules/brace-expansion/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/stylelint/node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/stylelint/node_modules/flat-cache": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.0.tgz", + "integrity": "sha512-EryKbCE/wxpxKniQlyas6PY1I9vwtF3uCBweX+N8KYTCn3Y12RTGtQAJ/bd5pl7kxUAc8v/R3Ake/N17OZiFqA==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4", + "rimraf": "^5.0.5" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/stylelint/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/stylelint/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/stylelint/node_modules/postcss": { + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/stylelint/node_modules/postcss-safe-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.0.tgz", + "integrity": "sha512-ovehqRNVCpuFzbXoTb4qLtyzK3xn3t/CUBxOs8LsnQjQrShaB4lKiHoVqY8ANaC0hBMHq5QVWk77rwGklFUDrg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/stylelint/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylelint/node_modules/rimraf": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/stylelint/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3946,6 +5312,19 @@ "node": ">=8" } }, + "node_modules/supports-hyperlinks": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", + "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -3958,6 +5337,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, "node_modules/synckit": { "version": "0.8.6", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.6.tgz", @@ -3974,6 +5359,44 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/table": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -4005,7 +5428,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, + "devOptional": true, "dependencies": { "is-number": "^7.0.0" }, @@ -4183,6 +5606,12 @@ "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", @@ -4286,12 +5715,128 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index e08e08b..ed7f7f5 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,11 @@ "eslint-config-next": "14.0.4", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.0", + "sass": "^1.69.7", + "stylelint": "^16.1.0", + "stylelint-config-standard-scss": "^12.0.0", + "stylelint-order": "^6.0.4", + "stylelint-prettier": "^5.0.0", "typescript": "^5" } } From 00f431981e2a4afdd2ce4e7f963a9ebefd23430a Mon Sep 17 00:00:00 2001 From: minh0518 Date: Wed, 3 Jan 2024 16:43:32 +0900 Subject: [PATCH 05/65] =?UTF-8?q?chore:=20PR=ED=85=9C=ED=94=8C=EB=A6=BF=20?= =?UTF-8?q?=EB=82=B4=EC=9A=A9=20=EA=B0=84=EC=86=8C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/PULL_REQUEST_TEMPLATE.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ba2581a..6188a46 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,13 +1,7 @@ ### 💁‍♂️ PR 개요 - 어떤 이유로 코드를 변경했는지 -- #{issue number} - -
- -### 📝 변경 사항 - -- 어떤 부분이 수정되었는지 +- #{issue number} (QA이슈)
From 3d9f082bc44b3736e4c46cfa0452a651b7d85703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=ED=98=B8?= <78631876+minh0518@users.noreply.github.com> Date: Wed, 3 Jan 2024 23:57:23 +0900 Subject: [PATCH 06/65] =?UTF-8?q?chore:=20husky,=20lint-stage,=20gitconfig?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: stylelint setting * chore: PR템플릿 내용 간소화 * chore: gitconfig설정 및 명령어 추가 * chore: husky,lint-staged 설정 적용 * chore: .env파일 추가, 린트 룰 추가 * chore: lint-staged 캐싱 옵션 추가 * chore: 사용하지 않는 husky파일(pre-push) 제거 * chore: stylelint파일 수정 * chore: .gitignore에 .eslintcache 추가 --- .env | 0 .eslintignore | 3 + .eslintrc.json | 2 + .gitconfig | 3 + .gitignore | 3 + .husky/commit-msg | 26 ++ .husky/pre-commit | 16 ++ .lintstagedrc.js | 13 + .stylelintrc.json | 1 - package-lock.json | 643 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 7 +- 11 files changed, 715 insertions(+), 2 deletions(-) create mode 100644 .env create mode 100644 .eslintignore create mode 100644 .gitconfig create mode 100644 .husky/commit-msg create mode 100644 .husky/pre-commit create mode 100644 .lintstagedrc.js diff --git a/.env b/.env new file mode 100644 index 0000000..e69de29 diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..7509ce0 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +next.config.js +/next.config.js +node_modules \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index 8859900..901fac3 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -15,6 +15,8 @@ }, "plugins": ["@typescript-eslint", "prettier"], "rules": { + "no-var": "error", + "no-console": ["warn", { "allow": ["warn", "error", "info"] }], "@typescript-eslint/consistent-type-imports": "off", "@typescript-eslint/explicit-function-return-type": "off", "@typescript-eslint/space-before-function-paren": "off", diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 0000000..c6cd23f --- /dev/null +++ b/.gitconfig @@ -0,0 +1,3 @@ +# .gitconfig +[core] + ignorecase = false \ No newline at end of file diff --git a/.gitignore b/.gitignore index fd3dbb5..f9c0840 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + + +.eslintcache \ No newline at end of file diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 0000000..313be5d --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,26 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +COMMIT_MSG_FILE=$1 +COMMIT_MSG=$(awk '!/^\s*#/' "$COMMIT_MSG_FILE") +SECOND_LINE=$(echo "$COMMIT_MSG" | sed -n '2p') + +IS_HEADER_FORMAT_VALID='^(:[a-zA-Z_]+: )?(feat|fix|docs|refactor|test|style|chore): .+' +IS_HEADER_LENGTH_UNDER_50='^(.{1,50}$)' + +# --- header --- +if ! echo "$COMMIT_MSG" | grep -qP "$IS_HEADER_FORMAT_VALID"; then + echo "🚨 커밋 메시지는 'feat: ', 'fix: ', 'docs: ', 'refactor: ', 'test: ', 'style: ', 'chore: ' 중 하나로 시작해야 합니다. (띄워쓰기 포함)" + exit 1 +fi + +if ! echo "$COMMIT_MSG" | grep -qP "$IS_HEADER_LENGTH_UNDER_50"; then + echo "🚨 커밋 메시지의 첫 줄은 50자를 넘을 수 없습니다." + exit 1 +fi + +# --- description --- +if ! [ -z "$SECOND_LINE" ]; then + echo "🚨 커밋 메시지의 두 번째 줄은 비워야 합니다." + exit 1 +fi \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..56e9824 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +branch_name=$(git branch --show-current) + +# check branch naming +pattern="^(feat|fix|docs|refactor|test|style|chore)\/.+$" + +if ! echo "$branch_name" | grep -Eq "$pattern"; then + echo "🚨 브랜치 이름이 규칙에 맞지 않습니다." + echo "수정 예시: feat/login_cookie, chore/ESLint,prettier 등" + exit 1 +fi + +# check ESlint&prettier before commit +npx lint-staged diff --git a/.lintstagedrc.js b/.lintstagedrc.js new file mode 100644 index 0000000..1937674 --- /dev/null +++ b/.lintstagedrc.js @@ -0,0 +1,13 @@ +module.exports = { + // Type check TypeScript files + '**/*.(ts|tsx)': () => 'npx tsc --noEmit', + + // Lint & Prettify TS and JS files + '**/*.(ts|tsx)': (filenames) => { + return [ + `npx eslint --cache --fix ${filenames.join(' ')}`, + `npx prettier --write ${filenames.join(' ')}`, + // `npx stylelint --ignore-path .gitignore ${filenames.join(' ')}`, + ]; + }, +}; diff --git a/.stylelintrc.json b/.stylelintrc.json index 4054c7b..03da3bc 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -8,7 +8,6 @@ } ], "rules": { - "prettier/prettier": [true, { "printWidth": 100 }], "media-feature-range-notation": "prefix", "order/properties-order": [ "display", diff --git a/package-lock.json b/package-lock.json index 1eaf758..9c3b1c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "ddd-fe", "version": "0.1.0", + "hasInstallScript": true, "dependencies": { "next": "14.0.4", "react": "^18", @@ -22,6 +23,8 @@ "eslint-config-next": "14.0.4", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.0", + "husky": "^8.0.3", + "lint-staged": "^15.2.0", "sass": "^1.69.7", "stylelint": "^16.1.0", "stylelint-config-standard-scss": "^12.0.0", @@ -984,6 +987,33 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-escapes": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", + "dev": true, + "dependencies": { + "type-fest": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -1401,6 +1431,127 @@ "node": ">= 6" } }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.0.0.tgz", + "integrity": "sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -1430,6 +1581,21 @@ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2277,6 +2443,12 @@ "node": ">=0.10.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, "node_modules/execa": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", @@ -2523,6 +2695,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", @@ -2834,6 +3018,21 @@ "node": ">=14.18.0" } }, + "node_modules/husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/ignore": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", @@ -3498,12 +3697,212 @@ "node": ">= 0.8.0" } }, + "node_modules/lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/lint-staged": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.0.tgz", + "integrity": "sha512-TFZzUEV00f+2YLaVPWBWGAMq7So6yQx+GG8YRMDeOEIf95Zn5RyiLMsEiX4KTNl9vq/w+NqRJkLA1kPIo15ufQ==", + "dev": true, + "dependencies": { + "chalk": "5.3.0", + "commander": "11.1.0", + "debug": "4.3.4", + "execa": "8.0.1", + "lilconfig": "3.0.0", + "listr2": "8.0.0", + "micromatch": "4.0.5", + "pidtree": "0.6.0", + "string-argv": "0.3.2", + "yaml": "2.3.4" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/lint-staged/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/listr2": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.0.tgz", + "integrity": "sha512-u8cusxAcyqAiQ2RhYvV7kRKNLgUvtObIbhOX2NCXqvp1UU32xIg5CT22ykS2TPKJXZWJwtK3IKLiqAGlGNE+Zg==", + "dev": true, + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.0.0", + "rfdc": "^1.3.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.0.0.tgz", + "integrity": "sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3531,6 +3930,135 @@ "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", "dev": true }, + "node_modules/log-update": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", + "dev": true, + "dependencies": { + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.0.0.tgz", + "integrity": "sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4084,6 +4612,18 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -4382,6 +4922,46 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -4392,6 +4972,12 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -4702,6 +5288,18 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -4718,6 +5316,15 @@ "node": ">=10.0.0" } }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -4753,12 +5360,39 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "node_modules/string-width/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", @@ -5843,6 +6477,15 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/yaml": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index ed7f7f5..1b4e7e7 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,10 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "gitconfig": "git config --local include.path ./.gitconfig", + "gitcase": "git rm -r --cached . && git add .", + "postinstall": "husky install" }, "dependencies": { "next": "14.0.4", @@ -23,6 +26,8 @@ "eslint-config-next": "14.0.4", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.0", + "husky": "^8.0.3", + "lint-staged": "^15.2.0", "sass": "^1.69.7", "stylelint": "^16.1.0", "stylelint-config-standard-scss": "^12.0.0", From f5f71a9ec5097727403b70b2246c2b96f4da6021 Mon Sep 17 00:00:00 2001 From: minh0518 Date: Fri, 5 Jan 2024 17:59:43 +0900 Subject: [PATCH 07/65] =?UTF-8?q?chore:=20githun=EC=BB=A8=EB=B2=A4?= =?UTF-8?q?=EC=85=98=20=EA=B4=80=EB=A0=A8=20husky=20=EC=9E=84=EC=8B=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .husky/commit-msg | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/.husky/commit-msg b/.husky/commit-msg index 313be5d..0c2ccb9 100644 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1,26 +1,26 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" -COMMIT_MSG_FILE=$1 -COMMIT_MSG=$(awk '!/^\s*#/' "$COMMIT_MSG_FILE") -SECOND_LINE=$(echo "$COMMIT_MSG" | sed -n '2p') +# COMMIT_MSG_FILE=$1 +# COMMIT_MSG=$(awk '!/^\s*#/' "$COMMIT_MSG_FILE") +# SECOND_LINE=$(echo "$COMMIT_MSG" | sed -n '2p') -IS_HEADER_FORMAT_VALID='^(:[a-zA-Z_]+: )?(feat|fix|docs|refactor|test|style|chore): .+' -IS_HEADER_LENGTH_UNDER_50='^(.{1,50}$)' +# IS_HEADER_FORMAT_VALID='^(:[a-zA-Z_]+: )?(feat|fix|docs|refactor|test|style|chore): .+' +# IS_HEADER_LENGTH_UNDER_50='^(.{1,50}$)' -# --- header --- -if ! echo "$COMMIT_MSG" | grep -qP "$IS_HEADER_FORMAT_VALID"; then - echo "🚨 커밋 메시지는 'feat: ', 'fix: ', 'docs: ', 'refactor: ', 'test: ', 'style: ', 'chore: ' 중 하나로 시작해야 합니다. (띄워쓰기 포함)" - exit 1 -fi +# # --- header --- +# if ! echo "$COMMIT_MSG" | grep -qP "$IS_HEADER_FORMAT_VALID"; then +# echo "🚨 커밋 메시지는 'feat: ', 'fix: ', 'docs: ', 'refactor: ', 'test: ', 'style: ', 'chore: ' 중 하나로 시작해야 합니다. (띄워쓰기 포함)" +# exit 1 +# fi -if ! echo "$COMMIT_MSG" | grep -qP "$IS_HEADER_LENGTH_UNDER_50"; then - echo "🚨 커밋 메시지의 첫 줄은 50자를 넘을 수 없습니다." - exit 1 -fi +# if ! echo "$COMMIT_MSG" | grep -qP "$IS_HEADER_LENGTH_UNDER_50"; then +# echo "🚨 커밋 메시지의 첫 줄은 50자를 넘을 수 없습니다." +# exit 1 +# fi -# --- description --- -if ! [ -z "$SECOND_LINE" ]; then - echo "🚨 커밋 메시지의 두 번째 줄은 비워야 합니다." - exit 1 -fi \ No newline at end of file +# # --- description --- +# if ! [ -z "$SECOND_LINE" ]; then +# echo "🚨 커밋 메시지의 두 번째 줄은 비워야 합니다." +# exit 1 +# fi \ No newline at end of file From b4a21eb77351bb18eb93e96d1c7faa4071c526bb Mon Sep 17 00:00:00 2001 From: minh0518 Date: Fri, 5 Jan 2024 18:11:05 +0900 Subject: [PATCH 08/65] =?UTF-8?q?.env=20gitignore=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 0 .gitignore | 6 +++++- .husky/pre-commit | 16 ++++++++-------- 3 files changed, 13 insertions(+), 9 deletions(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index e69de29..0000000 diff --git a/.gitignore b/.gitignore index f9c0840..8795eeb 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ yarn-error.log* # local env files .env*.local + # vercel .vercel @@ -36,4 +37,7 @@ yarn-error.log* next-env.d.ts -.eslintcache \ No newline at end of file +.eslintcache + + +.env \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit index 56e9824..54ee978 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,16 +1,16 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" -branch_name=$(git branch --show-current) +# branch_name=$(git branch --show-current) -# check branch naming -pattern="^(feat|fix|docs|refactor|test|style|chore)\/.+$" +# # check branch naming +# pattern="^(feat|fix|docs|refactor|test|style|chore)\/.+$" -if ! echo "$branch_name" | grep -Eq "$pattern"; then - echo "🚨 브랜치 이름이 규칙에 맞지 않습니다." - echo "수정 예시: feat/login_cookie, chore/ESLint,prettier 등" - exit 1 -fi +# if ! echo "$branch_name" | grep -Eq "$pattern"; then +# echo "🚨 브랜치 이름이 규칙에 맞지 않습니다." +# echo "수정 예시: feat/login_cookie, chore/ESLint,prettier 등" +# exit 1 +# fi # check ESlint&prettier before commit npx lint-staged From dbf043b355b69a826566bebf4c855377f3b78a57 Mon Sep 17 00:00:00 2001 From: minh0518 Date: Fri, 5 Jan 2024 18:13:48 +0900 Subject: [PATCH 09/65] =?UTF-8?q?chore:=20NextAuth=20=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 97 +++++++++++++++++++++++++ package.json | 1 + src/app/api/auth/[...nextauth]/route.ts | 1 + src/auth.ts | 39 ++++++++++ src/middleware.ts | 12 +++ 5 files changed, 150 insertions(+) create mode 100644 src/app/api/auth/[...nextauth]/route.ts create mode 100644 src/auth.ts create mode 100644 src/middleware.ts diff --git a/package-lock.json b/package-lock.json index 9c3b1c5..9c5eacb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "hasInstallScript": true, "dependencies": { "next": "14.0.4", + "next-auth": "^5.0.0-beta.4", "react": "^18", "react-dom": "^18" }, @@ -42,6 +43,27 @@ "node": ">=0.10.0" } }, + "node_modules/@auth/core": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.18.4.tgz", + "integrity": "sha512-GsNhsP1xE/3FoNS3dVkPjqRljLNJ4iyL2OLv3klQGNvw3bMpROFcK4lqhx7+pPHiamnVaYt2vg1xbB+lsNaevg==", + "dependencies": { + "@panva/hkdf": "^1.1.1", + "cookie": "0.6.0", + "jose": "^5.1.0", + "oauth4webapi": "^2.3.0", + "preact": "10.11.3", + "preact-render-to-string": "5.2.3" + }, + "peerDependencies": { + "nodemailer": "^6.8.0" + }, + "peerDependenciesMeta": { + "nodemailer": { + "optional": true + } + } + }, "node_modules/@babel/code-frame": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", @@ -652,6 +674,14 @@ "node": ">= 8" } }, + "node_modules/@panva/hkdf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.1.1.tgz", + "integrity": "sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1602,6 +1632,14 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cosmiconfig": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", @@ -3574,6 +3612,14 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/jose": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.2.0.tgz", + "integrity": "sha512-oW3PCnvyrcm1HMvGTzqjxxfnEs9EoFOFWi2HsEGhlFVOXxTE3K9GKWVMFoFw06yPUqwpvEWic1BmtUZBI/tIjw==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -4255,6 +4301,24 @@ } } }, + "node_modules/next-auth": { + "version": "5.0.0-beta.4", + "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-5.0.0-beta.4.tgz", + "integrity": "sha512-vgocjvwPA8gxd/zrIP/vr9lJ/HeNe+C56lPP1D3sdyenHt8KncQV6ro7q0xCsDp1fcOKx7WAWVZH5o8aMxDzgw==", + "dependencies": { + "@auth/core": "0.18.4" + }, + "peerDependencies": { + "next": "^14", + "nodemailer": "^6.6.5", + "react": "^18.2.0" + }, + "peerDependenciesMeta": { + "nodemailer": { + "optional": true + } + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -4291,6 +4355,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/oauth4webapi": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-2.4.1.tgz", + "integrity": "sha512-qor45aeDGaGqDOizwut+Q/rZ+J6BIJvOp7U0LtHfbFhg3O7JV5lvQFDXPNqSmcUjuq/Zeq8CIII4RD0sWLOdSQ==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4717,6 +4789,26 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/preact": { + "version": "10.11.3", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.11.3.tgz", + "integrity": "sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/preact-render-to-string": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.3.tgz", + "integrity": "sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==", + "dependencies": { + "pretty-format": "^3.8.0" + }, + "peerDependencies": { + "preact": ">=10" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4754,6 +4846,11 @@ "node": ">=6.0.0" } }, + "node_modules/pretty-format": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", + "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==" + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", diff --git a/package.json b/package.json index 1b4e7e7..ad93ae6 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "next": "14.0.4", + "next-auth": "^5.0.0-beta.4", "react": "^18", "react-dom": "^18" }, diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts new file mode 100644 index 0000000..fae4907 --- /dev/null +++ b/src/app/api/auth/[...nextauth]/route.ts @@ -0,0 +1 @@ +export { GET, POST } from '@/auth'; diff --git a/src/auth.ts b/src/auth.ts new file mode 100644 index 0000000..d498950 --- /dev/null +++ b/src/auth.ts @@ -0,0 +1,39 @@ +// src\auth.ts + +import NextAuth from 'next-auth'; +import CredentialsProvider from 'next-auth/providers/credentials'; + +export const { + handlers: { GET, POST }, + auth, + signIn, +} = NextAuth({ + secret: process.env.AUTH_SECRECT, + pages: { + signIn: '#', // 로그인 + newUser: '#', // 회원가입 + }, + providers: [ + CredentialsProvider({ + async authorize(credentials) { + const authResponse = await fetch(`${process.env.AUTH_URL}/#`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(credentials), + }); + + // fail + if (!authResponse.ok) { + return null; + } + + // success + const user = await authResponse.json(); + + return user; + }, + }), + ], +}); diff --git a/src/middleware.ts b/src/middleware.ts new file mode 100644 index 0000000..b80fa1b --- /dev/null +++ b/src/middleware.ts @@ -0,0 +1,12 @@ +import { NextResponse } from 'next/server'; +import { auth } from './auth'; + +export async function middleware() { + const session = await auth(); + if (!session) return NextResponse.redirect('#'); // 로그인 페이지 +} + +// See "Matching Paths" below to learn more +export const config = { + matcher: [], +}; From 6a6283d11e89ce406ffd3d8ec7e38abee79a0d42 Mon Sep 17 00:00:00 2001 From: minh0518 Date: Fri, 5 Jan 2024 18:30:34 +0900 Subject: [PATCH 10/65] =?UTF-8?q?chore:=20Tanstack/Query=20provider?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (afterlogin) 레이아웃에 적용해서 로그인 이후 적용 될 수 있도록 했습니다 --- package-lock.json | 51 +++++++++++++++++++ package.json | 2 + .../(afterlogin)/_components/RQProvider.tsx | 29 +++++++++++ src/app/(afterlogin)/layout.tsx | 20 ++++++++ src/app/types/common.ts | 5 ++ 5 files changed, 107 insertions(+) create mode 100644 src/app/(afterlogin)/_components/RQProvider.tsx create mode 100644 src/app/(afterlogin)/layout.tsx create mode 100644 src/app/types/common.ts diff --git a/package-lock.json b/package-lock.json index 9c5eacb..6d7c0eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,8 @@ "version": "0.1.0", "hasInstallScript": true, "dependencies": { + "@tanstack/react-query": "^5.17.1", + "@tanstack/react-query-devtools": "^5.17.1", "next": "14.0.4", "next-auth": "^5.0.0-beta.4", "react": "^18", @@ -726,6 +728,55 @@ "tslib": "^2.4.0" } }, + "node_modules/@tanstack/query-core": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.17.1.tgz", + "integrity": "sha512-kUXozQmU7NBtzX5dM6qfFNZN+YK/9Ct37hnG/ogdgI4mExIx7VH/qRepsPhKfNrJz2w81/JykmM3Uug6sVpUSw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/query-devtools": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.17.1.tgz", + "integrity": "sha512-gNdt6PYzYlyjtSAoO8Jt9GIFq5VSLLDV2qq0TCi1t/PGnpAIlIHqNZGYkQTPsy0FyGUTX3pCq4bd7v5z/wzf3A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.17.1.tgz", + "integrity": "sha512-4JYgX0kU+pvwVQi5eRiHGvBK7WnahEl6lmaxd32ZVSKmByAxLgaewoxBR03cdDNse8lUD2zGOe0sx3M/EGRlmA==", + "dependencies": { + "@tanstack/query-core": "5.17.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@tanstack/react-query-devtools": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.17.1.tgz", + "integrity": "sha512-QWHqdEN2TJpj76r0yzdOJEopmPvdAHOJHAKXaygubRASqCqfcWGkOHGD9pqqHOfTu5eQdV1Csx97EuSjnHMKcA==", + "dependencies": { + "@tanstack/query-devtools": "5.17.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-query": "^5.17.1", + "react": "^18.0.0" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", diff --git a/package.json b/package.json index ad93ae6..0490160 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,8 @@ "postinstall": "husky install" }, "dependencies": { + "@tanstack/react-query": "^5.17.1", + "@tanstack/react-query-devtools": "^5.17.1", "next": "14.0.4", "next-auth": "^5.0.0-beta.4", "react": "^18", diff --git a/src/app/(afterlogin)/_components/RQProvider.tsx b/src/app/(afterlogin)/_components/RQProvider.tsx new file mode 100644 index 0000000..dc93098 --- /dev/null +++ b/src/app/(afterlogin)/_components/RQProvider.tsx @@ -0,0 +1,29 @@ +'use client'; + +import React, { ReactNode, useState } from 'react'; +import { QueryClientProvider, QueryClient } from '@tanstack/react-query'; +import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; + +function RQProvider({ children }: { children: ReactNode }) { + const [client] = useState( + new QueryClient({ + defaultOptions: { + queries: { + refetchOnWindowFocus: false, + retryOnMount: true, + refetchOnReconnect: false, + retry: false, + }, + }, + }), + ); + + return ( + + {children} + + + ); +} + +export default RQProvider; diff --git a/src/app/(afterlogin)/layout.tsx b/src/app/(afterlogin)/layout.tsx new file mode 100644 index 0000000..4901ff9 --- /dev/null +++ b/src/app/(afterlogin)/layout.tsx @@ -0,0 +1,20 @@ +import { Metadata } from 'next'; + +import RQProvider from './_components/RQProvider'; + +import { ReactChildrenProps } from '@/app/types/common'; + +export const metadata: Metadata = { + title: '홈', + description: 'HOME', +}; + +export default function AfterLoginLayout({ children }: ReactChildrenProps) { + return ( +
+ +
{children}
+
+
+ ); +} diff --git a/src/app/types/common.ts b/src/app/types/common.ts new file mode 100644 index 0000000..3876637 --- /dev/null +++ b/src/app/types/common.ts @@ -0,0 +1,5 @@ +import { ReactNode } from 'react'; + +export interface ReactChildrenProps { + children: ReactNode; +} From 9352e0e6b18fe2d9f0db4d263d13980409155325 Mon Sep 17 00:00:00 2001 From: minh0518 Date: Fri, 5 Jan 2024 21:48:33 +0900 Subject: [PATCH 11/65] =?UTF-8?q?chore:=20=EC=B4=88=EA=B8=B0=20=ED=8F=B4?= =?UTF-8?q?=EB=8D=94=20=EC=83=9D=EC=84=B1,=20SessionProvider=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(afterlogin)/home/page.tsx | 0 src/app/(beforelogin)/layout.tsx | 0 src/app/(beforelogin)/login/page.tsx | 0 src/app/(beforelogin)/page.tsx | 0 src/app/_components/AuthSession.tsx | 10 ++++++++++ src/app/layout.tsx | 27 +++++++++++++-------------- 6 files changed, 23 insertions(+), 14 deletions(-) create mode 100644 src/app/(afterlogin)/home/page.tsx create mode 100644 src/app/(beforelogin)/layout.tsx create mode 100644 src/app/(beforelogin)/login/page.tsx create mode 100644 src/app/(beforelogin)/page.tsx create mode 100644 src/app/_components/AuthSession.tsx diff --git a/src/app/(afterlogin)/home/page.tsx b/src/app/(afterlogin)/home/page.tsx new file mode 100644 index 0000000..e69de29 diff --git a/src/app/(beforelogin)/layout.tsx b/src/app/(beforelogin)/layout.tsx new file mode 100644 index 0000000..e69de29 diff --git a/src/app/(beforelogin)/login/page.tsx b/src/app/(beforelogin)/login/page.tsx new file mode 100644 index 0000000..e69de29 diff --git a/src/app/(beforelogin)/page.tsx b/src/app/(beforelogin)/page.tsx new file mode 100644 index 0000000..e69de29 diff --git a/src/app/_components/AuthSession.tsx b/src/app/_components/AuthSession.tsx new file mode 100644 index 0000000..2839722 --- /dev/null +++ b/src/app/_components/AuthSession.tsx @@ -0,0 +1,10 @@ +'use client'; +import { SessionProvider } from 'next-auth/react'; + +type Props = { + children: React.ReactNode; +}; + +export default function AuthSession({ children }: Props) { + return {children}; +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 40e027f..5b6b499 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,22 +1,21 @@ -import type { Metadata } from 'next' -import { Inter } from 'next/font/google' -import './globals.css' +import type { Metadata } from 'next'; +import { Inter } from 'next/font/google'; +import './globals.css'; +import { SessionProvider } from 'next-auth/react'; -const inter = Inter({ subsets: ['latin'] }) +const inter = Inter({ subsets: ['latin'] }); export const metadata: Metadata = { - title: 'Create Next App', - description: 'Generated by create next app', -} + title: 'KKEUNKKEUN-WEB', + description: 'DDD 10th', +}; -export default function RootLayout({ - children, -}: { - children: React.ReactNode -}) { +export default function RootLayout({ children }: { children: React.ReactNode }) { return ( - {children} + + {children} + - ) + ); } From 8c75e153df23bf4e15d7b1547b72ef727fb7e53a Mon Sep 17 00:00:00 2001 From: minh0518 Date: Mon, 8 Jan 2024 14:38:02 +0900 Subject: [PATCH 12/65] =?UTF-8?q?chore:=20types=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(afterlogin)/layout.tsx | 2 +- src/{app => }/types/common.ts | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{app => }/types/common.ts (100%) diff --git a/src/app/(afterlogin)/layout.tsx b/src/app/(afterlogin)/layout.tsx index 4901ff9..77736e4 100644 --- a/src/app/(afterlogin)/layout.tsx +++ b/src/app/(afterlogin)/layout.tsx @@ -2,7 +2,7 @@ import { Metadata } from 'next'; import RQProvider from './_components/RQProvider'; -import { ReactChildrenProps } from '@/app/types/common'; +import { ReactChildrenProps } from '@/types/common'; export const metadata: Metadata = { title: '홈', diff --git a/src/app/types/common.ts b/src/types/common.ts similarity index 100% rename from src/app/types/common.ts rename to src/types/common.ts From a91f1fcf17a9c6070a159894dda5dac8e3c31103 Mon Sep 17 00:00:00 2001 From: minh0518 Date: Mon, 8 Jan 2024 16:03:04 +0900 Subject: [PATCH 13/65] =?UTF-8?q?NextAuth=EC=84=A4=EC=A0=95=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80,=20page.tsx=20=EB=9D=BC=EC=9A=B0=ED=8C=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(beforelogin)/layout.tsx | 5 + src/app/(beforelogin)/page.tsx | 7 + src/app/globals.css | 97 +------------ src/app/layout.tsx | 3 +- src/app/not-found.tsx | 11 ++ src/app/page.module.css | 229 ------------------------------- src/app/page.tsx | 95 ------------- src/auth.ts | 1 + 8 files changed, 29 insertions(+), 419 deletions(-) create mode 100644 src/app/not-found.tsx delete mode 100644 src/app/page.module.css delete mode 100644 src/app/page.tsx diff --git a/src/app/(beforelogin)/layout.tsx b/src/app/(beforelogin)/layout.tsx index e69de29..9be71c4 100644 --- a/src/app/(beforelogin)/layout.tsx +++ b/src/app/(beforelogin)/layout.tsx @@ -0,0 +1,5 @@ +import { ReactChildrenProps } from '@/types/common'; + +export default function BeforeLoginLayout({ children }: ReactChildrenProps) { + return
{children}
; +} diff --git a/src/app/(beforelogin)/page.tsx b/src/app/(beforelogin)/page.tsx index e69de29..6952f51 100644 --- a/src/app/(beforelogin)/page.tsx +++ b/src/app/(beforelogin)/page.tsx @@ -0,0 +1,7 @@ +export default function Page() { + return ( +
+

Main

+
+ ); +} diff --git a/src/app/globals.css b/src/app/globals.css index d4f491e..fbeb5f4 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,107 +1,16 @@ -:root { - --max-width: 1100px; - --border-radius: 12px; - --font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono', - 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro', - 'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace; - - --foreground-rgb: 0, 0, 0; - --background-start-rgb: 214, 219, 220; - --background-end-rgb: 255, 255, 255; - - --primary-glow: conic-gradient( - from 180deg at 50% 50%, - #16abff33 0deg, - #0885ff33 55deg, - #54d6ff33 120deg, - #0071ff33 160deg, - transparent 360deg - ); - --secondary-glow: radial-gradient( - rgba(255, 255, 255, 1), - rgba(255, 255, 255, 0) - ); - - --tile-start-rgb: 239, 245, 249; - --tile-end-rgb: 228, 232, 233; - --tile-border: conic-gradient( - #00000080, - #00000040, - #00000030, - #00000020, - #00000010, - #00000010, - #00000080 - ); - - --callout-rgb: 238, 240, 241; - --callout-border-rgb: 172, 175, 176; - --card-rgb: 180, 185, 188; - --card-border-rgb: 131, 134, 135; -} - -@media (prefers-color-scheme: dark) { - :root { - --foreground-rgb: 255, 255, 255; - --background-start-rgb: 0, 0, 0; - --background-end-rgb: 0, 0, 0; - - --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0)); - --secondary-glow: linear-gradient( - to bottom right, - rgba(1, 65, 255, 0), - rgba(1, 65, 255, 0), - rgba(1, 65, 255, 0.3) - ); - - --tile-start-rgb: 2, 13, 46; - --tile-end-rgb: 2, 5, 19; - --tile-border: conic-gradient( - #ffffff80, - #ffffff40, - #ffffff30, - #ffffff20, - #ffffff10, - #ffffff10, - #ffffff80 - ); - - --callout-rgb: 20, 20, 20; - --callout-border-rgb: 108, 108, 108; - --card-rgb: 100, 100, 100; - --card-border-rgb: 200, 200, 200; - } -} - * { box-sizing: border-box; - padding: 0; - margin: 0; } html, body { - max-width: 100vw; + width: 100dvw; + height: 100dvh; + margin: 0; overflow-x: hidden; } -body { - color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, - transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)); -} - a { color: inherit; text-decoration: none; } - -@media (prefers-color-scheme: dark) { - html { - color-scheme: dark; - } -} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 5b6b499..ae65f0f 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -2,6 +2,7 @@ import type { Metadata } from 'next'; import { Inter } from 'next/font/google'; import './globals.css'; import { SessionProvider } from 'next-auth/react'; +import { ReactChildrenProps } from '@/types/common'; const inter = Inter({ subsets: ['latin'] }); @@ -10,7 +11,7 @@ export const metadata: Metadata = { description: 'DDD 10th', }; -export default function RootLayout({ children }: { children: React.ReactNode }) { +export default function RootLayout({ children }: ReactChildrenProps) { return ( diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx new file mode 100644 index 0000000..ed413d2 --- /dev/null +++ b/src/app/not-found.tsx @@ -0,0 +1,11 @@ +import Link from 'next/link'; + +export default function NotFound() { + return ( +
+

Not Found

+

Could not find requested resource

+ Return Home +
+ ); +} diff --git a/src/app/page.module.css b/src/app/page.module.css deleted file mode 100644 index 6676d2c..0000000 --- a/src/app/page.module.css +++ /dev/null @@ -1,229 +0,0 @@ -.main { - display: flex; - flex-direction: column; - justify-content: space-between; - align-items: center; - padding: 6rem; - min-height: 100vh; -} - -.description { - display: inherit; - justify-content: inherit; - align-items: inherit; - font-size: 0.85rem; - max-width: var(--max-width); - width: 100%; - z-index: 2; - font-family: var(--font-mono); -} - -.description a { - display: flex; - justify-content: center; - align-items: center; - gap: 0.5rem; -} - -.description p { - position: relative; - margin: 0; - padding: 1rem; - background-color: rgba(var(--callout-rgb), 0.5); - border: 1px solid rgba(var(--callout-border-rgb), 0.3); - border-radius: var(--border-radius); -} - -.code { - font-weight: 700; - font-family: var(--font-mono); -} - -.grid { - display: grid; - grid-template-columns: repeat(4, minmax(25%, auto)); - max-width: 100%; - width: var(--max-width); -} - -.card { - padding: 1rem 1.2rem; - border-radius: var(--border-radius); - background: rgba(var(--card-rgb), 0); - border: 1px solid rgba(var(--card-border-rgb), 0); - transition: background 200ms, border 200ms; -} - -.card span { - display: inline-block; - transition: transform 200ms; -} - -.card h2 { - font-weight: 600; - margin-bottom: 0.7rem; -} - -.card p { - margin: 0; - opacity: 0.6; - font-size: 0.9rem; - line-height: 1.5; - max-width: 30ch; -} - -.center { - display: flex; - justify-content: center; - align-items: center; - position: relative; - padding: 4rem 0; -} - -.center::before { - background: var(--secondary-glow); - border-radius: 50%; - width: 480px; - height: 360px; - margin-left: -400px; -} - -.center::after { - background: var(--primary-glow); - width: 240px; - height: 180px; - z-index: -1; -} - -.center::before, -.center::after { - content: ''; - left: 50%; - position: absolute; - filter: blur(45px); - transform: translateZ(0); -} - -.logo { - position: relative; -} -/* Enable hover only on non-touch devices */ -@media (hover: hover) and (pointer: fine) { - .card:hover { - background: rgba(var(--card-rgb), 0.1); - border: 1px solid rgba(var(--card-border-rgb), 0.15); - } - - .card:hover span { - transform: translateX(4px); - } -} - -@media (prefers-reduced-motion) { - .card:hover span { - transform: none; - } -} - -/* Mobile */ -@media (max-width: 700px) { - .content { - padding: 4rem; - } - - .grid { - grid-template-columns: 1fr; - margin-bottom: 120px; - max-width: 320px; - text-align: center; - } - - .card { - padding: 1rem 2.5rem; - } - - .card h2 { - margin-bottom: 0.5rem; - } - - .center { - padding: 8rem 0 6rem; - } - - .center::before { - transform: none; - height: 300px; - } - - .description { - font-size: 0.8rem; - } - - .description a { - padding: 1rem; - } - - .description p, - .description div { - display: flex; - justify-content: center; - position: fixed; - width: 100%; - } - - .description p { - align-items: center; - inset: 0 0 auto; - padding: 2rem 1rem 1.4rem; - border-radius: 0; - border: none; - border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25); - background: linear-gradient( - to bottom, - rgba(var(--background-start-rgb), 1), - rgba(var(--callout-rgb), 0.5) - ); - background-clip: padding-box; - backdrop-filter: blur(24px); - } - - .description div { - align-items: flex-end; - pointer-events: none; - inset: auto 0 0; - padding: 2rem; - height: 200px; - background: linear-gradient( - to bottom, - transparent 0%, - rgb(var(--background-end-rgb)) 40% - ); - z-index: 1; - } -} - -/* Tablet and Smaller Desktop */ -@media (min-width: 701px) and (max-width: 1120px) { - .grid { - grid-template-columns: repeat(2, 50%); - } -} - -@media (prefers-color-scheme: dark) { - .vercelLogo { - filter: invert(1); - } - - .logo { - filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70); - } -} - -@keyframes rotate { - from { - transform: rotate(360deg); - } - to { - transform: rotate(0deg); - } -} diff --git a/src/app/page.tsx b/src/app/page.tsx deleted file mode 100644 index 657e775..0000000 --- a/src/app/page.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import Image from 'next/image' -import styles from './page.module.css' - -export default function Home() { - return ( -
-
-

- Get started by editing  - src/app/page.tsx -

- -
- -
- Next.js Logo -
- - -
- ) -} diff --git a/src/auth.ts b/src/auth.ts index d498950..848a8c7 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -9,6 +9,7 @@ export const { signIn, } = NextAuth({ secret: process.env.AUTH_SECRECT, + trustHost: true, pages: { signIn: '#', // 로그인 newUser: '#', // 회원가입 From aa1d3f78a932871ef87c57553b059af411651c06 Mon Sep 17 00:00:00 2001 From: minh0518 Date: Mon, 8 Jan 2024 21:28:58 +0900 Subject: [PATCH 14/65] =?UTF-8?q?chore:=20sync=EC=9E=90=EB=8F=99=ED=99=94?= =?UTF-8?q?=EB=A5=BC=20=EC=9C=84=ED=95=9C=20.yml=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/sync_develop.yml | 30 ++++++++++++++++++++++++++++++ .github/workflows/sync_main.yml | 30 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 .github/workflows/sync_develop.yml create mode 100644 .github/workflows/sync_main.yml diff --git a/.github/workflows/sync_develop.yml b/.github/workflows/sync_develop.yml new file mode 100644 index 0000000..b08d1b7 --- /dev/null +++ b/.github/workflows/sync_develop.yml @@ -0,0 +1,30 @@ +name: git push into another repo to deploy to vercel + +on: + push: + branches: [develop] + +jobs: + build: + runs-on: ubuntu-latest + container: pandoc/latex + steps: + - uses: actions/checkout@v3 + - name: Install mustache (to update the date) + run: apk add ruby && gem install mustache + - name: creates output + run: sh ./build.sh + - name: Pushes to another repository + id: push_directory + uses: cpina/github-action-push-to-another-repository@main + env: + API_TOKEN_GITHUB: ${{ secrets.AUTO_SYNC_KEY }} + with: + source-directory: 'output' + destination-github-username: minh0518 + destination-repository-name: DDD-10-KKEUNKKEUN-WEB + user-email: ${{ secrets.OFFICIAL_ACCOUNT_EMAIL }} + commit-message: ${{ github.event.commits[0].message }} + target-branch: develop + - name: Test get variable exported by push-to-another-repository + run: echo $DESTINATION_CLONED_DIRECTORY diff --git a/.github/workflows/sync_main.yml b/.github/workflows/sync_main.yml new file mode 100644 index 0000000..d56982e --- /dev/null +++ b/.github/workflows/sync_main.yml @@ -0,0 +1,30 @@ +name: git push into another repo to deploy to vercel + +on: + push: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + container: pandoc/latex + steps: + - uses: actions/checkout@v3 + - name: Install mustache (to update the date) + run: apk add ruby && gem install mustache + - name: creates output + run: sh ./build.sh + - name: Pushes to another repository + id: push_directory + uses: cpina/github-action-push-to-another-repository@main + env: + API_TOKEN_GITHUB: ${{ secrets.AUTO_SYNC_KEY }} + with: + source-directory: 'output' + destination-github-username: minh0518 + destination-repository-name: DDD-10-KKEUNKKEUN-WEB + user-email: ${{ secrets.OFFICIAL_ACCOUNT_EMAIL }} + commit-message: ${{ github.event.commits[0].message }} + target-branch: main + - name: Test get variable exported by push-to-another-repository + run: echo $DESTINATION_CLONED_DIRECTORY From 0029235d43ce1e465eb9dcfac4dc7eae4170cc65 Mon Sep 17 00:00:00 2001 From: minh0518 Date: Mon, 8 Jan 2024 21:32:33 +0900 Subject: [PATCH 15/65] chroe: build.sh --- build.sh | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 build.sh diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..496c82c --- /dev/null +++ b/build.sh @@ -0,0 +1,5 @@ +#!/bin/sh +cd ../ +mkdir output +cp -R ./DDD-10-KKEUNKKEUN-WEB/* ./output +cp -R ./output ./DDD-10-KKEUNKKEUN-WEB/ \ No newline at end of file From 47277edeb490b81f775de43e85121a23134d28c2 Mon Sep 17 00:00:00 2001 From: minh0518 Date: Mon, 8 Jan 2024 21:43:25 +0900 Subject: [PATCH 16/65] =?UTF-8?q?chore:=20next=20build=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20page.tsx=20export=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(afterlogin)/home/page.tsx | 7 +++++++ src/app/(beforelogin)/landing/page.tsx | 7 +++++++ src/app/(beforelogin)/login/page.tsx | 7 +++++++ 3 files changed, 21 insertions(+) create mode 100644 src/app/(beforelogin)/landing/page.tsx diff --git a/src/app/(afterlogin)/home/page.tsx b/src/app/(afterlogin)/home/page.tsx index e69de29..14ffe04 100644 --- a/src/app/(afterlogin)/home/page.tsx +++ b/src/app/(afterlogin)/home/page.tsx @@ -0,0 +1,7 @@ +export default function Page() { + return ( +
+

Home

+
+ ); +} diff --git a/src/app/(beforelogin)/landing/page.tsx b/src/app/(beforelogin)/landing/page.tsx new file mode 100644 index 0000000..9689c25 --- /dev/null +++ b/src/app/(beforelogin)/landing/page.tsx @@ -0,0 +1,7 @@ +export default function Page() { + return ( +
+

Landing

+
+ ); +} diff --git a/src/app/(beforelogin)/login/page.tsx b/src/app/(beforelogin)/login/page.tsx index e69de29..8713d25 100644 --- a/src/app/(beforelogin)/login/page.tsx +++ b/src/app/(beforelogin)/login/page.tsx @@ -0,0 +1,7 @@ +export default function Page() { + return ( +
+

Login

+
+ ); +} From e63625fd54339d33dbfb29bba3697b293a718fae Mon Sep 17 00:00:00 2001 From: minh0518 Date: Sat, 13 Jan 2024 18:54:13 +0900 Subject: [PATCH 17/65] =?UTF-8?q?chore:=20=ED=8F=B4=EB=8D=94=EB=AA=85=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 단수 -> 복수 형태로 변경, _lib -> _utils 변경, services 폴더 추가 --- src/services/user.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/services/user.ts diff --git a/src/services/user.ts b/src/services/user.ts new file mode 100644 index 0000000..e69de29 From 822911264a6d3343c19e22e8130273208b244b3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=ED=98=B8?= <78631876+minh0518@users.noreply.github.com> Date: Sat, 13 Jan 2024 20:07:23 +0900 Subject: [PATCH 18/65] =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=B4=88=EA=B8=B0=20=EB=A7=88=ED=81=AC?= =?UTF-8?q?=EC=97=85=20=EC=A7=84=ED=96=89=20(#5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: react-hook-form 설치 * style: 전역 스타일 및 변수 선언 * chore: 메인페이지 라우팅 변경 메인페이지를 랜딩페이지로 변경하고 로그인 페이지를 따로 분리합니다 * feat: 공통 컴포넌트와 타입 생성 button태그, li태그에 대한 공통컴포넌트와 타입을 생성합니다. * feat: 로그인 페이지 마크업 --- package-lock.json | 19 ++++- package.json | 3 +- src/app/(beforelogin)/landing/page.tsx | 7 -- src/app/(beforelogin)/layout.module.scss | 4 + src/app/(beforelogin)/layout.tsx | 4 +- .../login/_components/Login.module.scss | 62 ++++++++++++++ .../(beforelogin)/login/_components/Login.tsx | 28 ++++++ .../login/_components/LoginForm.module.scss | 48 +++++++++++ .../login/_components/LoginForm.tsx | 85 +++++++++++++++++++ .../login/_components/LoginMenus.module.scss | 24 ++++++ .../login/_components/LoginMenus.tsx | 38 +++++++++ .../login/_components/OAuthMenu.module.scss | 16 ++++ .../login/_components/OAuthMenu.tsx | 47 ++++++++++ src/app/(beforelogin)/login/page.tsx | 10 ++- src/app/(beforelogin)/page.tsx | 6 +- src/app/_components/_elements/Button.tsx | 17 ++++ src/app/_components/_elements/List.tsx | 17 ++++ src/app/_components/globals.scss | 18 ++++ src/app/globals.css | 8 ++ src/types/common.ts | 15 ++++ 20 files changed, 458 insertions(+), 18 deletions(-) delete mode 100644 src/app/(beforelogin)/landing/page.tsx create mode 100644 src/app/(beforelogin)/layout.module.scss create mode 100644 src/app/(beforelogin)/login/_components/Login.module.scss create mode 100644 src/app/(beforelogin)/login/_components/Login.tsx create mode 100644 src/app/(beforelogin)/login/_components/LoginForm.module.scss create mode 100644 src/app/(beforelogin)/login/_components/LoginForm.tsx create mode 100644 src/app/(beforelogin)/login/_components/LoginMenus.module.scss create mode 100644 src/app/(beforelogin)/login/_components/LoginMenus.tsx create mode 100644 src/app/(beforelogin)/login/_components/OAuthMenu.module.scss create mode 100644 src/app/(beforelogin)/login/_components/OAuthMenu.tsx create mode 100644 src/app/_components/_elements/Button.tsx create mode 100644 src/app/_components/_elements/List.tsx create mode 100644 src/app/_components/globals.scss diff --git a/package-lock.json b/package-lock.json index 6d7c0eb..0b790a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,8 @@ "next": "14.0.4", "next-auth": "^5.0.0-beta.4", "react": "^18", - "react-dom": "^18" + "react-dom": "^18", + "react-hook-form": "^7.49.3" }, "devDependencies": { "@types/node": "^20", @@ -4965,6 +4966,22 @@ "react": "^18.2.0" } }, + "node_modules/react-hook-form": { + "version": "7.49.3", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.49.3.tgz", + "integrity": "sha512-foD6r3juidAT1cOZzpmD/gOKt7fRsDhXXZ0y28+Al1CHgX+AY1qIN9VSIIItXRq1dN68QrRwl1ORFlwjBaAqeQ==", + "engines": { + "node": ">=18", + "pnpm": "8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/package.json b/package.json index 0490160..82d5f3e 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "next": "14.0.4", "next-auth": "^5.0.0-beta.4", "react": "^18", - "react-dom": "^18" + "react-dom": "^18", + "react-hook-form": "^7.49.3" }, "devDependencies": { "@types/node": "^20", diff --git a/src/app/(beforelogin)/landing/page.tsx b/src/app/(beforelogin)/landing/page.tsx deleted file mode 100644 index 9689c25..0000000 --- a/src/app/(beforelogin)/landing/page.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function Page() { - return ( -
-

Landing

-
- ); -} diff --git a/src/app/(beforelogin)/layout.module.scss b/src/app/(beforelogin)/layout.module.scss new file mode 100644 index 0000000..e01b0ea --- /dev/null +++ b/src/app/(beforelogin)/layout.module.scss @@ -0,0 +1,4 @@ +.container { + width: 100dvh; + height: 100dvh; +} diff --git a/src/app/(beforelogin)/layout.tsx b/src/app/(beforelogin)/layout.tsx index 9be71c4..763b483 100644 --- a/src/app/(beforelogin)/layout.tsx +++ b/src/app/(beforelogin)/layout.tsx @@ -1,5 +1,7 @@ import { ReactChildrenProps } from '@/types/common'; +import styles from './layout.module.scss'; + export default function BeforeLoginLayout({ children }: ReactChildrenProps) { - return
{children}
; + return
{children}
; } diff --git a/src/app/(beforelogin)/login/_components/Login.module.scss b/src/app/(beforelogin)/login/_components/Login.module.scss new file mode 100644 index 0000000..81fdf3c --- /dev/null +++ b/src/app/(beforelogin)/login/_components/Login.module.scss @@ -0,0 +1,62 @@ +@import '@/app/_components/globals'; + +.container { + @include flex-center; + @include full-size; + + background-color: $login-backgroud-color; +} + +.leftSection { + @include flex-center; + + flex: 1; +} + +.rightSection { + @include flex-center; + + margin-right: 150px; + flex: 1; +} + +.loginForm { + display: flex; + align-items: flex-start; + justify-content: center; + width: 550px; + height: 600px; + padding: 0 70px; + flex-direction: column; + background-color: white; + + & > p:nth-child(1) { + margin: 5px 0; + font-size: 1.3rem; + font-weight: bolder; + } + + & > p:nth-child(2) { + margin: 5px 0; + font-size: 1.1rem; + } +} + +.text { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + color: #d9d9d9; + + &::before, + &::after { + content: ''; + flex: 1; + border-bottom: 2px solid black; + } + + & > span { + padding: 0 30px; + } +} diff --git a/src/app/(beforelogin)/login/_components/Login.tsx b/src/app/(beforelogin)/login/_components/Login.tsx new file mode 100644 index 0000000..e3805e0 --- /dev/null +++ b/src/app/(beforelogin)/login/_components/Login.tsx @@ -0,0 +1,28 @@ +import styles from './Login.module.scss'; + +import LoginForm from './LoginForm'; +import LoginMenus from './LoginMenus'; +import OAuthMenu from './OAuthMenu'; + +const Login = () => { + return ( +
+
LOGO
+
+
+

완벽한 발표를 위한 최고의 선택

+

(서비스 이름)에서 발표 연습을 해보세요

+ + + +
+ 또는 +
+ +
+
+
+ ); +}; + +export default Login; diff --git a/src/app/(beforelogin)/login/_components/LoginForm.module.scss b/src/app/(beforelogin)/login/_components/LoginForm.module.scss new file mode 100644 index 0000000..af7aa0e --- /dev/null +++ b/src/app/(beforelogin)/login/_components/LoginForm.module.scss @@ -0,0 +1,48 @@ +@import '@/app/_components/globals'; + +.container { + width: 100%; +} + +.loginForm { + display: flex; + flex-direction: column; + margin-top: 20px; +} + +.loginInput { + display: flex; + margin: 5px 0; + padding: 5px; + border: 1px solid black; + flex-direction: column; + border-radius: 5px; + + label { + font-size: 0.9rem; + } + + &:focus-within { + border: 2px solid black; + } + + .input { + height: 35px; + border: none; + font-size: 1rem; + + &:focus { + outline: none; + } + } +} + +.submitButton { + @include pure-button; + + height: 45px; + border: none; + color: white; + margin-top: 10px; + background-color: black; +} diff --git a/src/app/(beforelogin)/login/_components/LoginForm.tsx b/src/app/(beforelogin)/login/_components/LoginForm.tsx new file mode 100644 index 0000000..019b096 --- /dev/null +++ b/src/app/(beforelogin)/login/_components/LoginForm.tsx @@ -0,0 +1,85 @@ +'use client'; + +import { FieldValues, useForm } from 'react-hook-form'; + +import styles from './LoginForm.module.scss'; + +import Button from '@/app/_components/_elements/Button'; + +interface LoginformType { + email: string; + password: number; +} + +function LoginForm() { + const { + register, + handleSubmit, + formState: { isSubmitting, isSubmitted, errors }, + } = useForm(); + + const loginSubmit = (data: FieldValues) => { + alert(JSON.stringify(data)); + }; + + return ( +
+ {/* data가 사용자가 입력한 최종 데이터 */} +
loginSubmit(data))}> +
+ + +
+ {errors.email && ( + + {errors.email?.message} + + )} +
+ + +
+ {errors.password && ( + + {errors.password?.message} + + )} + +
+
+ ); +} + +export default LoginForm; diff --git a/src/app/(beforelogin)/login/_components/LoginMenus.module.scss b/src/app/(beforelogin)/login/_components/LoginMenus.module.scss new file mode 100644 index 0000000..329f5c5 --- /dev/null +++ b/src/app/(beforelogin)/login/_components/LoginMenus.module.scss @@ -0,0 +1,24 @@ +@import '@/app/_components/globals'; + +.container { + display: flex; + justify-content: center; + width: 100%; +} + +.list { + display: flex; + padding: 0; + + li { + &:not(:last-child) { + border-right: 1px solid #d9d9d9; + } + } +} + +.menuButton { + @include pure-button; + + color: #d9d9d9; +} diff --git a/src/app/(beforelogin)/login/_components/LoginMenus.tsx b/src/app/(beforelogin)/login/_components/LoginMenus.tsx new file mode 100644 index 0000000..f5607c3 --- /dev/null +++ b/src/app/(beforelogin)/login/_components/LoginMenus.tsx @@ -0,0 +1,38 @@ +'use client'; + +import List from '@/app/_components/_elements/List'; +import Button from '@/app/_components/_elements/Button'; + +import styles from './LoginMenus.module.scss'; + +import { ListInfoType } from '@/types/common'; + +const LoginMenus = () => { + const listArr: ListInfoType = [ + { + content: ( + + ), + }, + { + content: ( + + ), + }, + { + content: ( + + ), + }, + ]; + + return ( +
+
    + +
+
+ ); +}; + +export default LoginMenus; diff --git a/src/app/(beforelogin)/login/_components/OAuthMenu.module.scss b/src/app/(beforelogin)/login/_components/OAuthMenu.module.scss new file mode 100644 index 0000000..fdc71d8 --- /dev/null +++ b/src/app/(beforelogin)/login/_components/OAuthMenu.module.scss @@ -0,0 +1,16 @@ +@import '@/app/_components/globals'; + +.container { + display: flex; + justify-content: center; + width: 100%; + + ul { + display: flex; + gap: 20px; + } +} + +.authButtons { + @include pure-button; +} diff --git a/src/app/(beforelogin)/login/_components/OAuthMenu.tsx b/src/app/(beforelogin)/login/_components/OAuthMenu.tsx new file mode 100644 index 0000000..1cd663c --- /dev/null +++ b/src/app/(beforelogin)/login/_components/OAuthMenu.tsx @@ -0,0 +1,47 @@ +'use client'; + +import styles from './OAuthMenu.module.scss'; + +import { ListInfoType } from '@/types/common'; + +import List from '@/app/_components/_elements/List'; +import Button from '@/app/_components/_elements/Button'; + +const OAuthMenu = () => { + const TmpSvg = ( + + + + ); + const listArr: ListInfoType = [ + { + content: ( + + ), + }, + { + content: ( + + ), + }, + { + content: ( + + ), + }, + { + content: ( + + ), + }, + ]; + return ( +
+
    + +
+
+ ); +}; + +export default OAuthMenu; diff --git a/src/app/(beforelogin)/login/page.tsx b/src/app/(beforelogin)/login/page.tsx index 8713d25..955a589 100644 --- a/src/app/(beforelogin)/login/page.tsx +++ b/src/app/(beforelogin)/login/page.tsx @@ -1,7 +1,11 @@ -export default function Page() { +import Login from './_components/Login'; + +const page = () => { return (
-

Login

+
); -} +}; + +export default page; diff --git a/src/app/(beforelogin)/page.tsx b/src/app/(beforelogin)/page.tsx index 6952f51..020a960 100644 --- a/src/app/(beforelogin)/page.tsx +++ b/src/app/(beforelogin)/page.tsx @@ -1,7 +1,3 @@ export default function Page() { - return ( -
-

Main

-
- ); + return
렌딩 페이지
; } diff --git a/src/app/_components/_elements/Button.tsx b/src/app/_components/_elements/Button.tsx new file mode 100644 index 0000000..8434990 --- /dev/null +++ b/src/app/_components/_elements/Button.tsx @@ -0,0 +1,17 @@ +import { ButtonInfoType } from '@/types/common'; + +const Button = ({ + _className, + _disabled = false, + _type = 'button', + content, + _onClick, +}: ButtonInfoType) => { + return ( + + ); +}; + +export default Button; diff --git a/src/app/_components/_elements/List.tsx b/src/app/_components/_elements/List.tsx new file mode 100644 index 0000000..87f52a9 --- /dev/null +++ b/src/app/_components/_elements/List.tsx @@ -0,0 +1,17 @@ +import { ListInfoType } from '@/types/common'; + +const List = ({ listArr }: { listArr: ListInfoType }) => { + return ( + <> + {listArr.map((item, index) => { + return ( +
  • + {item.content} +
  • + ); + })} + + ); +}; + +export default List; diff --git a/src/app/_components/globals.scss b/src/app/_components/globals.scss new file mode 100644 index 0000000..2455efc --- /dev/null +++ b/src/app/_components/globals.scss @@ -0,0 +1,18 @@ +@mixin flex-center { + display: flex; + align-items: center; + justify-content: center; +} + +@mixin full-size { + width: 100dvw; + height: 100dvh; +} + +@mixin pure-button { + background-color: transparent; + cursor: pointer; + border: none; +} + +$login-backgroud-color: #d5d5d5; diff --git a/src/app/globals.css b/src/app/globals.css index fbeb5f4..215776a 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -14,3 +14,11 @@ a { color: inherit; text-decoration: none; } + +ul { + padding: 0; +} + +li { + list-style: none; +} diff --git a/src/types/common.ts b/src/types/common.ts index 3876637..59030b8 100644 --- a/src/types/common.ts +++ b/src/types/common.ts @@ -3,3 +3,18 @@ import { ReactNode } from 'react'; export interface ReactChildrenProps { children: ReactNode; } + +export interface ButtonInfoType { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + content: any; + _onClick: () => void; + _type?: 'button' | 'submit' | 'reset'; + _disabled?: boolean; + _className?: string; // 각 버튼의 className +} + +export type ListInfoType = Array<{ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + content: any; + _className?: string; // 각 리스트의 className +}>; From 082b06e76631a50a289d403f1aa53cc345241d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=ED=98=B8?= <78631876+minh0518@users.noreply.github.com> Date: Sun, 21 Jan 2024 18:05:13 +0900 Subject: [PATCH 19/65] =?UTF-8?q?refactor:=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EC=97=98=EB=A6=AC=EB=A8=BC=ED=8A=B8=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(afterlogin)/layout.tsx | 1 - .../login/_components/LoginForm.tsx | 8 ++++---- .../login/_components/LoginMenus.tsx | 15 ++++++++------- .../login/_components/OAuthMenu.tsx | 19 ++++++++++--------- src/app/_components/_elements/Button.tsx | 14 ++++---------- src/app/_components/_elements/Input.tsx | 10 ++++++++++ src/app/_components/_elements/List.tsx | 6 +++--- src/types/common.ts | 15 --------------- src/types/element.ts | 19 +++++++++++++++++++ 9 files changed, 58 insertions(+), 49 deletions(-) create mode 100644 src/app/_components/_elements/Input.tsx create mode 100644 src/types/element.ts diff --git a/src/app/(afterlogin)/layout.tsx b/src/app/(afterlogin)/layout.tsx index 77736e4..68af235 100644 --- a/src/app/(afterlogin)/layout.tsx +++ b/src/app/(afterlogin)/layout.tsx @@ -1,7 +1,6 @@ import { Metadata } from 'next'; import RQProvider from './_components/RQProvider'; - import { ReactChildrenProps } from '@/types/common'; export const metadata: Metadata = { diff --git a/src/app/(beforelogin)/login/_components/LoginForm.tsx b/src/app/(beforelogin)/login/_components/LoginForm.tsx index 019b096..f642df2 100644 --- a/src/app/(beforelogin)/login/_components/LoginForm.tsx +++ b/src/app/(beforelogin)/login/_components/LoginForm.tsx @@ -71,10 +71,10 @@ function LoginForm() { )} diff --git a/src/app/(beforelogin)/login/_components/LoginMenus.tsx b/src/app/(beforelogin)/login/_components/LoginMenus.tsx index f5607c3..8b846c4 100644 --- a/src/app/(beforelogin)/login/_components/LoginMenus.tsx +++ b/src/app/(beforelogin)/login/_components/LoginMenus.tsx @@ -5,23 +5,24 @@ import Button from '@/app/_components/_elements/Button'; import styles from './LoginMenus.module.scss'; -import { ListInfoType } from '@/types/common'; +import { ListInfoType } from '@/types/element'; const LoginMenus = () => { const listArr: ListInfoType = [ { - content: ( - + _content: ( + ), + // style: { backgroundColor: 'blue' }, }, { - content: ( - + _content: ( + ), }, { - content: ( - + _content: ( + ), }, ]; diff --git a/src/app/(beforelogin)/login/_components/OAuthMenu.tsx b/src/app/(beforelogin)/login/_components/OAuthMenu.tsx index 1cd663c..e7942ba 100644 --- a/src/app/(beforelogin)/login/_components/OAuthMenu.tsx +++ b/src/app/(beforelogin)/login/_components/OAuthMenu.tsx @@ -2,7 +2,7 @@ import styles from './OAuthMenu.module.scss'; -import { ListInfoType } from '@/types/common'; +import { ListInfoType } from '@/types/element'; import List from '@/app/_components/_elements/List'; import Button from '@/app/_components/_elements/Button'; @@ -15,23 +15,24 @@ const OAuthMenu = () => { ); const listArr: ListInfoType = [ { - content: ( - + _content: ( + ), + // style: { backgroundColor: 'blue' }, }, { - content: ( - + _content: ( + ), }, { - content: ( - + _content: ( + ), }, { - content: ( - + _content: ( + ), }, ]; diff --git a/src/app/_components/_elements/Button.tsx b/src/app/_components/_elements/Button.tsx index 8434990..d5d1b2c 100644 --- a/src/app/_components/_elements/Button.tsx +++ b/src/app/_components/_elements/Button.tsx @@ -1,15 +1,9 @@ -import { ButtonInfoType } from '@/types/common'; +import { ButtonInfoType } from '@/types/element'; -const Button = ({ - _className, - _disabled = false, - _type = 'button', - content, - _onClick, -}: ButtonInfoType) => { +const Button = ({ _className, _content, ...rest }: ButtonInfoType) => { return ( - ); }; diff --git a/src/app/_components/_elements/Input.tsx b/src/app/_components/_elements/Input.tsx new file mode 100644 index 0000000..5fd165e --- /dev/null +++ b/src/app/_components/_elements/Input.tsx @@ -0,0 +1,10 @@ +import React, { forwardRef } from 'react'; +import { InputInfoType } from '@/types/element'; + +const Input = forwardRef(({ _className, ...rest }, ref) => { + return ; +}); + +Input.displayName = 'Input'; + +export default Input; diff --git a/src/app/_components/_elements/List.tsx b/src/app/_components/_elements/List.tsx index 87f52a9..e416841 100644 --- a/src/app/_components/_elements/List.tsx +++ b/src/app/_components/_elements/List.tsx @@ -1,12 +1,12 @@ -import { ListInfoType } from '@/types/common'; +import { ListInfoType } from '@/types/element'; const List = ({ listArr }: { listArr: ListInfoType }) => { return ( <> {listArr.map((item, index) => { return ( -
  • - {item.content} +
  • + {item._content}
  • ); })} diff --git a/src/types/common.ts b/src/types/common.ts index 59030b8..3876637 100644 --- a/src/types/common.ts +++ b/src/types/common.ts @@ -3,18 +3,3 @@ import { ReactNode } from 'react'; export interface ReactChildrenProps { children: ReactNode; } - -export interface ButtonInfoType { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - content: any; - _onClick: () => void; - _type?: 'button' | 'submit' | 'reset'; - _disabled?: boolean; - _className?: string; // 각 버튼의 className -} - -export type ListInfoType = Array<{ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - content: any; - _className?: string; // 각 리스트의 className -}>; diff --git a/src/types/element.ts b/src/types/element.ts new file mode 100644 index 0000000..2ec5562 --- /dev/null +++ b/src/types/element.ts @@ -0,0 +1,19 @@ +import { ButtonHTMLAttributes, InputHTMLAttributes, LiHTMLAttributes, ReactNode } from 'react'; + +export interface ButtonInfoType extends ButtonHTMLAttributes { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _content: React.ReactNode; + _className?: string; + // _onClick: React.MouseEventHandler; +} + +interface SingleListType extends LiHTMLAttributes { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _content: React.ReactNode; + _className?: string; +} +export type ListInfoType = SingleListType[]; + +export interface InputInfoType extends InputHTMLAttributes { + _className?: string; +} From 3df8f809a7701a62074a4543f41cd499b1206c2a Mon Sep 17 00:00:00 2001 From: Joie-Kim Date: Sun, 21 Jan 2024 15:21:13 +0900 Subject: [PATCH 20/65] feat: QRcode, audio recording, image logic --- package-lock.json | 31 ++++++++-- package.json | 3 +- src/app/(afterlogin)/practice/[id]/page.tsx | 29 +++++++++ .../practice/_components/Recorder.tsx | 59 +++++++++++++++++++ src/app/_components/_modules/ImagePreview.tsx | 26 ++++++++ .../_components/_modules/ImageUploader.tsx | 29 +++++++++ src/app/_hooks/useImageUploader.ts | 33 +++++++++++ 7 files changed, 204 insertions(+), 6 deletions(-) create mode 100644 src/app/(afterlogin)/practice/[id]/page.tsx create mode 100644 src/app/(afterlogin)/practice/_components/Recorder.tsx create mode 100644 src/app/_components/_modules/ImagePreview.tsx create mode 100644 src/app/_components/_modules/ImageUploader.tsx create mode 100644 src/app/_hooks/useImageUploader.ts diff --git a/package-lock.json b/package-lock.json index 0b790a4..60ce45b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,8 @@ "next-auth": "^5.0.0-beta.4", "react": "^18", "react-dom": "^18", - "react-hook-form": "^7.49.3" + "react-hook-form": "^7.49.3", + "react-qr-code": "^2.0.12" }, "devDependencies": { "@types/node": "^20", @@ -4419,7 +4420,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4907,7 +4907,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -4923,6 +4922,11 @@ "node": ">=6" } }, + "node_modules/qr.js": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", + "integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -4985,8 +4989,25 @@ "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-qr-code": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.0.12.tgz", + "integrity": "sha512-k+pzP5CKLEGBRwZsDPp98/CAJeXlsYRHM2iZn1Sd5Th/HnKhIZCSg27PXO58zk8z02RaEryg+60xa4vyywMJwg==", + "dependencies": { + "prop-types": "^15.8.1", + "qr.js": "0.0.0" + }, + "peerDependencies": { + "react": "^16.x || ^17.x || ^18.x", + "react-native-svg": "*" + }, + "peerDependenciesMeta": { + "react-native-svg": { + "optional": true + } + } }, "node_modules/readdirp": { "version": "3.6.0", diff --git a/package.json b/package.json index 82d5f3e..7008a9d 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "next-auth": "^5.0.0-beta.4", "react": "^18", "react-dom": "^18", - "react-hook-form": "^7.49.3" + "react-hook-form": "^7.49.3", + "react-qr-code": "^2.0.12" }, "devDependencies": { "@types/node": "^20", diff --git a/src/app/(afterlogin)/practice/[id]/page.tsx b/src/app/(afterlogin)/practice/[id]/page.tsx new file mode 100644 index 0000000..3bd6ed9 --- /dev/null +++ b/src/app/(afterlogin)/practice/[id]/page.tsx @@ -0,0 +1,29 @@ +'use client'; + +import QRCode from 'react-qr-code'; +import Recorder from '../_components/Recorder'; +import ImageUploader from '@/app/_components/_modules/ImageUploader'; +import ImagePreview from '@/app/_components/_modules/ImagePreview'; +import useImageUploader from '@/app/_hooks/useImageUploader'; + +export default function Page({ params }: { params: { id: string } }) { + const { selectedFiles, base64Strings, handleFileChange } = useImageUploader(); + return ( + <> +
    id: {params.id}
    +
    + +
    +
    + +
    +
    + + +
    + + ); +} diff --git a/src/app/(afterlogin)/practice/_components/Recorder.tsx b/src/app/(afterlogin)/practice/_components/Recorder.tsx new file mode 100644 index 0000000..28242f9 --- /dev/null +++ b/src/app/(afterlogin)/practice/_components/Recorder.tsx @@ -0,0 +1,59 @@ +'use client'; + +import React, { useState, useRef } from 'react'; + +const Recorder = () => { + const [isRecording, setIsRecording] = useState(false); + const [audioBlob, setAudioBlob] = useState(null); + const mediaRecorderRef = useRef(null); + const audioChunks: Blob[] = []; + + const startRecording = () => { + navigator.mediaDevices + .getUserMedia({ audio: true }) + .then((stream) => { + const mediaRecorder = new MediaRecorder(stream); + + mediaRecorder.ondataavailable = (e) => { + if (e.data.size > 0) { + audioChunks.push(e.data); + } + }; + + mediaRecorder.onstop = () => { + const audioBlob = new Blob(audioChunks, { type: 'audio/mp3' }); // 오디오 파일 형식 확인 필요 + console.log(audioBlob); + setAudioBlob(audioBlob); + }; + + mediaRecorderRef.current = mediaRecorder; + mediaRecorder.start(); + setIsRecording(true); + }) + .catch((error) => { + console.error('Error accessing microphone:', error); + }); + }; + + const stopRecording = () => { + if (mediaRecorderRef.current && isRecording) { + mediaRecorderRef.current.stop(); + setIsRecording(false); + } + }; + + return ( +
    + + {audioBlob && ( + + )} +
    + ); +}; + +export default Recorder; diff --git a/src/app/_components/_modules/ImagePreview.tsx b/src/app/_components/_modules/ImagePreview.tsx new file mode 100644 index 0000000..38689f6 --- /dev/null +++ b/src/app/_components/_modules/ImagePreview.tsx @@ -0,0 +1,26 @@ +'use client'; + +import { useEffect, useState } from 'react'; + +interface Props { + selectedFiles: File[]; + base64Strings: string[]; +} + +const ImagePreview = ({ selectedFiles, base64Strings }: Props) => { + return ( +
    + {selectedFiles.map((file, index) => ( +
    +

    File Name: {file.name}

    +

    File Size: {file.size} bytes

    +

    Base64 String: {base64Strings[index]}

    + preview +
    +
    + ))} +
    + ); +}; + +export default ImagePreview; diff --git a/src/app/_components/_modules/ImageUploader.tsx b/src/app/_components/_modules/ImageUploader.tsx new file mode 100644 index 0000000..5ce04f2 --- /dev/null +++ b/src/app/_components/_modules/ImageUploader.tsx @@ -0,0 +1,29 @@ +'use client'; + +import useImageUploader from '@/app/_hooks/useImageUploader'; +import { ChangeEvent, InputHTMLAttributes, useState } from 'react'; + +interface Props extends InputHTMLAttributes { + _classname?: string; + _handleFileChange: (e: ChangeEvent) => void; +} + +const ImageUploader = ({ _classname, _handleFileChange, ...rest }: Props) => { + return ( + <> +
    + + +
    + + ); +}; + +export default ImageUploader; diff --git a/src/app/_hooks/useImageUploader.ts b/src/app/_hooks/useImageUploader.ts new file mode 100644 index 0000000..2f25a4f --- /dev/null +++ b/src/app/_hooks/useImageUploader.ts @@ -0,0 +1,33 @@ +'use client'; + +import { ChangeEvent, useState } from 'react'; + +const useImageUploader = () => { + const [selectedFiles, setSelectedFiles] = useState([]); + const [base64Strings, setBase64Strings] = useState([]); + + const handleFileChange = (e: ChangeEvent) => { + const target = e.target as HTMLInputElement; + const files = target.files; + + if (files) Array.from(files).forEach((file) => readAndDisplayFile(file)); + }; + + const readAndDisplayFile = (file: File) => { + const reader = new FileReader(); + + reader.onload = (e) => { + const base64String = e.target?.result; + if (base64String && typeof base64String === 'string') { + setBase64Strings((prevBase64Strings) => [...prevBase64Strings, base64String]); + } + }; + + reader.readAsDataURL(file); + setSelectedFiles((prevSelectedFiles) => [...prevSelectedFiles, file]); + }; + + return { selectedFiles, base64Strings, handleFileChange }; +}; + +export default useImageUploader; From 7873127cd81dcc65bc38866ccadf9a63743aff91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=ED=98=B8?= <78631876+minh0518@users.noreply.github.com> Date: Tue, 23 Jan 2024 22:56:49 +0900 Subject: [PATCH 21/65] =?UTF-8?q?=EB=B0=9C=ED=91=9C=20=EC=83=9D=EC=84=B1/?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: Zustand 설치 * feat: route handler를 이용한 mock api 생성 및 관련 타입 생성 기존 발표 내용 수정에 대한 플로우를 구현하기 위해, Next의 route handler를 이용해서 mock api를 생성합니다. * feat: 발표 자료 업데이트 페이지 초기 기능 구현 - ppt 선택 및 관련 페이지 내용 작성 - ppt별 페이지 이동 및 기존 작성 내용 유지 - 각 페이지 내용 수정 - 신규 작성 및 기존 내용 수정(mock api 적용) * style: ppt사진 등록 및 버튼 디자인 적용 * feat: 발표 자료 업데이트 페이지 로직 변경(useRef->useState) 리렌더링 방지를 위해 ref를 사용했던 로직에서 state를 사용하는 로직으로 변경 합니다. * style: 이미지 수정 관련 hover스타일 및 액션 추가 * feat: 신규 작성 페이지, 수정 페이지(useSuspenseQuery적용) 분기 처리 useSuspenseQuery에 enabled속성을 핸들링 할 수 없기 때문에 발표 자료를 새로 생성하는 페이지, 수정하는 페이지에 대해 분기처리를 진행합니다. * feat: ppt 페이지 목록 드래그 앤 드랍 구현 * feat: 메모 기능 추가 * refactor: 공통 컴포넌트 분리 * feat: D-day,타이머 타입 변경 및 나머지 기본 스타일 적용 D-day와 타이머에 대한 세부적인 키값을 추가합니다(날짜, 일정 반복, 발표 마무리 전 알림 등..) --- .eslintrc.json | 1 + next.config.js | 4 +- package-lock.json | 316 ++++++++++-------- package.json | 6 +- .../_component/ControlButtons.module.scss | 59 ++++ .../upload/[id]/_component/ControlButtons.tsx | 160 +++++++++ .../[id]/_component/CreatePresentation.tsx | 39 +++ .../[id]/_component/EditPresentation.tsx | 61 ++++ .../[id]/_component/InputSection.module.scss | 62 ++++ .../upload/[id]/_component/InputSection.tsx | 82 +++++ .../[id]/_component/Spinner.module.scss | 22 ++ .../upload/[id]/_component/Spinner.tsx | 26 ++ .../[id]/_component/UploadDday.module.scss | 28 ++ .../upload/[id]/_component/UploadDday.tsx | 71 ++++ .../[id]/_component/UploadMemo.module.scss | 21 ++ .../upload/[id]/_component/UploadMemo.tsx | 47 +++ .../[id]/_component/UploadPpt.module.scss | 75 +++++ .../upload/[id]/_component/UploadPpt.tsx | 92 +++++ .../[id]/_component/UploadScript.module.scss | 14 + .../upload/[id]/_component/UploadScript.tsx | 46 +++ .../[id]/_component/UploadTimer.module.scss | 23 ++ .../upload/[id]/_component/UploadTimer.tsx | 57 ++++ .../[id]/_component/UploadTitle.module.scss | 12 + .../upload/[id]/_component/UploadTitle.tsx | 40 +++ .../upload/[id]/_hooks/presentation.ts | 14 + .../upload/[id]/_utils/getCurrentPageData.tsx | 18 + .../presentation/upload/[id]/page.module.scss | 7 + .../presentation/upload/[id]/page.tsx | 22 ++ .../login/_components/Login.module.scss | 2 +- src/app/_components/globals.scss | 10 +- src/app/api/get/list/[id]/route.ts | 115 +++++++ src/app/globals.css | 7 +- src/services/user.ts | 16 + src/types/service.ts | 22 ++ 34 files changed, 1444 insertions(+), 153 deletions(-) create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/ControlButtons.module.scss create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/ControlButtons.tsx create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/CreatePresentation.tsx create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/EditPresentation.tsx create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.module.scss create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.tsx create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/Spinner.module.scss create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/Spinner.tsx create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/UploadDday.module.scss create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/UploadDday.tsx create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/UploadMemo.module.scss create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/UploadMemo.tsx create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/UploadPpt.module.scss create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/UploadPpt.tsx create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/UploadScript.module.scss create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/UploadScript.tsx create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTimer.module.scss create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTimer.tsx create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTitle.module.scss create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTitle.tsx create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_hooks/presentation.ts create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/_utils/getCurrentPageData.tsx create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/page.module.scss create mode 100644 src/app/(afterlogin)/presentation/upload/[id]/page.tsx create mode 100644 src/app/api/get/list/[id]/route.ts create mode 100644 src/types/service.ts diff --git a/.eslintrc.json b/.eslintrc.json index 901fac3..9406290 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -25,6 +25,7 @@ "@typescript-eslint/no-floating-promises": "off", "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/no-unused-vars": "warn", + "@typescript-eslint/no-explicit-any": "warn", "@typescript-eslint/no-misused-promises": [ "error", { diff --git a/next.config.js b/next.config.js index 767719f..2f4b20a 100644 --- a/next.config.js +++ b/next.config.js @@ -1,4 +1,4 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {} +const nextConfig = { reactStrictMode: false }; -module.exports = nextConfig +module.exports = nextConfig; diff --git a/package-lock.json b/package-lock.json index 60ce45b..0811c31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,12 +11,16 @@ "dependencies": { "@tanstack/react-query": "^5.17.1", "@tanstack/react-query-devtools": "^5.17.1", + "@types/react-beautiful-dnd": "^13.1.8", + "classnames": "^2.5.1", "next": "14.0.4", "next-auth": "^5.0.0-beta.4", "react": "^18", + "react-beautiful-dnd": "^13.1.1", "react-dom": "^18", "react-hook-form": "^7.49.3", - "react-qr-code": "^2.0.12" + "react-qr-code": "^2.0.12", + "zustand": "^4.4.7" }, "devDependencies": { "@types/node": "^20", @@ -250,7 +254,6 @@ "version": "7.23.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz", "integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==", - "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -508,126 +511,6 @@ "glob": "7.1.7" } }, - "node_modules/@next/swc-darwin-arm64": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz", - "integrity": "sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.4.tgz", - "integrity": "sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz", - "integrity": "sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz", - "integrity": "sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz", - "integrity": "sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz", - "integrity": "sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz", - "integrity": "sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz", - "integrity": "sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@next/swc-win32-x64-msvc": { "version": "14.0.4", "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.4.tgz", @@ -779,6 +662,15 @@ "react": "^18.0.0" } }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", + "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -803,20 +695,26 @@ "node_modules/@types/prop-types": { "version": "15.7.11", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", - "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", - "dev": true + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" }, "node_modules/@types/react": { "version": "18.2.45", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.45.tgz", "integrity": "sha512-TtAxCNrlrBp8GoeEp1npd5g+d/OejJHFxS3OWmrPBMFaVQMSN0OFySozJio5BHxTuTeug00AVXVAjfDSfk+lUg==", - "dev": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", "csstype": "^3.0.2" } }, + "node_modules/@types/react-beautiful-dnd": { + "version": "13.1.8", + "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.8.tgz", + "integrity": "sha512-E3TyFsro9pQuK4r8S/OL6G99eq7p8v29sX0PM7oT8Z+PJfZvSQTx4zTQbUJ+QZXioAF0e7TGBEcA1XhYhCweyQ==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-dom": { "version": "18.2.18", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", @@ -826,11 +724,21 @@ "@types/react": "*" } }, + "node_modules/@types/react-redux": { + "version": "7.1.33", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.33.tgz", + "integrity": "sha512-NF8m5AjWCkert+fosDsN3hAlHzpjSiXlVy9EgQEmLoBhaNXbmyeGs/aj5dQzKuF+/q+S7JQagorGDW8pJ28Hmg==", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "node_modules/@types/scheduler": { "version": "0.16.8", "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", - "dev": true + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" }, "node_modules/@types/semver": { "version": "7.5.6", @@ -1514,6 +1422,11 @@ "node": ">= 6" } }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" + }, "node_modules/cli-cursor": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", @@ -1733,6 +1646,14 @@ "node": ">= 8" } }, + "node_modules/css-box-model": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", + "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", + "dependencies": { + "tiny-invariant": "^1.0.6" + } + }, "node_modules/css-functions-list": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.1.tgz", @@ -1770,8 +1691,7 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/damerau-levenshtein": { "version": "1.0.8", @@ -2736,20 +2656,6 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -3088,6 +2994,14 @@ "node": ">= 0.4" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/html-tags": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", @@ -4197,6 +4111,11 @@ "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", "dev": true }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" + }, "node_modules/meow": { "version": "13.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-13.0.0.tgz", @@ -4947,6 +4866,11 @@ } ] }, + "node_modules/raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -4958,6 +4882,24 @@ "node": ">=0.10.0" } }, + "node_modules/react-beautiful-dnd": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz", + "integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==", + "dependencies": { + "@babel/runtime": "^7.9.2", + "css-box-model": "^1.2.0", + "memoize-one": "^5.1.1", + "raf-schd": "^4.0.2", + "react-redux": "^7.2.0", + "redux": "^4.0.4", + "use-memo-one": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.5 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -5009,6 +4951,35 @@ } } }, + "node_modules/react-redux": { + "version": "7.2.9", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "dependencies": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + }, + "peerDependencies": { + "react": "^16.8.3 || ^17 || ^18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/react-redux/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -5021,6 +4992,14 @@ "node": ">=8.10.0" } }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", @@ -5044,8 +5023,7 @@ "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, "node_modules/regexp.prototype.flags": { "version": "1.5.1", @@ -6232,6 +6210,11 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/tiny-invariant": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + }, "node_modules/titleize": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", @@ -6426,6 +6409,22 @@ "punycode": "^2.1.0" } }, + "node_modules/use-memo-one": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", + "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -6683,6 +6682,33 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zustand": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.7.tgz", + "integrity": "sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==", + "dependencies": { + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } } } } diff --git a/package.json b/package.json index 7008a9d..73d6c62 100644 --- a/package.json +++ b/package.json @@ -14,12 +14,16 @@ "dependencies": { "@tanstack/react-query": "^5.17.1", "@tanstack/react-query-devtools": "^5.17.1", + "@types/react-beautiful-dnd": "^13.1.8", + "classnames": "^2.5.1", "next": "14.0.4", "next-auth": "^5.0.0-beta.4", "react": "^18", + "react-beautiful-dnd": "^13.1.1", "react-dom": "^18", "react-hook-form": "^7.49.3", - "react-qr-code": "^2.0.12" + "react-qr-code": "^2.0.12", + "zustand": "^4.4.7" }, "devDependencies": { "@types/node": "^20", diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/ControlButtons.module.scss b/src/app/(afterlogin)/presentation/upload/[id]/_component/ControlButtons.module.scss new file mode 100644 index 0000000..16b5ae9 --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/ControlButtons.module.scss @@ -0,0 +1,59 @@ +@import '@/app/_components/globals'; + +.container { + display: flex; + justify-content: center; + width: 100%; +} + +.buttons { + display: flex; + gap: 15px; + overflow-x: auto; +} + +.singlePptPage { + position: relative; + width: 85px; + height: 70px; + background-color: transparent; + border: 1px solid black; + border-radius: 8px; + cursor: pointer; +} + +.closeButton { + @include pure-button; + @include flex-center; + + position: absolute; + top: 3px; + right: 5px; + z-index: 10; + width: 15px; + height: 15px; + font-weight: bold; + border-radius: 15px; + cursor: pointer; + box-shadow: none; + transition: box-shadow 0.1s ease; + + &:hover { + box-shadow: 0 2px 4px rgb(0 0 0 / 100%); + } +} + +.addButton { + @include pure-button; + @include flex-center; + + display: inline-block; + min-width: 85px; + height: 70px; + border: 1px solid black; + border-radius: 15px; +} + +.selected { + border: 3px solid black; +} diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/ControlButtons.tsx b/src/app/(afterlogin)/presentation/upload/[id]/_component/ControlButtons.tsx new file mode 100644 index 0000000..49f3a59 --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/ControlButtons.tsx @@ -0,0 +1,160 @@ +'use client'; + +import Image from 'next/image'; +import { Dispatch, MouseEvent, SetStateAction } from 'react'; +import Button from '@/app/_components/_elements/Button'; +import { PagesDataType } from '@/types/service'; +import styles from './ControlButtons.module.scss'; +import classNames from 'classnames/bind'; +import { DragDropContext, Draggable, DropResult, Droppable } from 'react-beautiful-dnd'; + +const cx = classNames.bind(styles); + +interface ControlButtonsProps { + presentationData: PagesDataType; + setPresentationData: Dispatch>; + currentPageIndex: number; + setCurrpentPageIndex: Dispatch>; + initialState: PagesDataType; + slug?: string; +} + +const ControlButtons = ({ + presentationData, + setPresentationData, + currentPageIndex, + setCurrpentPageIndex, + slug, + initialState, +}: ControlButtonsProps) => { + const addButton = () => { + // 마지막 페이지(=작성 중이던 페이지)에서 눌렀다면 새로 추가 + if (currentPageIndex === presentationData.scripts.length - 1) { + setPresentationData((prev) => { + const shallow = [...prev.scripts]; + shallow.push(initialState.scripts[0]); + + return { + ...prev, + scripts: shallow, + }; + }); + setCurrpentPageIndex((prev) => prev + 1); + } else { + // 다른 페이지에 있었다면 마지막 페이지로 다시 복귀 + setCurrpentPageIndex(presentationData.scripts.length - 1); + } + }; + + const remove = (e: MouseEvent, index: number) => { + e.stopPropagation(); + setPresentationData((prev) => { + const shallow = [...prev.scripts]; + shallow.splice(index, 1); + + return { + ...prev, + scripts: shallow, + }; + }); + + // 삭제 시, 관련 페이지 인덱스 당기기 + if (index <= currentPageIndex) { + setCurrpentPageIndex((prev) => (prev === 0 ? 0 : prev - 1)); + } + }; + + const handleChange = (result: DropResult) => { + if (!result.destination) return; + const to = result.destination?.index; + const from = result.source.index; + + setPresentationData((prev) => { + const shallow = [...prev.scripts]; + const moveTarget = shallow.splice(from, 1); + shallow.splice(to, 0, ...moveTarget); + + return { + ...prev, + scripts: shallow, + }; + }); + }; + + return ( +
    + + + {(provided) => ( +
    + {presentationData.scripts.slice(0, -1).map((item, index) => ( + + {(provided, snapshot) => { + return ( +
    +
    setCurrpentPageIndex(index)} + className={cx('singlePptPage', { + selected: currentPageIndex === index, + })} + > + ppt이미지 +
    +
    + ); + }} +
    + ))} + {provided.placeholder} +
    + } + className={cx('addButton', { + selected: currentPageIndex === presentationData.scripts.length - 1, + })} + /> +
    + )} + + + + ); +}; + +export default ControlButtons; diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/CreatePresentation.tsx b/src/app/(afterlogin)/presentation/upload/[id]/_component/CreatePresentation.tsx new file mode 100644 index 0000000..2b1a94e --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/CreatePresentation.tsx @@ -0,0 +1,39 @@ +'use client'; + +import { useState } from 'react'; + +import { PagesDataType } from '@/types/service'; + +import InputSection from './InputSection'; + +const CreatePresentation = () => { + const initialState: PagesDataType = { + title: null, + dDay: { + date: null, + repeat: null, + includeToday: null, + }, + time: { + timer: null, + alramTime: null, + }, + scripts: [{ ppt: { dataURL: null, file: null }, script: null, memo: null }], + }; + + const [presentationData, setPresentationData] = useState(initialState); + const [currentPageIndex, setCurrpentPageIndex] = useState(0); + + return ( + + ); +}; + +export default CreatePresentation; diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/EditPresentation.tsx b/src/app/(afterlogin)/presentation/upload/[id]/_component/EditPresentation.tsx new file mode 100644 index 0000000..71bd214 --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/EditPresentation.tsx @@ -0,0 +1,61 @@ +'use client'; + +import { useEffect, useState } from 'react'; + +import { PagesDataType } from '@/types/service'; + +import { useGetPresentationData } from '../_hooks/presentation'; + +import InputSection from './InputSection'; + +interface EditPresentationProps { + slug: string; +} +const EditPresentation = ({ slug }: EditPresentationProps) => { + const initialState: PagesDataType = { + title: null, + dDay: { + date: null, + repeat: null, + includeToday: null, + }, + time: { + timer: null, + alramTime: null, + }, + scripts: [{ ppt: { dataURL: null, file: null }, script: null, memo: null }], + }; + + const [presentationData, setPresentationData] = useState(initialState); + const [currentPageIndex, setCurrpentPageIndex] = useState(0); + + const value = useGetPresentationData(slug); + useEffect(() => { + const initailSetting = async () => { + const { data: originData, id: originId } = value; + setPresentationData(() => { + const shallow = [...originData.scripts]; + shallow.push(...initialState.scripts); + return { + ...originData, + scripts: shallow, + }; + }); + }; + + initailSetting(); + }, [value]); + + return ( + + ); +}; + +export default EditPresentation; diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.module.scss b/src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.module.scss new file mode 100644 index 0000000..eb42f44 --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.module.scss @@ -0,0 +1,62 @@ +@import '@/app/_components/globals'; + +.container { + display: flex; + align-items: stretch; + gap: 60px; +} + +.leftSectionWrapper { + display: flex; + align-items: flex-start; + justify-content: flex-end; + flex-grow: 1; +} + +.leftSection { + width: 500px; +} + +.rightSectionWrapper { + display: flex; + justify-content: flex-start; + flex-grow: 1; +} + +.rightSection { + display: flex; + width: 875px; + flex-direction: column; +} + +.line { + margin-top: 10px; + border-top: 2px solid $tmp-backgroud-color; + width: 100%; +} + +.saveButtons { + margin-top: 20px; + display: flex; + justify-content: space-between; + + .save { + @include pure-button; + @include flex-center; + + width: 100%; + max-width: 99px; + border-radius: 30px; + background-color: #c9c9c9; + } + + .start { + @include pure-button; + @include flex-center; + + width: 100%; + max-width: 752px; + border-radius: 30px; + background-color: #d9d9d9; + } +} diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.tsx b/src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.tsx new file mode 100644 index 0000000..cfcc951 --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.tsx @@ -0,0 +1,82 @@ +'use client'; +import { PagesDataType } from '@/types/service'; +import styles from './InputSection.module.scss'; +import { Dispatch, SetStateAction } from 'react'; +import UploadTitle from './UploadTitle'; +import UploadScript from './UploadScript'; +import UploadMemo from './UploadMemo'; +import UploadDday from './UploadDday'; +import UploadTimer from './UploadTimer'; +import Button from '@/app/_components/_elements/Button'; +import UploadPpt from './UploadPpt'; +import ControlButtons from './ControlButtons'; + +interface InputSectionProps { + presentationData: PagesDataType; + setPresentationData: Dispatch>; + currentPageIndex: number; + setCurrpentPageIndex: Dispatch>; + initialState: PagesDataType; + slug?: string | 'new'; +} +const InputSection = ({ + presentationData, + setPresentationData, + currentPageIndex, + setCurrpentPageIndex, + initialState, + slug, +}: InputSectionProps) => { + return ( +
    +
    +
    + + +
    +
    +
    +
    + + + +
    + + + +
    +
    +
    +
    +
    + ); +}; + +export default InputSection; diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/Spinner.module.scss b/src/app/(afterlogin)/presentation/upload/[id]/_component/Spinner.module.scss new file mode 100644 index 0000000..94e51dc --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/Spinner.module.scss @@ -0,0 +1,22 @@ +@import '@/app/_components/globals'; + +@keyframes rotating { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +.container { + @include flex-center; + + width: 100dvw; + height: 100dvh; +} + +.loader { + animation: rotating 2s linear infinite; +} diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/Spinner.tsx b/src/app/(afterlogin)/presentation/upload/[id]/_component/Spinner.tsx new file mode 100644 index 0000000..cb01d7c --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/Spinner.tsx @@ -0,0 +1,26 @@ +import styles from './Spinner.module.scss'; + +export default function Spinner() { + return ( +
    + + + + +
    + ); +} diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadDday.module.scss b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadDday.module.scss new file mode 100644 index 0000000..eb0338b --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadDday.module.scss @@ -0,0 +1,28 @@ +@import '@/app/_components/globals'; + +.container { + width: 100%; +} + +.description { + font-weight: bolder; +} + +.inputWrapper { + display: flex; + justify-content: space-between; +} + +.dDayInput { + @include presentation-input; + + width: 60px; + height: 40px; + background-color: $tmp-backgroud-color; +} + +.includeTodayDescription { + margin: 0; + color: $tmp-backgroud-color; + font-size: 0.9rem; +} diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadDday.tsx b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadDday.tsx new file mode 100644 index 0000000..6145902 --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadDday.tsx @@ -0,0 +1,71 @@ +'use client'; + +import { ChangeEventHandler, Dispatch, SetStateAction, forwardRef } from 'react'; + +import { PagesDataType } from '@/types/service'; + +import Input from '@/app/_components/_elements/Input'; + +import styles from './UploadDday.module.scss'; + +interface UploadDdayProps { + dDay: PagesDataType['dDay']; + setPresentationData: Dispatch>; +} + +type dDayIndexType = 'date' | 'repeat' | 'includeToday'; +const UploadDday = forwardRef( + ({ dDay, setPresentationData }, ref) => { + const onChange: ChangeEventHandler = (e) => { + setPresentationData((prev) => { + const { name, value } = e.target; + + const shallow = { ...prev.dDay }; + shallow[name as dDayIndexType] = value; + + return { + ...prev, + dDay: shallow, + }; + }); + }; + return ( +
    +

    D-day 설정

    +
    +

    날짜

    + +
    +
    +

    일정 반복

    + +
    +
    +
    +

    설정일로부터 1일

    + +
    +

    디데이 날짜를 1일로 포함합니다.

    +
    +
    + ); + }, +); +UploadDday.displayName = 'UploadDay'; + +export default UploadDday; diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadMemo.module.scss b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadMemo.module.scss new file mode 100644 index 0000000..5855fcc --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadMemo.module.scss @@ -0,0 +1,21 @@ +@import '@/app/_components/globals'; + +.container { + width: 100%; +} + +.memoInput { + @include presentation-input; + + background-color: $tmp-backgroud-color; + padding-top: 20px; + padding-bottom: 20px; + height: 150px; +} + +.description { + margin-top: -10px; + margin-bottom: 10px; + color: $tmp-backgroud-color; + font-size: 0.9rem; +} diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadMemo.tsx b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadMemo.tsx new file mode 100644 index 0000000..523eb0b --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadMemo.tsx @@ -0,0 +1,47 @@ +'use client'; + +import { ChangeEventHandler, Dispatch, SetStateAction, forwardRef } from 'react'; + +import { PagesDataType } from '@/types/service'; + +import styles from './UploadMemo.module.scss'; + +interface UploadMemoProps { + memo: string | null; + currentPageIndex: number; + setPresentationData: Dispatch>; +} + +const UploadMemo = forwardRef( + ({ memo, currentPageIndex, setPresentationData }, ref) => { + const onChange: ChangeEventHandler = (e) => { + setPresentationData((prev) => { + const shallow = [...prev.scripts]; + shallow[currentPageIndex] = { + ...shallow[currentPageIndex], + memo: e.target.value, + }; + + return { + ...prev, + scripts: shallow, + }; + }); + }; + return ( +
    +

    메모 작성하기

    +

    발표하면서 계속 확인해야 하는 내용을 메모해보세요.

    + +
    + ); + }, +); + +UploadScript.displayName = 'UploadScript'; + +export default UploadScript; diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTimer.module.scss b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTimer.module.scss new file mode 100644 index 0000000..e95888c --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTimer.module.scss @@ -0,0 +1,23 @@ +@import '@/app/_components/globals'; + +.container { + margin-top: 20px; + width: 100%; +} + +.description { + font-weight: bolder; +} + +.inputWrapper { + display: flex; + justify-content: space-between; +} + +.timerInput { + @include presentation-input; + + width: 60px; + height: 40px; + background-color: $tmp-backgroud-color; +} diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTimer.tsx b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTimer.tsx new file mode 100644 index 0000000..f2a504b --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTimer.tsx @@ -0,0 +1,57 @@ +'use client'; + +import { ChangeEventHandler, Dispatch, SetStateAction, forwardRef } from 'react'; + +import Input from '@/app/_components/_elements/Input'; + +import { PagesDataType } from '@/types/service'; + +import styles from './UploadTimer.module.scss'; + +interface UploadTimerProps { + time: PagesDataType['time']; + setPresentationData: Dispatch>; +} +type timerIndexType = 'timer' | 'alramTime'; +const UploadTimer = forwardRef( + ({ time, setPresentationData }, ref) => { + const onChange: ChangeEventHandler = (e) => { + setPresentationData((prev) => { + const { name, value } = e.target; + + const shallow = { ...prev.time }; + shallow[name as timerIndexType] = value; + return { + ...prev, + time: shallow, + }; + }); + }; + return ( +
    +

    발표시간 설정

    +
    +

    타이머

    + +
    +
    +

    발표 마무리 전 알림

    + +
    +
    + ); + }, +); +UploadTimer.displayName = 'UploadTimer'; + +export default UploadTimer; diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTitle.module.scss b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTitle.module.scss new file mode 100644 index 0000000..bb2cad5 --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTitle.module.scss @@ -0,0 +1,12 @@ +@import '@/app/_components/globals'; + +.container { + width: 100%; +} + +.titleInput { + @include presentation-input; + + height: 40px; + background-color: $tmp-backgroud-color; +} diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTitle.tsx b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTitle.tsx new file mode 100644 index 0000000..b254252 --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/UploadTitle.tsx @@ -0,0 +1,40 @@ +'use client'; + +import { ChangeEventHandler, Dispatch, SetStateAction, forwardRef } from 'react'; + +import { PagesDataType } from '@/types/service'; + +import Input from '@/app/_components/_elements/Input'; + +import styles from './UploadTitle.module.scss'; + +interface UploadTitleProps { + title: string | null; + setPresentationData: Dispatch>; +} + +const UploadTitle = forwardRef( + ({ title, setPresentationData }, ref) => { + const onChange: ChangeEventHandler = (e) => { + setPresentationData((prev) => { + return { + ...prev, + title: e.target.value, + }; + }); + }; + return ( +
    +

    발표 이름

    + +
    + ); + }, +); +UploadTitle.displayName = 'UploadTitle'; +export default UploadTitle; diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_hooks/presentation.ts b/src/app/(afterlogin)/presentation/upload/[id]/_hooks/presentation.ts new file mode 100644 index 0000000..9120a6b --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_hooks/presentation.ts @@ -0,0 +1,14 @@ +import { userApi } from '@/services/user'; +import { PresentInfoType } from '@/types/service'; +import { useSuspenseQuery } from '@tanstack/react-query'; + +export const useGetPresentationData = (slug: string) => { + const { data: value } = useSuspenseQuery({ + queryKey: ['presentation', 'upload', slug], + queryFn: async () => { + const res = await userApi.getPresentData(slug); + return res; + }, + }); + return value; +}; diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_utils/getCurrentPageData.tsx b/src/app/(afterlogin)/presentation/upload/[id]/_utils/getCurrentPageData.tsx new file mode 100644 index 0000000..e566580 --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/_utils/getCurrentPageData.tsx @@ -0,0 +1,18 @@ +import { RefObject } from 'react'; + +interface RefsValueType { + title: string; + script: string; + day: any; + timer: any; +} +export const getCurrentRefsData = ( + inputRefs: Map>, +): RefsValueType => { + return { + title: inputRefs.get('title')?.current?.value || '', + script: inputRefs.get('script')?.current?.value || '', + day: inputRefs.get('day')?.current?.value || null, + timer: inputRefs.get('timer')?.current?.value || null, + }; +}; diff --git a/src/app/(afterlogin)/presentation/upload/[id]/page.module.scss b/src/app/(afterlogin)/presentation/upload/[id]/page.module.scss new file mode 100644 index 0000000..3673ae4 --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/page.module.scss @@ -0,0 +1,7 @@ +@import '@/app/_components/globals'; + +.container { + // @include flex-center; + + // margin: 0 240px; +} diff --git a/src/app/(afterlogin)/presentation/upload/[id]/page.tsx b/src/app/(afterlogin)/presentation/upload/[id]/page.tsx new file mode 100644 index 0000000..a9e7320 --- /dev/null +++ b/src/app/(afterlogin)/presentation/upload/[id]/page.tsx @@ -0,0 +1,22 @@ +import { Suspense } from 'react'; +import CreatePresentation from './_component/CreatePresentation'; +import EditPresentation from './_component/EditPresentation'; +import styles from './page.module.scss'; +import Spinner from './_component/Spinner'; + +interface PageProps { + params: { id: string }; +} +const page = ({ params }: PageProps) => { + const slug = params.id; + + return ( +
    + }> + {slug === 'new' ? : } + +
    + ); +}; + +export default page; diff --git a/src/app/(beforelogin)/login/_components/Login.module.scss b/src/app/(beforelogin)/login/_components/Login.module.scss index 81fdf3c..0d59da0 100644 --- a/src/app/(beforelogin)/login/_components/Login.module.scss +++ b/src/app/(beforelogin)/login/_components/Login.module.scss @@ -4,7 +4,7 @@ @include flex-center; @include full-size; - background-color: $login-backgroud-color; + background-color: $tmp-backgroud-color; } .leftSection { diff --git a/src/app/_components/globals.scss b/src/app/_components/globals.scss index 2455efc..64e4b61 100644 --- a/src/app/_components/globals.scss +++ b/src/app/_components/globals.scss @@ -15,4 +15,12 @@ border: none; } -$login-backgroud-color: #d5d5d5; +@mixin presentation-input { + width: 100%; + padding: 0 20px; + border: none; + font-size: 0.9rem; + border-radius: 15px; +} + +$tmp-backgroud-color: #d5d5d5; diff --git a/src/app/api/get/list/[id]/route.ts b/src/app/api/get/list/[id]/route.ts new file mode 100644 index 0000000..95c8445 --- /dev/null +++ b/src/app/api/get/list/[id]/route.ts @@ -0,0 +1,115 @@ +// src\app\api\get\list\[id]\route.ts + +import { PresentInfoType } from '@/types/service'; +import { NextRequest, NextResponse } from 'next/server'; + +const dummyFile = new File(['dummy content'], 'hello.png', { + type: 'image/png', + lastModified: new Date('2023-11-29T10:58:23Z').getTime(), +}); + +const mockPresentData: PresentInfoType[] = [ + { + id: 11111, + data: { + title: '발표1', + dDay: { + date: '2024.8.3', + repeat: '', + includeToday: '', + }, + time: { + timer: '200', + alramTime: '200', + }, + scripts: [ + { + ppt: { + dataURL: + 'data:image/png;base64,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', + file: dummyFile, + }, + script: '첫번째 내용내용내용내용내용내용', + memo: '첫번째 메모메모메모메모메모', + }, + { + ppt: { + dataURL: + 'data:image/png;base64,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', + file: dummyFile, + }, + script: '두번째 내용내용내용내용내용내용', + memo: '두번째 메모메모메모메모메모', + }, + { + ppt: { + dataURL: + 'data:image/png;base64,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', + file: dummyFile, + }, + script: '세번째 내용내용내용내용내용내용', + memo: '세번째 메모메모메모메모메모', + }, + ], + }, + }, + { + id: 22222, + data: { + title: '발표2', + dDay: { + date: '2024.8.3', + repeat: '', + includeToday: '', + }, + time: { + timer: '200', + alramTime: '200', + }, + scripts: [ + { + ppt: { + dataURL: + 'data:image/png;base64,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', + file: dummyFile, + }, + script: '첫번째 내용내용내용내용내용내용', + memo: '첫번째 메모메모메모메모메모', + }, + { + ppt: { + dataURL: + 'data:image/png;base64,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', + file: dummyFile, + }, + script: '두번째 내용내용내용내용내용내용', + memo: '두번째 메모메모메모메모메모', + }, + { + ppt: { + dataURL: + 'data:image/png;base64,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', + file: dummyFile, + }, + script: '세번째 내용내용내용내용내용내용', + memo: '세번째 메모메모메모메모메모', + }, + ], + }, + }, +]; + +export async function GET(request: NextRequest, { params }: { params: { id: string } }) { + const targetId = params.id; + + try { + return new Promise((resolve) => { + const result = mockPresentData.filter((i) => i.id === Number(targetId))[0]; + setTimeout(() => { + resolve(new NextResponse(JSON.stringify(result), { status: 200 })); + }, 500); + }); + } catch (e) { + return new NextResponse(null, { status: 500 }); + } +} diff --git a/src/app/globals.css b/src/app/globals.css index 215776a..0d33004 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -4,10 +4,11 @@ html, body { - width: 100dvw; - height: 100dvh; margin: 0; - overflow-x: hidden; + + /* overflow-x: hidden; */ + + /* overflow-x: auto; */ } a { diff --git a/src/services/user.ts b/src/services/user.ts index e69de29..a2241d0 100644 --- a/src/services/user.ts +++ b/src/services/user.ts @@ -0,0 +1,16 @@ +export const userApi = { + // mock + getPresentData: async (id: string) => { + const response = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/get/list/${id}`, { + cache: 'no-store', + }); + + if (!response.ok) { + throw new Error('something went to wrong'); + } + + const result = await response.json(); + + return result as T; + }, +}; diff --git a/src/types/service.ts b/src/types/service.ts new file mode 100644 index 0000000..d99c214 --- /dev/null +++ b/src/types/service.ts @@ -0,0 +1,22 @@ +export interface PagesDataType { + title: string | null; + dDay: { + date: any; + repeat: any; + includeToday: any; + }; + time: { + timer: any; + alramTime: any; + }; + scripts: { + ppt: { dataURL: string | null; file: File | null }; + script: string | null; + memo: string | null; + }[]; +} + +export interface PresentInfoType { + id: number | null; + data: PagesDataType; +} From cf7619d87a9d2a1ee61cc724a0b0e21d6a0f2d29 Mon Sep 17 00:00:00 2001 From: Huiju <61102301+Joie-Kim@users.noreply.github.com> Date: Wed, 24 Jan 2024 13:48:36 +0900 Subject: [PATCH 22/65] =?UTF-8?q?checkbox,=20toggle=20button=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add checkbox component * feat: add toggle button - 엘리먼트 prop 타입명 수정 - className 엮는 유틸 함수 --- src/app/(afterlogin)/element-test/page.tsx | 35 ++++++++++ .../login/_components/LoginMenus.tsx | 4 +- .../login/_components/OAuthMenu.tsx | 4 +- src/app/_components/_elements/Button.tsx | 4 +- src/app/_components/_elements/Checkbox.tsx | 12 ++++ src/app/_components/_elements/Input.tsx | 4 +- src/app/_components/_elements/List.tsx | 4 +- .../_elements/ToggleButton.module.scss | 64 +++++++++++++++++++ .../_components/_elements/ToggleButton.tsx | 45 +++++++++++++ src/app/_utils/style.ts | 4 ++ src/types/element.ts | 28 ++++++-- 11 files changed, 194 insertions(+), 14 deletions(-) create mode 100644 src/app/(afterlogin)/element-test/page.tsx create mode 100644 src/app/_components/_elements/Checkbox.tsx create mode 100644 src/app/_components/_elements/ToggleButton.module.scss create mode 100644 src/app/_components/_elements/ToggleButton.tsx create mode 100644 src/app/_utils/style.ts diff --git a/src/app/(afterlogin)/element-test/page.tsx b/src/app/(afterlogin)/element-test/page.tsx new file mode 100644 index 0000000..f9ec22b --- /dev/null +++ b/src/app/(afterlogin)/element-test/page.tsx @@ -0,0 +1,35 @@ +'use client'; + +import Checkbox from '@/app/_components/_elements/Checkbox'; +import ToggleButton from '@/app/_components/_elements/ToggleButton'; +import { useState } from 'react'; + +export default function Page() { + const [isAvailable, setIsAvailable] = useState(false); + const [isUsedAlarm, setIsUsedAlarm] = useState(false); + + const handleOnChange = () => { + setIsAvailable(!isAvailable); + }; + + const handleOnChangeAlarm = () => { + setIsUsedAlarm(!isUsedAlarm); + }; + + return ( +
    + + + +
    + ); +} diff --git a/src/app/(beforelogin)/login/_components/LoginMenus.tsx b/src/app/(beforelogin)/login/_components/LoginMenus.tsx index 8b846c4..5988719 100644 --- a/src/app/(beforelogin)/login/_components/LoginMenus.tsx +++ b/src/app/(beforelogin)/login/_components/LoginMenus.tsx @@ -5,10 +5,10 @@ import Button from '@/app/_components/_elements/Button'; import styles from './LoginMenus.module.scss'; -import { ListInfoType } from '@/types/element'; +import { ListProp } from '@/types/element'; const LoginMenus = () => { - const listArr: ListInfoType = [ + const listArr: ListProp = [ { _content: ( diff --git a/src/app/(beforelogin)/login/_components/OAuthMenu.tsx b/src/app/(beforelogin)/login/_components/OAuthMenu.tsx index e7942ba..2fcae97 100644 --- a/src/app/(beforelogin)/login/_components/OAuthMenu.tsx +++ b/src/app/(beforelogin)/login/_components/OAuthMenu.tsx @@ -2,7 +2,7 @@ import styles from './OAuthMenu.module.scss'; -import { ListInfoType } from '@/types/element'; +import { ListProp } from '@/types/element'; import List from '@/app/_components/_elements/List'; import Button from '@/app/_components/_elements/Button'; @@ -13,7 +13,7 @@ const OAuthMenu = () => { ); - const listArr: ListInfoType = [ + const listArr: ListProp = [ { _content: ( diff --git a/src/app/_components/_elements/Button.tsx b/src/app/_components/_elements/Button.tsx index d5d1b2c..b0091c1 100644 --- a/src/app/_components/_elements/Button.tsx +++ b/src/app/_components/_elements/Button.tsx @@ -1,6 +1,6 @@ -import { ButtonInfoType } from '@/types/element'; +import { ButtonProp } from '@/types/element'; -const Button = ({ _className, _content, ...rest }: ButtonInfoType) => { +const Button = ({ _className, _content, ...rest }: ButtonProp) => { return (
    - ) : ( -
    - ppt image -
    - )} + { + // pptInfo.file === null || + pptInfo.dataURL === null ? ( +
    +
    LOGO
    +
    + ) : ( +
    + ppt image +
    + ) + } ); diff --git a/src/app/api/get/list/[id]/route.ts b/src/app/api/get/list/[id]/route.ts index da86d35..5761fe9 100644 --- a/src/app/api/get/list/[id]/route.ts +++ b/src/app/api/get/list/[id]/route.ts @@ -3,10 +3,10 @@ import { PresentInfoType } from '@/types/service'; import { NextRequest, NextResponse } from 'next/server'; -const dummyFile = new File(['dummy content'], 'hello.png', { - type: 'image/png', - lastModified: new Date('2023-11-29T10:58:23Z').getTime(), -}); +// const dummyFile = new File(['dummy content'], 'hello.png', { +// type: 'image/png', +// lastModified: new Date('2023-11-29T10:58:23Z').getTime(), +// }); const mockPresentData: PresentInfoType[] = [ { @@ -27,7 +27,7 @@ const mockPresentData: PresentInfoType[] = [ ppt: { dataURL: 'data:image/png;base64,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', - file: dummyFile, + file: null, }, script: '첫번째 내용내용내용내용내용내용', memo: '첫번째 메모메모메모메모메모', @@ -36,7 +36,7 @@ const mockPresentData: PresentInfoType[] = [ ppt: { dataURL: 'data:image/png;base64,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', - file: dummyFile, + file: null, }, script: '두번째 내용내용내용내용내용내용', memo: '두번째 메모메모메모메모메모', @@ -45,7 +45,7 @@ const mockPresentData: PresentInfoType[] = [ ppt: { dataURL: 'data:image/png;base64,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', - file: dummyFile, + file: null, }, script: '세번째 내용내용내용내용내용내용', memo: '세번째 메모메모메모메모메모', @@ -71,7 +71,7 @@ const mockPresentData: PresentInfoType[] = [ ppt: { dataURL: 'data:image/png;base64,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', - file: dummyFile, + file: null, }, script: '첫번째 내용내용내용내용내용내용', memo: '첫번째 메모메모메모메모메모', @@ -80,7 +80,7 @@ const mockPresentData: PresentInfoType[] = [ ppt: { dataURL: 'data:image/png;base64,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', - file: dummyFile, + file: null, }, script: '두번째 내용내용내용내용내용내용', memo: '두번째 메모메모메모메모메모', @@ -89,7 +89,7 @@ const mockPresentData: PresentInfoType[] = [ ppt: { dataURL: 'data:image/png;base64,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', - file: dummyFile, + file: null, }, script: '세번째 내용내용내용내용내용내용', memo: '세번째 메모메모메모메모메모', From bf42953116a604936ccaf268d21659b2fb0aa497 Mon Sep 17 00:00:00 2001 From: Huiju <61102301+Joie-Kim@users.noreply.github.com> Date: Thu, 25 Jan 2024 18:20:19 +0900 Subject: [PATCH 25/65] =?UTF-8?q?=EC=97=98=EB=A6=AC=EB=A8=BC=ED=8A=B8=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80=20&=20?= =?UTF-8?q?=ED=83=80=EC=9E=84=ED=94=BC=EC=BB=A4=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80=20(#13)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 컴포넌트 prop 타입명 변경 및 타입 주석 추가 * feat: add time picker --- src/app/(afterlogin)/element-test/page.tsx | 46 +++++++++++++------ .../login/_components/LoginMenus.tsx | 4 +- .../login/_components/OAuthMenu.tsx | 4 +- src/app/_components/_elements/Button.tsx | 4 +- src/app/_components/_elements/Checkbox.tsx | 4 +- src/app/_components/_elements/Input.tsx | 4 +- src/app/_components/_elements/List.tsx | 4 +- src/app/_components/_elements/TimePicker.tsx | 36 +++++++++++++++ .../_components/_elements/ToggleButton.tsx | 4 +- src/types/element.ts | 35 ++++++++++---- 10 files changed, 109 insertions(+), 36 deletions(-) create mode 100644 src/app/_components/_elements/TimePicker.tsx diff --git a/src/app/(afterlogin)/element-test/page.tsx b/src/app/(afterlogin)/element-test/page.tsx index f9ec22b..4cb40b3 100644 --- a/src/app/(afterlogin)/element-test/page.tsx +++ b/src/app/(afterlogin)/element-test/page.tsx @@ -1,12 +1,15 @@ 'use client'; import Checkbox from '@/app/_components/_elements/Checkbox'; +import TimePicker from '@/app/_components/_elements/TimePicker'; import ToggleButton from '@/app/_components/_elements/ToggleButton'; +import { TimePickerProps } from '@/types/element'; import { useState } from 'react'; export default function Page() { const [isAvailable, setIsAvailable] = useState(false); const [isUsedAlarm, setIsUsedAlarm] = useState(false); + const [time, setTime] = useState('0'); const handleOnChange = () => { setIsAvailable(!isAvailable); @@ -16,20 +19,35 @@ export default function Page() { setIsUsedAlarm(!isUsedAlarm); }; + const handleOnChangeTime = (newTime: TimePickerProps['selectedValue']) => { + setTime(newTime); + }; + return ( -
    - - - -
    + <> +
    + + + +
    +
    + + time : {time} +
    + ); } diff --git a/src/app/(beforelogin)/login/_components/LoginMenus.tsx b/src/app/(beforelogin)/login/_components/LoginMenus.tsx index 5988719..1572086 100644 --- a/src/app/(beforelogin)/login/_components/LoginMenus.tsx +++ b/src/app/(beforelogin)/login/_components/LoginMenus.tsx @@ -5,10 +5,10 @@ import Button from '@/app/_components/_elements/Button'; import styles from './LoginMenus.module.scss'; -import { ListProp } from '@/types/element'; +import { ListProps } from '@/types/element'; const LoginMenus = () => { - const listArr: ListProp = [ + const listArr: ListProps = [ { _content: ( diff --git a/src/app/(beforelogin)/login/_components/OAuthMenu.tsx b/src/app/(beforelogin)/login/_components/OAuthMenu.tsx index 2fcae97..8fdc1d5 100644 --- a/src/app/(beforelogin)/login/_components/OAuthMenu.tsx +++ b/src/app/(beforelogin)/login/_components/OAuthMenu.tsx @@ -2,7 +2,7 @@ import styles from './OAuthMenu.module.scss'; -import { ListProp } from '@/types/element'; +import { ListProps } from '@/types/element'; import List from '@/app/_components/_elements/List'; import Button from '@/app/_components/_elements/Button'; @@ -13,7 +13,7 @@ const OAuthMenu = () => { ); - const listArr: ListProp = [ + const listArr: ListProps = [ { _content: ( diff --git a/src/app/_components/_elements/Button.tsx b/src/app/_components/_elements/Button.tsx index b0091c1..921641c 100644 --- a/src/app/_components/_elements/Button.tsx +++ b/src/app/_components/_elements/Button.tsx @@ -1,6 +1,6 @@ -import { ButtonProp } from '@/types/element'; +import { ButtonProps } from '@/types/element'; -const Button = ({ _className, _content, ...rest }: ButtonProp) => { +const Button = ({ _className, _content, ...rest }: ButtonProps) => { return ( ), - // style: { backgroundColor: 'blue' }, }, { _content: ( diff --git a/src/app/_components/_elements/Checkbox.tsx b/src/app/_components/_elements/Checkbox.tsx index d6a0cdd..186a3d8 100644 --- a/src/app/_components/_elements/Checkbox.tsx +++ b/src/app/_components/_elements/Checkbox.tsx @@ -1,9 +1,9 @@ import { CheckboxProps } from '@/types/element'; -const Checkbox = ({ _label, _isChecked, _onChange, ...rest }: CheckboxProps) => { +const Checkbox = ({ _label, _isChecked, ...rest }: CheckboxProps) => { return ( ); diff --git a/src/app/_components/_elements/ToggleButton.tsx b/src/app/_components/_elements/ToggleButton.tsx index 6e57b3a..aa03658 100644 --- a/src/app/_components/_elements/ToggleButton.tsx +++ b/src/app/_components/_elements/ToggleButton.tsx @@ -2,13 +2,7 @@ import { ToggleButtonProps } from '@/types/element'; import { combineClassName } from '@/app/_utils/style'; import styles from './ToggleButton.module.scss'; -const ToggleButton = ({ - _label, - _isChecked, - _activedLabel, - _onChange, - ...rest -}: ToggleButtonProps) => { +const ToggleButton = ({ _label, _isChecked, _activedLabel, ...rest }: ToggleButtonProps) => { return ( <> {_activedLabel ? ( @@ -19,7 +13,6 @@ const ToggleButton = ({ role="switch" type="checkbox" checked={_isChecked} - onChange={_onChange} {...rest} /> {_label} @@ -32,7 +25,6 @@ const ToggleButton = ({ role="switch" type="checkbox" checked={_isChecked} - onChange={_onChange} {...rest} /> diff --git a/src/app/_components/_modules/AlertModal.module.scss b/src/app/_components/_modules/AlertModal.module.scss new file mode 100644 index 0000000..6ea6cc1 --- /dev/null +++ b/src/app/_components/_modules/AlertModal.module.scss @@ -0,0 +1,50 @@ +@import '@/app/_components/globals'; + +@keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@keyframes fade-out { + from { + opacity: 1; + } + + to { + opacity: 0; + } +} + +.modalContainer { + position: absolute; + top: 40%; + left: 50%; + width: 250px; + height: 35px; + transform: translate(-50%, -50%); + animation: fade-in 0.5s; +} + +.modalContainer.fadeOut { + animation: fade-out 0.8s; // 0.5보다 조금 더 늘려야 함 +} + +.modalContent { + display: flex; + align-items: center; + justify-content: center; + gap: 20px; + width: 100%; + height: 100%; + background-color: darkgray; + border-radius: 20px; + + .closeButton { + @include pure-button; + } +} diff --git a/src/app/_components/_modules/AlertModal.tsx b/src/app/_components/_modules/AlertModal.tsx new file mode 100644 index 0000000..2ecd023 --- /dev/null +++ b/src/app/_components/_modules/AlertModal.tsx @@ -0,0 +1,46 @@ +'use client'; + +import { useState, useEffect } from 'react'; + +import { useAlertModalStore } from '@/store/modal'; + +import styles from './AlertModal.module.scss'; + +import Button from '../_elements/Button'; + +import classNames from 'classnames/bind'; + +const AlertModal = () => { + const { isOpen, modalData, closeModal } = useAlertModalStore(); + const { children } = modalData; + const [fadeOut, setFadeOut] = useState(false); + + const cx = classNames.bind(styles); + + useEffect(() => { + if (isOpen) { + setFadeOut(false); + const timer = setTimeout(() => { + setFadeOut(true); + setTimeout(closeModal, 500); // 0.5초 후에 모달창 닫기 + }, 1000); // 1초 후에 fadeOut 시작 + + return () => clearTimeout(timer); + } + }, [isOpen, closeModal]); + + if (!isOpen) { + return <>; + } + + return ( +
    +
    +
    {children}
    +
    +
    + ); +}; + +export default AlertModal; diff --git a/src/app/_components/_modules/ConfirmModal.module.scss b/src/app/_components/_modules/ConfirmModal.module.scss new file mode 100644 index 0000000..fa6e5c2 --- /dev/null +++ b/src/app/_components/_modules/ConfirmModal.module.scss @@ -0,0 +1,21 @@ +.modalContainer { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + inset: 0; + background-color: rgb(0 0 0 / 50%); +} + +.modalContent { + display: flex; + align-items: center; + justify-content: center; + position: relative; + top: 5%; + width: 500px; + height: 700px; + background: #fff; + border-radius: 20px; + flex-direction: column; +} diff --git a/src/app/_components/_modules/ConfirmModal.tsx b/src/app/_components/_modules/ConfirmModal.tsx new file mode 100644 index 0000000..c3792bf --- /dev/null +++ b/src/app/_components/_modules/ConfirmModal.tsx @@ -0,0 +1,42 @@ +'use client'; + +import { useConfirmModalStore } from '@/store/modal'; + +import styles from './ConfirmModal.module.scss'; + +const ConfirmModal = () => { + const { isOpen, modalData, closeModal } = useConfirmModalStore(); + + const { children, onCancel, onSubmit } = modalData; + + if (!isOpen) { + return <>; + } + + const onCancelInternal = () => { + onCancel?.(); + closeModal(); + }; + + const onSubmitInternal = () => { + onSubmit?.(); + closeModal(); + }; + + return ( +
    +
    +
    x
    +
    +
    {children}
    +
    + + +
    +
    +
    +
    + ); +}; + +export default ConfirmModal; diff --git a/src/app/_components/_modules/ImagePreview.tsx b/src/app/_components/_modules/ImagePreview.tsx index 38689f6..2b516b9 100644 --- a/src/app/_components/_modules/ImagePreview.tsx +++ b/src/app/_components/_modules/ImagePreview.tsx @@ -1,7 +1,5 @@ 'use client'; -import { useEffect, useState } from 'react'; - interface Props { selectedFiles: File[]; base64Strings: string[]; diff --git a/src/app/_components/_modules/ImageUploader.tsx b/src/app/_components/_modules/ImageUploader.tsx index 5ce04f2..7a3165c 100644 --- a/src/app/_components/_modules/ImageUploader.tsx +++ b/src/app/_components/_modules/ImageUploader.tsx @@ -1,7 +1,6 @@ 'use client'; -import useImageUploader from '@/app/_hooks/useImageUploader'; -import { ChangeEvent, InputHTMLAttributes, useState } from 'react'; +import { ChangeEvent, InputHTMLAttributes } from 'react'; interface Props extends InputHTMLAttributes { _classname?: string; diff --git a/src/store/modal.ts b/src/store/modal.ts new file mode 100644 index 0000000..343d82f --- /dev/null +++ b/src/store/modal.ts @@ -0,0 +1,56 @@ +import { ReactNode } from 'react'; +import { create } from 'zustand'; + +/** 모달 데이터 타입*/ +type ModalData = { + /** 모달 컨텐츠 */ + children?: ReactNode; + + /** 취소버튼 클릭시 트리거되는 콜백 */ + onCancel?: () => unknown; + + /** submit버튼 클릭시 트리거되는 콜백 */ + onSubmit?: () => unknown; +}; + +/** 모달 스토어 타입 */ +interface ModalStore { + /** 모달 렌더링 유무 플래그 */ + isOpen: boolean; + + /** 모달 데이터를 기반으로 모달을 생성하는 함수 */ + openModal: (modalData: ModalData) => unknown; + /** 모달을 닫는 함수 */ + closeModal: () => unknown; + + /** 모달창에 사용되는 모달 데이터 */ + modalData: ModalData; +} + +// confirm용 모달 스토어 +export const useConfirmModalStore = create((set) => ({ + isOpen: false, + modalData: {} as ModalData, + + openModal: (modalData: ModalData) => { + set((state) => ({ isOpen: true, modalData: { ...modalData } })); + }, + + closeModal: () => { + set((state) => ({ isOpen: false, modalData: {} })); + }, +})); + +// alert용 모달 스토어 +export const useAlertModalStore = create((set) => ({ + isOpen: false, + modalData: {} as ModalData, + + openModal: (modalData: ModalData) => { + set((state) => ({ isOpen: true, modalData: { ...modalData } })); + }, + + closeModal: () => { + set((state) => ({ isOpen: false, modalData: {} })); + }, +})); diff --git a/src/types/element.ts b/src/types/element.ts index 26e2013..0b78ec2 100644 --- a/src/types/element.ts +++ b/src/types/element.ts @@ -8,11 +8,15 @@ export interface ButtonProps extends ButtonHTMLAttributes { _className?: string; } -// TODO: 타입 주석 필요 +/** 단일 리스트(li) 타입 */ interface SingleList extends LiHTMLAttributes { + /** li 내 자식 컴포넌트 */ _content: React.ReactNode; + /** li 태그 스타일 */ _className?: string; } + +/** ul안에 들어갈 li태그 배열 */ export type ListProps = SingleList[]; /** 인풋 컴포넌트 prop */ @@ -27,8 +31,6 @@ export interface CheckboxProps extends InputHTMLAttributes { _label?: string; /** 체크 여부 */ _isChecked: boolean; - /** 체크 여부 변경 핸들러 */ - _onChange: () => void; } /** 토글 버튼 컴포넌트 prop */ From 43e441ea0a7fecc1fcfedf7c1b592dd6ab6a81cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=ED=98=B8?= <78631876+minh0518@users.noreply.github.com> Date: Tue, 30 Jan 2024 16:10:41 +0900 Subject: [PATCH 27/65] =?UTF-8?q?=ED=86=A0=EC=8A=A4=ED=8A=B8=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84=20(#15)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 모달 스토어 주석 수정 및 함수명 변경 * feat: 재사용 토스트 컴포넌트 구현(알람, 저장) * feat: 재사용 모달 컴포넌트 컨테이너 구현 * refactor: 컴포넌트명 수정 ToastProvider.tsx -> Toast.tsx * refactor: 전역 모달 타입 수정 각 버튼(취소,submit)에 사용될 문구도 고정값이 아니라 전달받는 내용을 사용하기 위해 관련 타입을 추가합니다. * feat: 전역 모달(alert, confirm)에 대한 재사용 컴포넌트 구현 * refactor: 토스트 스타일 클래스명 변경 '.modalContent'-> '.toastContent' * refactor: 모달 컴포넌트 타입 변경 각 컴포넌트에서 모달을 호출하면서 취소,submit 버튼의 문구나 이벤트 함수 대신, 버튼 자체를 만든 뒤 통째로 넘길 수 있도록 합니다 * refactor: 폴더 구조 변경 _modal에는 모달의 기능에 관련된 컴포넌트를, 그 외 UI관련 부분은 _modules로 이동합니다. --- src/app/(afterlogin)/layout.tsx | 9 +-- .../_component/ControlButtons.module.scss | 1 - .../[id]/_component/InputSection.module.scss | 4 -- .../upload/[id]/_component/InputSection.tsx | 12 ++-- src/app/(beforelogin)/layout.module.scss | 1 - .../_modules/AlarmToast.module.scss | 19 +++++++ src/app/_components/_modules/AlarmToast.tsx | 12 ++++ .../_modules/AlertModal.module.scss | 57 ++++++------------- src/app/_components/_modules/AlertModal.tsx | 42 ++++---------- .../_modules/ConfirmModal.module.scss | 34 ++++++----- src/app/_components/_modules/ConfirmModal.tsx | 38 ++++--------- .../_modules/SaveToast.module.scss | 19 +++++++ src/app/_components/_modules/SaveToast.tsx | 12 ++++ .../_modules/_modal/Modal.module.scss | 8 +++ src/app/_components/_modules/_modal/Modal.tsx | 25 ++++++++ .../_modules/_modal/Toast.module.scss | 33 +++++++++++ src/app/_components/_modules/_modal/Toast.tsx | 38 +++++++++++++ src/store/modal.ts | 33 +++++------ 18 files changed, 253 insertions(+), 144 deletions(-) create mode 100644 src/app/_components/_modules/AlarmToast.module.scss create mode 100644 src/app/_components/_modules/AlarmToast.tsx create mode 100644 src/app/_components/_modules/SaveToast.module.scss create mode 100644 src/app/_components/_modules/SaveToast.tsx create mode 100644 src/app/_components/_modules/_modal/Modal.module.scss create mode 100644 src/app/_components/_modules/_modal/Modal.tsx create mode 100644 src/app/_components/_modules/_modal/Toast.module.scss create mode 100644 src/app/_components/_modules/_modal/Toast.tsx diff --git a/src/app/(afterlogin)/layout.tsx b/src/app/(afterlogin)/layout.tsx index 79e5aa6..3edb55e 100644 --- a/src/app/(afterlogin)/layout.tsx +++ b/src/app/(afterlogin)/layout.tsx @@ -2,8 +2,9 @@ import { Metadata } from 'next'; import RQProvider from './_components/RQProvider'; import { ReactChildrenProps } from '@/types/common'; -import AlertModal from '../_components/_modules/AlertModal'; -import ConfirmModal from '../_components/_modules/ConfirmModal'; + +import Modal from '../_components/_modules/_modal/Modal'; +import Toast from '../_components/_modules/_modal/Toast'; export const metadata: Metadata = { title: '홈', @@ -15,8 +16,8 @@ export default function AfterLoginLayout({ children }: ReactChildrenProps) {
    {children}
    - - + +
    ); diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/ControlButtons.module.scss b/src/app/(afterlogin)/presentation/upload/[id]/_component/ControlButtons.module.scss index 16b5ae9..57fba8f 100644 --- a/src/app/(afterlogin)/presentation/upload/[id]/_component/ControlButtons.module.scss +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/ControlButtons.module.scss @@ -29,7 +29,6 @@ position: absolute; top: 3px; right: 5px; - z-index: 10; width: 15px; height: 15px; font-weight: bold; diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.module.scss b/src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.module.scss index 31d54d3..eb42f44 100644 --- a/src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.module.scss +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.module.scss @@ -60,7 +60,3 @@ background-color: #d9d9d9; } } - -.modalContent { - margin: 0; -} diff --git a/src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.tsx b/src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.tsx index bb5fc4c..453a839 100644 --- a/src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.tsx +++ b/src/app/(afterlogin)/presentation/upload/[id]/_component/InputSection.tsx @@ -10,7 +10,8 @@ import UploadTimer from './UploadTimer'; import Button from '@/app/_components/_elements/Button'; import UploadPpt from './UploadPpt'; import ControlButtons from './ControlButtons'; -import { useAlertModalStore } from '@/store/modal'; +import { useToastStore } from '@/store/modal'; +import SaveToast from '@/app/_components/_modules/SaveToast'; interface InputSectionProps { presentationData: PagesDataType; @@ -28,14 +29,11 @@ const InputSection = ({ initialState, slug, }: InputSectionProps) => { - const { openModal } = useAlertModalStore(); + const { openModal } = useToastStore(); const openModalWithData = (data: ReactNode) => - // ModalData 생성 openModal({ - children: data, - onSubmit: () => console.log('submit'), - onCancel: () => console.log('cancel'), + content: data, }); return ( @@ -80,7 +78,7 @@ const InputSection = ({ + {onSubmitButton} ); }; diff --git a/src/app/_components/_modules/ConfirmModal.module.scss b/src/app/_components/_modules/ConfirmModal.module.scss index fa6e5c2..ae3b229 100644 --- a/src/app/_components/_modules/ConfirmModal.module.scss +++ b/src/app/_components/_modules/ConfirmModal.module.scss @@ -1,21 +1,29 @@ -.modalContainer { - display: flex; - align-items: center; - justify-content: center; - position: absolute; - inset: 0; - background-color: rgb(0 0 0 / 50%); -} +@import '@/app/_components/globals'; .modalContent { display: flex; align-items: center; justify-content: center; position: relative; - top: 5%; - width: 500px; - height: 700px; - background: #fff; - border-radius: 20px; + min-width: 300px; + min-height: 200px; + background-color: white; flex-direction: column; + border-radius: 25px; + padding: 30px; +} + +.closeButton { + @include pure-button; + + position: absolute; + top: 15px; + right: 15px; + font-size: 1.1rem; +} + +.actionButtons { + display: flex; + justify-content: space-around; + width: 70%; } diff --git a/src/app/_components/_modules/ConfirmModal.tsx b/src/app/_components/_modules/ConfirmModal.tsx index c3792bf..5670cc7 100644 --- a/src/app/_components/_modules/ConfirmModal.tsx +++ b/src/app/_components/_modules/ConfirmModal.tsx @@ -1,39 +1,23 @@ 'use client'; -import { useConfirmModalStore } from '@/store/modal'; +import { useModalStore } from '@/store/modal'; import styles from './ConfirmModal.module.scss'; const ConfirmModal = () => { - const { isOpen, modalData, closeModal } = useConfirmModalStore(); + const { modalData, closeModal } = useModalStore(); - const { children, onCancel, onSubmit } = modalData; - - if (!isOpen) { - return <>; - } - - const onCancelInternal = () => { - onCancel?.(); - closeModal(); - }; - - const onSubmitInternal = () => { - onSubmit?.(); - closeModal(); - }; + const { content, onCancelButton, onSubmitButton } = modalData; return ( -
    -
    -
    x
    -
    -
    {children}
    -
    - - -
    -
    +
    +
    {content}
    + +
    + {onSubmitButton} + {onCancelButton}
    ); diff --git a/src/app/_components/_modules/SaveToast.module.scss b/src/app/_components/_modules/SaveToast.module.scss new file mode 100644 index 0000000..994e3bd --- /dev/null +++ b/src/app/_components/_modules/SaveToast.module.scss @@ -0,0 +1,19 @@ +.toastContent { + display: flex; + align-items: center; + justify-content: center; + position: fixed; + top: 10%; + left: 50%; + width: 250px; + height: 35px; + transform: translate(-50%, -50%); + gap: 20px; + background-color: #373737; + border-radius: 20px; + + p { + margin: 0; + color: white; + } +} diff --git a/src/app/_components/_modules/SaveToast.tsx b/src/app/_components/_modules/SaveToast.tsx new file mode 100644 index 0000000..cdf0a96 --- /dev/null +++ b/src/app/_components/_modules/SaveToast.tsx @@ -0,0 +1,12 @@ +'use client'; +import styles from './SaveToast.module.scss'; + +const SaveToast = () => { + return ( +
    +

    저장이 완료되었습니다

    +
    + ); +}; + +export default SaveToast; diff --git a/src/app/_components/_modules/_modal/Modal.module.scss b/src/app/_components/_modules/_modal/Modal.module.scss new file mode 100644 index 0000000..e2fded6 --- /dev/null +++ b/src/app/_components/_modules/_modal/Modal.module.scss @@ -0,0 +1,8 @@ +.modalContainer { + display: flex; + align-items: center; + justify-content: center; + position: fixed; + inset: 0; + background-color: rgb(0 0 0 / 50%); +} diff --git a/src/app/_components/_modules/_modal/Modal.tsx b/src/app/_components/_modules/_modal/Modal.tsx new file mode 100644 index 0000000..e7c9661 --- /dev/null +++ b/src/app/_components/_modules/_modal/Modal.tsx @@ -0,0 +1,25 @@ +'use client'; + +import { useModalStore } from '@/store/modal'; + +import styles from './Modal.module.scss'; +import AlertModal from '../AlertModal'; +import ConfirmModal from '../ConfirmModal'; + +const Modal = () => { + const { isOpen, modalData } = useModalStore(); + + const { onCancelButton } = modalData; + + if (!isOpen) { + return <>; + } + + return ( +
    + {onCancelButton ? : } +
    + ); +}; + +export default Modal; diff --git a/src/app/_components/_modules/_modal/Toast.module.scss b/src/app/_components/_modules/_modal/Toast.module.scss new file mode 100644 index 0000000..e4ef40a --- /dev/null +++ b/src/app/_components/_modules/_modal/Toast.module.scss @@ -0,0 +1,33 @@ +@import '@/app/_components/globals'; + +@keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@keyframes fade-out { + from { + opacity: 1; + } + + to { + opacity: 0; + } +} + +.toastContainer { + // position: fixed; + // top: 15%; + // left: 50%; + // transform: translate(-50%, -50%); + animation: fade-in 0.5s; + + &.fadeOut { + animation: fade-out 0.8s; + } +} diff --git a/src/app/_components/_modules/_modal/Toast.tsx b/src/app/_components/_modules/_modal/Toast.tsx new file mode 100644 index 0000000..4d2e287 --- /dev/null +++ b/src/app/_components/_modules/_modal/Toast.tsx @@ -0,0 +1,38 @@ +'use client'; + +import { useState, useLayoutEffect } from 'react'; + +import styles from './Toast.module.scss'; + +import classNames from 'classnames/bind'; +import { useToastStore } from '@/store/modal'; + +const Toast = () => { + const { isOpen, modalData, closeModal } = useToastStore(); + + const { content } = modalData; + + const [fadeOut, setFadeOut] = useState(false); + + const cx = classNames.bind(styles); + + useLayoutEffect(() => { + if (isOpen) { + setFadeOut(false); + const timer = setTimeout(() => { + setFadeOut(true); + setTimeout(closeModal, 500); + }, 1000); + + return () => clearTimeout(timer); + } + }, [isOpen, closeModal]); + + if (!isOpen) { + return <>; + } + + return
    {content}
    ; +}; + +export default Toast; diff --git a/src/store/modal.ts b/src/store/modal.ts index 343d82f..b5f9413 100644 --- a/src/store/modal.ts +++ b/src/store/modal.ts @@ -1,34 +1,35 @@ import { ReactNode } from 'react'; import { create } from 'zustand'; -/** 모달 데이터 타입*/ -type ModalData = { - /** 모달 컨텐츠 */ - children?: ReactNode; +/** 모달창에 사용되는 데이터 타입*/ +export type ModalData = { + /** 모달창 내부에 사용되는 컨텐츠 */ + content?: ReactNode; - /** 취소버튼 클릭시 트리거되는 콜백 */ - onCancel?: () => unknown; + /** 취소버튼 관련 데이터(이벤트 콜백, 버튼 컨텐츠)*/ + onCancelButton?: ReactNode; - /** submit버튼 클릭시 트리거되는 콜백 */ - onSubmit?: () => unknown; + /** submit버튼 관련 데이터(이벤트 콜백, 버튼 컨텐츠)*/ + onSubmitButton?: ReactNode; }; /** 모달 스토어 타입 */ interface ModalStore { - /** 모달 렌더링 유무 플래그 */ + /** 현재 모달 렌더링 유무 플래그 */ isOpen: boolean; - /** 모달 데이터를 기반으로 모달을 생성하는 함수 */ + /** 인자로 받은 모달 데이터를 기반으로 모달을 생성하는 함수 */ openModal: (modalData: ModalData) => unknown; - /** 모달을 닫는 함수 */ + + /** 모달을 닫는 함수(DOM에서 제거) */ closeModal: () => unknown; - /** 모달창에 사용되는 모달 데이터 */ + /** 모달창에 사용되는 데이터 */ modalData: ModalData; } -// confirm용 모달 스토어 -export const useConfirmModalStore = create((set) => ({ +/** confirm과 alert에 사용되는 스토어 */ +export const useModalStore = create((set) => ({ isOpen: false, modalData: {} as ModalData, @@ -41,8 +42,8 @@ export const useConfirmModalStore = create((set) => ({ }, })); -// alert용 모달 스토어 -export const useAlertModalStore = create((set) => ({ +/** toast에 사용되는 스토어 */ +export const useToastStore = create((set) => ({ isOpen: false, modalData: {} as ModalData, From 9fd9fbbf92492b5895e34df0fd7361d6f4f7a15c Mon Sep 17 00:00:00 2001 From: Joie-Kim Date: Tue, 30 Jan 2024 23:01:27 +0900 Subject: [PATCH 28/65] =?UTF-8?q?fix:=20getTimeList=20=ED=95=A8=EC=88=98?= =?UTF-8?q?=20utils=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/_components/_elements/TimePicker.tsx | 9 ++------- src/app/_utils/elements.ts | 13 +++++++++++++ 2 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 src/app/_utils/elements.ts diff --git a/src/app/_components/_elements/TimePicker.tsx b/src/app/_components/_elements/TimePicker.tsx index 7b4f797..5cad844 100644 --- a/src/app/_components/_elements/TimePicker.tsx +++ b/src/app/_components/_elements/TimePicker.tsx @@ -1,5 +1,6 @@ -import { TimePickerProps } from '@/types/element'; import { ChangeEvent } from 'react'; +import { TimePickerProps } from '@/types/element'; +import { getTimeList } from '@/app/_utils/elements'; const TimePicker = ({ type, min, max, gap, selectedValue, onChange }: TimePickerProps) => { const isHour = type === 'hour'; @@ -27,10 +28,4 @@ const TimePicker = ({ type, min, max, gap, selectedValue, onChange }: TimePicker ); }; -const getTimeList = (min: number, max: number, gap: number) => { - if (max - min < gap) return []; - - return Array.from({ length: (max - min) / gap + 1 }, (_, i) => (min + i * gap).toString()); -}; - export default TimePicker; diff --git a/src/app/_utils/elements.ts b/src/app/_utils/elements.ts new file mode 100644 index 0000000..acb8cf5 --- /dev/null +++ b/src/app/_utils/elements.ts @@ -0,0 +1,13 @@ +/** 시간 목록 반환 함수 + * + * TimePicker.tsx에서 사용 + * + * @param min 최솟값 + * @param max 최댓값 + * @param gap 시간 간격 + */ +export const getTimeList = (min: number, max: number, gap: number) => { + if (max - min < gap) return []; + + return Array.from({ length: (max - min) / gap + 1 }, (_, i) => (min + i * gap).toString()); +}; From f773b0f8305a8b9d3024a39ce59d78d695de1165 Mon Sep 17 00:00:00 2001 From: Joie-Kim Date: Tue, 30 Jan 2024 23:24:39 +0900 Subject: [PATCH 29/65] =?UTF-8?q?fix:=20Checkbox,=20ToggleButton=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit checked 속성을 기본 html에서 제공하기 때문에 _isChecked 속성을 제거 --- src/app/(afterlogin)/element-test/page.tsx | 8 ++++---- src/app/_components/_elements/Checkbox.tsx | 4 ++-- src/app/_components/_elements/ToggleButton.tsx | 18 +++--------------- src/types/element.ts | 2 -- 4 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/app/(afterlogin)/element-test/page.tsx b/src/app/(afterlogin)/element-test/page.tsx index fb6f7a2..97440a5 100644 --- a/src/app/(afterlogin)/element-test/page.tsx +++ b/src/app/(afterlogin)/element-test/page.tsx @@ -26,16 +26,16 @@ export default function Page() { return ( <>
    - +
    diff --git a/src/app/_components/_elements/Checkbox.tsx b/src/app/_components/_elements/Checkbox.tsx index 186a3d8..49d2b53 100644 --- a/src/app/_components/_elements/Checkbox.tsx +++ b/src/app/_components/_elements/Checkbox.tsx @@ -1,9 +1,9 @@ import { CheckboxProps } from '@/types/element'; -const Checkbox = ({ _label, _isChecked, ...rest }: CheckboxProps) => { +const Checkbox = ({ _label, ...rest }: CheckboxProps) => { return ( ); diff --git a/src/app/_components/_elements/ToggleButton.tsx b/src/app/_components/_elements/ToggleButton.tsx index aa03658..06d525c 100644 --- a/src/app/_components/_elements/ToggleButton.tsx +++ b/src/app/_components/_elements/ToggleButton.tsx @@ -2,31 +2,19 @@ import { ToggleButtonProps } from '@/types/element'; import { combineClassName } from '@/app/_utils/style'; import styles from './ToggleButton.module.scss'; -const ToggleButton = ({ _label, _isChecked, _activedLabel, ...rest }: ToggleButtonProps) => { +const ToggleButton = ({ _label, _activedLabel, ...rest }: ToggleButtonProps) => { return ( <> {_activedLabel ? ( <> ) : (
    - +
    )} diff --git a/src/types/element.ts b/src/types/element.ts index 0b78ec2..9d18442 100644 --- a/src/types/element.ts +++ b/src/types/element.ts @@ -29,8 +29,6 @@ export interface InputProps extends InputHTMLAttributes { export interface CheckboxProps extends InputHTMLAttributes { /** 레이블 */ _label?: string; - /** 체크 여부 */ - _isChecked: boolean; } /** 토글 버튼 컴포넌트 prop */ From 7b00aa8dacc9d76059b34ca2b0ccf7632c30eb21 Mon Sep 17 00:00:00 2001 From: Joie-Kim Date: Wed, 31 Jan 2024 00:35:43 +0900 Subject: [PATCH 30/65] feat: add Radio component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - lodash-es 설치 - Radio 컴포넌트 구현 - element 타입 주석 수정 --- package-lock.json | 265 +++++++++++---------- package.json | 4 +- src/app/(afterlogin)/element-test/page.tsx | 37 ++- src/app/_components/_elements/Radio.tsx | 32 +++ src/types/element.ts | 25 +- 5 files changed, 237 insertions(+), 126 deletions(-) create mode 100644 src/app/_components/_elements/Radio.tsx diff --git a/package-lock.json b/package-lock.json index 31764eb..442eae2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,8 @@ "dependencies": { "@tanstack/react-query": "^5.17.1", "@tanstack/react-query-devtools": "^5.17.1", - "@types/react-beautiful-dnd": "^13.1.8", "classnames": "^2.5.1", + "lodash-es": "^4.17.21", "next": "14.0.4", "next-auth": "^5.0.0-beta.4", "react": "^18", @@ -23,8 +23,10 @@ "zustand": "^4.4.7" }, "devDependencies": { + "@types/lodash-es": "^4.17.12", "@types/node": "^20", "@types/react": "^18", + "@types/react-beautiful-dnd": "^13.1.8", "@types/react-dom": "^18", "@typescript-eslint/eslint-plugin": "^6.15.0", "@typescript-eslint/parser": "^6.15.0", @@ -511,6 +513,126 @@ "glob": "7.1.7" } }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz", + "integrity": "sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.4.tgz", + "integrity": "sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz", + "integrity": "sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz", + "integrity": "sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz", + "integrity": "sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz", + "integrity": "sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz", + "integrity": "sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.0.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz", + "integrity": "sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@next/swc-win32-x64-msvc": { "version": "14.0.4", "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.4.tgz", @@ -683,6 +805,21 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.14.202", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", + "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", + "dev": true + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/node": { "version": "20.10.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", @@ -711,6 +848,7 @@ "version": "13.1.8", "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.8.tgz", "integrity": "sha512-E3TyFsro9pQuK4r8S/OL6G99eq7p8v29sX0PM7oT8Z+PJfZvSQTx4zTQbUJ+QZXioAF0e7TGBEcA1XhYhCweyQ==", + "dev": true, "dependencies": { "@types/react": "*" } @@ -3931,6 +4069,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -6709,126 +6852,6 @@ "optional": true } } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.4.tgz", - "integrity": "sha512-mF05E/5uPthWzyYDyptcwHptucf/jj09i2SXBPwNzbgBNc+XnwzrL0U6BmPjQeOL+FiB+iG1gwBeq7mlDjSRPg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.4.tgz", - "integrity": "sha512-IZQ3C7Bx0k2rYtrZZxKKiusMTM9WWcK5ajyhOZkYYTCc8xytmwSzR1skU7qLgVT/EY9xtXDG0WhY6fyujnI3rw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.4.tgz", - "integrity": "sha512-VwwZKrBQo/MGb1VOrxJ6LrKvbpo7UbROuyMRvQKTFKhNaXjUmKTu7wxVkIuCARAfiI8JpaWAnKR+D6tzpCcM4w==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.4.tgz", - "integrity": "sha512-8QftwPEW37XxXoAwsn+nXlodKWHfpMaSvt81W43Wh8dv0gkheD+30ezWMcFGHLI71KiWmHK5PSQbTQGUiidvLQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.4.tgz", - "integrity": "sha512-/s/Pme3VKfZAfISlYVq2hzFS8AcAIOTnoKupc/j4WlvF6GQ0VouS2Q2KEgPuO1eMBwakWPB1aYFIA4VNVh667A==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.4.tgz", - "integrity": "sha512-m8z/6Fyal4L9Bnlxde5g2Mfa1Z7dasMQyhEhskDATpqr+Y0mjOBZcXQ7G5U+vgL22cI4T7MfvgtrM2jdopqWaw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.4.tgz", - "integrity": "sha512-7Wv4PRiWIAWbm5XrGz3D8HUkCVDMMz9igffZG4NB1p4u1KoItwx9qjATHz88kwCEal/HXmbShucaslXCQXUM5w==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.0.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.4.tgz", - "integrity": "sha512-zLeNEAPULsl0phfGb4kdzF/cAVIfaC7hY+kt0/d+y9mzcZHsMS3hAS829WbJ31DkSlVKQeHEjZHIdhN+Pg7Gyg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } } } } diff --git a/package.json b/package.json index 73d6c62..0c645de 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,8 @@ "dependencies": { "@tanstack/react-query": "^5.17.1", "@tanstack/react-query-devtools": "^5.17.1", - "@types/react-beautiful-dnd": "^13.1.8", "classnames": "^2.5.1", + "lodash-es": "^4.17.21", "next": "14.0.4", "next-auth": "^5.0.0-beta.4", "react": "^18", @@ -26,8 +26,10 @@ "zustand": "^4.4.7" }, "devDependencies": { + "@types/lodash-es": "^4.17.12", "@types/node": "^20", "@types/react": "^18", + "@types/react-beautiful-dnd": "^13.1.8", "@types/react-dom": "^18", "@typescript-eslint/eslint-plugin": "^6.15.0", "@typescript-eslint/parser": "^6.15.0", diff --git a/src/app/(afterlogin)/element-test/page.tsx b/src/app/(afterlogin)/element-test/page.tsx index 97440a5..58d1a5e 100644 --- a/src/app/(afterlogin)/element-test/page.tsx +++ b/src/app/(afterlogin)/element-test/page.tsx @@ -1,15 +1,17 @@ 'use client'; +import { useState } from 'react'; +import { TimePickerProps } from '@/types/element'; import Checkbox from '@/app/_components/_elements/Checkbox'; +import Radio from '@/app/_components/_elements/Radio'; import TimePicker from '@/app/_components/_elements/TimePicker'; import ToggleButton from '@/app/_components/_elements/ToggleButton'; -import { TimePickerProps } from '@/types/element'; -import { useState } from 'react'; export default function Page() { const [isAvailable, setIsAvailable] = useState(false); const [isUsedAlarm, setIsUsedAlarm] = useState(false); const [time, setTime] = useState('0'); + const [radioValue, setRadioValue] = useState(1); const handleOnChange = () => { setIsAvailable(!isAvailable); @@ -23,6 +25,10 @@ export default function Page() { setTime(newTime); }; + const handleOnChangeRadio = (newValue: any) => { + setRadioValue(newValue); + }; + return ( <>
    @@ -48,6 +54,33 @@ export default function Page() { > time : {time}
    +
    + + + + selected : {radioValue} +
    ); } diff --git a/src/app/_components/_elements/Radio.tsx b/src/app/_components/_elements/Radio.tsx new file mode 100644 index 0000000..bfa71ff --- /dev/null +++ b/src/app/_components/_elements/Radio.tsx @@ -0,0 +1,32 @@ +import { ChangeEvent, useEffect, useState } from 'react'; +import { RadioProps } from '@/types/element'; +import _isEqual from 'lodash-es/isEqual'; + +const Radio = ({ _label, _selectedValue, _onChangeSelected, ...rest }: RadioProps) => { + const [id, setId] = useState('radio'); + const [isChecked, setIsChecked] = useState(false); + + useEffect(() => { + if (rest.id) setId(rest.id); + }, [rest.id]); + + useEffect(() => { + const checked = _isEqual(rest.value, _selectedValue) || true === rest.checked; + setIsChecked(checked); + }, [rest.value, rest.checked, _selectedValue]); + + const handleOnChange = (e: ChangeEvent) => { + if (!rest.value) return; + + _onChangeSelected(rest.value); + }; + + return ( + + ); +}; + +export default Radio; diff --git a/src/types/element.ts b/src/types/element.ts index 9d18442..fbfdfd8 100644 --- a/src/types/element.ts +++ b/src/types/element.ts @@ -1,23 +1,31 @@ import { ButtonHTMLAttributes, InputHTMLAttributes, LiHTMLAttributes, ReactNode } from 'react'; +// #region Button /** 버튼 컴포넌트 prop */ export interface ButtonProps extends ButtonHTMLAttributes { /** 버튼 내 자식 컴포넌트 */ - _content: React.ReactNode; + _content: ReactNode; /** 버튼 스타일 */ _className?: string; } +// #endregion +// #region List /** 단일 리스트(li) 타입 */ interface SingleList extends LiHTMLAttributes { /** li 내 자식 컴포넌트 */ - _content: React.ReactNode; + _content: ReactNode; /** li 태그 스타일 */ _className?: string; } /** ul안에 들어갈 li태그 배열 */ export type ListProps = SingleList[]; +// #endregion + +// #region Input +/** input 태그 value 속성 타입 */ +type InputValue = InputHTMLAttributes['value']; /** 인풋 컴포넌트 prop */ export interface InputProps extends InputHTMLAttributes { @@ -41,6 +49,18 @@ export interface ToggleButtonProps extends CheckboxProps { _activedLabel?: boolean; } +/** 라디오 컴포넌트 prop */ +export interface RadioProps extends InputHTMLAttributes { + /** 레이블 */ + _label?: string; + /** 선택된 값 */ + _selectedValue: InputValue; + /** 선택된 값 변경 핸들러 */ + _onChangeSelected: (value: InputValue) => void; +} +// #endregion + +// #region Custom /** 타임피커 컴포넌트 prop */ export interface TimePickerProps { /** 시간 타입 */ @@ -56,3 +76,4 @@ export interface TimePickerProps { /** 선택 값 변경 핸들러 */ onChange: (value: TimePickerProps['selectedValue']) => void; } +// #endregion From bbaa08ef9f9ce4bb0fab448cdf2b05bdea3e095c Mon Sep 17 00:00:00 2001 From: Joie-Kim Date: Wed, 31 Jan 2024 00:39:25 +0900 Subject: [PATCH 31/65] =?UTF-8?q?chore:=20=5Futils=20>=20element.ts?= =?UTF-8?q?=EB=A1=9C=20=ED=8C=8C=EC=9D=BC=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/_components/_elements/TimePicker.tsx | 2 +- src/app/_utils/{elements.ts => element.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/app/_utils/{elements.ts => element.ts} (100%) diff --git a/src/app/_components/_elements/TimePicker.tsx b/src/app/_components/_elements/TimePicker.tsx index 5cad844..2059338 100644 --- a/src/app/_components/_elements/TimePicker.tsx +++ b/src/app/_components/_elements/TimePicker.tsx @@ -1,6 +1,6 @@ import { ChangeEvent } from 'react'; import { TimePickerProps } from '@/types/element'; -import { getTimeList } from '@/app/_utils/elements'; +import { getTimeList } from '@/app/_utils/element'; const TimePicker = ({ type, min, max, gap, selectedValue, onChange }: TimePickerProps) => { const isHour = type === 'hour'; diff --git a/src/app/_utils/elements.ts b/src/app/_utils/element.ts similarity index 100% rename from src/app/_utils/elements.ts rename to src/app/_utils/element.ts From f40657ecd8346f10e077d2255294b745ac045130 Mon Sep 17 00:00:00 2001 From: Joie-Kim Date: Wed, 31 Jan 2024 22:55:41 +0900 Subject: [PATCH 32/65] fix: remove id --- src/app/_components/_elements/Checkbox.tsx | 4 ++-- src/app/_components/_elements/Radio.tsx | 9 ++------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/app/_components/_elements/Checkbox.tsx b/src/app/_components/_elements/Checkbox.tsx index 49d2b53..ab41d77 100644 --- a/src/app/_components/_elements/Checkbox.tsx +++ b/src/app/_components/_elements/Checkbox.tsx @@ -2,8 +2,8 @@ import { CheckboxProps } from '@/types/element'; const Checkbox = ({ _label, ...rest }: CheckboxProps) => { return ( -