From 80f7360a05594aa0dc2a350fa04c1aefbc0d14ca Mon Sep 17 00:00:00 2001 From: Amitjoiya Date: Thu, 6 Nov 2025 17:40:42 +0530 Subject: [PATCH 01/12] feat(project): render EditorJS code blocks with copy button and language detection (final clean) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit chore: final eslint and format clean — ready for review --- client/eslint.config.js | 7 + client/src/modules/profile/index.tsx | 7 +- .../project/components/project-content.tsx | 89 +- eslint.config.mjs | 22 +- package-lock.json | 1015 ++++++++++++++++- package.json | 7 +- 6 files changed, 1123 insertions(+), 24 deletions(-) diff --git a/client/eslint.config.js b/client/eslint.config.js index 0e16339d..9877d6f0 100644 --- a/client/eslint.config.js +++ b/client/eslint.config.js @@ -23,6 +23,13 @@ export default defineConfig([ // Disable react-in-jsx-scope for React 17+ (not needed) 'react/react-in-jsx-scope': 'off', 'react/jsx-uses-react': 'off', + + + }, + settings: { + react: { + version: "detect", // 👈 Add this line + }, }, }, ]) diff --git a/client/src/modules/profile/index.tsx b/client/src/modules/profile/index.tsx index 13b3775a..7ae2cd16 100644 --- a/client/src/modules/profile/index.tsx +++ b/client/src/modules/profile/index.tsx @@ -10,6 +10,7 @@ import { Virtuoso } from 'react-virtuoso'; import { BannerSkeleton } from '../../shared/components/atoms/skeleton'; import { UserAtom } from '../../infra/states/user'; import { Avatar, Box, CircularProgress } from '@mui/material'; +import type { Theme } from '@mui/material/styles'; import useHome from '../home/hooks'; import AboutUser from './components/about-user'; import A2ZTypography from '../../shared/components/atoms/typography'; @@ -58,7 +59,9 @@ const Profile = () => { minWidth: 400, gap: 2, pl: { md: 4 }, - borderLeft: theme => ({ md: `1px solid ${theme.palette.divider}` }), + borderLeft: (theme: Theme) => ({ + md: `1px solid ${theme.palette.divider}`, + }), }} > { ( + itemContent={(index: number) => ( )} overscan={200} diff --git a/client/src/modules/project/components/project-content.tsx b/client/src/modules/project/components/project-content.tsx index f6752826..a39edf6e 100644 --- a/client/src/modules/project/components/project-content.tsx +++ b/client/src/modules/project/components/project-content.tsx @@ -1,4 +1,5 @@ import { OutputBlockData } from '@editorjs/editorjs'; +import { useState } from 'react'; const Img = ({ url, caption }: { url: string; caption: string }) => { return ( @@ -56,42 +57,114 @@ const ProjectContent = ({ block }: { block: OutputBlockData }) => { const { type, data } = block; if (type === 'paragraph') { - return

; + return

; } if (type === 'header') { - if (data.level === 3) { + if (data?.level === 3) { return (

); } return (

); } if (type === 'image') { - return ; + return ; } if (type === 'quote') { - return ; + return ; } if (type === 'list') { return ( ); } + + if (type === 'code') { + // EditorJS code tool may store the actual code string under different keys + // depending on the tool used. Common keys: `code`, `text`, or `data.code`. + const codeText: string = + (data && (data.code || data.text || data.source || data.code || '')) || ''; + + // Some code tools include language info. Try common keys, otherwise try to + // do a tiny heuristic check for language keywords (very small and best-effort). + let language = data?.language || data?.lang || data?.meta?.language || ''; + + if (!language) { + const sample = (codeText || '').slice(0, 200).toLowerCase(); + if (/^\s*#include|std::|printf\(|cout\b/.test(sample)) language = 'cpp'; + else if (/^\s*import\s+react|from\s+'react'|console\.log\(/.test(sample)) + language = 'javascript'; + else if (/^\s*def\s+\w+\(|import\s+os\b|print\(/.test(sample)) language = 'python'; + else if (/^\s*<\w+.*>/.test(sample)) language = 'html'; + else language = ''; + } + + const [copied, setCopied] = useState(false); + + const handleCopy = async () => { + try { + await navigator.clipboard.writeText(codeText || ''); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch (err) { + // fallback: select and copy + const ta = document.createElement('textarea'); + ta.value = codeText || ''; + document.body.appendChild(ta); + ta.select(); + try { + document.execCommand('copy'); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch (e) { + // ignore + } + document.body.removeChild(ta); + } + }; + + return ( +
+
+ {language && ( + {language} + )} +
+ +
+
+
+          {codeText}
+        
+
+ ); + } +<<<<<<< HEAD +======= + + return null; +>>>>>>> 7d1792c (chore: final eslint and format clean — ready for review) }; export default ProjectContent; diff --git a/eslint.config.mjs b/eslint.config.mjs index 7e270a6c..e57b3c8a 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -5,7 +5,14 @@ import json from "@eslint/json"; import css from "@eslint/css"; import { defineConfig } from "eslint/config"; -export default defineConfig([ +import js from "@eslint/js"; +import pluginReact from "eslint-plugin-react"; +import globals from "globals"; +import tseslint from "@typescript-eslint/eslint-plugin"; +import tsParser from "@typescript-eslint/parser"; + +export default [ + js.configs.recommended, { ...js.configs.recommended, files: ["**/*.{js,mjs,cjs,jsx}"], @@ -17,8 +24,15 @@ export default defineConfig([ // Disable react-in-jsx-scope for React 17+ (not needed) files: ['**/*.{tsx,jsx}'], rules: { - 'react/react-in-jsx-scope': 'off', - 'react/jsx-uses-react': 'off', + ...pluginReact.configs.recommended.rules, + "react/react-in-jsx-scope": "off", + "react/prop-types": "off", + "@typescript-eslint/no-unused-vars": ["error"], + }, + settings: { + react: { + version: "detect", + }, }, }, { @@ -45,4 +59,4 @@ export default defineConfig([ plugins: { css }, language: "css/css", }, -]); +]); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4b3c9ffe..f3e3841a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,17 +10,261 @@ "license": "ISC", "devDependencies": { "@eslint/css": "^0.10.0", - "@eslint/js": "^9.34.0", + "@eslint/js": "^9.39.1", "@eslint/json": "^0.13.1", + "@typescript-eslint/eslint-plugin": "^8.46.3", + "@typescript-eslint/parser": "^8.46.3", "concurrently": "^9.2.0", "eslint": "^9.34.0", "eslint-plugin-react": "^7.37.5", - "globals": "^16.3.0", + "eslint-plugin-react-hooks": "^7.0.1", + "globals": "^16.5.0", "husky": "^9.1.7", "lint-staged": "^16.1.5", "prettier": "^3.6.2" } }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", @@ -168,9 +412,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", - "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", + "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", "dev": true, "license": "MIT", "engines": { @@ -308,6 +552,94 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -322,12 +654,285 @@ "dev": true, "license": "MIT" }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.3.tgz", + "integrity": "sha512-sbaQ27XBUopBkRiuY/P9sWGOWUW4rl8fDoHIUmLpZd8uldsTyB4/Zg6bWTegPoTLnKj9Hqgn3QD6cjPNB32Odw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.46.3", + "@typescript-eslint/type-utils": "8.46.3", + "@typescript-eslint/utils": "8.46.3", + "@typescript-eslint/visitor-keys": "8.46.3", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.46.3", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.3.tgz", + "integrity": "sha512-6m1I5RmHBGTnUGS113G04DMu3CpSdxCAU/UvtjNWL4Nuf3MW9tQhiJqRlHzChIkhy6kZSAQmc+I1bcGjE3yNKg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.46.3", + "@typescript-eslint/types": "8.46.3", + "@typescript-eslint/typescript-estree": "8.46.3", + "@typescript-eslint/visitor-keys": "8.46.3", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.3.tgz", + "integrity": "sha512-Fz8yFXsp2wDFeUElO88S9n4w1I4CWDTXDqDr9gYvZgUpwXQqmZBr9+NTTql5R3J7+hrJZPdpiWaB9VNhAKYLuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.46.3", + "@typescript-eslint/types": "^8.46.3", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.3.tgz", + "integrity": "sha512-FCi7Y1zgrmxp3DfWfr+3m9ansUUFoy8dkEdeQSgA9gbm8DaHYvZCdkFRQrtKiedFf3Ha6VmoqoAaP68+i+22kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.3", + "@typescript-eslint/visitor-keys": "8.46.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.3.tgz", + "integrity": "sha512-GLupljMniHNIROP0zE7nCcybptolcH8QZfXOpCfhQDAdwJ/ZTlcaBOYebSOZotpti/3HrHSw7D3PZm75gYFsOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.3.tgz", + "integrity": "sha512-ZPCADbr+qfz3aiTTYNNkCbUt+cjNwI/5McyANNrFBpVxPt7GqpEYz5ZfdwuFyGUnJ9FdDXbGODUu6iRCI6XRXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.3", + "@typescript-eslint/typescript-estree": "8.46.3", + "@typescript-eslint/utils": "8.46.3", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.3.tgz", + "integrity": "sha512-G7Ok9WN/ggW7e/tOf8TQYMaxgID3Iujn231hfi0Pc7ZheztIJVpO44ekY00b7akqc6nZcvregk0Jpah3kep6hA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.3.tgz", + "integrity": "sha512-f/NvtRjOm80BtNM5OQtlaBdM5BRFUv7gf381j9wygDNL+qOYSNOgtQ/DCndiYi80iIOv76QqaTmp4fa9hwI0OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.46.3", + "@typescript-eslint/tsconfig-utils": "8.46.3", + "@typescript-eslint/types": "8.46.3", + "@typescript-eslint/visitor-keys": "8.46.3", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/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/@typescript-eslint/utils": { + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.3.tgz", + "integrity": "sha512-VXw7qmdkucEx9WkmR3ld/u6VhRyKeiF1uxWwCy/iuNfokjJ7VhsgLSOTjsol8BunSw190zABzpwdNsze2Kpo4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.3", + "@typescript-eslint/types": "8.46.3", + "@typescript-eslint/typescript-estree": "8.46.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.46.3", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.3.tgz", + "integrity": "sha512-uk574k8IU0rOF/AjniX8qbLSGURJVUCeM5e4MIMKBFFi8weeiLrG1fyQejyLXQpRZbU/1BuQasleV/RfHC3hHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.3", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -585,6 +1190,16 @@ "dev": true, "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.25", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.25.tgz", + "integrity": "sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -609,6 +1224,41 @@ "node": ">=8" } }, + "node_modules/browserslist": { + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.8.19", + "caniuse-lite": "^1.0.30001751", + "electron-to-chromium": "^1.5.238", + "node-releases": "^2.0.26", + "update-browserslist-db": "^1.1.4" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -669,6 +1319,27 @@ "node": ">=6" } }, + "node_modules/caniuse-lite": { + "version": "1.0.30001754", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz", + "integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -882,6 +1553,13 @@ "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1040,6 +1718,13 @@ "node": ">= 0.4" } }, + "node_modules/electron-to-chromium": { + "version": "1.5.249", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.249.tgz", + "integrity": "sha512-5vcfL3BBe++qZ5kuFhD/p8WOM1N9m3nwvJPULJx+4xf2usSlZFJ0qoNYO2fOX4hi3ocuDcmDobtA+5SFr4OmBg==", + "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", @@ -1266,6 +1951,7 @@ "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -1354,6 +2040,26 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", + "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, "node_modules/eslint-scope": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", @@ -1397,6 +2103,19 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "9.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", + "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, "node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -1475,6 +2194,36 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/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==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -1489,6 +2238,16 @@ "dev": true, "license": "MIT" }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -1610,6 +2369,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "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", @@ -1704,9 +2473,9 @@ } }, "node_modules/globals": { - "version": "16.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", - "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", "dev": true, "license": "MIT", "engines": { @@ -1746,6 +2515,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -1840,6 +2616,23 @@ "node": ">= 0.4" } }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, "node_modules/husky": { "version": "9.1.7", "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", @@ -2367,6 +3160,19 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -2388,6 +3194,19 @@ "dev": true, "license": "MIT" }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -2527,6 +3346,16 @@ "loose-envify": "cli.js" } }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -2544,6 +3373,16 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -2611,6 +3450,13 @@ "dev": true, "license": "MIT" }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2843,6 +3689,13 @@ "dev": true, "license": "MIT" }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2927,6 +3780,27 @@ "node": ">=6" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -3033,6 +3907,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rfdc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", @@ -3040,6 +3925,30 @@ "dev": true, "license": "MIT" }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/rxjs": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", @@ -3549,6 +4458,19 @@ "tree-kill": "cli.js" } }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -3647,6 +4569,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", @@ -3666,6 +4603,37 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/update-browserslist-db": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -3857,6 +4825,13 @@ "node": ">=10" } }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, "node_modules/yaml": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", @@ -3959,6 +4934,30 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", + "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } } } } diff --git a/package.json b/package.json index 81777c0d..c42b6c6c 100644 --- a/package.json +++ b/package.json @@ -43,12 +43,15 @@ }, "devDependencies": { "@eslint/css": "^0.10.0", - "@eslint/js": "^9.34.0", + "@eslint/js": "^9.39.1", "@eslint/json": "^0.13.1", + "@typescript-eslint/eslint-plugin": "^8.46.3", + "@typescript-eslint/parser": "^8.46.3", "concurrently": "^9.2.0", "eslint": "^9.34.0", "eslint-plugin-react": "^7.37.5", - "globals": "^16.3.0", + "eslint-plugin-react-hooks": "^7.0.1", + "globals": "^16.5.0", "husky": "^9.1.7", "lint-staged": "^16.1.5", "prettier": "^3.6.2" From 21fc8d898a3f3925dfa98f7749d99f73e96ba47e Mon Sep 17 00:00:00 2001 From: Amitjoiya Date: Mon, 10 Nov 2025 12:08:38 +0530 Subject: [PATCH 02/12] fix: removed TypeScript annotations to resolve ESLint error --- client/eslint.config.js | 7 - client/src/modules/profile/index.tsx | 7 +- .../project/components/project-content.tsx | 171 ++++++------------ eslint.config.mjs | 22 +-- 4 files changed, 61 insertions(+), 146 deletions(-) diff --git a/client/eslint.config.js b/client/eslint.config.js index 9877d6f0..0e16339d 100644 --- a/client/eslint.config.js +++ b/client/eslint.config.js @@ -23,13 +23,6 @@ export default defineConfig([ // Disable react-in-jsx-scope for React 17+ (not needed) 'react/react-in-jsx-scope': 'off', 'react/jsx-uses-react': 'off', - - - }, - settings: { - react: { - version: "detect", // 👈 Add this line - }, }, }, ]) diff --git a/client/src/modules/profile/index.tsx b/client/src/modules/profile/index.tsx index 7ae2cd16..13b3775a 100644 --- a/client/src/modules/profile/index.tsx +++ b/client/src/modules/profile/index.tsx @@ -10,7 +10,6 @@ import { Virtuoso } from 'react-virtuoso'; import { BannerSkeleton } from '../../shared/components/atoms/skeleton'; import { UserAtom } from '../../infra/states/user'; import { Avatar, Box, CircularProgress } from '@mui/material'; -import type { Theme } from '@mui/material/styles'; import useHome from '../home/hooks'; import AboutUser from './components/about-user'; import A2ZTypography from '../../shared/components/atoms/typography'; @@ -59,9 +58,7 @@ const Profile = () => { minWidth: 400, gap: 2, pl: { md: 4 }, - borderLeft: (theme: Theme) => ({ - md: `1px solid ${theme.palette.divider}`, - }), + borderLeft: theme => ({ md: `1px solid ${theme.palette.divider}` }), }} > { ( + itemContent={index => ( )} overscan={200} diff --git a/client/src/modules/project/components/project-content.tsx b/client/src/modules/project/components/project-content.tsx index a39edf6e..d08c0372 100644 --- a/client/src/modules/project/components/project-content.tsx +++ b/client/src/modules/project/components/project-content.tsx @@ -1,158 +1,100 @@ -import { OutputBlockData } from '@editorjs/editorjs'; +/* eslint-disable react/prop-types */ import { useState } from 'react'; -const Img = ({ url, caption }: { url: string; caption: string }) => { - return ( -
- - {caption.length ? ( -

- {caption} -

- ) : ( - '' - )} -
- ); -}; - -const Quote = ({ quote, caption }: { quote: string; caption: string }) => { - return ( -
-

{quote}

- {caption.length ? ( -

{caption}

- ) : ( - '' - )} -
- ); -}; - -const List = ({ - style, - items, -}: { - style: 'ordered' | 'unordered'; - items: string[]; -}) => { - return ( -
    - {items.map((listItem, i) => { - return ( -
  1. - ); - })} -
- ); -}; - -const ProjectContent = ({ block }: { block: OutputBlockData }) => { +const ProjectContent = ({ block }) => { const { type, data } = block; if (type === 'paragraph') { - return

; + return

; } if (type === 'header') { - if (data?.level === 3) { - return ( -

- ); - } + const Tag = data?.level === 3 ? 'h3' : 'h2'; + const size = data?.level === 3 ? 'text-3xl' : 'text-4xl'; return ( -

+ /> ); } if (type === 'image') { - return ; + return ( +
+ {data?.caption + {data?.caption && ( +

+ {data.caption} +

+ )} +
+ ); } if (type === 'quote') { - return ; + return ( +
+

{data?.text}

+ {data?.caption && ( +

{data.caption}

+ )} +
+ ); } if (type === 'list') { + const Tag = data?.style === 'ordered' ? 'ol' : 'ul'; + const listClass = data?.style === 'ordered' ? 'list-decimal' : 'list-disc'; return ( - + + {data?.items?.map((item, i) => ( +
  • + ))} + ); } if (type === 'code') { - // EditorJS code tool may store the actual code string under different keys - // depending on the tool used. Common keys: `code`, `text`, or `data.code`. - const codeText: string = - (data && (data.code || data.text || data.source || data.code || '')) || ''; - - // Some code tools include language info. Try common keys, otherwise try to - // do a tiny heuristic check for language keywords (very small and best-effort). - let language = data?.language || data?.lang || data?.meta?.language || ''; - - if (!language) { - const sample = (codeText || '').slice(0, 200).toLowerCase(); - if (/^\s*#include|std::|printf\(|cout\b/.test(sample)) language = 'cpp'; - else if (/^\s*import\s+react|from\s+'react'|console\.log\(/.test(sample)) - language = 'javascript'; - else if (/^\s*def\s+\w+\(|import\s+os\b|print\(/.test(sample)) language = 'python'; - else if (/^\s*<\w+.*>/.test(sample)) language = 'html'; - else language = ''; - } - + const codeText = data?.code || ''; const [copied, setCopied] = useState(false); const handleCopy = async () => { try { - await navigator.clipboard.writeText(codeText || ''); + await navigator.clipboard.writeText(codeText); setCopied(true); setTimeout(() => setCopied(false), 2000); - } catch (err) { - // fallback: select and copy + } catch { const ta = document.createElement('textarea'); - ta.value = codeText || ''; + ta.value = codeText; document.body.appendChild(ta); ta.select(); - try { - document.execCommand('copy'); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - } catch (e) { - // ignore - } + document.execCommand('copy'); document.body.removeChild(ta); + setCopied(true); + setTimeout(() => setCopied(false), 2000); } }; return (
    - {language && ( - {language} + {data?.language && ( + + {data.language} + )} -
    - -
    +
               {codeText}
    @@ -160,11 +102,8 @@ const ProjectContent = ({ block }: { block: OutputBlockData }) => {
           
    ); } -<<<<<<< HEAD -======= return null; ->>>>>>> 7d1792c (chore: final eslint and format clean — ready for review) }; export default ProjectContent; diff --git a/eslint.config.mjs b/eslint.config.mjs index e57b3c8a..7e270a6c 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -5,14 +5,7 @@ import json from "@eslint/json"; import css from "@eslint/css"; import { defineConfig } from "eslint/config"; -import js from "@eslint/js"; -import pluginReact from "eslint-plugin-react"; -import globals from "globals"; -import tseslint from "@typescript-eslint/eslint-plugin"; -import tsParser from "@typescript-eslint/parser"; - -export default [ - js.configs.recommended, +export default defineConfig([ { ...js.configs.recommended, files: ["**/*.{js,mjs,cjs,jsx}"], @@ -24,15 +17,8 @@ export default [ // Disable react-in-jsx-scope for React 17+ (not needed) files: ['**/*.{tsx,jsx}'], rules: { - ...pluginReact.configs.recommended.rules, - "react/react-in-jsx-scope": "off", - "react/prop-types": "off", - "@typescript-eslint/no-unused-vars": ["error"], - }, - settings: { - react: { - version: "detect", - }, + 'react/react-in-jsx-scope': 'off', + 'react/jsx-uses-react': 'off', }, }, { @@ -59,4 +45,4 @@ export default [ plugins: { css }, language: "css/css", }, -]); \ No newline at end of file +]); From 01bf2060e2a5dd2a718d6ae45b826dad22080200 Mon Sep 17 00:00:00 2001 From: Amitjoiya Date: Tue, 11 Nov 2025 11:48:07 +0530 Subject: [PATCH 03/12] refactor: replaced Tailwind with MUI and segregated blocks as per maintainer feedback --- .../project/components/project-content.tsx | 228 ++-- package-lock.json | 1015 +---------------- package.json | 7 +- 3 files changed, 145 insertions(+), 1105 deletions(-) diff --git a/client/src/modules/project/components/project-content.tsx b/client/src/modules/project/components/project-content.tsx index d08c0372..d9180400 100644 --- a/client/src/modules/project/components/project-content.tsx +++ b/client/src/modules/project/components/project-content.tsx @@ -1,109 +1,151 @@ /* eslint-disable react/prop-types */ import { useState } from 'react'; +import { Box, Typography, Button } from '@mui/material'; -const ProjectContent = ({ block }) => { - const { type, data } = block; - - if (type === 'paragraph') { - return

    ; - } +const ParagraphBlock = ({ data }) => ( + +); - if (type === 'header') { - const Tag = data?.level === 3 ? 'h3' : 'h2'; - const size = data?.level === 3 ? 'text-3xl' : 'text-4xl'; - return ( - - ); - } +const HeaderBlock = ({ data }) => { + const Tag = data?.level === 3 ? 'h3' : 'h2'; + const size = data?.level === 3 ? 'h5' : 'h4'; + return ( + + ); +}; - if (type === 'image') { - return ( -

    - {data?.caption - {data?.caption && ( -

    - {data.caption} -

    - )} -
    - ); - } +const ImageBlock = ({ data }) => ( + + {data?.caption + {data?.caption && ( + + {data.caption} + + )} + +); - if (type === 'quote') { - return ( -
    -

    {data?.text}

    - {data?.caption && ( -

    {data.caption}

    - )} -
    - ); - } +const QuoteBlock = ({ data }) => ( + + + {data?.text} + + {data?.caption && ( + + {data.caption} + + )} + +); - if (type === 'list') { - const Tag = data?.style === 'ordered' ? 'ol' : 'ul'; - const listClass = data?.style === 'ordered' ? 'list-decimal' : 'list-disc'; - return ( - - {data?.items?.map((item, i) => ( -
  • { + const Tag = data?.style === 'ordered' ? 'ol' : 'ul'; + const styleType = data?.style === 'ordered' ? 'decimal' : 'disc'; + return ( + + {data?.items?.map((item, i) => ( +
  • + - ))} - - ); - } +
  • + ))} + + ); +}; - if (type === 'code') { - const codeText = data?.code || ''; - const [copied, setCopied] = useState(false); +const CodeBlock = ({ data }) => { + const codeText = data?.code || ''; + const [copied, setCopied] = useState(false); - const handleCopy = async () => { - try { - await navigator.clipboard.writeText(codeText); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - } catch { - const ta = document.createElement('textarea'); - ta.value = codeText; - document.body.appendChild(ta); - ta.select(); - document.execCommand('copy'); - document.body.removeChild(ta); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - } - }; + const handleCopy = async () => { + try { + await navigator.clipboard.writeText(codeText); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch { + setCopied(false); + } + }; - return ( -
    -
    - {data?.language && ( - - {data.language} - - )} - -
    -
    -          {codeText}
    -        
    -
    - ); - } + return ( + + {data?.language && ( + + {data.language} + + )} + + + {codeText} + + + ); +}; - return null; +const ProjectContent = ({ block }) => { + const { type, data } = block; + + switch (type) { + case 'paragraph': + return ; + case 'header': + return ; + case 'image': + return ; + case 'quote': + return ; + case 'list': + return ; + case 'code': + return ; + default: + return null; + } }; export default ProjectContent; diff --git a/package-lock.json b/package-lock.json index f3e3841a..4b3c9ffe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,261 +10,17 @@ "license": "ISC", "devDependencies": { "@eslint/css": "^0.10.0", - "@eslint/js": "^9.39.1", + "@eslint/js": "^9.34.0", "@eslint/json": "^0.13.1", - "@typescript-eslint/eslint-plugin": "^8.46.3", - "@typescript-eslint/parser": "^8.46.3", "concurrently": "^9.2.0", "eslint": "^9.34.0", "eslint-plugin-react": "^7.37.5", - "eslint-plugin-react-hooks": "^7.0.1", - "globals": "^16.5.0", + "globals": "^16.3.0", "husky": "^9.1.7", "lint-staged": "^16.1.5", "prettier": "^3.6.2" } }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", - "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", - "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", - "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.5" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", - "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.5", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", @@ -412,9 +168,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.39.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", - "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "version": "9.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", + "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", "dev": true, "license": "MIT", "engines": { @@ -552,94 +308,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -654,285 +322,12 @@ "dev": true, "license": "MIT" }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.46.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.3.tgz", - "integrity": "sha512-sbaQ27XBUopBkRiuY/P9sWGOWUW4rl8fDoHIUmLpZd8uldsTyB4/Zg6bWTegPoTLnKj9Hqgn3QD6cjPNB32Odw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.46.3", - "@typescript-eslint/type-utils": "8.46.3", - "@typescript-eslint/utils": "8.46.3", - "@typescript-eslint/visitor-keys": "8.46.3", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.46.3", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.46.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.3.tgz", - "integrity": "sha512-6m1I5RmHBGTnUGS113G04DMu3CpSdxCAU/UvtjNWL4Nuf3MW9tQhiJqRlHzChIkhy6kZSAQmc+I1bcGjE3yNKg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@typescript-eslint/scope-manager": "8.46.3", - "@typescript-eslint/types": "8.46.3", - "@typescript-eslint/typescript-estree": "8.46.3", - "@typescript-eslint/visitor-keys": "8.46.3", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.46.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.3.tgz", - "integrity": "sha512-Fz8yFXsp2wDFeUElO88S9n4w1I4CWDTXDqDr9gYvZgUpwXQqmZBr9+NTTql5R3J7+hrJZPdpiWaB9VNhAKYLuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.46.3", - "@typescript-eslint/types": "^8.46.3", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.46.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.3.tgz", - "integrity": "sha512-FCi7Y1zgrmxp3DfWfr+3m9ansUUFoy8dkEdeQSgA9gbm8DaHYvZCdkFRQrtKiedFf3Ha6VmoqoAaP68+i+22kg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.46.3", - "@typescript-eslint/visitor-keys": "8.46.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.46.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.3.tgz", - "integrity": "sha512-GLupljMniHNIROP0zE7nCcybptolcH8QZfXOpCfhQDAdwJ/ZTlcaBOYebSOZotpti/3HrHSw7D3PZm75gYFsOA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.46.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.3.tgz", - "integrity": "sha512-ZPCADbr+qfz3aiTTYNNkCbUt+cjNwI/5McyANNrFBpVxPt7GqpEYz5ZfdwuFyGUnJ9FdDXbGODUu6iRCI6XRXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.46.3", - "@typescript-eslint/typescript-estree": "8.46.3", - "@typescript-eslint/utils": "8.46.3", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.46.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.3.tgz", - "integrity": "sha512-G7Ok9WN/ggW7e/tOf8TQYMaxgID3Iujn231hfi0Pc7ZheztIJVpO44ekY00b7akqc6nZcvregk0Jpah3kep6hA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.46.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.3.tgz", - "integrity": "sha512-f/NvtRjOm80BtNM5OQtlaBdM5BRFUv7gf381j9wygDNL+qOYSNOgtQ/DCndiYi80iIOv76QqaTmp4fa9hwI0OA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.46.3", - "@typescript-eslint/tsconfig-utils": "8.46.3", - "@typescript-eslint/types": "8.46.3", - "@typescript-eslint/visitor-keys": "8.46.3", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/typescript-estree/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/@typescript-eslint/utils": { - "version": "8.46.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.3.tgz", - "integrity": "sha512-VXw7qmdkucEx9WkmR3ld/u6VhRyKeiF1uxWwCy/iuNfokjJ7VhsgLSOTjsol8BunSw190zABzpwdNsze2Kpo4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.46.3", - "@typescript-eslint/types": "8.46.3", - "@typescript-eslint/typescript-estree": "8.46.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.46.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.3.tgz", - "integrity": "sha512-uk574k8IU0rOF/AjniX8qbLSGURJVUCeM5e4MIMKBFFi8weeiLrG1fyQejyLXQpRZbU/1BuQasleV/RfHC3hHg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.46.3", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1190,16 +585,6 @@ "dev": true, "license": "MIT" }, - "node_modules/baseline-browser-mapping": { - "version": "2.8.25", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.25.tgz", - "integrity": "sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -1224,41 +609,6 @@ "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.27.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", - "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "baseline-browser-mapping": "^2.8.19", - "caniuse-lite": "^1.0.30001751", - "electron-to-chromium": "^1.5.238", - "node-releases": "^2.0.26", - "update-browserslist-db": "^1.1.4" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -1319,27 +669,6 @@ "node": ">=6" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001754", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz", - "integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1553,13 +882,6 @@ "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1718,13 +1040,6 @@ "node": ">= 0.4" } }, - "node_modules/electron-to-chromium": { - "version": "1.5.249", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.249.tgz", - "integrity": "sha512-5vcfL3BBe++qZ5kuFhD/p8WOM1N9m3nwvJPULJx+4xf2usSlZFJ0qoNYO2fOX4hi3ocuDcmDobtA+5SFr4OmBg==", - "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", @@ -1951,7 +1266,6 @@ "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -2040,26 +1354,6 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", - "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.24.4", - "@babel/parser": "^7.24.4", - "hermes-parser": "^0.25.1", - "zod": "^3.25.0 || ^4.0.0", - "zod-validation-error": "^3.5.0 || ^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" - } - }, "node_modules/eslint-scope": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", @@ -2103,19 +1397,6 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/eslint/node_modules/@eslint/js": { - "version": "9.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", - "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, "node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -2194,36 +1475,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/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==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -2238,16 +1489,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -2369,16 +1610,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "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", @@ -2473,9 +1704,9 @@ } }, "node_modules/globals": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", - "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", "dev": true, "license": "MIT", "engines": { @@ -2515,13 +1746,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -2616,23 +1840,6 @@ "node": ">= 0.4" } }, - "node_modules/hermes-estree": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", - "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", - "dev": true, - "license": "MIT" - }, - "node_modules/hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", - "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "hermes-estree": "0.25.1" - } - }, "node_modules/husky": { "version": "9.1.7", "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", @@ -3160,19 +2367,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -3194,19 +2388,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -3346,16 +2527,6 @@ "loose-envify": "cli.js" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -3373,16 +2544,6 @@ "dev": true, "license": "CC0-1.0" }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -3450,13 +2611,6 @@ "dev": true, "license": "MIT" }, - "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "dev": true, - "license": "MIT" - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3689,13 +2843,6 @@ "dev": true, "license": "MIT" }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -3780,27 +2927,6 @@ "node": ">=6" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -3907,17 +3033,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, "node_modules/rfdc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", @@ -3925,30 +3040,6 @@ "dev": true, "license": "MIT" }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, "node_modules/rxjs": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", @@ -4458,19 +3549,6 @@ "tree-kill": "cli.js" } }, - "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -4569,21 +3647,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", @@ -4603,37 +3666,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/update-browserslist-db": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", - "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -4825,13 +3857,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, "node_modules/yaml": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", @@ -4934,30 +3959,6 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/zod": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", - "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", - "dev": true, - "license": "MIT", - "peer": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-validation-error": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", - "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "zod": "^3.25.0 || ^4.0.0" - } } } } diff --git a/package.json b/package.json index c42b6c6c..81777c0d 100644 --- a/package.json +++ b/package.json @@ -43,15 +43,12 @@ }, "devDependencies": { "@eslint/css": "^0.10.0", - "@eslint/js": "^9.39.1", + "@eslint/js": "^9.34.0", "@eslint/json": "^0.13.1", - "@typescript-eslint/eslint-plugin": "^8.46.3", - "@typescript-eslint/parser": "^8.46.3", "concurrently": "^9.2.0", "eslint": "^9.34.0", "eslint-plugin-react": "^7.37.5", - "eslint-plugin-react-hooks": "^7.0.1", - "globals": "^16.5.0", + "globals": "^16.3.0", "husky": "^9.1.7", "lint-staged": "^16.1.5", "prettier": "^3.6.2" From 0bbe2893543a2e9878738821323e41769c6363f0 Mon Sep 17 00:00:00 2001 From: Amitjoiya Date: Thu, 13 Nov 2025 11:45:20 +0530 Subject: [PATCH 04/12] fix(project): resolve TS/ESLint issues in project-content.tsx (no-explicit-any) --- .../project/components/project-content.tsx | 183 +++++++++--------- 1 file changed, 90 insertions(+), 93 deletions(-) diff --git a/client/src/modules/project/components/project-content.tsx b/client/src/modules/project/components/project-content.tsx index d9180400..92043ae5 100644 --- a/client/src/modules/project/components/project-content.tsx +++ b/client/src/modules/project/components/project-content.tsx @@ -1,78 +1,89 @@ -/* eslint-disable react/prop-types */ -import { useState } from 'react'; -import { Box, Typography, Button } from '@mui/material'; +import { OutputBlockData } from "@editorjs/editorjs"; +import React, { useState } from "react"; +import { Box, Typography, Button } from "@mui/material"; -const ParagraphBlock = ({ data }) => ( - -); +interface ProjectContentProps { + block: OutputBlockData; +} -const HeaderBlock = ({ data }) => { - const Tag = data?.level === 3 ? 'h3' : 'h2'; - const size = data?.level === 3 ? 'h5' : 'h4'; +type EJData = Record | undefined; + +const ParagraphBlock = ({ data }: { data?: EJData }) => { + const text = (data && (data["text"] as string)) || ""; + return ; +}; + +const HeaderBlock = ({ data }: { data?: EJData }) => { + const level = (data && (data["level"] as number)) || 2; + const Tag = level === 3 ? "h3" : "h2"; + const size = level === 3 ? "h5" : "h4"; + const text = (data && (data["text"] as string)) || ""; return ( ); }; -const ImageBlock = ({ data }) => ( - - {data?.caption - {data?.caption && ( - - {data.caption} - - )} - -); +const ImageBlock = ({ data }: { data?: EJData }) => { + const file = data && (data["file"] as EJData); + const url = (file && (file["url"] as string)) || ""; + const caption = (data && (data["caption"] as string)) || ""; + return ( + + {caption} + {caption ? ( + + {caption} + + ) : null} + + ); +}; -const QuoteBlock = ({ data }) => ( - - - {data?.text} - - {data?.caption && ( - - {data.caption} +const QuoteBlock = ({ data }: { data?: EJData }) => { + const text = (data && (data["text"] as string)) || ""; + const caption = (data && (data["caption"] as string)) || ""; + return ( + + + {text} - )} - -); + {caption ? {caption} : null} + + ); +}; -const ListBlock = ({ data }) => { - const Tag = data?.style === 'ordered' ? 'ol' : 'ul'; - const styleType = data?.style === 'ordered' ? 'decimal' : 'disc'; +const ListBlock = ({ data }: { data?: EJData }) => { + const style = (data && (data["style"] as string)) || "unordered"; + const Tag = style === "ordered" ? "ol" : "ul"; + const styleType = style === "ordered" ? "decimal" : "disc"; + const items = (data && (data["items"] as string[])) || []; return ( - - {data?.items?.map((item, i) => ( + + {items.map((item, i) => (
  • - +
  • ))}
    ); }; -const CodeBlock = ({ data }) => { - const codeText = data?.code || ''; +const CodeBlock = ({ data }: { data?: EJData }) => { + const codeText = (data && (data["code"] as string)) || ""; + const language = (data && (data["language"] as string)) || ""; const [copied, setCopied] = useState(false); const handleCopy = async () => { @@ -88,61 +99,47 @@ const CodeBlock = ({ data }) => { return ( - {data?.language && ( + {language ? ( - {data.language} + {language} - )} - - + {codeText} ); }; -const ProjectContent = ({ block }) => { +const ProjectContent = ({ block }: ProjectContentProps) => { const { type, data } = block; switch (type) { - case 'paragraph': - return ; - case 'header': - return ; - case 'image': - return ; - case 'quote': - return ; - case 'list': - return ; - case 'code': - return ; + case "paragraph": + return ; + case "header": + return ; + case "image": + return ; + case "quote": + return ; + case "list": + return ; + case "code": + return ; default: return null; } From dbc12fbdcbd038d8e4c297a85be48422f55a0ee4 Mon Sep 17 00:00:00 2001 From: Amitjoiya Date: Mon, 17 Nov 2025 10:41:25 +0530 Subject: [PATCH 05/12] Migrate Manage Projects UI to MUI (cards + search) --- .../components/draft-projects.tsx | 64 ++++------ .../components/publish-projects.tsx | 115 ++++++------------ client/src/modules/manage-projects/index.tsx | 28 +++-- 3 files changed, 85 insertions(+), 122 deletions(-) diff --git a/client/src/modules/manage-projects/components/draft-projects.tsx b/client/src/modules/manage-projects/components/draft-projects.tsx index 731ac097..16a4c043 100644 --- a/client/src/modules/manage-projects/components/draft-projects.tsx +++ b/client/src/modules/manage-projects/components/draft-projects.tsx @@ -1,3 +1,7 @@ +import { Link } from 'react-router-dom'; +import { Box, Typography, Button, Card, CardContent, Stack } from '@mui/material'; +import { Project, deleteProject } from './publish-projects'; + const ManageDraftProjectPost = ({ project }: { project: Project }) => { const { title, des } = project; let { index = 0 } = project; @@ -5,44 +9,28 @@ const ManageDraftProjectPost = ({ project }: { project: Project }) => { index++; return ( -
    -

    - {index < 10 ? '0' + index : index} -

    - -
    -

    {title}

    - -

    - {des?.length ? des : 'No Description'} -

    - -
    - - Edit - - - -
    -
    - -
    - -
    -
    + + + + + {index < 10 ? '0' + index : index} + + + + {title} + + + {des?.length ? des : 'No Description'} + + + + + + + + + + ); }; diff --git a/client/src/modules/manage-projects/components/publish-projects.tsx b/client/src/modules/manage-projects/components/publish-projects.tsx index bcdbfa93..43e54607 100644 --- a/client/src/modules/manage-projects/components/publish-projects.tsx +++ b/client/src/modules/manage-projects/components/publish-projects.tsx @@ -4,6 +4,7 @@ import { useState } from 'react'; import { useAtom } from 'jotai'; import { UserAtom } from '../../../../shared/states/user'; import axios from 'axios'; +import { Box, Typography, Button, Card, CardContent, CardActions, Avatar, Stack } from '@mui/material'; import { SetStateAction } from 'react'; import { AllProjectsData } from '../../../../infra/rest/typings'; @@ -15,7 +16,7 @@ interface ProjectStats { [key: string]: number; // Allow dynamic key access } -interface Project { +export interface Project { _id?: string; project_id: string; title: string; @@ -29,32 +30,20 @@ interface Project { const ProjectStats = ({ stats }: { stats: ProjectStats }) => { return ( -
    - {Object.keys(stats).map((key, i) => { - return !key.includes('parent') ? ( -
    -

    - {stats[key].toLocaleString()} -

    -

    - {key.split('_')[1]} -

    -
    - ) : ( - '' - ); - })} -
    + + {Object.keys(stats).map((key, i) => + !key.includes('parent') ? ( + + {stats[key].toLocaleString()} + {key.split('_')[1]} + + ) : null + )} + ); }; -const deleteProject = ( +export const deleteProject = ( project: Project, access_token: string, target: EventTarget | null @@ -123,60 +112,36 @@ const ManagePublishedProjectCard = ({ project }: { project: Project }) => { const [showStat, setShowStat] = useState(false); return ( - <> -
    - - -
    -
    - - {title} - - -

    Published on {getDay(publishedAt)}

    -
    - -
    - - Edit - - - - - -
    -
    - -
    - {activity && } -
    -
    + + + + {banner ? ( + + ) : ( + + )} + + + {title} + Published on {getDay(publishedAt)} + + + + + + + + + {activity && } + + {showStat ? ( -
    + {activity && } -
    - ) : ( - '' - )} - + + ) : null} +
    ); }; diff --git a/client/src/modules/manage-projects/index.tsx b/client/src/modules/manage-projects/index.tsx index 80b68dd1..d200975c 100644 --- a/client/src/modules/manage-projects/index.tsx +++ b/client/src/modules/manage-projects/index.tsx @@ -5,6 +5,8 @@ import InPageNavigation from '../../shared/components/molecules/page-navigation' import NoDataMessageBox from '../../shared/components/atoms/no-data-msg'; import ManagePublishedProjectCard from './components/publish-projects'; import ManageDraftProjectPost from './components/draft-projects'; +import { Box, Typography, TextField, InputAdornment } from '@mui/material'; +import SearchIcon from '@mui/icons-material/Search'; const ManageProjects = () => { const [projects, setProjects] = useAtom(AllProjectsAtom); @@ -84,21 +86,29 @@ const ManageProjects = () => { return ( <> -

    Manage Projects

    -
    - + Manage Projects + + + + + + + ), + }} /> - - -
    +
    { From 539950a7e48b54c18b3087d23db05eeb8622a677 Mon Sep 17 00:00:00 2001 From: Amitjoiya Date: Mon, 17 Nov 2025 10:51:15 +0530 Subject: [PATCH 06/12] chore: format manage-projects + project content with Prettier --- .../components/draft-projects.tsx | 30 ++++++++++++++----- .../components/publish-projects.tsx | 21 +++++++++++-- .../project/components/project-content.tsx | 6 ++-- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/client/src/modules/manage-projects/components/draft-projects.tsx b/client/src/modules/manage-projects/components/draft-projects.tsx index 16a4c043..47f6b98a 100644 --- a/client/src/modules/manage-projects/components/draft-projects.tsx +++ b/client/src/modules/manage-projects/components/draft-projects.tsx @@ -13,19 +13,35 @@ const ManageDraftProjectPost = ({ project }: { project: Project }) => { - {index < 10 ? '0' + index : index} + {index < 10 ? '0' + index : index} - {title} + + {title} + - - {des?.length ? des : 'No Description'} - + + {des?.length ? des : 'No Description'} + - - + + diff --git a/client/src/modules/manage-projects/components/publish-projects.tsx b/client/src/modules/manage-projects/components/publish-projects.tsx index 43e54607..d0d08c2b 100644 --- a/client/src/modules/manage-projects/components/publish-projects.tsx +++ b/client/src/modules/manage-projects/components/publish-projects.tsx @@ -4,7 +4,16 @@ import { useState } from 'react'; import { useAtom } from 'jotai'; import { UserAtom } from '../../../../shared/states/user'; import axios from 'axios'; -import { Box, Typography, Button, Card, CardContent, CardActions, Avatar, Stack } from '@mui/material'; +import { + Box, + Typography, + Button, + Card, + CardContent, + CardActions, + Avatar, + Stack, +} from '@mui/material'; import { SetStateAction } from 'react'; import { AllProjectsData } from '../../../../infra/rest/typings'; @@ -30,10 +39,16 @@ export interface Project { const ProjectStats = ({ stats }: { stats: ProjectStats }) => { return ( - + {Object.keys(stats).map((key, i) => !key.includes('parent') ? ( - + {stats[key].toLocaleString()} {key.split('_')[1]} diff --git a/client/src/modules/project/components/project-content.tsx b/client/src/modules/project/components/project-content.tsx index 92043ae5..1c67b6cd 100644 --- a/client/src/modules/project/components/project-content.tsx +++ b/client/src/modules/project/components/project-content.tsx @@ -2,7 +2,7 @@ import { OutputBlockData } from "@editorjs/editorjs"; import React, { useState } from "react"; import { Box, Typography, Button } from "@mui/material"; -interface ProjectContentProps { +const ParagraphBlock = ({ data }: { data?: EJData }) => { block: OutputBlockData; } @@ -16,14 +16,14 @@ const ParagraphBlock = ({ data }: { data?: EJData }) => { const HeaderBlock = ({ data }: { data?: EJData }) => { const level = (data && (data["level"] as number)) || 2; const Tag = level === 3 ? "h3" : "h2"; - const size = level === 3 ? "h5" : "h4"; + const size = level === 3 ? 'h5' : 'h4'; const text = (data && (data["text"] as string)) || ""; return ( ); }; From 1b3b90114715ff850d9ebdf72f3fcaf53560413d Mon Sep 17 00:00:00 2001 From: Amitjoiya Date: Mon, 17 Nov 2025 10:59:28 +0530 Subject: [PATCH 07/12] fix: move deleteProject & Project type to utils; remove local exports; fix project-content --- .../components/draft-projects.tsx | 65 ++++--- .../components/publish-projects.tsx | 163 +++++++++--------- .../manage-projects/components/utils.ts | 82 +++++++++ client/src/modules/manage-projects/index.tsx | 7 +- .../project/components/project-content.tsx | 115 +++++++----- 5 files changed, 276 insertions(+), 156 deletions(-) create mode 100644 client/src/modules/manage-projects/components/utils.ts diff --git a/client/src/modules/manage-projects/components/draft-projects.tsx b/client/src/modules/manage-projects/components/draft-projects.tsx index 47f6b98a..1301979f 100644 --- a/client/src/modules/manage-projects/components/draft-projects.tsx +++ b/client/src/modules/manage-projects/components/draft-projects.tsx @@ -1,6 +1,13 @@ import { Link } from 'react-router-dom'; -import { Box, Typography, Button, Card, CardContent, Stack } from '@mui/material'; -import { Project, deleteProject } from './publish-projects'; +import { + Box, + Typography, + Button, + Card, + CardContent, + Stack, +} from '@mui/material'; +import { Project, deleteProject } from './utils'; const ManageDraftProjectPost = ({ project }: { project: Project }) => { const { title, des } = project; @@ -11,37 +18,43 @@ const ManageDraftProjectPost = ({ project }: { project: Project }) => { return ( - + - {index < 10 ? '0' + index : index} + + {index < 10 ? '0' + index : index} + - - {title} - + + {title} + - - {des?.length ? des : 'No Description'} - + + {des?.length ? des : 'No Description'} + - - + + diff --git a/client/src/modules/manage-projects/components/publish-projects.tsx b/client/src/modules/manage-projects/components/publish-projects.tsx index d0d08c2b..17f2b800 100644 --- a/client/src/modules/manage-projects/components/publish-projects.tsx +++ b/client/src/modules/manage-projects/components/publish-projects.tsx @@ -3,7 +3,6 @@ import { getDay } from '../../../../shared/utils/date'; import { useState } from 'react'; import { useAtom } from 'jotai'; import { UserAtom } from '../../../../shared/states/user'; -import axios from 'axios'; import { Box, Typography, @@ -14,9 +13,7 @@ import { Avatar, Stack, } from '@mui/material'; - -import { SetStateAction } from 'react'; -import { AllProjectsData } from '../../../../infra/rest/typings'; +import { Project, deleteProject } from './utils'; interface ProjectStats { total_likes: number; @@ -25,17 +22,8 @@ interface ProjectStats { [key: string]: number; // Allow dynamic key access } -export interface Project { - _id?: string; - project_id: string; - title: string; - des?: string; - banner?: string; - publishedAt: string; - activity?: ProjectStats; - index?: number; - setStateFunc?: (value: SetStateAction) => void; -} +// Project type and deleteProject helper are moved to ./utils to avoid exporting non-component +// functions from this file (react-refresh requirement). const ProjectStats = ({ stats }: { stats: ProjectStats }) => { return ( @@ -47,10 +35,21 @@ const ProjectStats = ({ stats }: { stats: ProjectStats }) => { !key.includes('parent') ? ( {stats[key].toLocaleString()} - {key.split('_')[1]} + + {key.split('_')[1]} + ) : null )} @@ -58,65 +57,7 @@ const ProjectStats = ({ stats }: { stats: ProjectStats }) => { ); }; -export const deleteProject = ( - project: Project, - access_token: string, - target: EventTarget | null -) => { - const { index, project_id, setStateFunc } = project; - - if (!(target instanceof HTMLElement)) return; - - target.setAttribute('disabled', 'true'); - - axios - .post( - import.meta.env.VITE_SERVER_DOMAIN + '/api/project/delete', - { project_id }, - { - headers: { - Authorization: `Bearer ${access_token}`, - }, - } - ) - .then(() => { - target.removeAttribute('disabled'); - - if (setStateFunc) { - setStateFunc((preVal: AllProjectsData | null) => { - if (!preVal) return null; - - const { deletedDocCount = 0, totalDocs = 0, results = [] } = preVal; - - if ( - typeof index === 'number' && - index >= 0 && - index < results.length - ) { - results.splice(index, 1); - } - - const newTotalDocs = totalDocs - 1; - const newDeletedCount = deletedDocCount + 1; - - if (!results.length && newTotalDocs > 0) { - return null; - } - - return { - ...preVal, - results, - totalDocs: newTotalDocs, - deletedDocCount: newDeletedCount, - }; - }); - } - }) - .catch(err => { - console.error('Error deleting project:', err); - target.removeAttribute('disabled'); - }); -}; +// deleteProject is imported from ./utils const ManagePublishedProjectCard = ({ project }: { project: Project }) => { const { banner, project_id, title, publishedAt, activity } = project; @@ -129,25 +70,77 @@ const ManagePublishedProjectCard = ({ project }: { project: Project }) => { return ( - + {banner ? ( - + ) : ( - + )} - {title} - Published on {getDay(publishedAt)} + + {title} + + + Published on {getDay(publishedAt)} + - - - + + + - {activity && } + + {activity && } + diff --git a/client/src/modules/manage-projects/components/utils.ts b/client/src/modules/manage-projects/components/utils.ts new file mode 100644 index 00000000..c7180183 --- /dev/null +++ b/client/src/modules/manage-projects/components/utils.ts @@ -0,0 +1,82 @@ +import axios from 'axios'; +import { SetStateAction } from 'react'; +import { AllProjectsData } from '../../../../infra/rest/typings'; + +interface ProjectStats { + total_likes: number; + total_comments: number; + total_reads: number; + [key: string]: number; +} + +export interface Project { + _id?: string; + project_id: string; + title: string; + des?: string; + banner?: string; + publishedAt: string; + activity?: ProjectStats; + index?: number; + setStateFunc?: (value: SetStateAction) => void; +} + +export const deleteProject = ( + project: Project, + access_token: string, + target: EventTarget | null +) => { + const { index, project_id, setStateFunc } = project; + + if (!(target instanceof HTMLElement)) return; + + target.setAttribute('disabled', 'true'); + + axios + .post( + import.meta.env.VITE_SERVER_DOMAIN + '/api/project/delete', + { project_id }, + { + headers: { + Authorization: `Bearer ${access_token}`, + }, + } + ) + .then(() => { + target.removeAttribute('disabled'); + + if (setStateFunc) { + setStateFunc((preVal: AllProjectsData | null) => { + if (!preVal) return null; + + const { deletedDocCount = 0, totalDocs = 0, results = [] } = preVal; + + if ( + typeof index === 'number' && + index >= 0 && + index < results.length + ) { + results.splice(index, 1); + } + + const newTotalDocs = totalDocs - 1; + const newDeletedCount = deletedDocCount + 1; + + if (!results.length && newTotalDocs > 0) { + return null; + } + + return { + ...preVal, + results, + totalDocs: newTotalDocs, + deletedDocCount: newDeletedCount, + }; + }); + } + }) + .catch(err => { + console.error('Error deleting project:', err); + target.removeAttribute('disabled'); + }); +}; diff --git a/client/src/modules/manage-projects/index.tsx b/client/src/modules/manage-projects/index.tsx index d200975c..d942a775 100644 --- a/client/src/modules/manage-projects/index.tsx +++ b/client/src/modules/manage-projects/index.tsx @@ -86,7 +86,10 @@ const ManageProjects = () => { return ( <> - + Manage Projects @@ -108,7 +111,7 @@ const ManageProjects = () => { { diff --git a/client/src/modules/project/components/project-content.tsx b/client/src/modules/project/components/project-content.tsx index 1c67b6cd..38f520d9 100644 --- a/client/src/modules/project/components/project-content.tsx +++ b/client/src/modules/project/components/project-content.tsx @@ -1,40 +1,44 @@ -import { OutputBlockData } from "@editorjs/editorjs"; -import React, { useState } from "react"; -import { Box, Typography, Button } from "@mui/material"; +import { OutputBlockData } from '@editorjs/editorjs'; +import React, { useState } from 'react'; +import { Box, Typography, Button } from '@mui/material'; -const ParagraphBlock = ({ data }: { data?: EJData }) => { +interface ProjectContentProps { block: OutputBlockData; } type EJData = Record | undefined; const ParagraphBlock = ({ data }: { data?: EJData }) => { - const text = (data && (data["text"] as string)) || ""; + const text = (data && (data['text'] as string)) || ''; return ; }; const HeaderBlock = ({ data }: { data?: EJData }) => { - const level = (data && (data["level"] as number)) || 2; - const Tag = level === 3 ? "h3" : "h2"; - const size = level === 3 ? 'h5' : 'h4'; - const text = (data && (data["text"] as string)) || ""; + const level = (data && (data['level'] as number)) || 2; + const Tag = level === 3 ? 'h3' : 'h2'; + const size = level === 3 ? 'h5' : 'h4'; + const text = (data && (data['text'] as string)) || ''; return ( ); }; const ImageBlock = ({ data }: { data?: EJData }) => { - const file = data && (data["file"] as EJData); - const url = (file && (file["url"] as string)) || ""; - const caption = (data && (data["caption"] as string)) || ""; + const file = data && (data['file'] as EJData); + const url = (file && (file['url'] as string)) || ''; + const caption = (data && (data['caption'] as string)) || ''; return ( - {caption} + {caption} {caption ? ( {caption} @@ -45,13 +49,13 @@ const ImageBlock = ({ data }: { data?: EJData }) => { }; const QuoteBlock = ({ data }: { data?: EJData }) => { - const text = (data && (data["text"] as string)) || ""; - const caption = (data && (data["caption"] as string)) || ""; + const text = (data && (data['text'] as string)) || ''; + const caption = (data && (data['caption'] as string)) || ''; return ( { {text} - {caption ? {caption} : null} + {caption ? ( + + {caption} + + ) : null} ); }; const ListBlock = ({ data }: { data?: EJData }) => { - const style = (data && (data["style"] as string)) || "unordered"; - const Tag = style === "ordered" ? "ol" : "ul"; - const styleType = style === "ordered" ? "decimal" : "disc"; - const items = (data && (data["items"] as string[])) || []; + const style = (data && (data['style'] as string)) || 'unordered'; + const Tag = style === 'ordered' ? 'ol' : 'ul'; + const styleType = style === 'ordered' ? 'decimal' : 'disc'; + const items = (data && (data['items'] as string[])) || []; return ( - + {items.map((item, i) => (
  • - +
  • ))}
    @@ -82,8 +97,8 @@ const ListBlock = ({ data }: { data?: EJData }) => { }; const CodeBlock = ({ data }: { data?: EJData }) => { - const codeText = (data && (data["code"] as string)) || ""; - const language = (data && (data["language"] as string)) || ""; + const codeText = (data && (data['code'] as string)) || ''; + const language = (data && (data['language'] as string)) || ''; const [copied, setCopied] = useState(false); const handleCopy = async () => { @@ -99,25 +114,39 @@ const CodeBlock = ({ data }: { data?: EJData }) => { return ( {language ? ( {language} ) : null} - - + {codeText} @@ -128,17 +157,17 @@ const ProjectContent = ({ block }: ProjectContentProps) => { const { type, data } = block; switch (type) { - case "paragraph": + case 'paragraph': return ; - case "header": + case 'header': return ; - case "image": + case 'image': return ; - case "quote": + case 'quote': return ; - case "list": + case 'list': return ; - case "code": + case 'code': return ; default: return null; From 772a6311a98bfab8f3c09565ebd2927919e0806d Mon Sep 17 00:00:00 2001 From: Amitjoiya Date: Mon, 17 Nov 2025 23:17:09 +0530 Subject: [PATCH 08/12] feat(manage-projects): migrate UI to MUI and enable route --- client/.vercelignore | 14 +++--- client/src/App.tsx | 4 +- .../components/draft-projects.tsx | 19 ++++++++ .../components/publish-projects.tsx | 13 +----- client/src/modules/manage-projects/index.tsx | 43 +++++++++---------- .../modules/manage-projects/states/index.ts | 6 +++ 6 files changed, 56 insertions(+), 43 deletions(-) diff --git a/client/.vercelignore b/client/.vercelignore index 051e59ff..2627ca56 100644 --- a/client/.vercelignore +++ b/client/.vercelignore @@ -1,8 +1,6 @@ -projects/* -server/* -client/src/modules/edit-profile/* -client/src/modules/manage-projects/* -client/src/modules/notification/* -src/modules/edit-profile/* -src/modules/manage-projects/* -src/modules/notification/* +projects/* +server/* +client/src/modules/edit-profile/* +client/src/modules/notification/* +src/modules/edit-profile/* +src/modules/notification/* diff --git a/client/src/App.tsx b/client/src/App.tsx index b82e81a1..755f0019 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -13,7 +13,7 @@ import Profile from './modules/profile'; import Project from './modules/project'; import Sidebar from './shared/components/organisms/sidebar'; // import ChangePassword from "./modules/change-password"; -// import ManageProjects from "./modules/manage-projects"; +import ManageProjects from "./modules/manage-projects"; // import EditProfile from "./modules/edit-profile"; // import Notifications from "./modules/notification"; @@ -35,7 +35,7 @@ function App() { } /> }> - {/* } /> */} + } /> {/* } /> */} }> diff --git a/client/src/modules/manage-projects/components/draft-projects.tsx b/client/src/modules/manage-projects/components/draft-projects.tsx index 1301979f..0e466d6e 100644 --- a/client/src/modules/manage-projects/components/draft-projects.tsx +++ b/client/src/modules/manage-projects/components/draft-projects.tsx @@ -1,4 +1,5 @@ import { Link } from 'react-router-dom'; +<<<<<<< HEAD import { Box, Typography, @@ -8,6 +9,9 @@ import { Stack, } from '@mui/material'; import { Project, deleteProject } from './utils'; +======= +import { Box, Typography, Button, Card, CardContent, Stack } from '@mui/material'; +>>>>>>> 9e71369 (feat(manage-projects): migrate UI to MUI and enable route) const ManageDraftProjectPost = ({ project }: { project: Project }) => { const { title, des } = project; @@ -18,6 +22,7 @@ const ManageDraftProjectPost = ({ project }: { project: Project }) => { return ( +<<<<<<< HEAD { {title} +======= + + + {index < 10 ? '0' + index : index} + + + + {title} +>>>>>>> 9e71369 (feat(manage-projects): migrate UI to MUI and enable route) {des?.length ? des : 'No Description'} +<<<<<<< HEAD +======= + + +>>>>>>> 9e71369 (feat(manage-projects): migrate UI to MUI and enable route) diff --git a/client/src/modules/manage-projects/components/publish-projects.tsx b/client/src/modules/manage-projects/components/publish-projects.tsx index 17f2b800..e1dfe861 100644 --- a/client/src/modules/manage-projects/components/publish-projects.tsx +++ b/client/src/modules/manage-projects/components/publish-projects.tsx @@ -2,17 +2,8 @@ import { Link } from 'react-router-dom'; import { getDay } from '../../../../shared/utils/date'; import { useState } from 'react'; import { useAtom } from 'jotai'; -import { UserAtom } from '../../../../shared/states/user'; -import { - Box, - Typography, - Button, - Card, - CardContent, - CardActions, - Avatar, - Stack, -} from '@mui/material'; +import { UserAtom } from '../../../infra/states/user'; +import { Box, Typography, Button, Card, CardContent, CardActions, Avatar, Stack } from '@mui/material'; import { Project, deleteProject } from './utils'; interface ProjectStats { diff --git a/client/src/modules/manage-projects/index.tsx b/client/src/modules/manage-projects/index.tsx index d942a775..a0ab4b34 100644 --- a/client/src/modules/manage-projects/index.tsx +++ b/client/src/modules/manage-projects/index.tsx @@ -5,8 +5,13 @@ import InPageNavigation from '../../shared/components/molecules/page-navigation' import NoDataMessageBox from '../../shared/components/atoms/no-data-msg'; import ManagePublishedProjectCard from './components/publish-projects'; import ManageDraftProjectPost from './components/draft-projects'; -import { Box, Typography, TextField, InputAdornment } from '@mui/material'; +import { Box, Typography, TextField, InputAdornment, CircularProgress } from '@mui/material'; import SearchIcon from '@mui/icons-material/Search'; +import { AllProjectsAtom, DraftProjectAtom } from './states'; +import { UserAtom } from '../../infra/states/user'; +import { filterPaginationData } from '../../shared/requests/filter-pagination-data'; +import LoadMoreDataBtn from '../../shared/components/molecules/load-more-data'; +import { userProjects } from '../../infra/rest/apis/project'; const ManageProjects = () => { const [projects, setProjects] = useAtom(AllProjectsAtom); @@ -17,20 +22,16 @@ const ManageProjects = () => { const [query, setQuery] = useState(''); const getProjects = useCallback( - (params: Record) => { - const { page = 1, draft = false, deletedDocCount = 0 } = params; - - userWrittenProjects({ - page: page as number, - draft: draft as boolean, - query, - deletedDocCount: deletedDocCount as number, - }) + (params: { page?: number; draft?: boolean; deletedDocCount?: number } | undefined) => { + const { page = 1, draft = false, deletedDocCount = 0 } = params || {}; + + // userProjects expects is_draft instead of draft + userProjects({ is_draft: draft, page, query, deletedDocCount }) .then(async data => { const formattedData = (await filterPaginationData({ state: draft ? drafts : projects, data: data.projects || [], - page: page as number, + page: page, countRoute: '/search-projects-count', data_to_send: { query, @@ -38,7 +39,7 @@ const ManageProjects = () => { author: user.username || '', draft, }, - })) as AllProjectsData; + })); if (formattedData) { if (draft) { @@ -86,10 +87,7 @@ const ManageProjects = () => { return ( <> - + Manage Projects @@ -110,14 +108,13 @@ const ManageProjects = () => { />
    - + { // Published Projects projects === null ? ( - + + + ) : projects.results.length ? ( <> {projects.results.map((project, i) => { @@ -150,7 +147,9 @@ const ManageProjects = () => { { // Draft Projects drafts === null ? ( - + + + ) : drafts.results.length ? ( <> {drafts.results.map((project, i) => { diff --git a/client/src/modules/manage-projects/states/index.ts b/client/src/modules/manage-projects/states/index.ts index e69de29b..6b78c701 100644 --- a/client/src/modules/manage-projects/states/index.ts +++ b/client/src/modules/manage-projects/states/index.ts @@ -0,0 +1,6 @@ +import { atom } from 'jotai'; + +// Shared atoms for manage-projects module +// Use a permissive any for the pagination shape to avoid coupling to a specific typing export +export const AllProjectsAtom = atom(null); +export const DraftProjectAtom = atom(null); From e1843db4893076c28a86bff780d2fae9a1d09bec Mon Sep 17 00:00:00 2001 From: Amitjoiya Date: Mon, 17 Nov 2025 23:34:16 +0530 Subject: [PATCH 09/12] fix(manage-projects): add typed PaginatedProjects atom to avoid any --- client/src/App.tsx | 2 +- .../components/draft-projects.tsx | 19 -------- .../components/publish-projects.tsx | 11 ++++- client/src/modules/manage-projects/index.tsx | 46 +++++++++++++++---- .../modules/manage-projects/states/index.ts | 19 +++++--- 5 files changed, 62 insertions(+), 35 deletions(-) diff --git a/client/src/App.tsx b/client/src/App.tsx index 755f0019..36bd99e9 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -13,7 +13,7 @@ import Profile from './modules/profile'; import Project from './modules/project'; import Sidebar from './shared/components/organisms/sidebar'; // import ChangePassword from "./modules/change-password"; -import ManageProjects from "./modules/manage-projects"; +import ManageProjects from './modules/manage-projects'; // import EditProfile from "./modules/edit-profile"; // import Notifications from "./modules/notification"; diff --git a/client/src/modules/manage-projects/components/draft-projects.tsx b/client/src/modules/manage-projects/components/draft-projects.tsx index 0e466d6e..1301979f 100644 --- a/client/src/modules/manage-projects/components/draft-projects.tsx +++ b/client/src/modules/manage-projects/components/draft-projects.tsx @@ -1,5 +1,4 @@ import { Link } from 'react-router-dom'; -<<<<<<< HEAD import { Box, Typography, @@ -9,9 +8,6 @@ import { Stack, } from '@mui/material'; import { Project, deleteProject } from './utils'; -======= -import { Box, Typography, Button, Card, CardContent, Stack } from '@mui/material'; ->>>>>>> 9e71369 (feat(manage-projects): migrate UI to MUI and enable route) const ManageDraftProjectPost = ({ project }: { project: Project }) => { const { title, des } = project; @@ -22,7 +18,6 @@ const ManageDraftProjectPost = ({ project }: { project: Project }) => { return ( -<<<<<<< HEAD { {title} -======= - - - {index < 10 ? '0' + index : index} - - - - {title} ->>>>>>> 9e71369 (feat(manage-projects): migrate UI to MUI and enable route) {des?.length ? des : 'No Description'} -<<<<<<< HEAD -======= - - ->>>>>>> 9e71369 (feat(manage-projects): migrate UI to MUI and enable route) diff --git a/client/src/modules/manage-projects/components/publish-projects.tsx b/client/src/modules/manage-projects/components/publish-projects.tsx index e1dfe861..f479dc12 100644 --- a/client/src/modules/manage-projects/components/publish-projects.tsx +++ b/client/src/modules/manage-projects/components/publish-projects.tsx @@ -3,7 +3,16 @@ import { getDay } from '../../../../shared/utils/date'; import { useState } from 'react'; import { useAtom } from 'jotai'; import { UserAtom } from '../../../infra/states/user'; -import { Box, Typography, Button, Card, CardContent, CardActions, Avatar, Stack } from '@mui/material'; +import { + Box, + Typography, + Button, + Card, + CardContent, + CardActions, + Avatar, + Stack, +} from '@mui/material'; import { Project, deleteProject } from './utils'; interface ProjectStats { diff --git a/client/src/modules/manage-projects/index.tsx b/client/src/modules/manage-projects/index.tsx index a0ab4b34..1eb65d9f 100644 --- a/client/src/modules/manage-projects/index.tsx +++ b/client/src/modules/manage-projects/index.tsx @@ -5,7 +5,13 @@ import InPageNavigation from '../../shared/components/molecules/page-navigation' import NoDataMessageBox from '../../shared/components/atoms/no-data-msg'; import ManagePublishedProjectCard from './components/publish-projects'; import ManageDraftProjectPost from './components/draft-projects'; -import { Box, Typography, TextField, InputAdornment, CircularProgress } from '@mui/material'; +import { + Box, + Typography, + TextField, + InputAdornment, + CircularProgress, +} from '@mui/material'; import SearchIcon from '@mui/icons-material/Search'; import { AllProjectsAtom, DraftProjectAtom } from './states'; import { UserAtom } from '../../infra/states/user'; @@ -22,13 +28,17 @@ const ManageProjects = () => { const [query, setQuery] = useState(''); const getProjects = useCallback( - (params: { page?: number; draft?: boolean; deletedDocCount?: number } | undefined) => { + ( + params: + | { page?: number; draft?: boolean; deletedDocCount?: number } + | undefined + ) => { const { page = 1, draft = false, deletedDocCount = 0 } = params || {}; // userProjects expects is_draft instead of draft userProjects({ is_draft: draft, page, query, deletedDocCount }) .then(async data => { - const formattedData = (await filterPaginationData({ + const formattedData = await filterPaginationData({ state: draft ? drafts : projects, data: data.projects || [], page: page, @@ -39,7 +49,7 @@ const ManageProjects = () => { author: user.username || '', draft, }, - })); + }); if (formattedData) { if (draft) { @@ -87,7 +97,10 @@ const ManageProjects = () => { return ( <> - + Manage Projects @@ -108,11 +121,21 @@ const ManageProjects = () => { />
    - + { // Published Projects projects === null ? ( - + ) : projects.results.length ? ( @@ -147,7 +170,14 @@ const ManageProjects = () => { { // Draft Projects drafts === null ? ( - + ) : drafts.results.length ? ( diff --git a/client/src/modules/manage-projects/states/index.ts b/client/src/modules/manage-projects/states/index.ts index 6b78c701..6dfd1c4f 100644 --- a/client/src/modules/manage-projects/states/index.ts +++ b/client/src/modules/manage-projects/states/index.ts @@ -1,6 +1,13 @@ -import { atom } from 'jotai'; - -// Shared atoms for manage-projects module -// Use a permissive any for the pagination shape to avoid coupling to a specific typing export -export const AllProjectsAtom = atom(null); -export const DraftProjectAtom = atom(null); +import { atom } from 'jotai'; +import { PROJECT_DB_STATE } from '../../../infra/rest/typings'; + +// Minimal pagination type used across the app +export interface PaginatedProjects { + results: PROJECT_DB_STATE[]; + totalDocs: number; + deletedDocCount?: number; + page?: number; +} + +export const AllProjectsAtom = atom(null); +export const DraftProjectAtom = atom(null); From 4c8437e9b89ea8030f82d877003f654966ba22eb Mon Sep 17 00:00:00 2001 From: Amitjoiya Date: Wed, 19 Nov 2025 12:03:19 +0530 Subject: [PATCH 10/12] feat: migrate manage-projects UI to MUI (Fixes #1281) --- .../components/publish-projects.tsx | 7 +- client/src/modules/manage-projects/index.tsx | 335 ++++++++---------- 2 files changed, 146 insertions(+), 196 deletions(-) diff --git a/client/src/modules/manage-projects/components/publish-projects.tsx b/client/src/modules/manage-projects/components/publish-projects.tsx index f479dc12..d01cc68b 100644 --- a/client/src/modules/manage-projects/components/publish-projects.tsx +++ b/client/src/modules/manage-projects/components/publish-projects.tsx @@ -1,5 +1,5 @@ import { Link } from 'react-router-dom'; -import { getDay } from '../../../../shared/utils/date'; +import { getDay } from '../../../shared/utils/date'; import { useState } from 'react'; import { useAtom } from 'jotai'; import { UserAtom } from '../../../infra/states/user'; @@ -63,7 +63,10 @@ const ManagePublishedProjectCard = ({ project }: { project: Project }) => { const { banner, project_id, title, publishedAt, activity } = project; const [user] = useAtom(UserAtom); - const access_token = user.access_token || ''; + // USER_DB_STATE doesn't include access_token; if present (legacy/session), read safely + const access_token = user + ? ((user as unknown as { access_token?: string }).access_token ?? '') + : ''; const [showStat, setShowStat] = useState(false); diff --git a/client/src/modules/manage-projects/index.tsx b/client/src/modules/manage-projects/index.tsx index 1eb65d9f..fa965f38 100644 --- a/client/src/modules/manage-projects/index.tsx +++ b/client/src/modules/manage-projects/index.tsx @@ -1,216 +1,163 @@ -import { useAtom, useAtomValue } from 'jotai'; -import { useEffect, useState, useCallback } from 'react'; -import { useSearchParams } from 'react-router-dom'; +import { useEffect } from 'react'; +import { useParams } from 'react-router-dom'; import InPageNavigation from '../../shared/components/molecules/page-navigation'; -import NoDataMessageBox from '../../shared/components/atoms/no-data-msg'; -import ManagePublishedProjectCard from './components/publish-projects'; -import ManageDraftProjectPost from './components/draft-projects'; -import { - Box, - Typography, - TextField, - InputAdornment, - CircularProgress, -} from '@mui/material'; -import SearchIcon from '@mui/icons-material/Search'; -import { AllProjectsAtom, DraftProjectAtom } from './states'; +import NoDataMessage from '../../shared/components/atoms/no-data-msg'; +import { useAtom, useAtomValue } from 'jotai'; +import { HomePageProjectsAtom } from '../home/states'; +import BannerProjectCard from '../home/components/banner-project-card'; +import { ProfileAtom } from '../profile/states'; +import { Virtuoso } from 'react-virtuoso'; +import { BannerSkeleton } from '../../shared/components/atoms/skeleton'; import { UserAtom } from '../../infra/states/user'; -import { filterPaginationData } from '../../shared/requests/filter-pagination-data'; -import LoadMoreDataBtn from '../../shared/components/molecules/load-more-data'; -import { userProjects } from '../../infra/rest/apis/project'; - -const ManageProjects = () => { - const [projects, setProjects] = useAtom(AllProjectsAtom); - const [drafts, setDrafts] = useAtom(DraftProjectAtom); +import { Avatar, Box, CircularProgress } from '@mui/material'; +import useHome from '../home/hooks'; +import AboutUser from '../profile/components/about-user'; +import A2ZTypography from '../../shared/components/atoms/typography'; +import Button from '../../shared/components/atoms/button'; +import useProfile from '../profile/hooks'; + +const Profile = () => { + const { username } = useParams(); const user = useAtomValue(UserAtom); - - const activeTab = useSearchParams()[0].get('tab'); - const [query, setQuery] = useState(''); - - const getProjects = useCallback( - ( - params: - | { page?: number; draft?: boolean; deletedDocCount?: number } - | undefined - ) => { - const { page = 1, draft = false, deletedDocCount = 0 } = params || {}; - - // userProjects expects is_draft instead of draft - userProjects({ is_draft: draft, page, query, deletedDocCount }) - .then(async data => { - const formattedData = await filterPaginationData({ - state: draft ? drafts : projects, - data: data.projects || [], - page: page, - countRoute: '/search-projects-count', - data_to_send: { - query, - tag: query, - author: user.username || '', - draft, - }, - }); - - if (formattedData) { - if (draft) { - setDrafts(formattedData); - } else { - setProjects(formattedData); - } - } - }) - .catch(err => { - console.log(err); - }); - }, - [drafts, projects, query, setDrafts, setProjects, user.username] - ); + const profile = useAtomValue(ProfileAtom); + const [projects, setProjects] = useAtom(HomePageProjectsAtom); + const { fetchProjectsByCategory } = useHome(); + const { fetchUserProfile } = useProfile(); useEffect(() => { - if (user.access_token) { - if (projects === null) { - getProjects({ page: 1, draft: false }); - } - if (drafts === null) { - getProjects({ page: 1, draft: true }); - } + if (username !== user?.personal_info.username) { + setProjects([]); } - }, [user.access_token, projects, drafts, query, getProjects]); - - const handleSearch = (e: React.KeyboardEvent) => { - const searchQuery = e.currentTarget.value; - setQuery(searchQuery); - - if (e.keyCode === 13 && searchQuery.length) { - setProjects(null); - setDrafts(null); + if (projects.length === 0 || profile?.personal_info.username !== username) { + fetchUserProfile(); } - }; + }, [username]); - const handleChange = (e: React.ChangeEvent) => { - if (!e.currentTarget.value.length) { - setQuery(''); - setProjects(null); - setDrafts(null); - } - }; + if (!profile) { + return ; + } return ( - <> - + {/* Right Column (Profile Info) */} + ({ md: `1px solid ${theme.palette.divider}` }), + }} > - Manage Projects - - - - - - - ), + + + + + + + {user && username === user.personal_info.username ? ( + + ) : undefined} + + + + - - { - // Published Projects - projects === null ? ( - + {projects.length ? ( + ( + + )} + overscan={200} + endReached={() => { + const nextPage = Math.floor(projects.length / 10) + 1; // Assuming page size of 10 + fetchProjectsByCategory({ + page: nextPage, + user_id: profile._id, + }); }} - > - - - ) : projects.results.length ? ( - <> - {projects.results.map((project, i) => { - return ( - - ); - })} - - - - ) : ( - - ) - } - - { - // Draft Projects - drafts === null ? ( - + !projects || projects.length === 0 ? ( + + ) : null, // FIX ME }} - > - - - ) : drafts.results.length ? ( - <> - {drafts.results.map((project, i) => { - return ( - - ); - })} - - - + /> ) : ( - - ) - } - - + + )} + + + + + ); }; -export default ManageProjects; +export default Profile; From 9f821894e464d96750483f4cd081720a3661561e Mon Sep 17 00:00:00 2001 From: Amitjoiya Date: Wed, 19 Nov 2025 23:56:06 +0530 Subject: [PATCH 11/12] feat(manage-projects): migrate UI to MUI (UI-only) --- .../components/draft-projects.tsx | 22 +- .../components/publish-projects.tsx | 32 ++- client/src/modules/manage-projects/index.tsx | 244 ++++++++++-------- 3 files changed, 167 insertions(+), 131 deletions(-) diff --git a/client/src/modules/manage-projects/components/draft-projects.tsx b/client/src/modules/manage-projects/components/draft-projects.tsx index 1301979f..432c8a2a 100644 --- a/client/src/modules/manage-projects/components/draft-projects.tsx +++ b/client/src/modules/manage-projects/components/draft-projects.tsx @@ -1,12 +1,5 @@ import { Link } from 'react-router-dom'; -import { - Box, - Typography, - Button, - Card, - CardContent, - Stack, -} from '@mui/material'; +import { Box, Typography, Button, Card, CardContent } from '@mui/material'; import { Project, deleteProject } from './utils'; const ManageDraftProjectPost = ({ project }: { project: Project }) => { @@ -18,10 +11,13 @@ const ManageDraftProjectPost = ({ project }: { project: Project }) => { return ( - @@ -57,7 +53,7 @@ const ManageDraftProjectPost = ({ project }: { project: Project }) => { - + ); diff --git a/client/src/modules/manage-projects/components/publish-projects.tsx b/client/src/modules/manage-projects/components/publish-projects.tsx index d01cc68b..b7f461cc 100644 --- a/client/src/modules/manage-projects/components/publish-projects.tsx +++ b/client/src/modules/manage-projects/components/publish-projects.tsx @@ -3,6 +3,13 @@ import { getDay } from '../../../shared/utils/date'; import { useState } from 'react'; import { useAtom } from 'jotai'; import { UserAtom } from '../../../infra/states/user'; +import { + Card, + CardContent, + CardActions, + Typography, + Button, +} from '@mui/material'; import { Box, Typography, @@ -11,7 +18,6 @@ import { CardContent, CardActions, Avatar, - Stack, } from '@mui/material'; import { Project, deleteProject } from './utils'; @@ -27,9 +33,12 @@ interface ProjectStats { const ProjectStats = ({ stats }: { stats: ProjectStats }) => { return ( - {Object.keys(stats).map((key, i) => !key.includes('parent') ? ( @@ -53,7 +62,7 @@ const ProjectStats = ({ stats }: { stats: ProjectStats }) => { ) : null )} - + ); }; @@ -73,10 +82,13 @@ const ManagePublishedProjectCard = ({ project }: { project: Project }) => { return ( - {banner ? ( { {activity && } - + {showStat ? ( diff --git a/client/src/modules/manage-projects/index.tsx b/client/src/modules/manage-projects/index.tsx index fa965f38..714eb88f 100644 --- a/client/src/modules/manage-projects/index.tsx +++ b/client/src/modules/manage-projects/index.tsx @@ -9,7 +9,7 @@ import { ProfileAtom } from '../profile/states'; import { Virtuoso } from 'react-virtuoso'; import { BannerSkeleton } from '../../shared/components/atoms/skeleton'; import { UserAtom } from '../../infra/states/user'; -import { Avatar, Box, CircularProgress } from '@mui/material'; +import { Avatar, Box, CircularProgress, Grid } from '@mui/material'; import useHome from '../home/hooks'; import AboutUser from '../profile/components/about-user'; import A2ZTypography from '../../shared/components/atoms/typography'; @@ -31,131 +31,159 @@ const Profile = () => { if (projects.length === 0 || profile?.personal_info.username !== username) { fetchUserProfile(); } - }, [username]); + }, [ + username, + user?.personal_info.username, + projects.length, + profile?.personal_info.username, + fetchUserProfile, + setProjects, + ]); if (!profile) { - return ; - } - - return ( - - {/* Right Column (Profile Info) */} + return ( ({ md: `1px solid ${theme.palette.divider}` }), + alignItems: 'center', + justifyContent: 'center', + p: 3, }} > - + + ); + } + + return ( + + + {/* Right Column (Profile Info) */} + ({ md: `1px solid ${theme.palette.divider}` }), }} - /> + > + + + + + - - - + {user && username === user.personal_info.username ? ( + + ) : undefined} - {user && username === user.personal_info.username ? ( - - ) : undefined} + + + - - - - + + {projects.length ? ( + ( + + )} + overscan={200} + endReached={() => { + const nextPage = Math.floor(projects.length / 10) + 1; // Assuming page size of 10 + fetchProjectsByCategory({ + page: nextPage, + user_id: profile._id, + }); + }} + components={{ + Footer: () => + !projects || projects.length === 0 ? ( + + ) : null, // FIX ME + }} + /> + ) : ( + + )} - {/* Left Column (Projects + About Tabs) */} - - - {projects.length ? ( - ( - - )} - overscan={200} - endReached={() => { - const nextPage = Math.floor(projects.length / 10) + 1; // Assuming page size of 10 - fetchProjectsByCategory({ - page: nextPage, - user_id: profile._id, - }); - }} - components={{ - Footer: () => - !projects || projects.length === 0 ? ( - - ) : null, // FIX ME - }} + - ) : ( - - )} - - - - + + + ); }; From 48242e7ee937890c7c6e815cf2091621d2db9dc5 Mon Sep 17 00:00:00 2001 From: Amitjoiya Date: Thu, 20 Nov 2025 00:40:26 +0530 Subject: [PATCH 12/12] add sidebar code --- .../components/publish-projects.tsx | 7 --- .../components/organisms/sidebar/index.tsx | 44 ++++++++++++++++--- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/client/src/modules/manage-projects/components/publish-projects.tsx b/client/src/modules/manage-projects/components/publish-projects.tsx index b7f461cc..d09a95c5 100644 --- a/client/src/modules/manage-projects/components/publish-projects.tsx +++ b/client/src/modules/manage-projects/components/publish-projects.tsx @@ -3,13 +3,6 @@ import { getDay } from '../../../shared/utils/date'; import { useState } from 'react'; import { useAtom } from 'jotai'; import { UserAtom } from '../../../infra/states/user'; -import { - Card, - CardContent, - CardActions, - Typography, - Button, -} from '@mui/material'; import { Box, Typography, diff --git a/client/src/shared/components/organisms/sidebar/index.tsx b/client/src/shared/components/organisms/sidebar/index.tsx index 7e2a7984..84c5b840 100644 --- a/client/src/shared/components/organisms/sidebar/index.tsx +++ b/client/src/shared/components/organisms/sidebar/index.tsx @@ -1,7 +1,5 @@ -import { useAtomValue } from 'jotai'; import { useEffect, useState } from 'react'; import { Navigate, NavLink, Outlet, useLocation } from 'react-router-dom'; -import { UserAtom } from '../../../../infra/states/user'; import { useAuth } from '../../../hooks/use-auth'; import { notificationStatus } from '../../../../infra/rest/apis/notification'; @@ -19,6 +17,7 @@ import { Typography, useMediaQuery, useTheme, + CircularProgress, } from '@mui/material'; import MenuIcon from '@mui/icons-material/Menu'; import NotificationsNoneIcon from '@mui/icons-material/NotificationsNone'; @@ -30,8 +29,7 @@ import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; const drawerWidth = 240; const Sidebar = () => { - const user = useAtomValue(UserAtom); - const { isAuthenticated } = useAuth(); + const { isAuthenticated, initialized } = useAuth(); const location = useLocation(); const page = location.pathname.split('/')[2]; @@ -43,7 +41,23 @@ const Sidebar = () => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('md')); + // TEMP DEBUG: log auth init and token presence to help diagnose routing issues useEffect(() => { + try { + console.debug('Sidebar debug:', { + initialized, + isAuthenticated: isAuthenticated(), + token: localStorage.getItem('access_token'), + }); + } catch (err) { + console.debug('Sidebar debug error', err); + } + }, [initialized]); + + useEffect(() => { + // Only fetch notification status after auth initialization and when authenticated. + if (!initialized || !isAuthenticated()) return; + const fetchNotificationStatus = async () => { const response = await notificationStatus(); if (response.status === 'success' && response.data) { @@ -51,9 +65,27 @@ const Sidebar = () => { } }; fetchNotificationStatus(); - }, []); + }, [initialized, isAuthenticated]); + + // If auth hasn't finished initializing yet, render a small loader to avoid + // premature redirects while the token/user is being restored. + if (!initialized) { + return ( + + + + ); + } - if (!user || !isAuthenticated()) { + // After initialization, if not authenticated, redirect to login. + if (!isAuthenticated()) { return ; }