diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 0000000..c4c61b3 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,123 @@ +language: 'ko-KR' +early_access: true + +tone_instructions: | + 1. 피드백은 명확하고 구체적으로 작성하고, 문제 원인과 개선 방법을 함께 제시하세요. + 2. 리뷰는 교육적인 방향을 지향하며, 관련 공식 문서 링크를 함께 추천하세요. + 3. 비판보다는 개선 제안을 우선하세요. + 4. 칭찬은 짧고 위트 있게 작성하세요. + +reviews: + profile: educational + request_changes_workflow: true + high_level_summary: true + high_level_summary_placeholder: | + @coderabbitai summary + (졸업작품 평가 기준: 구조 / 타입 안정성 / 접근성 관점 요약) + poem: false + review_status: true + suggested_labels: true + commit_status: true + fail_commit_status: false + abort_on_close: true + high_level_summary_in_walkthrough: true + high_level_summary_placeholder: '@coderabbitai summary' + collapse_walkthrough: true + + path_instructions: + - path: 'src/**/components/**/*.tsx' + instructions: | + React 컴포넌트 리뷰 시: + - 파일명은 PascalCase인지 확인 + - Props 타입은 컴포넌트명Props 형식인지 확인 + - 단일 export는 default export 권장 (팀 규칙 우선) + - 이벤트 핸들러는 handle 접두사 사용 + - 접근성 고려 (label 연결, aria-* 속성) + - 접근성 관련 지적 시, 사용자 영향 예시 포함 + - 불필요한 re-render 방지를 위한 memo/useCallback 검토 + - premature optimization 지양 + + - path: 'src/**/hooks/**/*.ts' + instructions: | + 커스텀 훅 리뷰 시: + - 파일명과 함수명은 use* 접두사 사용 + - 반환 타입의 일관성 유지 (object 또는 tuple) + - 에러/로딩 상태 명확히 분리 + - TanStack Query 훅 네이밍 규칙 준수 + (use + Action + Target + Query/Mutation) + + - path: 'src/**/*.ts' + instructions: | + TypeScript 코드 리뷰 시: + - 타입/인터페이스는 PascalCase 사용 + - interface는 객체 타입, type은 union/alias에 사용 + - API 응답 타입은 XXXResponse 네이밍 + - var 사용 금지, const 우선 + - type-only import 적극 사용 + - any 사용 시 사유 명확히 작성 + + - path: 'src/**' + instructions: | + 프로젝트 전반 리뷰 기준: + + # 기본 기술 스택 + - React + TypeScript 사용 + - 스타일링은 Tailwind CSS v4 사용 + - 절대 경로 임포트(@/...) 사용 + - Client / Server 컴포넌트 구분 명확 + + # 네이밍 컨벤션 + - 컴포넌트: PascalCase + - 폴더명: kebab-case + - 일반 파일명: kebab-case + - 변수/함수: camelCase + - 상수: BIG_SNAKE_CASE + - Props 타입: 컴포넌트명Props + + # 환경 변수 + - 환경 변수는 process.env.NEXT_PUBLIC_* 사용 + - 민감 정보 하드코딩 금지 + + # 성능 + - 불필요한 클라이언트 컴포넌트 사용 지양 + - 리스트 렌더링 시 key 안정성 확인 + + # Git 규칙 + - 커밋 메시지: #issue type: subject + (예: #12 feat: 로그인 기능 추가) + - 브랜치 패턴: type/issuenumber-issue-short-description + (예: feat/1-auth) + + auto_review: + enabled: true + drafts: false + base_branches: + - 'main' + - 'develop' + labels: + - '!wip' + - '!draft' + ignore_usernames: + - 'dependabot' + - 'renovate' + + tools: + eslint: + enabled: true + markdownlint: + enabled: true + gitleaks: + enabled: true + yamllint: + enabled: true + actionlint: + enabled: true + +chat: + auto_reply: true + +knowledge_base: + code_guidelines: + enabled: true + filePatterns: + - 'README.md' diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 0000000..89e023f --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,34 @@ +echo "📝 커밋 메시지를 검증합니다..." + +# 커밋 메시지 읽기 +commit_msg=$(cat $1) + +# 이슈 번호 뒤에 공백 없이 문자가 오는 경우 체크 (#13test, #13chore 등) +if echo "$commit_msg" | grep -qE '^#[0-9]+[a-zA-Z]'; then + echo "❌ 이슈 번호 뒤에는 공백이 필요합니다." + echo "잘못된 형식: $(echo "$commit_msg" | grep -oE '^#[0-9]+[a-zA-Z][^ ]*')" + echo "올바른 형식: #13 chore: 메시지" + exit 1 +fi + +# commitlint 실행 +if npx --no -- commitlint --edit $1; then + echo "✅ 커밋 메시지가 규칙에 맞습니다." + exit 0 +else + echo "❌ 커밋 메시지가 컨벤션에 맞지 않습니다." + echo "" + echo "올바른 커밋 메시지 형식:" + echo " : " + echo " #<이슈번호> : (이슈 번호는 선택사항)" + echo "" + echo "예시:" + echo " feat: 새로운 기능 추가" + echo " #13 fix: 버그 수정" + echo " docs: 문서 수정" + echo " #42 refactor: 코드 리팩토링" + echo "" + echo "사용 가능한 type:" + echo " feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert" + exit 1 +fi diff --git a/.prettierrc b/.prettierrc index b9e1aba..7a7b126 100644 --- a/.prettierrc +++ b/.prettierrc @@ -17,5 +17,6 @@ "requirePragma": false, "tabWidth": 2, "useTabs": false, - "embeddedLanguageFormatting": "auto" + "embeddedLanguageFormatting": "auto", + "tailwindStylesheet": "src/index.css" } diff --git a/commitlint.config.cjs b/commitlint.config.cjs new file mode 100644 index 0000000..84dcb12 --- /dev/null +++ b/commitlint.config.cjs @@ -0,0 +1,3 @@ +module.exports = { + extends: ['@commitlint/config-conventional'], +}; diff --git a/package-lock.json b/package-lock.json index 0c36197..69d5c9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,8 @@ "tailwindcss": "^4.1.11" }, "devDependencies": { + "@commitlint/cli": "^20.3.0", + "@commitlint/config-conventional": "^20.3.0", "@eslint/js": "^9.29.0", "@types/node": "^24.2.1", "@types/react": "^19.1.8", @@ -24,6 +26,8 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "globals": "^16.2.0", + "prettier": "^3.6.2", + "prettier-plugin-tailwindcss": "^0.6.14", "tsconfig-paths": "^4.2.0", "typescript": "~5.8.3", "typescript-eslint": "^8.34.1", @@ -327,6 +331,483 @@ "node": ">=6.9.0" } }, + "node_modules/@commitlint/cli": { + "version": "20.3.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.3.0.tgz", + "integrity": "sha512-HXO8YVfqdBK+MnlX2zqNrv6waGYPs6Ysjm5W2Y0GMagWXwiIKx7C8dcIX9ca+QdHq4WA0lcMnZLQ0pzQh1piZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/format": "^20.2.0", + "@commitlint/lint": "^20.3.0", + "@commitlint/load": "^20.3.0", + "@commitlint/read": "^20.2.0", + "@commitlint/types": "^20.2.0", + "tinyexec": "^1.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "20.3.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-20.3.0.tgz", + "integrity": "sha512-g1OXVl6E2v0xF1Ru2RpxQ+Vfy7XUcUsCmLKzGUrhFLS4hSNykje0QSy6djBtzOiOBQCepBrmIlqx/gRlzrSh5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.2.0", + "conventional-changelog-conventionalcommits": "^7.0.2" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-20.2.0.tgz", + "integrity": "sha512-SQCBGsL9MFk8utWNSthdxd9iOD1pIVZSHxGBwYIGfd67RTjxqzFOSAYeQVXOu3IxRC3YrTOH37ThnTLjUlyF2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.2.0", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@commitlint/config-validator/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, + "license": "MIT" + }, + "node_modules/@commitlint/ensure": { + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-20.2.0.tgz", + "integrity": "sha512-+8TgIGv89rOWyt3eC6lcR1H7hqChAKkpawytlq9P1i/HYugFRVqgoKJ8dhd89fMnlrQTLjA5E97/4sF09QwdoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.2.0", + "lodash.camelcase": "^4.3.0", + "lodash.kebabcase": "^4.1.1", + "lodash.snakecase": "^4.1.1", + "lodash.startcase": "^4.4.0", + "lodash.upperfirst": "^4.3.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-20.0.0.tgz", + "integrity": "sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/format": { + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-20.2.0.tgz", + "integrity": "sha512-PhNoLNhxpfIBlW/i90uZ3yG3hwSSYx7n4d9Yc+2FAorAHS0D9btYRK4ZZXX+Gm3W5tDtu911ow/eWRfcRVgNWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.2.0", + "chalk": "^5.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/format/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-20.2.0.tgz", + "integrity": "sha512-Lz0OGeZCo/QHUDLx5LmZc0EocwanneYJUM8z0bfWexArk62HKMLfLIodwXuKTO5y0s6ddXaTexrYHs7v96EOmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.2.0", + "semver": "^7.6.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/is-ignored/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@commitlint/lint": { + "version": "20.3.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-20.3.0.tgz", + "integrity": "sha512-X19HOGU5nRo6i9DIY0kG0mhgtvpn1UGO1D6aLX1ILLyeqSM5yJyMcrRqNj8SLgeSeUDODhLY9QYsBIG0LdNHkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/is-ignored": "^20.2.0", + "@commitlint/parse": "^20.2.0", + "@commitlint/rules": "^20.3.0", + "@commitlint/types": "^20.2.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load": { + "version": "20.3.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-20.3.0.tgz", + "integrity": "sha512-amkdVZTXp5R65bsRXRSCwoNXbJHR2aAIY/RGFkoyd63t8UEwqEgT3f0MgeLqYw4hwXyq+TYXKdaW133E29pnGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^20.2.0", + "@commitlint/execute-rule": "^20.0.0", + "@commitlint/resolve-extends": "^20.2.0", + "@commitlint/types": "^20.2.0", + "chalk": "^5.3.0", + "cosmiconfig": "^9.0.0", + "cosmiconfig-typescript-loader": "^6.1.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "lodash.uniq": "^4.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@commitlint/load/node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@commitlint/load/node_modules/cosmiconfig-typescript-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.2.0.tgz", + "integrity": "sha512-GEN39v7TgdxgIoNcdkRE3uiAzQt3UXLyHbRHD6YoL048XAeOomyxaP+Hh/+2C6C2wYjxJ2onhJcsQp+L4YEkVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "jiti": "^2.6.1" + }, + "engines": { + "node": ">=v18" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=9", + "typescript": ">=5" + } + }, + "node_modules/@commitlint/message": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-20.0.0.tgz", + "integrity": "sha512-gLX4YmKnZqSwkmSB9OckQUrI5VyXEYiv3J5JKZRxIp8jOQsWjZgHSG/OgEfMQBK9ibdclEdAyIPYggwXoFGXjQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/parse": { + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-20.2.0.tgz", + "integrity": "sha512-LXStagGU1ivh07X7sM+hnEr4BvzFYn1iBJ6DRg2QsIN8lBfSzyvkUcVCDwok9Ia4PWiEgei5HQjju6xfJ1YaSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.2.0", + "conventional-changelog-angular": "^7.0.0", + "conventional-commits-parser": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/read": { + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-20.2.0.tgz", + "integrity": "sha512-+SjF9mxm5JCbe+8grOpXCXMMRzAnE0WWijhhtasdrpJoAFJYd5UgRTj/oCq5W3HJTwbvTOsijEJ0SUGImECD7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/top-level": "^20.0.0", + "@commitlint/types": "^20.2.0", + "git-raw-commits": "^4.0.0", + "minimist": "^1.2.8", + "tinyexec": "^1.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-20.2.0.tgz", + "integrity": "sha512-KVoLDi9BEuqeq+G0wRABn4azLRiCC22/YHR2aCquwx6bzCHAIN8hMt3Nuf1VFxq/c8ai6s8qBxE8+ZD4HeFTlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^20.2.0", + "@commitlint/types": "^20.2.0", + "global-directory": "^4.0.1", + "import-meta-resolve": "^4.0.0", + "lodash.mergewith": "^4.6.2", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/resolve-extends/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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@commitlint/rules": { + "version": "20.3.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-20.3.0.tgz", + "integrity": "sha512-TGgXN/qBEhbzVD13crE1l7YSMJRrbPbUL0OBZALbUM5ER36RZmiZRu2ud2W/AA7HO9YLBRbyx6YVi2t/2Be0yQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/ensure": "^20.2.0", + "@commitlint/message": "^20.0.0", + "@commitlint/to-lines": "^20.0.0", + "@commitlint/types": "^20.2.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-20.0.0.tgz", + "integrity": "sha512-2l9gmwiCRqZNWgV+pX1X7z4yP0b3ex/86UmUFgoRt672Ez6cAM2lOQeHFRUTuE6sPpi8XBCGnd8Kh3bMoyHwJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/top-level": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-20.0.0.tgz", + "integrity": "sha512-drXaPSP2EcopukrUXvUXmsQMu3Ey/FuJDc/5oiW4heoCfoE5BdLQyuc7veGeE3aoQaTVqZnh4D5WTWe2vefYKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^7.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/top-level/node_modules/find-up": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", + "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^7.2.0", + "path-exists": "^5.0.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/@commitlint/top-level/node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/types": { + "version": "20.2.0", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-20.2.0.tgz", + "integrity": "sha512-KTy0OqRDLR5y/zZMnizyx09z/rPlPC/zKhYgH8o/q6PuAjoQAKlRfY4zzv0M64yybQ//6//4H1n14pxaLZfUnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/conventional-commits-parser": "^5.0.0", + "chalk": "^5.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/types/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", @@ -1880,6 +2361,16 @@ "@babel/types": "^7.20.7" } }, + "node_modules/@types/conventional-commits-parser": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.2.tgz", + "integrity": "sha512-BgT2szDXnVypgpNxOK8aL5SGjUdaQbC++WZNjF1Qge3Og2+zhHj+RWhmehLhYyvQwqAmvezruVfOf8+3m74W+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -2254,6 +2745,16 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2277,6 +2778,13 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true, + "license": "MIT" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2411,6 +2919,21 @@ "node": ">=18" } }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2431,6 +2954,17 @@ "dev": true, "license": "MIT" }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2438,6 +2972,51 @@ "dev": true, "license": "MIT" }, + "node_modules/conventional-changelog-angular": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", + "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -2503,6 +3082,19 @@ "dev": true, "license": "MIT" }, + "node_modules/dargs": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", + "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/debug": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", @@ -2548,6 +3140,19 @@ "tslib": "^2.0.3" } }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.179", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.179.tgz", @@ -2555,6 +3160,13 @@ "dev": true, "license": "ISC" }, + "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, + "license": "MIT" + }, "node_modules/enhanced-resolve": { "version": "5.18.2", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", @@ -2581,6 +3193,16 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2890,6 +3512,23 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fastq": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", @@ -2985,7 +3624,35 @@ "dev": true, "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/git-raw-commits": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", + "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dargs": "^8.0.0", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.mjs" + }, + "engines": { + "node": ">=16" } }, "node_modules/glob-parent": { @@ -3001,6 +3668,22 @@ "node": ">=10.13.0" } }, + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "4.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globals": { "version": "16.3.0", "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", @@ -3071,6 +3754,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -3081,6 +3775,16 @@ "node": ">=0.8.19" } }, + "node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -3098,6 +3802,16 @@ "node": ">=0.10.0" } }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -3121,6 +3835,29 @@ "node": ">=0.12.0" } }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3129,9 +3866,9 @@ "license": "ISC" }, "node_modules/jiti": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", - "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -3211,6 +3948,33 @@ "node": ">=6" } }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3486,6 +4250,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -3493,6 +4278,41 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "dev": true, + "license": "MIT" + }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -3522,6 +4342,19 @@ "@jridgewell/sourcemap-codec": "^1.5.0" } }, + "node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3824,6 +4657,109 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-tailwindcss": { + "version": "0.6.14", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.14.tgz", + "integrity": "sha512-pi2e/+ZygeIqntN+vC573BcW5Cve8zUB0SSAGxqpB4f96boZF4M3phPVoOFCeypwkpRYdi7+jQ5YJJUwrkGUAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "@ianvs/prettier-plugin-sort-imports": "*", + "@prettier/plugin-hermes": "*", + "@prettier/plugin-oxc": "*", + "@prettier/plugin-pug": "*", + "@shopify/prettier-plugin-liquid": "*", + "@trivago/prettier-plugin-sort-imports": "*", + "@zackad/prettier-plugin-twig": "*", + "prettier": "^3.0", + "prettier-plugin-astro": "*", + "prettier-plugin-css-order": "*", + "prettier-plugin-import-sort": "*", + "prettier-plugin-jsdoc": "*", + "prettier-plugin-marko": "*", + "prettier-plugin-multiline-arrays": "*", + "prettier-plugin-organize-attributes": "*", + "prettier-plugin-organize-imports": "*", + "prettier-plugin-sort-imports": "*", + "prettier-plugin-style-order": "*", + "prettier-plugin-svelte": "*" + }, + "peerDependenciesMeta": { + "@ianvs/prettier-plugin-sort-imports": { + "optional": true + }, + "@prettier/plugin-hermes": { + "optional": true + }, + "@prettier/plugin-oxc": { + "optional": true + }, + "@prettier/plugin-pug": { + "optional": true + }, + "@shopify/prettier-plugin-liquid": { + "optional": true + }, + "@trivago/prettier-plugin-sort-imports": { + "optional": true + }, + "@zackad/prettier-plugin-twig": { + "optional": true + }, + "prettier-plugin-astro": { + "optional": true + }, + "prettier-plugin-css-order": { + "optional": true + }, + "prettier-plugin-import-sort": { + "optional": true + }, + "prettier-plugin-jsdoc": { + "optional": true + }, + "prettier-plugin-marko": { + "optional": true + }, + "prettier-plugin-multiline-arrays": { + "optional": true + }, + "prettier-plugin-organize-attributes": { + "optional": true + }, + "prettier-plugin-organize-imports": { + "optional": true + }, + "prettier-plugin-sort-imports": { + "optional": true + }, + "prettier-plugin-style-order": { + "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + } + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3924,6 +4860,26 @@ "react-dom": ">=18" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -4073,6 +5029,44 @@ "node": ">=0.10.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "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, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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, + "license": "MIT", + "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", @@ -4157,6 +5151,36 @@ "node": ">=18" } }, + "node_modules/text-extensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", @@ -4325,6 +5349,19 @@ "devOptional": true, "license": "MIT" }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", @@ -4527,6 +5564,34 @@ "node": ">=0.10.0" } }, + "node_modules/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, + "license": "MIT", + "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/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -4534,6 +5599,35 @@ "dev": true, "license": "ISC" }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "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 dfa3505..7b4d64b 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,8 @@ "tailwindcss": "^4.1.11" }, "devDependencies": { + "@commitlint/cli": "^20.3.0", + "@commitlint/config-conventional": "^20.3.0", "@eslint/js": "^9.29.0", "@types/node": "^24.2.1", "@types/react": "^19.1.8", @@ -27,6 +29,8 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "globals": "^16.2.0", + "prettier": "^3.6.2", + "prettier-plugin-tailwindcss": "^0.6.14", "tsconfig-paths": "^4.2.0", "typescript": "~5.8.3", "typescript-eslint": "^8.34.1", diff --git a/public/svg/profileImage.svg b/public/svg/profileImage.svg new file mode 100644 index 0000000..213c774 --- /dev/null +++ b/public/svg/profileImage.svg @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/svg/search.svg b/public/svg/search.svg new file mode 100644 index 0000000..f0bf38e --- /dev/null +++ b/public/svg/search.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/App.tsx b/src/App.tsx index 0272ffd..313d1b5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,11 +3,12 @@ import Layout from './layout/Layout'; import LandingPage from './pages/common/LandingPage'; import UserIdInputPage from './pages/common/UserIdInputPage'; import Dashboard from './pages/common/Dashboard'; +import AssignmentsPage from './pages/admin/assignments/AssignmentsPage'; +import AssignmentSelectPage from './pages/admin/assignments/AssignmentSelectPage'; import CourseOverviewPage from './pages/common/CourseOverviewPage'; import AssignmentCreatePage from './pages/admin/assignments/AssignmentCreatePage'; import CourseCreatePage from './pages/admin/courses/CourseCreatePage'; -import AssignmentsPage from './pages/admin/assignments/AssignmentsPage'; -import AssignmentSelectPage from './pages/admin/assignments/AssignmentSelectPage'; +import StudentManagementPage from './pages/admin/student/studentManagementPage'; function App() { return ( @@ -16,7 +17,7 @@ function App() { {/* 공통 영역 */} }> } /> - } /> + } /> {/* 학생 전용 영역 */} @@ -31,13 +32,11 @@ function App() { {/* 추가 페이지들 */} } /> } /> + } /> } /> } /> - } - /> - } /> + } /> + } /> diff --git a/src/assets/svg/AddIcon.tsx b/src/assets/svg/AddIcon.tsx deleted file mode 100644 index 71637e0..0000000 --- a/src/assets/svg/AddIcon.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgAddIcon = (props: SVGProps) => ( - - - -); -export default SvgAddIcon; diff --git a/src/assets/svg/ArrowdownIcon.tsx b/src/assets/svg/ArrowdownIcon.tsx deleted file mode 100644 index 6f96561..0000000 --- a/src/assets/svg/ArrowdownIcon.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgArrowdownIcon = (props: SVGProps) => ( - - - -); -export default SvgArrowdownIcon; diff --git a/src/assets/svg/ArrowleftIcon.tsx b/src/assets/svg/ArrowleftIcon.tsx deleted file mode 100644 index 4793458..0000000 --- a/src/assets/svg/ArrowleftIcon.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgArrowleftIcon = (props: SVGProps) => ( - - - -); -export default SvgArrowleftIcon; diff --git a/src/assets/svg/ArrowrightIcon.tsx b/src/assets/svg/ArrowrightIcon.tsx deleted file mode 100644 index c0a119e..0000000 --- a/src/assets/svg/ArrowrightIcon.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgArrowrightIcon = (props: SVGProps) => ( - - - -); -export default SvgArrowrightIcon; diff --git a/src/assets/svg/ChatIcon.tsx b/src/assets/svg/ChatIcon.tsx deleted file mode 100644 index e3f8a0f..0000000 --- a/src/assets/svg/ChatIcon.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgChatIcon = (props: SVGProps) => ( - - - -); -export default SvgChatIcon; diff --git a/src/assets/svg/Chevrondown.tsx b/src/assets/svg/Chevrondown.tsx deleted file mode 100644 index e5bd8cb..0000000 --- a/src/assets/svg/Chevrondown.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgChevrondown = (props: SVGProps) => ( - - - -); -export default SvgChevrondown; diff --git a/src/assets/svg/DeleteIcon.tsx b/src/assets/svg/DeleteIcon.tsx deleted file mode 100644 index fce305c..0000000 --- a/src/assets/svg/DeleteIcon.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgDeleteIcon = (props: SVGProps) => ( - - - -); -export default SvgDeleteIcon; diff --git a/src/assets/svg/DragAndDropIcon.tsx b/src/assets/svg/DragAndDropIcon.tsx deleted file mode 100644 index 6fda321..0000000 --- a/src/assets/svg/DragAndDropIcon.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgDragAndDropIcon = (props: SVGProps) => ( - - - - - - - - -); -export default SvgDragAndDropIcon; diff --git a/src/assets/svg/EditIcon.tsx b/src/assets/svg/EditIcon.tsx deleted file mode 100644 index 1bd6f31..0000000 --- a/src/assets/svg/EditIcon.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgEditIcon = (props: SVGProps) => ( - - - -); -export default SvgEditIcon; diff --git a/src/assets/svg/EllipsisIcon.tsx b/src/assets/svg/EllipsisIcon.tsx deleted file mode 100644 index e679841..0000000 --- a/src/assets/svg/EllipsisIcon.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgEllipsisIcon = (props: SVGProps) => ( - - - - - -); -export default SvgEllipsisIcon; diff --git a/src/assets/svg/File.tsx b/src/assets/svg/File.tsx deleted file mode 100644 index ddef665..0000000 --- a/src/assets/svg/File.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgFile = (props: SVGProps) => ( - - - - -); -export default SvgFile; diff --git a/src/assets/svg/NotificationIcon.tsx b/src/assets/svg/NotificationIcon.tsx deleted file mode 100644 index 3b7f13e..0000000 --- a/src/assets/svg/NotificationIcon.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgNotificationIcon = (props: SVGProps) => ( - - - -); -export default SvgNotificationIcon; diff --git a/src/assets/svg/SignoutIcon.tsx b/src/assets/svg/SignoutIcon.tsx deleted file mode 100644 index feba1ab..0000000 --- a/src/assets/svg/SignoutIcon.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgSignoutIcon = (props: SVGProps) => ( - - - - -); -export default SvgSignoutIcon; diff --git a/src/assets/svg/SingleEllipsisIcon.tsx b/src/assets/svg/SingleEllipsisIcon.tsx deleted file mode 100644 index 2194480..0000000 --- a/src/assets/svg/SingleEllipsisIcon.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import type {SVGProps} from 'react'; -const SvgSingleEllipsisIcon = (props: SVGProps) => ( - - - -); -export default SvgSingleEllipsisIcon; diff --git a/src/assets/svg/UserIcon.tsx b/src/assets/svg/UserIcon.tsx deleted file mode 100644 index e2cc120..0000000 --- a/src/assets/svg/UserIcon.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import * as React from 'react'; -import type {SVGProps} from 'react'; -const SvgUserIcon = (props: SVGProps) => ( - - - - -); -export default SvgUserIcon; diff --git a/src/assets/svg/index.ts b/src/assets/svg/index.ts deleted file mode 100644 index f686fb5..0000000 --- a/src/assets/svg/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -export {default as AddIcon} from './AddIcon'; -export {default as ArrowdownIcon} from './ArrowdownIcon'; -export {default as ArrowleftIcon} from './ArrowleftIcon'; -export {default as ArrowrightIcon} from './ArrowrightIcon'; -export {default as ChatIcon} from './ChatIcon'; -export {default as Chevrondown} from './Chevrondown'; -export {default as DeleteIcon} from './DeleteIcon'; -export {default as DragAndDropIcon} from './DragAndDropIcon'; -export {default as EditIcon} from './EditIcon'; -export {default as EllipsisIcon} from './EllipsisIcon'; -export {default as File} from './File'; -export {default as NotificationIcon} from './NotificationIcon'; -export {default as SignoutIcon} from './SignoutIcon'; -export {default as SingleEllipsisIcon} from './SingleEllipsisIcon'; -export {default as UserIcon} from './UserIcon'; diff --git a/src/components/admin/assignments/AssignmentCard.tsx b/src/components/admin/assignments/AssignmentCard.tsx index 75b3727..214f459 100644 --- a/src/components/admin/assignments/AssignmentCard.tsx +++ b/src/components/admin/assignments/AssignmentCard.tsx @@ -1,10 +1,8 @@ import {useState} from 'react'; -import { - SingleEllipsisIcon, - DragAndDropIcon, - DeleteIcon, - EditIcon, -} from '../../../assets/svg'; +import SingleEllipsisIcon from '/svg/singleEllipsisIcon.svg?react'; +import DragAndDropIcon from '/svg/dragAndDropIcon.svg?react'; +import DeleteIcon from '/svg/deleteIcon.svg?react'; +import EditIcon from '/svg/editIcon.svg?react'; import type {Assignment} from './dummy/types'; interface AssignmentCardProps extends Assignment { diff --git a/src/components/admin/assignments/AssignmentFormLayout.tsx b/src/components/admin/assignments/AssignmentFormLayout.tsx index d7c5697..3ddd194 100644 --- a/src/components/admin/assignments/AssignmentFormLayout.tsx +++ b/src/components/admin/assignments/AssignmentFormLayout.tsx @@ -2,6 +2,7 @@ import Button from '@/components/common/Button'; type AssignmentFormLayoutProps = { title: string; + titleExtra?: React.ReactNode; content: React.ReactNode; onCancel: () => void; onConfirm: () => void; @@ -9,6 +10,7 @@ type AssignmentFormLayoutProps = { const AssignmentFormLayout = ({ title, + titleExtra, content, onCancel, onConfirm, @@ -17,7 +19,10 @@ const AssignmentFormLayout = ({
{/* 제목 */} -

{title}

+
+

{title}

+ {titleExtra} +
{/* 본문 */}
{content}
diff --git a/src/components/admin/assignments/AssignmentPageLayout.tsx b/src/components/admin/assignments/AssignmentPageLayout.tsx index e72355a..66327d1 100644 --- a/src/components/admin/assignments/AssignmentPageLayout.tsx +++ b/src/components/admin/assignments/AssignmentPageLayout.tsx @@ -1,8 +1,8 @@ import CourseSelector from './CourseSelector'; import AssignmentList from './AssignmentList'; -import Button from '../../common/Button'; +import Button from '@/components/common/Button'; import type {Course} from './dummy/types'; -import {AddIcon} from '../../../assets/svg'; +import AddIcon from '/svg/addIcon.svg?react'; import {useState} from 'react'; interface AssignmentPageLayoutProps { diff --git a/src/components/admin/assignments/CourseSelector.tsx b/src/components/admin/assignments/CourseSelector.tsx index db13060..aef0a1a 100644 --- a/src/components/admin/assignments/CourseSelector.tsx +++ b/src/components/admin/assignments/CourseSelector.tsx @@ -1,5 +1,5 @@ import {useState} from 'react'; -import {ArrowdownIcon} from '../../../assets/svg'; +import ArrowdownIcon from '/svg/arrowdownIcon.svg?react'; import type {Course} from './dummy/types'; interface CourseSelectorProps { diff --git a/src/components/admin/form/FileUpload.tsx b/src/components/admin/form/FileUpload.tsx index 8b817e6..b86e3e7 100644 --- a/src/components/admin/form/FileUpload.tsx +++ b/src/components/admin/form/FileUpload.tsx @@ -1,6 +1,6 @@ import {useRef, useState} from 'react'; import type {ChangeEvent} from 'react'; -import {File} from '@/assets/svg'; +import FileIcon from '/svg/file.svg?react'; type FileUploadProps = { label: string; @@ -103,7 +103,7 @@ export default function FileUpload({ 'focus:outline-none focus:ring-2 focus:ring-primary', ].join(' ')}>
- +
{description}
diff --git a/src/components/admin/form/LabeledDropdown.tsx b/src/components/admin/form/LabeledDropdown.tsx index 680d2df..20e22cb 100644 --- a/src/components/admin/form/LabeledDropdown.tsx +++ b/src/components/admin/form/LabeledDropdown.tsx @@ -1,5 +1,5 @@ import {useState, useRef} from 'react'; -import {Chevrondown} from '@/assets/svg'; +import Chevrondown from '/svg/chevrondown.svg?react'; import useClickOutside from '@/hooks/useClickOutside'; interface LabeledDropdownProps diff --git a/src/components/common/BaseHeader.tsx b/src/components/common/BaseHeader.tsx index d3fef36..0234e0e 100644 --- a/src/components/common/BaseHeader.tsx +++ b/src/components/common/BaseHeader.tsx @@ -1,4 +1,4 @@ -import logo from '../../assets/images/snowCode_logo.svg'; +import logo from '@/assets/images/snowCode_logo.svg'; interface BaseHeaderProps { leftContent?: React.ReactNode; diff --git a/src/components/common/Button.tsx b/src/components/common/Button.tsx index 4be7e34..9ff4b1c 100644 --- a/src/components/common/Button.tsx +++ b/src/components/common/Button.tsx @@ -16,9 +16,10 @@ const buttonTheme: ButtonTheme = { secondaryPurpleStroke: 'secondary-btn bg-purple-stroke text-secondary-black', }; -const Button = ({theme, text, icon}: ButtonProps) => { +const Button = ({theme, text, icon, onClick}: ButtonProps) => { return ( ; }; -export default IconButton; +export default IconButton; \ No newline at end of file diff --git a/src/index.css b/src/index.css index 9dd07ce..26c7fe3 100644 --- a/src/index.css +++ b/src/index.css @@ -48,6 +48,9 @@ --color-primary-black: #2c2a36; --color-purple-stroke: #dfdbf0; --color-hover: #b4a5ff; + --color-status-green: #c4ffa4; + --color-status-yellow: #ffe292; + --color-status-red: #ffb3b3; --font-coolvetica: 'Coolvetica', sans-serif; --shadow-card: 0px 0px 14px 0px rgba(223, 219, 240, 0.4); diff --git a/src/layout/Layout.tsx b/src/layout/Layout.tsx index ea5f579..09eeeae 100644 --- a/src/layout/Layout.tsx +++ b/src/layout/Layout.tsx @@ -1,8 +1,19 @@ // Layout.js import {useLocation, Outlet} from 'react-router-dom'; -import BaseHeader from '../components/common/BaseHeader'; -import {NotificationIcon, SignoutIcon, UserIcon, ChatIcon} from '../assets/svg'; -import IconButton from '../components/common/IconButton'; +import BaseHeader from '@/components/common/BaseHeader'; +import NotificationIcon from '/svg/notificationIcon.svg?react'; +import SignoutIcon from '/svg/signoutIcon.svg?react'; +import UserIcon from '/svg/userIcon.svg?react'; +import ChatIcon from '/svg/chatIcon.svg?react'; +import IconButton from '@/components/common/IconButton'; +import React from 'react'; + +type UserType = 'admin' | 'student'; + +interface NavButton { + icon: React.ReactElement; + label: string; +} const Layout = () => { const location = useLocation(); @@ -13,8 +24,8 @@ const Layout = () => { const showHeader = !noHeaderPages.includes(pathname); // 네비게이션 아이콘 버튼들 - const getNavigationButtons = (userType) => { - const commonButtons = [ + const getNavigationButtons = (userType: UserType): NavButton[] => { + const commonButtons: NavButton[] = [ {icon: , label: '알림'}, {icon: , label: '프로필'}, {icon: , label: '로그아웃'}, @@ -31,14 +42,20 @@ const Layout = () => { }; // 사용자 환영 메시지 - const getWelcomeMessage = (userName) => ( + const getWelcomeMessage = (userName: string) => ( {userName}님 환영합니다! ); // 네비게이션 컴포넌트 - const NavigationBar = ({buttons, width}) => ( + const NavigationBar = ({ + buttons, + width, + }: { + buttons: NavButton[]; + width: string; + }) => (