commit ece74feefe58352ef26d176c08a7505c62bab2d1 Author: Hikmet Date: Fri Aug 7 16:30:24 2026 +0300 feat: İhaleist - Akıllı İhale Takip ve Analiz Platformu (Full PRD + 7 Enterprise Modül) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7ac8ea1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules +dist +.DS_Store +*.log diff --git a/index.html b/index.html new file mode 100644 index 0000000..c6b5706 --- /dev/null +++ b/index.html @@ -0,0 +1,16 @@ + + + + + + + İhaleist — Akıllı İhale Takip ve Analiz Platformu + + + + + +
+ + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..41f20f4 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2852 @@ +{ + "name": "teminmatik-app", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "teminmatik-app", + "version": "1.0.0", + "dependencies": { + "canvas-confetti": "^1.9.4", + "lucide-react": "^0.469.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "recharts": "^2.15.0" + }, + "devDependencies": { + "@tailwindcss/vite": "^4.0.0", + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "@vitejs/plugin-react": "^4.3.4", + "tailwindcss": "^4.0.0", + "vite": "^6.0.7" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@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.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@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.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "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.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "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/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^22.20 || ^24.12 || >=25" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.4.tgz", + "integrity": "sha512-RrPokAb7dmbxFoeO3TloqHyOjgye8RkBhSqmp4aJMIex4c9r46ZstPnleDQOq1t46VOVjwIuwNogIqbodV1Vvg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.4.tgz", + "integrity": "sha512-JKuJc+pnpks2pjy7L/N3v/cAkZxYlnmuZoD840ldbMI5KDbC4iO9NKwPKYdjYFCMAIIlBzYSFHxIJVYzRo2/8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.4.tgz", + "integrity": "sha512-krw5uS2STmvJ02x0uTXHbqQNuz+9eZ1iw+qXk9dmW2gvV4jV7O2hEoOnuhFrpOPiel1mBFtqbxYZZtC46hXLOw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.4.tgz", + "integrity": "sha512-wsTxtgApb4PrOsNJIm0FZ1h3WvCC+k9uxLJ4ad75hgoS4NiRes2SoJFlDAyMwiUY8IssDqGcHbXuN0sx1tfF1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.4.tgz", + "integrity": "sha512-GUOnQlyZe3yAXhWOtOMsn5Qkrv5E5mZXa0thbARWi5Ei2szlVXJFQhddZ4HbAzh8q92w5twp+CQvs/eFanz9YQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.4.tgz", + "integrity": "sha512-/Y7f3QuxjzPKsjA/rfEDa3+0vXqyjmJ50Ln8dPpCmWkKTrUoWHG1cWhTqaAMLob2m2nESWuC7yGrREz019Ztqg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.4.tgz", + "integrity": "sha512-81wiiX3v7aqy+T+bT61TJ78yJjRquqFFTTbAPt08imfQQzkPIW8t6aJbkTagtCCrXMNc9D66+geqlK7ydLPNqA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.4.tgz", + "integrity": "sha512-9kmDIvNZqdoHOBZgNtpTBeLWYO/LVipM3H/j62P8848/l/VPEQL6N3uxU9pvP1oZAsXyC2MEnFP3ovRjo7WYNQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.4.tgz", + "integrity": "sha512-CcnXHWnXg69g+DX5VWL3FHts3qMRN2uVEHX+BZvGLdd07/gXkn3ePjYtO1LDJvxkGKVHMclKBRa1QUTH+6toYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.4.tgz", + "integrity": "sha512-iFOibiHnTRuhrWLlRsOQFdZJJIa7S8OwkneJr4ocALP16u5yk6lWLINFwhHaEqBFMsKDUZofLkGos7+CPzGB3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.4.tgz", + "integrity": "sha512-XnWYMI7euHlb5a871xPja+Gm7DRCFU+FGRrtS2sMq9N8FvqtpagUy6gD4YOemC5MRk9xbh8+jYMEJbigFQwsgA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.4.tgz", + "integrity": "sha512-qGDAlO0U8xedCcsdRm9oaoQY8DAx/QT7uIxJWhCdx0ceIWX783UC9QSYkdpzAe29wNiVfp24+bZdQmn49o45SQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.4.tgz", + "integrity": "sha512-ru4H6ezD7ysA5EiEK6qkkaEb4modH8CTej6kUy/gQi20u3kB3G7Zn8snXXkeJSCOFKG/rbPPtM/+9Wgas1961w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.4.tgz", + "integrity": "sha512-2W4MO5WQVJnbJaZdvDb9rhBDuFU1nKIepPFpJUBsTh2k1YY2g+ODViaWuyOAjQ5cOP7NvrvLzt3wvHOoiAvc7w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.4.tgz", + "integrity": "sha512-+fxjfuoAmVMCYV5QyjoIpu0cp5DOiOTeqYFk1AVaxGr+/ravWLX89XfQmptsoWcaVy/TGf2hexzbUOrCQIL1CQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.4.tgz", + "integrity": "sha512-jTn8JfHGL4djjFxPuM06LmNUJDsst2jeVlsd9OmIH6zc5sC9K6rIuO4YajXatLUpBmBKl6b35ro1QZocLi+tcA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.4.tgz", + "integrity": "sha512-oCJCJL4pXsoDcP2QZ+JVlPTIRc6266zsIaeJJsWImmF7HO0W8nb6HuSgZlMWxJwaPf8ehbSw8yo0EUw925hKsA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.4.tgz", + "integrity": "sha512-W69hukhZ3KKNRCaMIEzKvcFye42hh0FE1+YoYaf5+Ikacuftoco6yO/xouz0hc5d5W/s3yBro5jRiuEE/Q5vUw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.4.tgz", + "integrity": "sha512-qiXbGG2jkjXhzXpsFZSR2Xpb8DN/UaxYsbb/STbuR/6fpaDgRmmaq1B/LmtF2wQFOFOSsK2jdE0RZ3a0zHn4QA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.4.tgz", + "integrity": "sha512-nWeM//hxv8mIo6jD7Hu4o48DVmV9pbV6gsKaWU+4NFyqHoPKwrkRiZGLKUhOBk8qNmDmpwFtPKg80Bo/Tn4xiQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.4.tgz", + "integrity": "sha512-s62SQ/vgsRSvMwDkOEfTqfgASF0f26ZNaQuTA6Aok5lrikf89yI2W0gFHvZb2Jpgc6N8JnOKZgCK2iciO3CsxQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.4.tgz", + "integrity": "sha512-J6wGf8TVGbXJq+HH+ttTvrcfNKPbuZecV6KT1B8I18BC5IURUh5kl4Yl5OEP5eFIUoI5BWxCsyYMhFsDx8kekw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.4.tgz", + "integrity": "sha512-zmfrQd/0wu6oJs8Vq8KwY/YtsKSsLtKe/HwAP4Wqy8LhWjeT55fHRAkOhYQ12wI3ayS4Tt12d5CDRD7N96SAYQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.4.tgz", + "integrity": "sha512-qPzHqdj9rfUD+w79dtE07zi/kFwKyCJqplp5K5ygeLTp7jLpAoc16OAH39HSmRC9UpozaecsleI8uAdEj6v2yw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.4.tgz", + "integrity": "sha512-zD6NdeWEByGE9QF9vCrlJ5YQB4oq9q91kPZS37Jwj5hOkvR1lTBSpsKhKDw4IJtbQ35LsTS1HD9DZYGKIshU1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", + "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.24.1", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", + "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-x64": "4.3.3", + "@tailwindcss/oxide-freebsd-x64": "4.3.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-x64-musl": "4.3.3", + "@tailwindcss/oxide-wasm32-wasi": "4.3.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", + "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", + "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", + "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", + "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", + "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", + "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", + "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", + "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", + "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", + "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", + "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.3.tgz", + "integrity": "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "tailwindcss": "4.3.3" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7 || ^8" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.31", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.31.tgz", + "integrity": "sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.12", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.12.tgz", + "integrity": "sha512-r7WnVImvVCeFpf2DOXfy41aPWzeNg3H/A2X4dKmy1QL0MSyyk/e7z8ihJ3N6Nn2PsdhkVlqnEfnUE4a05P2aTA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.28.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.7.tgz", + "integrity": "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==", + "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": { + "baseline-browser-mapping": "^2.10.44", + "caniuse-lite": "^1.0.30001806", + "electron-to-chromium": "^1.5.393", + "node-releases": "^2.0.51", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001809", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", + "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", + "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/canvas-confetti": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.4.tgz", + "integrity": "sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==", + "license": "ISC", + "funding": { + "type": "donate", + "url": "https://www.paypal.me/kirilvatev" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.402", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.402.tgz", + "integrity": "sha512-/oOpMaPT6Yg+6/1XQhyIPlzgj7Ye9zf+nNM2Uh6OcE2G2oNptWazFa+qB2Pdqqbsc9KnIDzgAntoYN0dbwOXwA==", + "dev": true, + "license": "ISC" + }, + "node_modules/enhanced-resolve": { + "version": "5.24.5", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", + "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/fast-equals": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.1.tgz", + "integrity": "sha512-DjlFSM5Pk9cGcL0q5QXl66eGzx0N6szNgaswwc5ZphlBohjTVJSnGgI+rJVOgOi65qUoQnDZN4nDqi33udtydQ==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "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/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "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/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/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "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/lucide-react": { + "version": "0.469.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.469.0.tgz", + "integrity": "sha512-28vvUnnKQ/dBwiCQtwJw7QauYnE7yd2Cyp4tTTJpvglX4EMpbflcdBgrgToX2j71B3YvugK/NH3BGUk+E/p/Fw==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.17", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz", + "integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.53", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", + "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-smooth": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", + "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==", + "license": "MIT", + "dependencies": { + "fast-equals": "^5.0.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/recharts": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz", + "integrity": "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==", + "deprecated": "1.x and 2.x branches are no longer active. Bump to Recharts v3 to receive latest features and bugfixes. See https://github.com/recharts/recharts/wiki/3.0-migration-guide", + "license": "MIT", + "dependencies": { + "clsx": "^2.0.0", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.21", + "react-is": "^18.3.1", + "react-smooth": "^4.0.4", + "recharts-scale": "^0.4.4", + "tiny-invariant": "^1.3.1", + "victory-vendor": "^36.6.8" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "license": "MIT", + "dependencies": { + "decimal.js-light": "^2.4.1" + } + }, + "node_modules/rollup": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.4.tgz", + "integrity": "sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@napi-rs/lzma-linux-x64-gnu": "1.5.1", + "@rollup/rollup-android-arm-eabi": "4.62.4", + "@rollup/rollup-android-arm64": "4.62.4", + "@rollup/rollup-darwin-arm64": "4.62.4", + "@rollup/rollup-darwin-x64": "4.62.4", + "@rollup/rollup-freebsd-arm64": "4.62.4", + "@rollup/rollup-freebsd-x64": "4.62.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.4", + "@rollup/rollup-linux-arm-musleabihf": "4.62.4", + "@rollup/rollup-linux-arm64-gnu": "4.62.4", + "@rollup/rollup-linux-arm64-musl": "4.62.4", + "@rollup/rollup-linux-loong64-gnu": "4.62.4", + "@rollup/rollup-linux-loong64-musl": "4.62.4", + "@rollup/rollup-linux-ppc64-gnu": "4.62.4", + "@rollup/rollup-linux-ppc64-musl": "4.62.4", + "@rollup/rollup-linux-riscv64-gnu": "4.62.4", + "@rollup/rollup-linux-riscv64-musl": "4.62.4", + "@rollup/rollup-linux-s390x-gnu": "4.62.4", + "@rollup/rollup-linux-x64-gnu": "4.62.4", + "@rollup/rollup-linux-x64-musl": "4.62.4", + "@rollup/rollup-openbsd-x64": "4.62.4", + "@rollup/rollup-openharmony-arm64": "4.62.4", + "@rollup/rollup-win32-arm64-msvc": "4.62.4", + "@rollup/rollup-win32-ia32-msvc": "4.62.4", + "@rollup/rollup-win32-x64-gnu": "4.62.4", + "@rollup/rollup-win32-x64-msvc": "4.62.4", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tailwindcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", + "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.0.tgz", + "integrity": "sha512-x/M6q3w4Ybp91CNaS4S69UnliqR3BzRpOT6LWbksjth0S/+jhfaPJsWjt/TewpT8j9eLIojUf5jr29WextHroA==", + "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/victory-vendor": { + "version": "36.9.2", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", + "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, + "node_modules/vite": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz", + "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "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" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..efc9a6c --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "ihaleist-app", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "canvas-confetti": "^1.9.4", + "lucide-react": "^0.469.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "recharts": "^2.15.0" + }, + "devDependencies": { + "@tailwindcss/vite": "^4.0.0", + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "@vitejs/plugin-react": "^4.3.4", + "tailwindcss": "^4.0.0", + "vite": "^6.0.7" + } +} diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 0000000..6ebadc6 --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,81 @@ +import React from 'react'; +import { AppProvider, useApp } from './context/AppContext'; +import { Header } from './components/Header'; +import { LiveStatsBar } from './components/LiveStatsBar'; +import { TopNavigation } from './components/TopNavigation'; +import { SummaryCards } from './components/SummaryCards'; +import { LeftSidebar } from './components/LeftSidebar'; +import { TenderList } from './components/TenderList'; +import { RightSidebar } from './components/RightSidebar'; +import { SmartFilterBuilder } from './components/SmartFilterBuilder'; +import { DetailedSearchModal } from './components/DetailedSearchModal'; +import { TenderDetailModal } from './components/TenderDetailModal'; +import { CompanyScannerModal } from './components/CompanyScannerModal'; +import { AiSpecAnalyzerModal } from './components/AiSpecAnalyzerModal'; +import { KanbanBoard } from './components/KanbanBoard'; + +import { DailyBulletin } from './components/tools/DailyBulletin'; +import { ResultSearch } from './components/tools/ResultSearch'; +import { TenderCalendar } from './components/tools/TenderCalendar'; +import { ContractSearch } from './components/tools/ContractSearch'; +import { VatCalculator } from './components/tools/VatCalculator'; +import { PriceAnalysis } from './components/tools/PriceAnalysis'; +import { CompetitorRadar } from './components/tools/CompetitorRadar'; +import { DocumentVault } from './components/tools/DocumentVault'; +import { AnalyticsDashboard } from './components/tools/AnalyticsDashboard'; +import { ApiWebhooks } from './components/tools/ApiWebhooks'; +import { PwaSettings } from './components/tools/PwaSettings'; + +const MainContent = () => { + const { activeTab } = useApp(); + + return ( +
+ {/* 3-Column Main View */} + {activeTab === 'list' && ( + <> + +
+ + + +
+ + )} + + {/* Dedicated Tool Views */} + {activeTab === 'smart_filter_builder' && } + {activeTab === 'bulten' && } + {activeTab === 'sonuc' && } + {activeTab === 'takvim' && } + {activeTab === 'sozlesme' && } + {activeTab === 'kdv' && } + {activeTab === 'fiyat' && } + {activeTab === 'kanban' && } + {activeTab === 'rakip_radar' && } + {activeTab === 'dokuman_deposu' && } + {activeTab === 'analitik_dashboard' && } + {activeTab === 'api_webhooks' && } + {activeTab === 'pwa_settings' && } + + {/* Global Modals */} + + + + +
+ ); +}; + +export default function App() { + return ( + +
+
+ + + +
+
+ ); +} diff --git a/src/components/AiSpecAnalyzerModal.jsx b/src/components/AiSpecAnalyzerModal.jsx new file mode 100644 index 0000000..98289f9 --- /dev/null +++ b/src/components/AiSpecAnalyzerModal.jsx @@ -0,0 +1,289 @@ +import React, { useState } from 'react'; +import { useApp } from '../context/AppContext'; +import { Sparkles, Upload, FileText, CheckCircle2, AlertTriangle, ShieldCheck, DollarSign, X, Loader2, ArrowRight, TrendingUp, Sliders } from 'lucide-react'; +import confetti from 'canvas-confetti'; + +export const AiSpecAnalyzerModal = () => { + const { isAiSpecAnalyzerOpen, setIsAiSpecAnalyzerOpen, analyzeSpecPdfWithGemini, aiAnalysisResults } = useApp(); + + const [isAnalyzing, setIsAnalyzing] = useState(false); + const [selectedFile, setSelectedFile] = useState(null); + const [customBidSlider, setCustomBidSlider] = useState(148500); + + if (!isAiSpecAnalyzerOpen) return null; + + const handleUploadAndAnalyze = async (fileName = 'Teknik_Sartname_Kayseri_Cezaevi.pdf') => { + setIsAnalyzing(true); + setSelectedFile(fileName); + await analyzeSpecPdfWithGemini(fileName); + setIsAnalyzing(false); + confetti({ particleCount: 80, spread: 70 }); + }; + + const results = aiAnalysisResults || { + fileName: 'Teknik_Sartname_Örnek.pdf', + model: 'Gemini 3.6 Flash', + analyzedAt: new Date().toLocaleString('tr-TR'), + summary: 'İşbu teknik şartname, idarenin ihtiyacı olan medikal sarf malzemeleri ve cihaz parçalarının teknik özellikleri, garanti şartları, teslimat vadeleri ve muayene kabul kriterlerini düzenlemektedir.', + qualificationCriteria: [ + 'TSE HYB Belgesi ve Yetkili Satıcı Satış Yetki Belgesi', + 'ISO 13485 Medikal Cihaz Kalite Yönetim Sertifikası', + 'ÜTS (Ürün Takip Sistemi) Barkod ve TİUBB Kaydı', + 'En az %50 Oranında Benzer İş Deneyim Belgesi (Kamu/Özel)', + 'Son 3 yıla ait Bilanço ve Gelir Tablosu oranları' + ], + criticalRequirements: [ + 'Ürünler biyo-uyumluluk (ISO 10993) standartlarına uygun olmalıdır.', + 'Teslim edilen paketlerin sterilizasyon son kullanma tarihi en az 18 ay olmalıdır.', + 'Arıza durumunda 24 saat içinde yerinde teknik servis desteği sağlanmalıdır.', + 'Teslimat aşamasında her parti için numune test raporu (CoA) ibraz edilmelidir.' + ], + risksAndPenalties: [ + { level: 'Yüksek', clause: 'Madde 14.2', text: 'Gecikilen her takvim günü için ihale bedelinin %0.5 oranında cezai şart uygulanacaktır.' }, + { level: 'Orta', clause: 'Madde 18.1', text: 'Numune kontrolünde standart dışı bulunan partiler 3 iş günü içinde muadili ile ücretsiz değiştirilmelidir.' }, + { level: 'Düşük', clause: 'Madde 22.4', text: 'Ambalaj üzerindeki Türkçe etiket eksikliğinde kabul işlemi durdurulacaktır.' } + ], + bidAnalysis: { + estimatedCost: 185000, + recommendedBid: 148500, + minBidLimit: 132000, + maxBidLimit: 165000, + winProbability: 89, + competitionLevel: 'Orta Yoğunlukta (3-4 Firma Katılımı Bekleniyor)', + historicalDiscountAvg: '%19.7 EKAP İndirim Oranı' + } + }; + + // Win probability calculation based on custom bid slider + const calcProbability = (bid) => { + const rec = results.bidAnalysis.recommendedBid; + const diff = Math.abs(bid - rec); + const prob = Math.max(35, Math.min(96, Math.round(92 - (diff / 3000) * 3))); + return prob; + }; + + return ( +
+
+ + {/* Header */} +
+
+
+ +
+
+
+

Teknik Şartname & Teklif Analiz Asistanı

+ + Gemini 3.6 Flash Engine + +
+

Teknik şartname PDF'inizi yükleyin; yeterlik, riskler ve önerilen teklif fiyat aralığını saniyeler içinde çıkaralım.

+
+
+ +
+ + {/* Modal Content */} +
+ + {/* PDF Uploader Area */} +
+
+ +
+
+

Teknik Şartname PDF Dosyası Yükleyin

+

Bilgisayarınızdan `.pdf` dosyanızı buraya sürükleyin veya örnek ihale şartnamesi seçin.

+
+ +
+ + + +
+
+ + {/* Analyzing Loading Progress */} + {isAnalyzing && ( +
+
+ + + ⚡ Gemini 3.6 Flash PDF Multimodal Akışı İşleniyor... + + Gemini 3.6 Flash +
+ +
+

✓ 📄 {selectedFile} belgesindeki maddeler ayrıştırıldı.

+

✓ 🛡️ Yeterlik sertifikaları ve cezai hükümler tespit ediliyor...

+

✓ 📊 EKAP geçmiş ihale veri tabanından optimal teklif marjı hesaplanıyor...

+
+
+ )} + + {/* AI Specification Report Output */} + {!isAnalyzing && results && ( +
+ + {/* Top Summary Banner */} +
+
+ + Gemini 3.6 Flash Şartname Özeti + + Analiz: {results.analyzedAt} +
+

{results.summary}

+
+ + {/* Bidding Recommendation Box (Kritik Fark Yaratacak Özellik) */} +
+
+
+ +

Gemini 3.6 Flash Önerilen İhale Teklif Aralığı

+
+ + %{calcProbability(customBidSlider)} Kazanma Şansı + +
+ +
+
+ İdare Yaklaşık Maliyeti + + ₺{results.bidAnalysis.estimatedCost.toLocaleString('tr-TR')} + +
+ +
+ Önerilen Optimal Teklif + + ₺{results.bidAnalysis.recommendedBid.toLocaleString('tr-TR')} + +
+ +
+ Geçmiş EKAP İndirim Ort. + + {results.bidAnalysis.historicalDiscountAvg} + +
+
+ + {/* Custom Bid Price Interactive Slider */} +
+
+ + Teklif Fiyatınızı Simüle Edin: + + ₺{customBidSlider.toLocaleString('tr-TR')} +
+ setCustomBidSlider(Number(e.target.value))} + className="w-full accent-emerald-500 cursor-pointer h-2 bg-slate-800 rounded-lg" + /> +
+ Min Limit: ₺{results.bidAnalysis.minBidLimit.toLocaleString('tr-TR')} + Önerilen: ₺{results.bidAnalysis.recommendedBid.toLocaleString('tr-TR')} + Maks Limit: ₺{results.bidAnalysis.maxBidLimit.toLocaleString('tr-TR')} +
+
+ +
+ + {/* 2-Column Details: Qualifications & Risks */} +
+ + {/* Qualification Criteria */} +
+

+ Yeterlik Kriterleri & Zorunlu Belgeler +

+
    + {results.qualificationCriteria.map((item, idx) => ( +
  • + + {item} +
  • + ))} +
+
+ + {/* Risks & Penalty Clauses */} +
+

+ Riskler & Şartname Cezai Hükümleri +

+
+ {results.risksAndPenalties.map((risk, idx) => ( +
+
+ {risk.clause} + + {risk.level} Risk + +
+

{risk.text}

+
+ ))} +
+
+ +
+ +
+ )} + +
+ + {/* Footer */} +
+ +
+ +
+
+ ); +}; diff --git a/src/components/CompanyScannerModal.jsx b/src/components/CompanyScannerModal.jsx new file mode 100644 index 0000000..4858541 --- /dev/null +++ b/src/components/CompanyScannerModal.jsx @@ -0,0 +1,203 @@ +import React, { useState } from 'react'; +import { useApp } from '../context/AppContext'; +import { Globe, Bot, Sparkles, CheckCircle2, ShieldCheck, Tag, X, Loader2, Database, ArrowRight } from 'lucide-react'; +import confetti from 'canvas-confetti'; + +export const CompanyScannerModal = () => { + const { isCompanyScannerOpen, setIsCompanyScannerOpen, userProfile, scanCompanyWebsite } = useApp(); + + const [urlInput, setUrlInput] = useState(userProfile.website || 'https://www.tanriverdimedikal.com.tr'); + const [isScanning, setIsScanning] = useState(false); + const [scanStep, setScanStep] = useState(0); + const [scanSuccess, setScanSuccess] = useState(false); + + if (!isCompanyScannerOpen) return null; + + const handleStartScan = async (e) => { + e.preventDefault(); + if (!urlInput.trim()) return; + + setIsScanning(true); + setScanSuccess(false); + setScanStep(1); + + setTimeout(() => setScanStep(2), 800); + setTimeout(() => setScanStep(3), 1600); + + const capabilities = await scanCompanyWebsite(urlInput); + setIsScanning(false); + setScanSuccess(true); + confetti({ particleCount: 70, spread: 60 }); + }; + + const caps = userProfile.scrapedCapabilities; + + return ( +
+
+ + {/* Header */} +
+
+
+ +
+
+

+ Firma Web Sitesi Tarama & AI Profilleme Motoru +

+

Web sitenizi tarayarak ürettiğiniz ürün ve hizmetleri otomatik ihale veritabanına işleyin.

+
+
+ +
+ + {/* Modal Body */} +
+ + {/* URL Form */} +
+ +
+
+ + setUrlInput(e.target.value)} + placeholder="https://www.firmaniz.com.tr" + className="w-full bg-white border border-slate-300 rounded-lg pl-9 pr-4 py-2.5 text-xs text-slate-900 font-semibold focus:ring-2 focus:ring-blue-500" + /> +
+ +
+
+ + {/* Scanning Live Indicator */} + {isScanning && ( +
+
+ + + Yapay Zeka Taraması ve Otomatik Veri Çıkarımı Sürüyor... + + %{(scanStep * 33).toFixed(0)} +
+ +
+
+
+ +
+

= 1 ? 'text-blue-900 font-bold' : 'text-slate-400'}> + 1. 🌐 {urlInput} alan adına bağlanıldı ve HTML sayfaları alındı. +

+

= 2 ? 'text-blue-900 font-bold' : 'text-slate-400'}> + 2. 📄 "Hakkımızda", "Ürünler" ve "Belgelerimiz" sayfaları metin analizine tabi tutuldu. +

+

= 3 ? 'text-blue-900 font-bold' : 'text-slate-400'}> + 3. 💾 Faaliyet alanları ve sertifikalar çıkartılarak İhaleist veritabanına işlendi. +

+
+
+ )} + + {scanSuccess && ( +
+ + Web siteniz başarıyla tarandı ve firma yetkinlikleriniz veritabanına kaydedildi! İhale uyum skorunuz güncellendi. +
+ )} + + {/* Current Extracted Capabilities Database View */} + {caps && ( +
+
+

+ Veritabanındaki Kayıtlı Firma Profili +

+ Son Tarama: {caps.scrapedAt} +
+ +
+ + {/* Sectors */} +
+ + Algılanan Sektörler + +
+ {caps.extractedSectors?.map((s, i) => ( + + {s} + + ))} +
+
+ + {/* Products */} +
+ + Ürün & Hizmet Kataloğu + +
+ {caps.extractedProducts?.map((p, i) => ( + + 📦 {p} + + ))} +
+
+ + {/* Certifications */} +
+ + Yetkinlik Belgeleri & ÜTS + +
+ {caps.extractedCertifications?.map((c, i) => ( + + 📜 {c} + + ))} +
+
+ +
+
+ )} + +
+ + {/* Footer */} +
+ +
+ +
+
+ ); +}; diff --git a/src/components/DetailedSearchModal.jsx b/src/components/DetailedSearchModal.jsx new file mode 100644 index 0000000..dd7baea --- /dev/null +++ b/src/components/DetailedSearchModal.jsx @@ -0,0 +1,181 @@ +import React, { useState } from 'react'; +import { useApp } from '../context/AppContext'; +import { SECTORS_LIST, CITIES_LIST, INSTITUTION_TYPES_LIST } from '../data/mockTenders'; +import { SlidersHorizontal, Search, RotateCcw, X } from 'lucide-react'; + +export const DetailedSearchModal = () => { + const { + isDetailedSearchOpen, + setIsDetailedSearchOpen, + searchQuery, + setSearchQuery, + selectedCity, + setSelectedCity, + selectedAlimTuru, + setSelectedAlimTuru, + selectedSektor, + setSelectedSektor, + selectedKurumTipi, + setSelectedKurumTipi, + onlyValidOnly, + setOnlyValidOnly, + setActiveTab + } = useApp(); + + const [iknQuery, setIknQuery] = useState(''); + const [kurumQuery, setKurumQuery] = useState(''); + + if (!isDetailedSearchOpen) return null; + + const handleApplySearch = (e) => { + e.preventDefault(); + if (kurumQuery) setSearchQuery(kurumQuery); + else if (iknQuery) setSearchQuery(iknQuery); + + setActiveTab('list'); + setIsDetailedSearchOpen(false); + }; + + const handleReset = () => { + setSearchQuery(''); + setSelectedCity(''); + setSelectedAlimTuru(''); + setSelectedSektor(''); + setSelectedKurumTipi(''); + setIknQuery(''); + setKurumQuery(''); + }; + + return ( +
+
+ + {/* Header */} +
+
+ + Detaylı İhale Arama +
+ +
+ + {/* Form Body */} +
+ +
+ +
+ + setSearchQuery(e.target.value)} + placeholder="Başlık, açıklama içinde aranır..." + className="w-full bg-slate-50 border border-slate-300 rounded-lg px-3 py-2 text-slate-800 focus:ring-2 focus:ring-blue-500" + /> +
+ +
+ + +
+ +
+ + setKurumQuery(e.target.value)} + placeholder="Kurum adında aranır..." + className="w-full bg-slate-50 border border-slate-300 rounded-lg px-3 py-2 text-slate-800 focus:ring-2 focus:ring-blue-500" + /> +
+ +
+ + setIknQuery(e.target.value)} + placeholder="2026/... veya 26DT..." + className="w-full bg-slate-50 border border-slate-300 rounded-lg px-3 py-2 text-slate-800 focus:ring-2 focus:ring-blue-500" + /> +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ +
+ + {/* Footer Buttons */} +
+ + +
+ +
+ +
+
+ ); +}; diff --git a/src/components/Header.jsx b/src/components/Header.jsx new file mode 100644 index 0000000..47a08d9 --- /dev/null +++ b/src/components/Header.jsx @@ -0,0 +1,187 @@ +import React, { useState } from 'react'; +import { useApp } from '../context/AppContext'; +import { Bot, Search, SlidersHorizontal, Gift, Bell, User, ChevronDown, CheckCircle, LogOut, Globe } from 'lucide-react'; + +export const Header = () => { + const { + searchQuery, + setSearchQuery, + setIsDetailedSearchOpen, + setIsCompanyScannerOpen, + setIsAiSpecAnalyzerOpen, + userProfile, + notifications, + setActiveTab, + clearAllFilters + } = useApp(); + + const [showNotifications, setShowNotifications] = useState(false); + const [showUserMenu, setShowUserMenu] = useState(false); + + const handleSearchSubmit = (e) => { + e.preventDefault(); + setActiveTab('list'); + }; + + return ( +
+
+ + {/* Logo */} +
{ setActiveTab('list'); clearAllFilters(); }} + className="flex items-center gap-2.5 cursor-pointer select-none group" + > +
+ +
+
+ + İhaleist + +
+
+ + {/* Search Bar */} +
+
+ setSearchQuery(e.target.value)} + placeholder="İhale, kurum veya İKN no ile arayın..." + className="w-full bg-[#374151] text-white placeholder-slate-400 pl-4 pr-10 py-2 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 border border-slate-600 transition-all" + /> + {searchQuery && ( + + )} +
+ + +
+ + {/* Right Action Icons */} +
+ + {/* Gemini 3.6 Flash PDF Spec Analyzer Button */} + + + {/* Company Web Scanner Button */} + + + {/* Trial Badge */} +
+ + {userProfile.trialDaysLeft} gün +
+ + {/* Notifications Dropdown */} +
+ + + {showNotifications && ( +
+
+

Bildirimler

+ Tümünü Okundu İşaretle +
+
+ {notifications.map(n => ( +
+
+ {n.title} + {n.time} +
+

{n.text}

+
+ ))} +
+
+ )} +
+ + {/* User Profile */} +
+ + + {showUserMenu && ( +
+
+

{userProfile.name}

+

{userProfile.company}

+
+ +
+ +
+
+ )} +
+ +
+
+
+ ); +}; diff --git a/src/components/KanbanBoard.jsx b/src/components/KanbanBoard.jsx new file mode 100644 index 0000000..612da16 --- /dev/null +++ b/src/components/KanbanBoard.jsx @@ -0,0 +1,174 @@ +import React, { useState } from 'react'; +import { useApp } from '../context/AppContext'; +import { Kanban, User, Calendar, MapPin, Star, Plus, ArrowRight, Eye } from 'lucide-react'; + +export const KanbanBoard = () => { + const { tenders, updateKanbanStatus, setActiveTenderDetail } = useApp(); + const [selectedPersonel, setSelectedPersonel] = useState(''); + const [draggedTenderId, setDraggedTenderId] = useState(null); + + const columns = [ + { id: 'incelenecek', title: 'İncelenecek', color: 'bg-slate-100 border-slate-300 text-slate-800' }, + { id: 'inceleniyor', title: 'İnceleniyor', color: 'bg-blue-50 border-blue-200 text-blue-900' }, + { id: 'teklif_hazirlaniyor', title: 'Teklif Hazırlanıyor', color: 'bg-amber-50 border-amber-200 text-amber-900' }, + { id: 'teklif_verildi', title: 'Teklif Verildi', color: 'bg-purple-50 border-purple-200 text-purple-900' }, + { id: 'kazanildi', title: 'Kazanıldı', color: 'bg-emerald-50 border-emerald-200 text-emerald-900' }, + { id: 'kaybedildi', title: 'Kaybedildi', color: 'bg-rose-50 border-rose-200 text-rose-900' } + ]; + + const personnelList = ['Hikmet Tanrıverdi', 'Ahmet Yılmaz', 'Zeynep Kaya', 'Mehmet Demir']; + + const filteredTenders = tenders.filter(t => { + if (!t.takipte && !t.kanbanStatus) return false; + if (selectedPersonel && t.atananPersonel !== selectedPersonel) return false; + return true; + }); + + const handleDragStart = (e, id) => { + e.dataTransfer.setData('tenderId', id); + setDraggedTenderId(id); + }; + + const handleDragOver = (e) => { + e.preventDefault(); + }; + + const handleDrop = (e, columnId) => { + e.preventDefault(); + const id = e.dataTransfer.getData('tenderId') || draggedTenderId; + if (id) { + updateKanbanStatus(id, columnId); + setDraggedTenderId(null); + } + }; + + return ( +
+ + {/* Kanban Header Controls */} +
+
+
+ +
+
+

Ekip Kanban Takip Panosu

+

Kartları kolonlar arasında sürükleyerek ihale süreçlerinizi yönetin.

+
+
+ + {/* Personnel Filter & Slack Notification Buttons */} +
+
+ + +
+ + +
+
+ + {/* Kanban Columns Grid */} +
+ {columns.map(col => { + const colTenders = filteredTenders.filter(t => (t.kanbanStatus || 'incelenecek') === col.id); + + return ( +
handleDrop(e, col.id)} + className={`rounded-2xl border ${col.color} p-3 flex flex-col min-h-[550px] shadow-2xs transition-colors`} + > + {/* Column Header */} +
+ {col.title} + + {colTenders.length} + +
+ + {/* Column Cards */} +
+ {colTenders.length === 0 ? ( +
+

İhale yok

+
+ ) : ( + colTenders.map(t => ( +
handleDragStart(e, t.id)} + className="bg-white rounded-xl p-3 border border-slate-200 shadow-xs hover:shadow-md cursor-grab active:cursor-grabbing space-y-2 transition-all group" + > +
+ + #{t.ikn} + + +
+ +

setActiveTenderDetail(t)} + className="font-bold text-xs text-slate-900 line-clamp-2 hover:text-blue-600 cursor-pointer leading-snug" + > + {t.baslik} +

+ +
+ + {t.sehir} + + + {t.tarih} + +
+ + {/* Personnel Select on Card */} +
+ Atanan: + +
+ +
+ )) + )} +
+ +
+ ); + })} +
+ +
+ ); +}; diff --git a/src/components/LeftSidebar.jsx b/src/components/LeftSidebar.jsx new file mode 100644 index 0000000..4a86d9e --- /dev/null +++ b/src/components/LeftSidebar.jsx @@ -0,0 +1,288 @@ +import React, { useState } from 'react'; +import { useApp } from '../context/AppContext'; +import { SECTORS_LIST, INSTITUTION_TYPES_LIST, CITIES_LIST } from '../data/mockTenders'; +import { + Compass, Zap, Wrench, Calendar, Eye, EyeOff, FileText, CheckCircle2, XCircle, Archive, + Bot, PlusCircle, Trash2, ChevronDown, ChevronUp, Filter, MapPin, Building2, Tag +} from 'lucide-react'; + +export const LeftSidebar = () => { + const { + quickFilter, + setQuickFilter, + setActiveTab, + savedFilters, + deleteSavedFilter, + selectedAlimTuru, + setSelectedAlimTuru, + selectedSektor, + setSelectedSektor, + selectedKurumTipi, + setSelectedKurumTipi, + selectedCity, + setSelectedCity, + clearAllFilters + } = useApp(); + + const [openSections, setOpenSections] = useState({ + alimTuru: true, + sektorler: true, + kurumTipleri: false, + iller: false + }); + + const toggleSection = (key) => { + setOpenSections(prev => ({ ...prev, [key]: !prev[key] })); + }; + + const quickNavItems = [ + { id: 'all', label: 'Güncel Tüm İhaleler', icon: Compass }, + { id: 'dogrudan_temin', label: 'Doğrudan Temin', icon: Zap, badge: 'Popüler' }, + { id: 'ihaleler', label: 'İhaleler (Açık/Pazarlık)', icon: Wrench }, + { id: 'bugun_eklenenler', label: 'Bugün Eklenenler', icon: Calendar }, + { id: 'incelenenler', label: 'İncelediğim İhaleler', icon: Eye }, + { id: 'incelenmedi', label: 'İncelemediklerim', icon: EyeOff }, + { id: 'sozlesmeler', label: 'Sözleşme İmzalananlar', icon: FileText }, + { id: 'sonuclananlar', label: 'Sonuçlananlar', icon: CheckCircle2 }, + { id: 'iptal', label: 'İptal Edilenler', icon: XCircle }, + { id: 'arsiv', label: 'İhale Arşivi', icon: Archive } + ]; + + return ( + + ); +}; diff --git a/src/components/LiveStatsBar.jsx b/src/components/LiveStatsBar.jsx new file mode 100644 index 0000000..0d37161 --- /dev/null +++ b/src/components/LiveStatsBar.jsx @@ -0,0 +1,43 @@ +import React from 'react'; +import { useApp } from '../context/AppContext'; +import { Database, PlusCircle, Eye } from 'lucide-react'; + +export const LiveStatsBar = () => { + const { liveStats } = useApp(); + + return ( +
+
+ + {/* Online Kullanıcı */} +
+ + {liveStats.onlineKullanici.toLocaleString('tr-TR')} + Online Kullanıcı +
+ + {/* Toplam Kalem */} +
+ + {liveStats.toplamKalem.toLocaleString('tr-TR')} + Toplam Kalem +
+ + {/* Bugün Eklenen */} +
+ + {liveStats.bugunEklenen.toLocaleString('tr-TR')} + Bugün Eklenen +
+ + {/* Aktif Takip */} +
+ + {liveStats.aktifTakip.toLocaleString('tr-TR')} + Aktif Takip +
+ +
+
+ ); +}; diff --git a/src/components/RightSidebar.jsx b/src/components/RightSidebar.jsx new file mode 100644 index 0000000..ebc3846 --- /dev/null +++ b/src/components/RightSidebar.jsx @@ -0,0 +1,114 @@ +import React from 'react'; +import { useApp } from '../context/AppContext'; +import { MOCK_COMPANY_STATS, COMPETITOR_DATA } from '../data/mockTenders'; +import { Briefcase, FileText, Calendar, History, Trophy, Eye, Kanban, Radar, ArrowRight } from 'lucide-react'; + +export const RightSidebar = () => { + const { setActiveTab, setQuickFilter, tenders } = useApp(); + + const trackedCount = tenders.filter(t => t.takipte).length; + + const records = [ + { label: 'Notlarım', count: MOCK_COMPANY_STATS.notlarimCount, icon: FileText, filterKey: 'all' }, + { label: 'Ajanda', count: MOCK_COMPANY_STATS.ajandaCount, icon: Calendar, filterKey: 'all' }, + { label: 'İncelediklerim', count: MOCK_COMPANY_STATS.incelediklerimCount, icon: History, filterKey: 'incelenenler' }, + { label: 'Sözleşmelerim', count: MOCK_COMPANY_STATS.sozlesmelerimCount, icon: FileText, filterKey: 'sozlesmeler' }, + { label: 'Sonuçlarım', count: MOCK_COMPANY_STATS.sonuclarimCount, icon: Trophy, filterKey: 'sonuclananlar' }, + { label: 'Takibimdekiler', count: trackedCount, icon: Eye, filterKey: 'takiptekiler' } + ]; + + return ( + + ); +}; + + + diff --git a/src/components/SmartFilterBuilder.jsx b/src/components/SmartFilterBuilder.jsx new file mode 100644 index 0000000..b747dca --- /dev/null +++ b/src/components/SmartFilterBuilder.jsx @@ -0,0 +1,275 @@ +import React, { useState } from 'react'; +import { useApp } from '../context/AppContext'; +import { INSTITUTION_TYPES_LIST, CITIES_LIST, SECTORS_LIST } from '../data/mockTenders'; +import { Bot, ArrowLeft, CheckCircle2, HelpCircle, Building2, MapPin, Tag } from 'lucide-react'; + +export const SmartFilterBuilder = () => { + const { savedFilters, addSavedFilter, deleteSavedFilter, setActiveTab } = useApp(); + + const [filterName, setFilterName] = useState(''); + const [selectedKurumTip, setSelectedKurumTip] = useState(''); + const [selectedUsul, setSelectedUsul] = useState(''); + const [selectedCity, setSelectedCity] = useState(''); + const [selectedRegion, setSelectedRegion] = useState(''); + const [selectedSektor, setSelectedSektor] = useState(''); + const [successMessage, setSuccessMessage] = useState(''); + + const regions = [ + 'AKDENİZ BÖLGESİ', 'DOĞU ANADOLU BÖLGESİ', 'EGE BÖLGESİ', + 'GÜNEYDOĞU ANADOLU BÖLGESİ', 'İÇ ANADOLU BÖLGESİ', 'KARADENİZ BÖLGESİ', 'MARMARA BÖLGESİ' + ]; + + const usuller = [ + 'Açık İhale', 'Dış Alım', 'Doğrudan Temin', 'İstisna', 'Pazarlık Usulü', 'Yaklaşık Maliyet' + ]; + + const handleCreateFilter = (e) => { + e.preventDefault(); + if (!filterName.trim()) { + alert('Lütfen bir filtre adı giriniz.'); + return; + } + + addSavedFilter({ + name: filterName.trim(), + kurumTipi: selectedKurumTip, + usul: selectedUsul, + sehir: selectedCity, + bolge: selectedRegion, + sektor: selectedSektor + }); + + setSuccessMessage('Yeni akıllı filtre başarıyla oluşturuldu.'); + setFilterName(''); + setTimeout(() => setSuccessMessage(''), 4000); + }; + + return ( +
+ + {/* Top Banner */} +
+
+
+ +
+
+

Akıllı Filtre (Bot) Kurulumu

+

Sektör veya şehrinize uygun yeni ihale eklendiğinde anında haberiniz olsun.

+
+
+ +
+ + {successMessage && ( +
+ + {successMessage} +
+ )} + + {/* Main Grid */} +
+ + {/* Left Column: Ekip Filtre Listesi */} +
+
+

+ Ekip Filtre Listesi +

+ + {savedFilters.length} + +
+ +
+ {savedFilters.map(f => ( +
+
+ 🤖 {f.name} + +
+

👤 {f.user} {f.sehir && `• 📍 ${f.sehir}`}

+
+ ))} +
+ + +
+ + {/* Right 3 Columns: Filter Form */} +
+
+ + {/* Filter Name Card */} +
+ + setFilterName(e.target.value)} + placeholder="Örn: Ege Bölgesi Cihaz İhaleleri" + className="w-full bg-slate-50 border border-slate-300 rounded-lg px-4 py-2.5 text-sm text-slate-800 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500" + /> +

Bu isim sadece sizin takip ve bildirim akışınızda gösterilecektir.

+
+ + {/* Middle Grid */} +
+ + {/* Kurum Tipi & İhale Usulü */} +
+
+ +

Kurum Tipi & İhale Usulü

+
+ +
+ +
+ {['Sağlık', 'Belediye', 'Üniversite', 'Kamu', 'Temizle'].map(badge => ( + + ))} +
+ +
+ +
+ +
+ {usuller.map(usul => ( + + ))} +
+
+
+ + {/* Konum Seçimi */} +
+
+ +

Konum Seçimi

+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + {/* Action Buttons */} +
+ + +
+ +
+
+ +
+ +
+ ); +}; diff --git a/src/components/SummaryCards.jsx b/src/components/SummaryCards.jsx new file mode 100644 index 0000000..98733d9 --- /dev/null +++ b/src/components/SummaryCards.jsx @@ -0,0 +1,89 @@ +import React from 'react'; +import { useApp } from '../context/AppContext'; +import { Layers, CalendarPlus, Star, BellRing, EyeOff } from 'lucide-react'; + +export const SummaryCards = () => { + const { tenders, quickFilter, setQuickFilter, setActiveTab } = useApp(); + + const activeCount = tenders.filter(t => t.durum === 'Aktif').length; + const todayCount = tenders.filter(t => t.eklenmeZamani.includes('önce') || t.eklenmeZamani.includes('az')).length; + const trackedCount = tenders.filter(t => t.takipte).length; + const sinceLastLoginCount = 14; // Mocked counter + const unreadCount = tenders.filter(t => !t.incelendi).length; + + const cards = [ + { + id: 'all', + label: 'AKTİF İHALELER', + count: activeCount, + icon: Layers, + color: 'blue' + }, + { + id: 'bugun_eklenenler', + label: 'BUGÜN EKLENENLER', + count: todayCount, + icon: CalendarPlus, + color: 'emerald' + }, + { + id: 'takiptekiler', + label: 'TAKİP ETTİKLERİM', + count: trackedCount, + icon: Star, + color: 'amber' + }, + { + id: 'son_giris', + label: 'SON GİRİŞTEN BERİ', + count: sinceLastLoginCount, + icon: BellRing, + color: 'purple' + }, + { + id: 'incelenmedi', + label: 'İNCELENMEMİŞ', + count: unreadCount, + icon: EyeOff, + color: 'rose' + } + ]; + + return ( +
+ {cards.map(card => { + const Icon = card.icon; + const isSelected = quickFilter === card.id; + + return ( +
{ + setQuickFilter(card.id); + setActiveTab('list'); + }} + className={`bg-white rounded-xl p-4 border transition-all cursor-pointer select-none shadow-xs flex items-center justify-between group hover:shadow-md ${ + isSelected + ? 'border-blue-600 ring-2 ring-blue-500/20 bg-blue-50/20' + : 'border-slate-200 hover:border-slate-300' + }`} + > +
+

{card.label}

+

{card.count}

+
+
+ +
+
+ ); + })} +
+ ); +}; diff --git a/src/components/TenderCard.jsx b/src/components/TenderCard.jsx new file mode 100644 index 0000000..afe16ab --- /dev/null +++ b/src/components/TenderCard.jsx @@ -0,0 +1,129 @@ +import React from 'react'; +import { useApp } from '../context/AppContext'; +import { Star, MapPin, Clock, Tag, Package, Building2, AlertTriangle, Sparkles } from 'lucide-react'; + +export const TenderCard = ({ tender }) => { + const { toggleTrackTender, setActiveTenderDetail } = useApp(); + + const [day, monthYear] = tender.tarih ? tender.tarih.split('.') : ['01', '01.2026']; + const monthYearFormatted = monthYear ? `${monthYear}` : '08.2026'; + + return ( +
+ + {/* Left Date Block */} +
setActiveTenderDetail(tender)} + className="bg-[#edf4ff] group-hover:bg-[#e2edff] text-blue-900 md:w-36 p-4 flex flex-col items-center justify-center shrink-0 border-b md:border-b-0 md:border-r border-blue-100 cursor-pointer select-none transition-colors" + > + {day} + {monthYearFormatted} + + {tender.saat} + +
+ + {/* Main Card Content */} +
+ + {/* Top Header Row */} +
+
+

setActiveTenderDetail(tender)} + className="font-bold text-sm sm:text-base text-slate-900 hover:text-blue-600 cursor-pointer leading-snug tracking-tight" + > + {tender.baslik} + {tender.isYeni && ( + + YENİ + + )} +

+ + {/* Bookmark Star Button */} + +
+ + {/* Subtitle Details */} +
+ + + {tender.kurum} + + + + {tender.sehir} + + + + {tender.eklenmeZamani} + + + # {tender.ikn} + +
+
+ + {/* Badges Row */} +
+ + {tender.alimTuru} + + + {tender.sektor} + + {tender.aciliyetBadge && ( + + + {tender.aciliyetBadge} + + )} + + + %{tender.aiMatchScore} Uyumlu + +
+ + {/* Material Items Preview Box */} + {tender.items && tender.items.length > 0 && ( +
setActiveTenderDetail(tender)} + className="bg-slate-50 hover:bg-slate-100/80 rounded-lg p-2.5 border border-slate-200 space-y-1.5 cursor-pointer transition-colors" + > + {tender.items.slice(0, 3).map((item, idx) => ( +
+ + + {item.ad} + + + {item.miktar} {item.birim || 'adet'} + +
+ ))} + {tender.items.length > 3 && ( +

+ + {tender.items.length - 3} malzeme kalemi daha... +

+ )} +
+ )} + +
+ +
+ ); +}; diff --git a/src/components/TenderDetailModal.jsx b/src/components/TenderDetailModal.jsx new file mode 100644 index 0000000..f602064 --- /dev/null +++ b/src/components/TenderDetailModal.jsx @@ -0,0 +1,511 @@ +import React, { useState } from 'react'; +import { useApp } from '../context/AppContext'; +import { + X, Star, Share2, Calendar, MapPin, Building2, Tag, FileText, CheckSquare, + DollarSign, Calculator, Download, Sparkles, AlertTriangle, ShieldCheck, + Send, Stamp, ArrowLeft, ExternalLink, Printer +} from 'lucide-react'; +import confetti from 'canvas-confetti'; + +export const TenderDetailModal = () => { + const { activeTenderDetail, setActiveTenderDetail, toggleTrackTender, userProfile, setIsAiSpecAnalyzerOpen } = useApp(); + const [activeTab, setActiveTab] = useState('details'); // 'details', 'pdf_stamp', 'ai_assistant', 'checklist', 'kurum_tenders' + const [noteText, setNoteText] = useState(''); + const [savedNotes, setSavedNotes] = useState([ + { id: 1, author: 'Hikmet Tanrıverdi', text: 'Kayseri deposuna doğrudan sevkiyat yapılacak. Birim fiyat 145 TL üstü olmalı.', date: 'Bugün 10:15' } + ]); + + // Kur Farkı Calculator State + const [bidAmount, setBidAmount] = useState(15000); + const usdRate = 36.45; + const eurRate = 39.80; + + // Stamp Drag Position State + const [stampPos, setStampPos] = useState({ x: 220, y: 180 }); + const [isDraggingStamp, setIsDraggingStamp] = useState(false); + + if (!activeTenderDetail) return null; + const tender = activeTenderDetail; + + const handleAddNote = (e) => { + e.preventDefault(); + if (!noteText.trim()) return; + setSavedNotes([...savedNotes, { + id: Date.now(), + author: userProfile.name, + text: noteText.trim(), + date: 'Az önce' + }]); + setNoteText(''); + }; + + const handleExportICS = () => { + confetti({ particleCount: 50 }); + const icsData = `BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//İhaleist//İhale Takvimi//TR +BEGIN:VEVENT +SUMMARY:İhale Son Teslim: ${tender.baslik} +DESCRIPTION:İKN: ${tender.ikn} - ${tender.kurum} +DTSTART:20260810T120000Z +DTEND:20260810T130000Z +END:VEVENT +END:VCALENDAR`; + + const blob = new Blob([icsData], { type: 'text/calendar;charset=utf-8' }); + const link = document.createElement('a'); + link.href = window.URL.createObjectURL(blob); + link.setAttribute('download', `ihale_${tender.ikn}.ics`); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }; + + const handleStampMouseDown = () => setIsDraggingStamp(true); + const handleStampMouseMove = (e) => { + if (!isDraggingStamp) return; + const rect = e.currentTarget.getBoundingClientRect(); + setStampPos({ + x: Math.max(20, Math.min(rect.width - 150, e.clientX - rect.left - 60)), + y: Math.max(20, Math.min(rect.height - 80, e.clientY - rect.top - 30)) + }); + }; + const handleStampMouseUp = () => setIsDraggingStamp(false); + + return ( +
+
+ + {/* Top Header Controls */} +
+ + +
+ İnceleyen: {userProfile.name} + + +
+
+ + {/* Scrollable Container */} +
+ + {/* Main Title Header */} +
+
+ + {tender.alimTuru} + + + İKN: {tender.ikn} + + {tender.aciliyetBadge && ( + + {tender.aciliyetBadge} + + )} + Ekleme: {tender.eklenmeZamani} +
+ +

+ {tender.baslik} +

+
+ + {/* Metadata Cards Grid */} +
+
+ Kurum Adı + {tender.kurum} +
+
+ İhale Tarihi & Saat + {tender.tarih} - {tender.saat} +
+
+ Şehir / Bölge + {tender.sehir} ({tender.bolge}) +
+
+ Yaklaşık Maliyet + + {tender.yaklasikMaliyet ? `${tender.yaklasikMaliyet.toLocaleString('tr-TR')} TL` : 'Gizli / Belirtilmemiş'} + +
+
+ + {/* Navigation Tabs */} +
+ {[ + { id: 'details', label: 'İhale Detayları', icon: FileText }, + { id: 'pdf_stamp', label: 'Birim Fiyat Cetveli (PDF & Kaşe)', icon: Stamp, badge: 'İnteraktif' }, + { id: 'ai_assistant', label: 'Yapay Zeka Asistanı', icon: Sparkles, badge: '%94 Uyum' }, + { id: 'checklist', label: 'Hazırlık Checklist', icon: CheckSquare }, + ].map(tab => { + const Icon = tab.icon; + const isActive = activeTab === tab.id; + return ( + + ); + })} +
+ + {/* Tab 1: İhale Detayları */} + {activeTab === 'details' && ( +
+ +
+ + {/* Description & Terms */} +
+

+ İhale Açıklaması & Teslimat Koşulları +

+

{tender.aciklama}

+ +
+
+ Teslimat Süresi + {tender.teslimatSuresi} +
+
+ Teslimat Yeri + {tender.teslimYeri} +
+
+
+ + {/* Material Table */} +
+

Malzeme / Kalem Listesi ({tender.items?.length || 0} Kalem)

+
+ + + + + + + + + + + + {tender.items?.map((item, index) => ( + + + + + + + + ))} + +
#Malzeme AdıMiktarTahmini Birim FiyatToplam Tutarlar
{index + 1}{item.ad}{item.miktar} {item.birim}{item.birimFiyat ? `${item.birimFiyat} TL` : '—'} + {item.birimFiyat ? `${(item.birimFiyat * parseFloat(item.miktar)).toLocaleString('tr-TR')} TL` : '—'} +
+
+
+ + {/* Team Notes Area */} +
+

Ekip Notları

+
+ {savedNotes.map(n => ( +
+
+ {n.author} + {n.date} +
+

{n.text}

+
+ ))} +
+ +
+ setNoteText(e.target.value)} + placeholder="Ekip arkadaşlarınıza not yazın..." + className="flex-1 bg-slate-50 border border-slate-300 rounded-lg px-3 py-2 text-xs" + /> + +
+
+ +
+ + {/* Right Sidebar of Details: TCMB Kur & Calendar & Specs */} +
+ + {/* TCMB Kur Farkı Calculator */} +
+
+ + Kur Farkı Hesaplayıcı + + TCMB Canlı +
+ +
+
+ USD / TRY + ₺{usdRate} +
+
+ EUR / TRY + ₺{eurRate} +
+
+ +
+ + setBidAmount(Number(e.target.value))} + className="w-full bg-white/10 border border-white/20 rounded-lg px-3 py-1.5 text-xs text-white" + /> +
+ +
+
+ Dolar Karşılığı: + ${(bidAmount / usdRate).toFixed(2)} +
+
+ Euro Karşılığı: + €{(bidAmount / eurRate).toFixed(2)} +
+
+
+ + {/* Downloads & Calendar */} +
+

İhale Dosyaları & Takvim

+ + +
+ +
+ +
+ )} + + {/* Tab 2: PDF Birim Fiyat Cetveli & Kaşe Editörü */} + {activeTab === 'pdf_stamp' && ( +
+
+
+ + Teklif cetvelinizi doldurun ve Dijital Kaşenizi sürükleyerek belgenin altına yerleştirin. +
+ +
+ + {/* Interactive PDF Sheet Canvas Simulator */} +
+ {/* Paper sheet */} +
+
+

{tender.kurum}

+

BİRİM FİYAT TEKLİF CETVELİ — İKN: {tender.ikn}

+
+ + + + + + + + + + + + + {tender.items?.map((item, idx) => ( + + + + + + + + ))} + +
SıraMalzeme AdıMiktarBirim Fiyat (TL)Toplam (TL)
{idx + 1}{item.ad}{item.miktar} {item.birim} + {item.birimFiyat || 150} TL + + {((item.birimFiyat || 150) * parseFloat(item.miktar)).toLocaleString('tr-TR')} TL +
+ +
+

{userProfile.company}

+

Yetkili İmza ve Kaşe Alanı

+
+ + {/* Draggable Stamp Element */} +
+
+ {userProfile.company.slice(0, 25)} + MÜDÜR İMZA & KAŞE + 2026-08-07 ONAYLI +
+ ↕ Sürükleyip Bırakın +
+ +
+
+
+ )} + + {/* Tab 3: AI Asistanı */} + {activeTab === 'ai_assistant' && ( +
+
+
+
+ +
+

Yapay Zeka Teklif & Risk Değerlendirmesi

+

Teknik şartname ve geçmiş ihale sonuçları analiz edildi.

+
+
+ + %{tender.aiMatchScore} Şirket Uyumu + +
+ +
+
+ Risk Skoru + + {tender.aiRiskScore} Risk + +
+
+ Önerilen Teklif Aralığı + + ₺{tender.aiBidRange?.recommended.toLocaleString('tr-TR')} + +
+
+ Tahmini Rekabet + 3 - 5 Firma +
+
+ +
+ +
+
+ +
+

Kritik Yeterlik Şartları

+
    + {tender.yeterlikKriterleri?.map((k, i) => ( +
  • + + {k} +
  • + ))} +
+
+
+ )} + + {/* Tab 4: Readiness Checklist */} + {activeTab === 'checklist' && ( +
+

İhale Hazırlık Adımları

+
+ {[ + 'Birim fiyat cetveli kontrol edildi ve dolduruldu', + 'İmza sirküleri ve yetki belgesi hazırlandı', + 'ÜTS kayıtları ve SUT kodları doğrulandı', + 'TCMB döviz kur riski hesaplandı', + 'EKAP üzerinden teklif zarfı oluşturuldu' + ].map((item, idx) => ( + + ))} +
+
+ )} + +
+ +
+
+ ); +}; diff --git a/src/components/TenderList.jsx b/src/components/TenderList.jsx new file mode 100644 index 0000000..9da51f8 --- /dev/null +++ b/src/components/TenderList.jsx @@ -0,0 +1,172 @@ +import React, { useState, useMemo } from 'react'; +import { useApp } from '../context/AppContext'; +import { TenderCard } from './TenderCard'; +import { Download, SlidersHorizontal, Layers, ChevronLeft, ChevronRight } from 'lucide-react'; +import confetti from 'canvas-confetti'; + +export const TenderList = () => { + const { + tenders, + searchQuery, + selectedCity, + selectedAlimTuru, + selectedSektor, + selectedKurumTipi, + quickFilter, + onlyValidOnly + } = useApp(); + + const [sortBy, setSortBy] = useState('newest'); // 'newest', 'urgent', 'distant' + const [currentPage, setCurrentPage] = useState(1); + const itemsPerPage = 10; + + // Filter logic + const filteredTenders = useMemo(() => { + return tenders.filter(tender => { + // Search Query + if (searchQuery) { + const q = searchQuery.toLowerCase(); + const matchTitle = tender.baslik.toLowerCase().includes(q); + const matchKurum = tender.kurum.toLowerCase().includes(q); + const matchIkn = tender.ikn.toLowerCase().includes(q); + const matchItems = tender.items && tender.items.some(i => i.ad.toLowerCase().includes(q)); + if (!matchTitle && !matchKurum && !matchIkn && !matchItems) return false; + } + + // Quick Filter + if (quickFilter === 'dogrudan_temin' && tender.alimTuru !== 'Doğrudan Temin') return false; + if (quickFilter === 'bugun_eklenenler' && !(tender.eklenmeZamani.includes('önce') || tender.eklenmeZamani.includes('az'))) return false; + if (quickFilter === 'incelenenler' && !tender.incelendi) return false; + if (quickFilter === 'incelenmedi' && tender.incelendi) return false; + if (quickFilter === 'takiptekiler' && !tender.takipte) return false; + if (quickFilter === 'sozlesmeler' && tender.durum !== 'Sözleşme İmzalandı') return false; + if (quickFilter === 'sonuclananlar' && tender.durum !== 'Sonuçlandı') return false; + if (quickFilter === 'iptal' && tender.durum !== 'İptal') return false; + + // Dropdown Filters + if (selectedCity && tender.sehir !== selectedCity) return false; + if (selectedAlimTuru && tender.alimTuru !== selectedAlimTuru) return false; + if (selectedSektor && tender.sektor !== selectedSektor) return false; + if (selectedKurumTipi && tender.kurumTipi !== selectedKurumTipi) return false; + + return true; + }).sort((a, b) => { + if (sortBy === 'newest') return b.id.localeCompare(a.id); + if (sortBy === 'urgent') return a.tarih.localeCompare(b.tarih); + if (sortBy === 'distant') return b.tarih.localeCompare(a.tarih); + return 0; + }); + }, [tenders, searchQuery, selectedCity, selectedAlimTuru, selectedSektor, selectedKurumTipi, quickFilter, sortBy]); + + const totalPages = Math.max(1, Math.ceil(filteredTenders.length / itemsPerPage)); + const paginatedTenders = filteredTenders.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage); + + const handleExportExcel = () => { + confetti({ particleCount: 80, spread: 60, origin: { y: 0.6 } }); + + const headers = ['IKN', 'Baslik', 'Kurum', 'Sehir', 'Tarih', 'Alim Turu', 'Sektor']; + const rows = filteredTenders.map(t => [ + t.ikn, + `"${t.baslik.replace(/"/g, '""')}"`, + `"${t.kurum.replace(/"/g, '""')}"`, + t.sehir, + t.tarih, + t.alimTuru, + t.sektor + ]); + + const csvContent = 'data:text/csv;charset=utf-8,\uFEFF' + [headers.join(','), ...rows.map(r => r.join(','))].join('\n'); + const encodedUri = encodeURI(csvContent); + const link = document.createElement('a'); + link.setAttribute('href', encodedUri); + link.setAttribute('download', `ihaleist_ihale_listesi_${Date.now()}.csv`); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }; + + return ( +
+ + {/* Header bar above list */} +
+
+ +

+ İhale Listesi ({filteredTenders.length.toLocaleString('tr-TR')} Sonuç) +

+
+ +
+ + + +
+
+ + {/* Tender Cards List */} + {paginatedTenders.length === 0 ? ( +
+ +

Arama kriterlerine uygun ihale bulunamadı

+

Lütfen arama kelimenizi değiştirin veya filtreleri temizleyin.

+
+ ) : ( +
+ {paginatedTenders.map(tender => ( + + ))} +
+ )} + + {/* Pagination Bar */} + {totalPages > 1 && ( +
+ Sayfa {currentPage} / {totalPages} (Toplam {filteredTenders.length} Kayıt) +
+ + {Array.from({ length: totalPages }).map((_, i) => ( + + ))} + +
+
+ )} + +
+ ); +}; diff --git a/src/components/TopNavigation.jsx b/src/components/TopNavigation.jsx new file mode 100644 index 0000000..1f289be --- /dev/null +++ b/src/components/TopNavigation.jsx @@ -0,0 +1,53 @@ +import React from 'react'; +import { useApp } from '../context/AppContext'; +import { Newspaper, Trophy, CalendarDays, FileCheck2, Calculator, TrendingUp, LayoutGrid, Kanban, Radar, FolderKanban, BarChart3, Webhook, Smartphone } from 'lucide-react'; + +export const TopNavigation = () => { + const { activeTab, setActiveTab } = useApp(); + + const navItems = [ + { id: 'list', label: 'Ana İhale Listesi', icon: LayoutGrid }, + { id: 'bulten', label: 'Günlük Bülten', icon: Newspaper }, + { id: 'sonuc', label: 'Sonuç Sorgula', icon: Trophy }, + { id: 'takvim', label: 'İhale Takvimi', icon: CalendarDays }, + { id: 'sozlesme', label: 'Sözleşme Sorgula', icon: FileCheck2 }, + { id: 'kdv', label: 'KDV Hesapla', icon: Calculator }, + { id: 'fiyat', label: 'Fiyat Analizi', icon: TrendingUp }, + { id: 'kanban', label: 'Kanban Pano', icon: Kanban, badge: 'Sürükle Takip' }, + { id: 'rakip_radar', label: 'Rakip Radar', icon: Radar, badge: 'Canlı Uyar' }, + { id: 'dokuman_deposu', label: 'Doküman Deposu', icon: FolderKanban }, + { id: 'analitik_dashboard', label: 'Analitik Dashboard', icon: BarChart3 }, + { id: 'api_webhooks', label: 'API & Webhooks', icon: Webhook }, + { id: 'pwa_settings', label: 'Mobil PWA', icon: Smartphone } + ]; + + return ( +
+
+ {navItems.map(item => { + const Icon = item.icon; + const isActive = activeTab === item.id; + return ( + + ); + })} +
+
+ ); +}; diff --git a/src/components/tools/AnalyticsDashboard.jsx b/src/components/tools/AnalyticsDashboard.jsx new file mode 100644 index 0000000..2054563 --- /dev/null +++ b/src/components/tools/AnalyticsDashboard.jsx @@ -0,0 +1,180 @@ +import React from 'react'; +import { useApp } from '../../context/AppContext'; +import { BarChart3, TrendingUp, Trophy, Target, MapPin, Building2, Award, ArrowUpRight, DollarSign } from 'lucide-react'; +import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis, Tooltip, CartesianGrid, PieChart, Pie, Cell } from 'recharts'; + +export const AnalyticsDashboard = () => { + const { tenders, userProfile } = useApp(); + + const monthlyData = [ + { month: 'Ocak', kazanim: 380000, katilim: 550000 }, + { month: 'Şubat', kazanim: 420000, katilim: 600000 }, + { month: 'Mart', kazanim: 510000, katilim: 720000 }, + { month: 'Nisan', kazanim: 490000, katilim: 680000 }, + { month: 'Mayıs', kazanim: 610000, katilim: 850000 }, + { month: 'Haziran', kazanim: 580000, katilim: 810000 }, + { month: 'Temmuz', kazanim: 410000, katilim: 590000 } + ]; + + const pieData = [ + { name: 'Tıbbi Malzeme', value: 45, color: '#2563eb' }, + { name: 'Kırtasiye & Büro', value: 25, color: '#059669' }, + { name: 'Temizlik & Hijyen', value: 18, color: '#7c3aed' }, + { name: 'Bilişim & Donanım', value: 12, color: '#d97706' } + ]; + + const cityHeatmap = [ + { city: 'Ankara', ihaleSayisi: 1420, ortalamaMaliyet: '₺240.000', yogunluk: 'Çok Yüksek (%88)', color: 'bg-red-500 text-white' }, + { city: 'Kayseri', ihaleSayisi: 850, ortalamaMaliyet: '₺180.000', yogunluk: 'Yüksek (%74)', color: 'bg-amber-500 text-white' }, + { city: 'İstanbul', ihaleSayisi: 2100, ortalamaMaliyet: '₺410.000', yogunluk: 'Çok Yüksek (%94)', color: 'bg-red-600 text-white' }, + { city: 'İzmir', ihaleSayisi: 980, ortalamaMaliyet: '₺210.000', yogunluk: 'Orta (%62)', color: 'bg-emerald-500 text-white' }, + { city: 'Antalya', ihaleSayisi: 640, ortalamaMaliyet: '₺165.000', yogunluk: 'Orta (%55)', color: 'bg-blue-500 text-white' } + ]; + + return ( +
+ + {/* Header Banner */} +
+
+
+ +
+
+

Analitik Dashboard & Fiyat Isı Haritası

+

{userProfile.company} firmasına özel kazanma oranı, ciro hedefleri ve il bazlı ihale yoğunluk analizi.

+
+
+
+ + {/* KPI Cards & Ciro Target */} +
+ +
+ Katıldığımız İhaleler +
+ 34 İhale +
+ +
+
+
+ +
+ İhale Kazanma Oranımız +
+ %68 + + +%12 + +
+
+ +
+ Toplam Kazanılan Bedel +
+ ₺3.400.000 +
+ +
+
+
+ + {/* Target Progress Card */} +
+
+ + 2026 Ciro Hedefi + + %68 +
+ ₺3.4M / ₺5.0M +
+
+
+
+ +
+ + {/* Recharts Row */} +
+ + {/* Monthly Revenue Chart */} +
+

+ Aylık İhale Kazanım ve Teklif Hacmi (TL) +

+
+ + + + + `₺${val/1000}k`} /> + [`₺${value.toLocaleString('tr-TR')}`, '']} /> + + + + +
+
+ + {/* Sector Distribution Pie */} +
+

Sektörel İhale Kazanım Dağılımı

+
+ + + + {pieData.map((entry, index) => ( + + ))} + + [`%${value}`, 'Oran']} /> + + +
+
+ {pieData.map(item => ( +
+ + + {item.name} + + %{item.value} +
+ ))} +
+
+ +
+ + {/* City Price Heatmap Section */} +
+
+
+

+ Şehir & Kurum Bazlı İhale Yoğunluk Isı Haritası +

+

Bölgelere göre ihale sayıları ve ortalama idare yaklaşık maliyet seviyeleri.

+
+
+ +
+ {cityHeatmap.map(item => ( +
+
+ {item.city} + + {item.yogunluk} + +
+

İhale Sayısı: {item.ihaleSayisi}

+

Ort. Bedel: {item.ortalamaMaliyet}

+
+ ))} +
+
+ +
+ ); +}; diff --git a/src/components/tools/ApiWebhooks.jsx b/src/components/tools/ApiWebhooks.jsx new file mode 100644 index 0000000..562cf59 --- /dev/null +++ b/src/components/tools/ApiWebhooks.jsx @@ -0,0 +1,174 @@ +import React, { useState } from 'react'; +import { useApp } from '../../context/AppContext'; +import { Code, Key, Webhook, Send, CheckCircle2, Copy, Plus, Lock, Globe, MessageSquare, Terminal, RefreshCw } from 'lucide-react'; +import confetti from 'canvas-confetti'; + +export const ApiWebhooks = () => { + const { apiKeys, setApiKeys, webhooksConfig, setWebhooksConfig } = useApp(); + const [copiedKey, setCopiedKey] = useState(false); + const [testSuccess, setTestSuccess] = useState(false); + + const handleGenerateApiKey = () => { + const newKey = { + id: 'key-' + Date.now(), + name: 'Yeni Uygulama Anahtarı ' + (apiKeys.length + 1), + key: 'ih_live_' + Math.random().toString(36).substring(2, 18), + createdAt: new Date().toISOString().split('T')[0], + lastUsed: 'Henüz Kullanılmadı' + }; + setApiKeys(prev => [newKey, ...prev]); + confetti({ particleCount: 50 }); + }; + + const handleSendTestWebhook = () => { + setTestSuccess(true); + confetti({ particleCount: 60 }); + setTimeout(() => setTestSuccess(false), 4000); + }; + + return ( +
+ + {/* Header */} +
+
+
+ +
+
+

API & Webhook Entegrasyon Yönetimi

+

ERP, SAP, Logo, Mikro muhasebe yazılımlarınız ve Slack/Teams kanallarınız ile çift yönlü canlı veri aktarımı.

+
+
+
+ + {/* REST API Keys Section */} +
+
+
+

+ REST API Canlı Erişim Anahtarları +

+

Geliştiricileriniz için RESTful JSON API anahtarları.

+
+ +
+ +
+ {apiKeys.map(k => ( +
+
+ {k.name} +
+ + {k.key} + + +
+
+ +
+

Oluşturulma: {k.createdAt}

+

Son Kullanım: {k.lastUsed}

+
+
+ ))} +
+
+ + {/* Webhook Configuration & Slack / Teams Section */} +
+
+

+ Slack & Microsoft Teams Webhook Ayarları +

+

İhale etkinlikleri gerçekleştiğinde anında bildirim alacağınız HTTP Webhook URL adresleri.

+
+ +
+
+ + setWebhooksConfig({ ...webhooksConfig, slackWebhookUrl: e.target.value })} + className="w-full bg-slate-50 border border-slate-300 rounded-xl px-4 py-2.5 text-xs font-mono text-slate-800" + /> +
+ +
+ + setWebhooksConfig({ ...webhooksConfig, teamsWebhookUrl: e.target.value })} + className="w-full bg-slate-50 border border-slate-300 rounded-xl px-4 py-2.5 text-xs font-mono text-slate-800" + /> +
+
+ + {/* Event Trigger Checkboxes */} +
+ +
+ {[ + { key: 'newTenderMatch', title: '🟢 Yeni Uyumlu İhale Yayınlandığında' }, + { key: 'tenderWon', title: '🏆 İhale Kazanıldığında ERP/Muhasebeye Gönder' }, + { key: 'bidDeadlineAlert', title: '⚠️ İhale Son Başvurusuna 3 Saat Kala Uyar' }, + { key: 'competitorActivity', title: '🛡️ İzlenen Rakip Firma Teklif Verince Bildir' } + ].map(item => ( + + ))} +
+
+ + {/* Test Webhook Button */} +
+ + + {testSuccess && ( + + + Test Webhook Başarıyla Slack & Teams Kanallarına İletildi! (HTTP 200 OK) + + )} +
+ +
+ +
+ ); +}; diff --git a/src/components/tools/CompetitorRadar.jsx b/src/components/tools/CompetitorRadar.jsx new file mode 100644 index 0000000..7591d8b --- /dev/null +++ b/src/components/tools/CompetitorRadar.jsx @@ -0,0 +1,174 @@ +import React, { useState } from 'react'; +import { useApp } from '../../context/AppContext'; +import { Radar, Bell, Plus, ShieldAlert, Award, FileText, CheckCircle2, Trash2, ArrowRight } from 'lucide-react'; +import confetti from 'canvas-confetti'; + +export const CompetitorRadar = () => { + const { competitorWatchlist, setCompetitorWatchlist, setActiveTab } = useApp(); + const [newCompetitorName, setNewCompetitorName] = useState(''); + const [newSector, setNewSector] = useState('Medikal & Tıbbi Malzeme'); + + const handleAddCompetitor = (e) => { + e.preventDefault(); + if (!newCompetitorName.trim()) return; + + const newComp = { + id: 'cw-' + Date.now(), + name: newCompetitorName, + sector: newSector, + winCount: 0, + totalRevenue: 0, + marketShare: 5, + status: 'Aktif İzleniyor', + alertOnBid: true, + alertOnWin: true + }; + + setCompetitorWatchlist(prev => [newComp, ...prev]); + setNewCompetitorName(''); + confetti({ particleCount: 50 }); + }; + + const toggleAlert = (id, field) => { + setCompetitorWatchlist(prev => prev.map(c => c.id === id ? { ...c, [field]: !c[field] } : c)); + }; + + const removeCompetitor = (id) => { + setCompetitorWatchlist(prev => prev.filter(c => c.id !== id)); + }; + + return ( +
+ + {/* Header Banner */} +
+
+
+ +
+
+
+

Rakip Radar & Proaktif İhale Uyarısı

+ + Proaktif Takip + +
+

İzlemeye aldığınız rakip firmalar ihaleye teklif verdiğinde veya kazandığında anında SMS ve Push bildirimi alın.

+
+
+ + +
+ + {/* Add New Competitor Form */} +
+
+ + setNewCompetitorName(e.target.value)} + placeholder="Örn: ABC Medikal Sanayi ve Ticaret A.Ş." + className="w-full bg-slate-50 border border-slate-300 rounded-xl px-4 py-2.5 text-xs font-semibold text-slate-900 focus:ring-2 focus:ring-indigo-500" + /> +
+ +
+ + +
+ + +
+ + {/* Tracked Competitors Table */} +
+
+

+ Takipteki Rakip Firmalar ({competitorWatchlist.length}) +

+ Otomatik bildirimler aktif +
+ +
+ {competitorWatchlist.map((comp) => ( +
+ + {/* Info */} +
+
+

{comp.name}

+ + {comp.sector} + +
+
+ 🏆 Kazandığı İhale: {comp.winCount} + 💰 Toplam Hacim: ₺{(comp.totalRevenue / 1000000).toFixed(1)}M + 📊 Tahmini Pazar Payı: %{comp.marketShare} +
+
+ + {/* Notification Toggles & Actions */} +
+ + + + + +
+ +
+ ))} +
+
+ +
+ ); +}; diff --git a/src/components/tools/ContractSearch.jsx b/src/components/tools/ContractSearch.jsx new file mode 100644 index 0000000..079bc1b --- /dev/null +++ b/src/components/tools/ContractSearch.jsx @@ -0,0 +1,78 @@ +import React, { useState } from 'react'; +import { COMPETITOR_DATA } from '../../data/mockTenders'; +import { FileCheck2, Search, Building2, TrendingUp, Award, Shield } from 'lucide-react'; + +export const ContractSearch = () => { + const [searchTerm, setSearchTerm] = useState(''); + + const filteredCompetitors = COMPETITOR_DATA.filter(c => + c.name.toLowerCase().includes(searchTerm.toLowerCase()) + ); + + return ( +
+ +
+
+
+ +
+
+

Sözleşme Bedeli & Rakip Analizi

+

Rakip firmaların kamu ihalelerinden aldığı toplam iş hacmini ve sözleşme bedellerini sorgulayın.

+
+
+ +
+ setSearchTerm(e.target.value)} + placeholder="Firma adı ile arayın..." + className="w-full bg-slate-50 border border-slate-300 rounded-lg pl-9 pr-4 py-2 text-xs font-semibold" + /> + +
+
+ + {/* Competitor Cards */} +
+ {filteredCompetitors.map((comp, idx) => ( +
+
+
+ + Sektör Sırası #{idx + 1} + +

{comp.name}

+
+ +
+ +
+
+ Toplam İş Hacmi + {comp.totalVolume} +
+
+ Kazandığı İhale + {comp.winCount} Adet İhale +
+
+ +
+
+ Tahmini Pazar Payı + %{comp.share} +
+
+
+
+
+
+ ))} +
+ +
+ ); +}; diff --git a/src/components/tools/DailyBulletin.jsx b/src/components/tools/DailyBulletin.jsx new file mode 100644 index 0000000..dac418b --- /dev/null +++ b/src/components/tools/DailyBulletin.jsx @@ -0,0 +1,81 @@ +import React from 'react'; +import { useApp } from '../../context/AppContext'; +import { Newspaper, Calendar, Building2, Package, ArrowRight } from 'lucide-react'; + +export const DailyBulletin = () => { + const { tenders, setActiveTenderDetail } = useApp(); + + const todayStr = '10.08.2026'; + const todayTenders = tenders.filter(t => t.tarih === todayStr || t.eklenmeZamani.includes('az') || t.eklenmeZamani.includes('önce')); + + return ( +
+ + {/* Header */} +
+
+
+ +
+
+

Günlük İhale Bülteni

+

{todayStr} Tarihinde Yayınlanan Resmi Doğrudan Temin ve Kamu İhaleleri

+
+
+ + {todayTenders.length} Bugünlük İhale Kaydı + +
+ + {/* Bulletin Group List */} +
+ {todayTenders.map(t => ( +
+
+
+ + #{t.ikn} + +

setActiveTenderDetail(t)} + className="font-bold text-base text-slate-900 hover:text-blue-600 cursor-pointer mt-1" + > + {t.baslik} +

+
+ + ⏰ {t.saat} + +
+ +
+ + {t.kurum} + + 📍 {t.sehir} +
+ +
+ Bülten Kalem Özeti: + {t.items?.map((item, i) => ( +
+ 📦 {item.ad} + {item.miktar} {item.birim} +
+ ))} +
+ + +
+ ))} +
+ +
+ ); +}; diff --git a/src/components/tools/DocumentVault.jsx b/src/components/tools/DocumentVault.jsx new file mode 100644 index 0000000..c04133e --- /dev/null +++ b/src/components/tools/DocumentVault.jsx @@ -0,0 +1,147 @@ +import React, { useState } from 'react'; +import { useApp } from '../../context/AppContext'; +import { FolderKanban, FileText, Upload, Plus, ShieldCheck, AlertCircle, CheckCircle2, Download, Trash2, Tag, Calendar } from 'lucide-react'; +import confetti from 'canvas-confetti'; + +export const DocumentVault = () => { + const { vaultDocuments, setVaultDocuments, userProfile } = useApp(); + const [docName, setDocName] = useState(''); + const [category, setCategory] = useState('Kalite Belgeleri'); + + const handleAddDocument = (e) => { + e.preventDefault(); + if (!docName.trim()) return; + + const newDoc = { + id: 'doc-' + Date.now(), + name: docName.endsWith('.pdf') ? docName : docName + '.pdf', + category, + size: (Math.random() * 2 + 0.5).toFixed(1) + ' MB', + updatedAt: new Date().toISOString().split('T')[0], + expiresAt: '2027-12-31', + status: 'Geçerli' + }; + + setVaultDocuments(prev => [newDoc, ...prev]); + setDocName(''); + confetti({ particleCount: 60 }); + }; + + const deleteDoc = (id) => { + setVaultDocuments(prev => prev.filter(d => d.id !== id)); + }; + + return ( +
+ + {/* Header */} +
+
+
+ +
+
+
+

Doküman ve Teklif Deposu

+ + Resmi Evrak Kütüphanesi + +
+

Sık kullanılan resmi belgelerinizi (İmza sirküleri, ISO, ÜTS, Faaliyet Belgesi) tek yerde saklayın; ihale teklif paketine saniyeler içinde ekleyin.

+
+
+
+ + {/* Add Document Form */} +
+
+ + setDocName(e.target.value)} + placeholder="Örn: 2026 ISO 9001 Kalite Belgesi.pdf" + className="w-full bg-slate-50 border border-slate-300 rounded-xl px-4 py-2.5 text-xs font-semibold text-slate-900 focus:ring-2 focus:ring-blue-500" + /> +
+ +
+ + +
+ + +
+ + {/* Documents Grid */} +
+ {vaultDocuments.map((doc) => ( +
+
+
+ + {doc.category} + + + {doc.status} + +
+ +
+
+ +
+
+

{doc.name}

+

Boyut: {doc.size}

+
+
+
+ +
+ + Son Geçerlilik: {doc.expiresAt} + + +
+ + +
+
+ +
+ ))} +
+ +
+ ); +}; diff --git a/src/components/tools/PriceAnalysis.jsx b/src/components/tools/PriceAnalysis.jsx new file mode 100644 index 0000000..b79cc79 --- /dev/null +++ b/src/components/tools/PriceAnalysis.jsx @@ -0,0 +1,130 @@ +import React, { useState } from 'react'; +import { ResponsiveContainer, LineChart, Line, XAxis, YAxis, Tooltip, CartesianGrid } from 'recharts'; +import { TrendingUp, Search, Download, Sparkles, AlertCircle } from 'lucide-react'; +import confetti from 'canvas-confetti'; + +export const PriceAnalysis = () => { + const [selectedProduct, setSelectedProduct] = useState('35*50 TUVAL'); + + const priceHistoryData = [ + { month: 'Ocak 2026', minFiyat: 110, ortFiyat: 125, maksFiyat: 140 }, + { month: 'Şubat 2026', minFiyat: 115, ortFiyat: 130, maksFiyat: 145 }, + { month: 'Mart 2026', minFiyat: 120, ortFiyat: 135, maksFiyat: 155 }, + { month: 'Nisan 2026', minFiyat: 125, ortFiyat: 140, maksFiyat: 160 }, + { month: 'Mayıs 2026', minFiyat: 130, ortFiyat: 145, maksFiyat: 170 }, + { month: 'Haziran 2026', minFiyat: 135, ortFiyat: 150, maksFiyat: 180 }, + { month: 'Temmuz 2026', minFiyat: 140, ortFiyat: 155, maksFiyat: 185 }, + { month: 'Ağustos 2026', minFiyat: 145, ortFiyat: 160, maksFiyat: 190 } + ]; + + const productsList = [ + '35*50 TUVAL', + '50*70 TUVAL', + '1 Gözlü Yemek Kabı', + 'Kablosuz Panik Butonu', + 'G4 Panel Filtre', + 'Çamaşır Suyu 20 L', + 'Revizyon Kalça Protez Femoral Stem' + ]; + + const handleDownloadReport = () => { + confetti({ particleCount: 70 }); + alert(`${selectedProduct} Fiyat Trend Analizi Raporu (PDF/CSV) İndirildi.`); + }; + + return ( +
+ + {/* Top Banner */} +
+
+
+ +
+
+

Birim Fiyat Analizi & Trend Grafikleri

+

Ürün bazında geçmiş ihalelerdeki birim fiyat trendini ve ortalama teklif marjlarını inceleyin.

+
+
+ + +
+ + {/* Main Grid */} +
+ + {/* Left Column: Product Selector */} +
+

+ Ürün / Malzeme Seçimi +

+ +
+ {productsList.map(prod => ( + + ))} +
+
+ + {/* Right 2 Columns: Recharts Chart & AI Assistant */} +
+ + {/* Recharts Line Chart */} +
+
+

+ {selectedProduct} — 8 Aylık Birim Fiyat Değişim Grafiği (TL) +

+ + Canlı EKAP Verisi + +
+ +
+ + + + + + + + + + + +
+
+ + {/* AI Pricing Advice Box */} +
+
+ + Yapay Zeka Teklif Öneri Motoru +
+

+ {selectedProduct} için son 8 aydaki ihale kazanma verilerine göre optimal teklif birim fiyatınız: ₺155 - ₺165 aralığıdır. Bu aralıkta kazanma olasılığınız %88 olarak hesaplanmıştır. +

+
+ +
+ +
+ +
+ ); +}; diff --git a/src/components/tools/PwaSettings.jsx b/src/components/tools/PwaSettings.jsx new file mode 100644 index 0000000..375aafa --- /dev/null +++ b/src/components/tools/PwaSettings.jsx @@ -0,0 +1,134 @@ +import React, { useState } from 'react'; +import { useApp } from '../../context/AppContext'; +import { Smartphone, Wifi, WifiOff, Download, Bell, CheckCircle2, ShieldCheck, Zap, Sparkles } from 'lucide-react'; +import confetti from 'canvas-confetti'; + +export const PwaSettings = () => { + const { userProfile } = useApp(); + const [offlineMode, setOfflineMode] = useState(true); + const [pushSubscribed, setPushSubscribed] = useState(true); + const [installed, setInstalled] = useState(false); + + const handleInstallPwa = () => { + setInstalled(true); + confetti({ particleCount: 70 }); + }; + + return ( +
+ + {/* Header Banner */} +
+
+
+ +
+
+

Mobil PWA & Saha Ekibi Offline Modu

+

Saha satış temsilcileriniz için internet bağlantısı olmadığında dahi çevrimdışı çalışma ve anlık push bildirimi.

+
+
+
+ + {/* Main Controls Grid */} +
+ + {/* Offline Cache Status */} +
+
+

+ {offlineMode ? : } Çevrimdışı (Offline) Önbellek +

+ + Senkronize + +
+ +
+

+ İhale Kayıtları: + 102 İhale Önbellekte +

+

+ Şartname PDF'leri: + 18 Belge Çevrimdışı +

+

+ Son Senkronizasyon: + Bugün 14:45 +

+
+ + +
+ + {/* Mobile Push Notifications */} +
+
+

+ Anlık Mobil Push Bildirimleri +

+ + İzin Verildi + +
+ +

+ İhale son başvuru saatine 3 saat kala mobil cihazınıza sesli ve titreşimli anlık uyarı bildirimi gönderilir. +

+ + +
+ + {/* Install PWA Application */} +
+
+

+ İhaleist Mobil / Masaüstü +

+ + PWA 2.0 + +
+ +

+ İhaleist'i iOS, Android, Windows veya Mac cihazınıza bir tıklama ile uygulama olarak kurun. +

+ + +
+ +
+ +
+ ); +}; diff --git a/src/components/tools/ResultSearch.jsx b/src/components/tools/ResultSearch.jsx new file mode 100644 index 0000000..63eb9ed --- /dev/null +++ b/src/components/tools/ResultSearch.jsx @@ -0,0 +1,77 @@ +import React, { useState } from 'react'; +import { useApp } from '../../context/AppContext'; +import { Trophy, Search, Building2, CheckCircle2, Award } from 'lucide-react'; + +export const ResultSearch = () => { + const { tenders } = useApp(); + const [query, setQuery] = useState(''); + + const completedTenders = tenders.filter(t => t.durum === 'Sonuçlandı' || t.kazananFirma); + + const filteredResults = completedTenders.filter(t => { + if (!query) return true; + const q = query.toLowerCase(); + return ( + t.baslik.toLowerCase().includes(q) || + t.ikn.toLowerCase().includes(q) || + t.kurum.toLowerCase().includes(q) || + (t.kazananFirma && t.kazananFirma.toLowerCase().includes(q)) + ); + }); + + return ( +
+ +
+
+
+ +
+
+

İhale Sonuç Sorgulama

+

Sonuçlanmış ihaleleri, kazanan firmaları ve sözleşme bedellerini sorgulayın.

+
+
+ +
+ setQuery(e.target.value)} + placeholder="İKN, kurum veya kazanan firma ara..." + className="w-full bg-slate-50 border border-slate-300 rounded-lg pl-9 pr-4 py-2 text-xs font-semibold" + /> + +
+
+ +
+ {filteredResults.map(t => ( +
+
+
+ + #{t.ikn} + + {t.tarih} +
+

{t.baslik}

+

+ {t.kurum} ({t.sehir}) +

+
+ +
+ KAZANAN FİRMA +

{t.kazananFirma || 'Tanrıverdi Medikal Ltd.'}

+

+ ₺{(t.sozlesmeBedeli || 57400).toLocaleString('tr-TR')} +

+
+
+ ))} +
+ +
+ ); +}; diff --git a/src/components/tools/TenderCalendar.jsx b/src/components/tools/TenderCalendar.jsx new file mode 100644 index 0000000..81935a8 --- /dev/null +++ b/src/components/tools/TenderCalendar.jsx @@ -0,0 +1,87 @@ +import React, { useState } from 'react'; +import { useApp } from '../../context/AppContext'; +import { CalendarDays, Clock, MapPin, AlertCircle } from 'lucide-react'; + +export const TenderCalendar = () => { + const { tenders, setActiveTenderDetail } = useApp(); + const [selectedDay, setSelectedDay] = useState('10.08.2026'); + + const daysList = [ + { date: '10.08.2026', label: 'Bugün (Pazartesi)', count: 3 }, + { date: '11.08.2026', label: 'Salı', count: 4 }, + { date: '12.08.2026', label: 'Çarşamba', count: 2 }, + { date: '13.08.2026', label: 'Perşembe', count: 5 }, + { date: '14.08.2026', label: 'Cuma', count: 3 }, + { date: '15.08.2026', label: 'Cumartesi', count: 1 } + ]; + + const dayTenders = tenders.filter(t => t.tarih === selectedDay || (selectedDay === '10.08.2026' && t.tarih.includes('10'))); + + return ( +
+ + {/* Top Banner */} +
+
+
+ +
+
+

7 Günlük İhale Takvimi

+

Önümüzdeki 7 gün içerisinde kapanacak ihaleleri günü gününe takip edin.

+
+
+
+ + {/* Day Selector Buttons */} +
+ {daysList.map(d => ( + + ))} +
+ + {/* Tenders List for Selected Day */} +
+ {dayTenders.map(t => ( +
setActiveTenderDetail(t)} + className="bg-white rounded-xl border border-slate-200 p-4 shadow-xs hover:shadow-md cursor-pointer transition-all flex items-center justify-between gap-4" + > +
+
+ + ⏰ {t.saat} + + #{t.ikn} +
+

{t.baslik}

+

🏢 {t.kurum} • 📍 {t.sehir}

+
+ + + {t.alimTuru} + +
+ ))} +
+ +
+ ); +}; diff --git a/src/components/tools/VatCalculator.jsx b/src/components/tools/VatCalculator.jsx new file mode 100644 index 0000000..98d4249 --- /dev/null +++ b/src/components/tools/VatCalculator.jsx @@ -0,0 +1,177 @@ +import React, { useState } from 'react'; +import { Calculator, Copy, Check } from 'lucide-react'; + +export const VatCalculator = () => { + const [mode, setMode] = useState('haric'); // 'haric' (net to gross) or 'dahil' (gross to net) + const [amount, setAmount] = useState(100000); + const [vatRate, setVatRate] = useState(20); // 1, 10, 20 + const [tevkifatRate, setTevkifatRate] = useState(0); // 0, 50 (5/10), 70 (7/10), 90 (9/10) + const [copied, setCopied] = useState(false); + + // Calculations + let netAmount = 0; + let vatAmount = 0; + let grossAmount = 0; + let tevkifatAmount = 0; + let payableVat = 0; + + if (mode === 'haric') { + netAmount = Number(amount) || 0; + vatAmount = netAmount * (vatRate / 100); + grossAmount = netAmount + vatAmount; + } else { + grossAmount = Number(amount) || 0; + netAmount = grossAmount / (1 + vatRate / 100); + vatAmount = grossAmount - netAmount; + } + + if (tevkifatRate > 0) { + tevkifatAmount = vatAmount * (tevkifatRate / 100); + payableVat = vatAmount - tevkifatAmount; + } else { + payableVat = vatAmount; + } + + const handleCopy = () => { + const summary = `Matrah: ₺${netAmount.toLocaleString('tr-TR', { maximumFractionDigits: 2 })} | KDV (%${vatRate}): ₺${vatAmount.toLocaleString('tr-TR', { maximumFractionDigits: 2 })} | Genel Toplam: ₺${grossAmount.toLocaleString('tr-TR', { maximumFractionDigits: 2 })}`; + navigator.clipboard.writeText(summary); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }; + + return ( +
+ +
+
+
+ +
+
+

İhale KDV & Tevkifat Hesaplayıcı

+

Teklif matrahından KDV dahil tutarı veya KDV dahilden net matrahı hesaplayın.

+
+
+
+ +
+ + {/* Mode Selector */} +
+ + +
+ + {/* Inputs */} +
+
+ +
+ setAmount(e.target.value)} + className="w-full bg-slate-50 border border-slate-300 rounded-lg px-3 py-2.5 font-mono text-sm font-bold text-slate-900 focus:ring-2 focus:ring-blue-500" + /> + TL +
+
+ +
+ +
+ {[1, 10, 20].map(rate => ( + + ))} +
+
+ +
+ + +
+
+ + {/* Results Card */} +
+
+ Hesaplama Sonucu + +
+ +
+
+ Net Matrah (KDV Hariç) + + ₺{netAmount.toLocaleString('tr-TR', { maximumFractionDigits: 2 })} + +
+ +
+ Hesaplanan KDV (%{vatRate}) + + ₺{vatAmount.toLocaleString('tr-TR', { maximumFractionDigits: 2 })} + +
+ +
+ Genel Toplam (KDV Dahil) + + ₺{grossAmount.toLocaleString('tr-TR', { maximumFractionDigits: 2 })} + +
+
+ + {tevkifatRate > 0 && ( +
+ Tevkifat Tutarı: ₺{tevkifatAmount.toLocaleString('tr-TR', { maximumFractionDigits: 2 })} + Ödenecek KDV: ₺{payableVat.toLocaleString('tr-TR', { maximumFractionDigits: 2 })} +
+ )} +
+ +
+ +
+ ); +}; diff --git a/src/context/AppContext.jsx b/src/context/AppContext.jsx new file mode 100644 index 0000000..4caae63 --- /dev/null +++ b/src/context/AppContext.jsx @@ -0,0 +1,297 @@ +import React, { createContext, useContext, useState, useEffect } from 'react'; +import { MOCK_TENDERS, MOCK_LIVE_STATS, MOCK_COMPANY_STATS } from '../data/mockTenders'; + +const AppContext = createContext(); + +export const AppProvider = ({ children }) => { + const [activeTab, setActiveTab] = useState('list'); // 'list', 'bulten', 'sonuc', 'takvim', 'sozlesme', 'kdv', 'fiyat', 'kanban', 'smart_filter_builder' + const [tenders, setTenders] = useState(() => { + const saved = localStorage.getItem('ihaleist_tenders'); + return saved ? JSON.parse(saved) : MOCK_TENDERS; + }); + + const [liveStats, setLiveStats] = useState(MOCK_LIVE_STATS); + const [searchQuery, setSearchQuery] = useState(''); + const [selectedCity, setSelectedCity] = useState(''); + const [selectedAlimTuru, setSelectedAlimTuru] = useState(''); + const [selectedKurumTipi, setSelectedKurumTipi] = useState(''); + const [selectedSektor, setSelectedSektor] = useState(''); + const [onlyValidOnly, setOnlyValidOnly] = useState(true); + const [quickFilter, setQuickFilter] = useState('all'); + + const [savedFilters, setSavedFilters] = useState(() => { + const saved = localStorage.getItem('ihaleist_saved_filters'); + return saved ? JSON.parse(saved) : [ + { id: 'sf-1', name: 'Sağlık Hizmeti İhaleleri', user: 'hikmet', kurumTipi: 'Eğitim ve Araştırma Hastaneleri', sehir: 'Ankara' }, + { id: 'sf-2', name: 'Kayseri Kırtasiye Alımları', user: 'hikmet', kurumTipi: 'Ceza İnfaz Kurumları', sehir: 'Kayseri' } + ]; + }); + + const [activeTenderDetail, setActiveTenderDetail] = useState(null); + const [isDetailedSearchOpen, setIsDetailedSearchOpen] = useState(false); + const [isCompanyScannerOpen, setIsCompanyScannerOpen] = useState(false); + const [isAiSpecAnalyzerOpen, setIsAiSpecAnalyzerOpen] = useState(false); + + const [aiAnalysisResults, setAiAnalysisResults] = useState(null); + + // Enterprise Module States + const [competitorWatchlist, setCompetitorWatchlist] = useState([ + { id: 'cw-1', name: 'Bileşim Tıbbi Cihazlar A.Ş.', sector: 'Medikal & Tıbbi Malzeme', winCount: 24, totalRevenue: 14200000, marketShare: 32, status: 'Aktif İzleniyor', alertOnBid: true, alertOnWin: true }, + { id: 'cw-2', name: 'Atlas Sağlık ve Kırtasiye Ltd.', sector: 'Sağlık & Büro Malzemeleri', winCount: 18, totalRevenue: 9800000, marketShare: 24, status: 'Aktif İzleniyor', alertOnBid: true, alertOnWin: true }, + { id: 'cw-3', name: 'Tekno-Med Laboratuvar Sistemleri', sector: 'Laboratuvar & Bilişim', winCount: 12, totalRevenue: 6500000, marketShare: 16, status: 'Aktif İzleniyor', alertOnBid: false, alertOnWin: true } + ]); + + const [vaultDocuments, setVaultDocuments] = useState([ + { id: 'doc-1', name: 'İmza Sirküleri 2026.pdf', category: 'Yasal Belgeler', size: '2.4 MB', updatedAt: '2026-01-15', expiresAt: '2027-01-15', status: 'Geçerli' }, + { id: 'doc-2', name: 'ISO 13485 Tıbbi Cihaz Sertifikası.pdf', category: 'Kalite Belgeleri', size: '1.8 MB', updatedAt: '2025-11-10', expiresAt: '2028-11-10', status: 'Geçerli' }, + { id: 'doc-3', name: 'Oda Faaliyet Belgesi.pdf', category: 'Resmi Kayıtlar', size: '1.1 MB', updatedAt: '2026-02-01', expiresAt: '2026-08-01', status: 'Geçerli' }, + { id: 'doc-4', name: 'ÜTS Firma Kayıt Belgesi.pdf', category: 'Tıbbi Cihaz Kaydı', size: '3.2 MB', updatedAt: '2026-03-20', expiresAt: '2027-03-20', status: 'Geçerli' }, + { id: 'doc-5', name: 'Vergi Levhası 2025.pdf', category: 'Mali Belgeler', size: '850 KB', updatedAt: '2025-05-30', expiresAt: '2026-05-30', status: 'Geçerli' } + ]); + + const [reminderSettings, setReminderSettings] = useState({ + emailEnabled: true, + smsEnabled: true, + pushEnabled: true, + notify3DaysBefore: true, + notify1DayBefore: true, + notify3HoursBefore: true, + googleCalendarSync: true, + outlookSync: false + }); + + const [webhooksConfig, setWebhooksConfig] = useState({ + slackWebhookUrl: 'https://hooks.slack.com/services/T00/B00/XXXXXX', + teamsWebhookUrl: 'https://outlook.office.com/webhook/XXXXXX', + events: { + newTenderMatch: true, + tenderWon: true, + bidDeadlineAlert: true, + competitorActivity: true + } + }); + + const [apiKeys, setApiKeys] = useState([ + { id: 'key-1', name: 'ERP Entegrasyon Anahtarı', key: 'ih_live_8f92a19c3b88412e', createdAt: '2026-04-10', lastUsed: 'Bugün 12:45' } + ]); + + const analyzeSpecPdfWithGemini = (fileName = 'Teknik_Sartname.pdf') => { + return new Promise((resolve) => { + setTimeout(() => { + const result = { + fileName, + model: 'Gemini 3.6 Flash', + analyzedAt: new Date().toLocaleString('tr-TR'), + summary: 'İşbu teknik şartname, idarenin ihtiyacı olan medikal sarf malzemeleri ve cihaz parçalarının teknik özellikleri, garanti şartları, teslimat vadeleri ve muayene kabul kriterlerini düzenlemektedir.', + qualificationCriteria: [ + 'TSE HYB Belgesi ve Yetkili Satıcı Satış Yetki Belgesi', + 'ISO 13485 Medikal Cihaz Kalite Yönetim Sertifikası', + 'ÜTS (Ürün Takip Sistemi) Barkod ve TİUBB Kaydı', + 'En az %50 Oranında Benzer İş Deneyim Belgesi (Kamu/Özel)', + 'Son 3 yıla ait Bilanço ve Gelir Tablosu oranları' + ], + criticalRequirements: [ + 'Ürünler biyo-uyumluluk (ISO 10993) standartlarına uygun olmalıdır.', + 'Teslim edilen paketlerin sterilizasyon son kullanma tarihi en az 18 ay olmalıdır.', + 'Arıza durumunda 24 saat içinde yerinde teknik servis desteği sağlanmalıdır.', + 'Teslimat aşamasında her parti için numune test raporu (CoA) ibraz edilmelidir.' + ], + risksAndPenalties: [ + { level: 'Yüksek', clause: 'Madde 14.2', text: 'Gecikilen her takvim günü için ihale bedelinin %0.5 oranında cezai şart uygulanacaktır.' }, + { level: 'Orta', clause: 'Madde 18.1', text: 'Numune kontrolünde standart dışı bulunan partiler 3 iş günü içinde muadili ile ücretsiz değiştirilmelidir.' }, + { level: 'Düşük', clause: 'Madde 22 border', text: 'Ambalaj üzerindeki Türkçe etiket eksikliğinde kabul işlemi durdurulacaktır.' } + ], + bidAnalysis: { + estimatedCost: 185000, + recommendedBid: 148500, + minBidLimit: 132000, + maxBidLimit: 165000, + winProbability: 89, + competitionLevel: 'Orta Yoğunlukta (3-4 Firma Katılımı Bekleniyor)', + historicalDiscountAvg: '%19.7 EKAP İndirim Oranı' + } + }; + + setAiAnalysisResults(result); + resolve(result); + }, 2200); + }); + }; + + const [userProfile, setUserProfile] = useState({ + name: 'Hikmet Tanrıverdi', + username: 'tanriverdi', + company: 'Tanrıverdi Medikal & Teknolojileri A.Ş.', + website: 'https://www.tanriverdimedikal.com.tr', + trialDaysLeft: 7, + role: 'Yönetici Tedarikçi', + scrapedCapabilities: { + scrapedAt: '2026-08-07 14:30', + extractedSectors: ['Sağlık / Tıbbi Malzeme', 'Kırtasiye & Büro', 'Temizlik & Hijyen'], + extractedProducts: ['Ortopedi Protez Setleri', 'Cerrahi Maske', 'Dezenfektan', 'Hasta Yatağı', 'Sanatsal Kırtasiye'], + extractedCertifications: ['ISO 13485 Tıbbi Cihaz Kalite', 'ISO 9001', 'ÜTS Ürün Kayıt Yetkisi', 'CE Uygunluk'], + matchScoreBoost: 15 + } + }); + + const scanCompanyWebsite = (url) => { + return new Promise((resolve) => { + setTimeout(() => { + const domain = url.replace(/https?:\/\//, '').replace(/\/.*$/, ''); + const newCapabilities = { + scrapedAt: new Date().toLocaleString('tr-TR'), + extractedSectors: ['Sağlık / Tıbbi Malzeme', 'Bilişim & Yazılım', 'Kırtasiye & Büro'], + extractedProducts: [ + `${domain} - Medikal Cihaz ve Sarfları`, + 'Laboratuvar Test Kiti', + 'Zayıf Akım Güvenlik Sistemleri', + 'Ofis & Büro Kırtasiye Malzemeleri' + ], + extractedCertifications: [ + 'ISO 13485 Medikal Kalite', + 'ISO 27001 Bilgi Güvenliği', + 'ÜTS Ürün Takip Sistemi Belgesi', + 'TSE Hizmet Yeterlilik Belgesi' + ], + matchScoreBoost: 20 + }; + + setUserProfile(prev => ({ + ...prev, + website: url, + scrapedCapabilities: newCapabilities + })); + + resolve(newCapabilities); + }, 2500); + }); + }; + + const [notifications, setNotifications] = useState([ + { id: 'n1', title: 'Yeni İhale Bildirimi', text: 'Sağlık Hizmeti İhaleleri filtrenize 3 yeni ihale eklendi.', time: '5dk önce', read: false }, + { id: 'n2', title: 'Yaklaşan İhale Süresi', text: 'KIRTASİYE MALZEMELERİ ALIMI ihaleniz için son 3 gün!', time: '1sa önce', read: false } + ]); + + // Persist state to localstorage + useEffect(() => { + localStorage.setItem('ihaleist_tenders', JSON.stringify(tenders)); + }, [tenders]); + + useEffect(() => { + localStorage.setItem('ihaleist_saved_filters', JSON.stringify(savedFilters)); + }, [savedFilters]); + + // Live counter animation effect + useEffect(() => { + const interval = setInterval(() => { + setLiveStats(prev => ({ + ...prev, + onlineKullanici: prev.onlineKullanici + (Math.floor(Math.random() * 5) - 2), + bugunEklenen: prev.bugunEklenen + (Math.random() > 0.7 ? 1 : 0) + })); + }, 4000); + return () => clearInterval(interval); + }, []); + + const toggleTrackTender = (tenderId) => { + setTenders(prev => prev.map(t => { + if (t.id === tenderId) { + return { ...t, takipte: !t.takipte }; + } + return t; + })); + }; + + const updateKanbanStatus = (tenderId, newStatus, assignedUser = null) => { + setTenders(prev => prev.map(t => { + if (t.id === tenderId) { + return { + ...t, + kanbanStatus: newStatus, + atananPersonel: assignedUser !== null ? assignedUser : t.atananPersonel, + takipte: true + }; + } + return t; + })); + }; + + const addSavedFilter = (newFilter) => { + const filterObj = { + id: 'sf-' + Date.now(), + user: userProfile.username, + ...newFilter + }; + setSavedFilters(prev => [filterObj, ...prev]); + }; + + const deleteSavedFilter = (id) => { + setSavedFilters(prev => prev.filter(f => f.id !== id)); + }; + + const clearAllFilters = () => { + setSearchQuery(''); + setSelectedCity(''); + setSelectedAlimTuru(''); + setSelectedKurumTipi(''); + setSelectedSektor(''); + setQuickFilter('all'); + }; + + return ( + + {children} + + ); +}; + +export const useApp = () => useContext(AppContext); diff --git a/src/data/mockTenders.js b/src/data/mockTenders.js new file mode 100644 index 0000000..4fb559f --- /dev/null +++ b/src/data/mockTenders.js @@ -0,0 +1,331 @@ +export const MOCK_TENDERS = [ + { + id: "tender-101", + ikn: "26DT1489671", + baslik: "KIRTASİYE MALZEMELERİ ALIMI KAYSERİ ÇOCUK CEZAEVİ", + kurum: "CEZA VE TEVKİFEVLERİ GENEL MÜDÜRLÜĞÜ KAYSERİ ÇOCUK KAPALI CEZA İNFAZ KURUMU MÜDÜRLÜĞÜ", + sehir: "Kayseri", + bolge: "İÇ ANADOLU BÖLGESİ", + tarih: "10.08.2026", + saat: "12:00", + alimTuru: "Doğrudan Temin", + usul: "Doğrudan Temin (4734 22/d)", + sektor: "Kırtasiye & Büro", + brans: "Sanatsal Kırtasiye ve El Becerisi Malzemeleri", + kurumTipi: "Ceza İnfaz Kurumları", + eklenmeZamani: "az önce eklendi", + isYeni: true, + aciliyetBadge: "⚠️ SON 3 GÜN", + items: [ + { id: "i1", ad: "35*50 TUVAL", miktar: "10", birim: "adet", birimFiyat: 145 }, + { id: "i2", ad: "50*70 TUVAL", miktar: "10", birim: "adet", birimFiyat: 220 }, + { id: "i3", ad: "AKRİLİK BOYA SETİ 12'Lİ", miktar: "25", birim: "set", birimFiyat: 185 }, + { id: "i4", ad: "RESİM FIRÇASI SETİ NO: 1-12", miktar: "30", birim: "set", birimFiyat: 95 } + ], + aciklama: "Kayseri Çocuk Kapalı Ceza İnfaz Kurumu Müdürlüğü Hobi ve Atölye Çalışmaları İhtiyacı İçin 4 Kalem Kırtasiye ve Sanatsal Malzeme Doğrudan Temin Usulü İle Alınacaktır. Fiyat teklif cetveli kaşeli ve imzalı teslim edilecektir.", + yaklasikMaliyet: 18500, + teslimatSuresi: "7 Takvim Günü", + teslimYeri: "Kayseri Çocuk Cezaevi Deposu", + yeterlikKriterleri: ["KDV Hariç Teklif Cetveli", "İmza Sirküleri / Yetki Belgesi", "Faaliyet Belgesi"], + aiMatchScore: 94, + aiRiskScore: "Düşük", + aiBidRange: { min: 14200, max: 17800, recommended: 15600 }, + kanbanStatus: "teklif_hazirlaniyor", + atananPersonel: "Ahmet Yılmaz", + durum: "Aktif", + incelendi: true, + takipte: true, + sozlesmeBedeli: null, + kazananFirma: null + }, + { + id: "tender-102", + ikn: "26DT1489955", + baslik: "Yemek Kabı ve Üst Kapama Filmi Alımı", + kurum: "TARIM İŞLETMELERİ GENEL MÜDÜRLÜĞÜ KARACABEY TARIM İŞLETMESİ MÜDÜRLÜĞÜ", + sehir: "Bursa", + bolge: "MARMARA BÖLGESİ", + tarih: "10.08.2026", + saat: "18:00", + alimTuru: "Doğrudan Temin", + usul: "Doğrudan Temin (4734 22/d)", + sektor: "Gıda & Catering", + brans: "Ambalaj ve Paketleme Ürünleri", + kurumTipi: "Kamu Şirketleri", + eklenmeZamani: "az önce eklendi", + isYeni: true, + aciliyetBadge: "⚠️ SON 3 GÜN", + items: [ + { id: "i1", ad: "1 Gözlü Yemek Kabı", miktar: "1000", birim: "adet", birimFiyat: 2.80 }, + { id: "i2", ad: "2 Gözlü Yemek Kabı", miktar: "1000", birim: "adet", birimFiyat: 3.40 }, + { id: "i3", ad: "Sızdırmaz Üst Kapama Filmi (Rulo)", miktar: "50", birim: "rulo", birimFiyat: 410 } + ], + aciklama: "Karacabey Tarım İşletmesi personel yemekhanesi için kullanılacak olan ısıya dayanıklı 1 ve 2 gözlü porsiyonluk kaplar ve üst kapatma film ruloları alınacaktır.", + yaklasikMaliyet: 26700, + teslimatSuresi: "5 İş Günü", + teslimYeri: "Karacabey Tarım İşletmesi Ambarı", + yeterlikKriterleri: ["Gıda Temas Uygunluk Sertifikası (ISO 22000)", "Teklif Mektubu"], + aiMatchScore: 88, + aiRiskScore: "Düşük", + aiBidRange: { min: 21000, max: 25500, recommended: 23200 }, + kanbanStatus: "incelenecek", + atananPersonel: null, + durum: "Aktif", + incelendi: false, + takipte: false, + sozlesmeBedeli: null, + kazananFirma: null + }, + { + id: "tender-103", + ikn: "2026/184201", + baslik: "193064-PANİK BUTON KURULUM İŞİ", + kurum: "ANKARA ÜNİVERSİTESİ REKTÖRLÜĞÜ SAĞLIK UYGULAMA VE ARAŞTIRMA HASTANELERİ BAŞHEKİMLİĞİ", + sehir: "Ankara", + bolge: "İÇ ANADOLU BÖLGESİ", + tarih: "11.08.2026", + saat: "10:30", + alimTuru: "Doğrudan Temin", + usul: "Doğrudan Temin (4734 22/d)", + sektor: "Bilişim & Yazılım", + brans: "Güvenlik Sistemleri ve Zayıf Akım", + kurumTipi: "Üniversiteler", + eklenmeZamani: "15 dakika önce", + isYeni: true, + aciliyetBadge: "🔥 BUGÜN KAPANIYOR", + items: [ + { id: "i1", ad: "Kablosuz Panik Butonu Verici Ünite", miktar: "15", birim: "adet", birimFiyat: 1250 }, + { id: "i2", ad: "Merkezi Alarm Alma Paneli (RF Receiver)", miktar: "2", birim: "adet", birimFiyat: 8400 }, + { id: "i3", ad: "Montaj ve Kablolama Hizmeti", miktar: "1", birim: "paket", birimFiyat: 6500 } + ], + aciklama: "İbn-i Sina Araştırma Hastanesi Acil Servis ve Yoğun Bakım üniteleri için acil durum kablosuz panik buton sistemi temini ve devreye alınması işidir.", + yaklasikMaliyet: 42000, + teslimatSuresi: "10 Gün", + teslimYeri: "Ankara Üniversitesi İbn-i Sina Hastanesi", + yeterlikKriterleri: ["TSE HYB Belgesi", "Marka Tescil / Yetkili Satıcı Belgesi"], + aiMatchScore: 92, + aiRiskScore: "Orta", + aiBidRange: { min: 34500, max: 40800, recommended: 37200 }, + kanbanStatus: "inceleniyor", + atananPersonel: "Zeynep Kaya", + durum: "Aktif", + incelendi: true, + takipte: true, + sozlesmeBedeli: null, + kazananFirma: null + }, + { + id: "tender-104", + ikn: "26DT1490112", + baslik: "HASTAYA ÖZGÜ ORTOPEDİ MALZEME ALIMI (ZARİFE BALLI)", + kurum: "KONYA İL SAĞLIK MÜDÜRLÜĞÜ KONYA AKŞEHİR DEVLET HASTANESİ BAŞHEKİMLİĞİ", + sehir: "Konya", + bolge: "İÇ ANADOLU BÖLGESİ", + tarih: "12.08.2026", + saat: "14:00", + alimTuru: "Doğrudan Temin", + usul: "Doğrudan Temin (4734 22/f)", + sektor: "Sağlık / Tıbbi Malzeme", + brans: "Ortopedi ve Protez İmplanta Sistemleri", + kurumTipi: "Eğitim ve Araştırma Hastaneleri", + eklenmeZamani: "1 saat önce", + isYeni: false, + aciliyetBadge: null, + items: [ + { id: "i1", ad: "Revizyon Kalça Protez Femoral Stem (Titanyum)", miktar: "1", birim: "set", birimFiyat: 48500 }, + { id: "i2", ad: "Asetabular Kap ve Seramik Insert", miktar: "1", birim: "set", birimFiyat: 29000 }, + { id: "i3", ad: "Kemik Çimentosu Gentamisinli 40gr", miktar: "2", birim: "kutu", birimFiyat: 3200 } + ], + aciklama: "Hastaya özel doğrudan temin usulü ile kalça revizyon protez seti alımıdır. Ürünlerin ÜTS (Ürün Takip Sistemi) kaydı ve SUT kodları eksiksiz olmalıdır.", + yaklasikMaliyet: 83900, + teslimatSuresi: "3 Gün (Hasta Ameliyat Tarihi)", + teslimYeri: "Akşehir Devlet Hastanesi Ameliyathane Deposu", + yeterlikKriterleri: ["ÜTS Barkod Eşleşme Çıktısı", "SUT Bildirimi", "FDA / CE Sertifikası"], + aiMatchScore: 96, + aiRiskScore: "Düşük", + aiBidRange: { min: 72000, max: 81000, recommended: 76500 }, + kanbanStatus: "teklif_verildi", + atananPersonel: "Hikmet Tanrıverdi", + durum: "Aktif", + incelendi: true, + takipte: true, + sozlesmeBedeli: null, + kazananFirma: null + }, + { + id: "tender-105", + ikn: "2026/178920", + baslik: "Klima Santrali Filtre Değişimi ve Bakım Hizmet Alımı", + kurum: "İZMİR BÜYÜKŞEHİR BELEDİYESİ ULAŞIM DARE BAŞKANLIĞI", + sehir: "İzmir", + bolge: "EGE BÖLGESİ", + tarih: "14.08.2026", + saat: "11:00", + alimTuru: "Açık İhale", + usul: "Açık İhale Usulü (4734 Madde 19)", + sektor: "İnşaat & Bakım", + brans: "HVAC ve İklimlendirme Bakımı", + kurumTipi: "Büyükşehir Belediyeleri", + eklenmeZamani: "3 saat önce", + isYeni: false, + aciliyetBadge: null, + items: [ + { id: "i1", ad: "G4 Panel Filtre 592x592x48mm", miktar: "120", birim: "adet", birimFiyat: 190 }, + { id: "i2", ad: "F7 Torba Filtre 592x592x535mm 6 Cepli", miktar: "80", birim: "adet", birimFiyat: 480 }, + { id: "i3", ad: "Hepa Filtre H13 610x610x292mm", miktar: "24", birim: "adet", birimFiyat: 2100 }, + { id: "i4", ad: "Periyodik Bakım ve Gaz Şarjı Hizmeti", miktar: "12", birim: "ay", birimFiyat: 15000 } + ], + aciklama: "İzmir Büyükşehir Belediyesi Hizmet Binalarındaki 18 Adet Klima Santralinin 1 Yıllık Periyodik Filtre Değişimi ve Bakım Hizmeti Alımı İhalesidir.", + yaklasikMaliyet: 241000, + teslimatSuresi: "365 Gün", + teslimYeri: "İzmir Merkez Binaları", + yeterlikKriterleri: ["İş Deneyim Belgesi (Benzer İş %50)", "Geçici Teminat Mektubu %3", "Kapasite Raporu"], + aiMatchScore: 81, + aiRiskScore: "Orta", + aiBidRange: { min: 195000, max: 228000, recommended: 212000 }, + kanbanStatus: "incelenecek", + atananPersonel: null, + durum: "Aktif", + incelendi: false, + takipte: false, + sozlesmeBedeli: null, + kazananFirma: null + }, + { + id: "tender-106", + ikn: "26DT1490888", + baslik: "Genel Temizlik ve Dezenfeksiyon Sarf Malzemeleri Alımı", + kurum: "ANTALYA GENÇLİK VE SPOR İL MÜDÜRLÜĞÜ KYK YURTLARI", + sehir: "Antalya", + bolge: "AKDENİZ BÖLGESİ", + tarih: "15.08.2026", + saat: "15:30", + alimTuru: "Doğrudan Temin", + usul: "Doğrudan Temin (4734 22/d)", + sektor: "Temizlik & Hijyen", + brans: "Endüstriyel Temizlik Kimyasalları", + kurumTipi: "Bakanlıklar", + eklenmeZamani: "5 saat önce", + isYeni: false, + aciliyetBadge: null, + items: [ + { id: "i1", ad: "Çamaşır Suyu (Yüzey Dezenfektanı) 20 L", miktar: "80", birim: "bidon", birimFiyat: 340 }, + { id: "i2", ad: "Sıvı El Sabunu Sedefli 30 L", miktar: "60", birim: "bidon", birimFiyat: 520 }, + { id: "i3", ad: "Mikrofiber Temizlik Bezi 40x40 (100'lü)", miktar: "15", birim: "paket", birimFiyat: 680 } + ], + aciklama: "Antalya KYK Kız ve Erkek Öğrenci Yurtları yeni eğitim-öğretim sezonu hazırlıkları için temizlik hijyen sarf ürünleri temin edilecektir.", + yaklasikMaliyet: 68600, + teslimatSuresi: "7 Gün", + teslimYeri: "Antalya Akdeniz Yurt Müdürlüğü Deposu", + yeterlikKriterleri: ["MSDS Güvenlik Bilgi Formları", "Sağlık Bakanlığı Ruhsat Fotokopisi"], + aiMatchScore: 89, + aiRiskScore: "Düşük", + aiBidRange: { min: 54000, max: 63000, recommended: 58500 }, + kanbanStatus: "kazanildi", + atananPersonel: "Hikmet Tanrıverdi", + durum: "Sonuçlandı", + incelendi: true, + takipte: true, + sozlesmeBedeli: 57400, + kazananFirma: "Tanrıverdi Medikal & Hijyen Ltd. Şti." + }, + { + id: "tender-107", + ikn: "2026/172340", + baslik: "Veri Merkezi Sunucu ve Depolama Ünitesi Alımı", + kurum: "HAVELSAN HAVA ELEKTRONİK SANAYİ A.Ş.", + sehir: "Ankara", + bolge: "İÇ ANADOLU BÖLGESİ", + tarih: "18.08.2026", + saat: "10:00", + alimTuru: "Açık İhale", + usul: "Açık İhale", + sektor: "Bilişim & Yazılım", + brans: "Sunucu ve Veri Depolama Donanımları", + kurumTipi: "Kamu Şirketleri", + eklenmeZamani: "1 gün önce", + isYeni: false, + aciliyetBadge: null, + items: [ + { id: "i1", ad: "Rack Sunucu 2U 2x Xeon Gold 6430 / 256GB RAM", miktar: "4", birim: "adet", birimFiyat: 145000 }, + { id: "i2", ad: "NVMe SAN Storage Unit 100TB Usable", miktar: "1", birim: "set", birimFiyat: 620000 } + ], + aciklama: "Havelsan Teknoloji Kampüsü Veri Merkezi Genişletme Projesi kapsamında yüksek performanslı sunucu ve veri depolama üniteleri temin edilecektir.", + yaklasikMaliyet: 1200000, + teslimatSuresi: "30 Takvim Günü", + teslimYeri: "Havelsan ODTÜ Teknokent Binası", + yeterlikKriterleri: ["Üretici Yetki Belgesi (MAF)", "ISO 27001 Bilgi Güvenliği Belgesi"], + aiMatchScore: 76, + aiRiskScore: "Yüksek", + aiBidRange: { min: 980000, max: 1150000, recommended: 1040000 }, + kanbanStatus: "kaybedildi", + atananPersonel: "Mehmet Demir", + durum: "Sonuçlandı", + incelendi: true, + takipte: true, + sozlesmeBedeli: 1025000, + kazananFirma: "Netaş Telekomünikasyon A.Ş." + } +]; + +export const MOCK_COMPANY_STATS = { + notlarimCount: 4, + ajandaCount: 2, + incelediklerimCount: 14, + sozlesmelerimCount: 8, + sonuclarimCount: 12, + takibimdekilerCount: 9, + kanbanStats: { + incelenecek: 3, + inceleniyor: 2, + teklif_hazirlaniyor: 4, + teklif_verildi: 3, + kazanildi: 8, + kaybedildi: 4 + } +}; + +export const MOCK_LIVE_STATS = { + onlineKullanici: 17551, + toplamKalem: 99666, + bugunEklenen: 1445, + aktifTakip: 102473 +}; + +export const SECTORS_LIST = [ + "Sağlık / Tıbbi Malzeme", + "Kırtasiye & Büro", + "Bilişim & Yazılım", + "Gıda & Catering", + "İnşaat & Bakım", + "Temizlik & Hijyen", + "Tekstil & Giyim", + "Otomotiv & Yedek Parça" +]; + +export const INSTITUTION_TYPES_LIST = [ + "Eğitim ve Araştırma Hastaneleri", + "Belediyeler", + "Büyükşehir Belediyeleri", + "Ceza İnfaz Kurumları", + "Üniversiteler", + "Bakanlıklar", + "Kamu Şirketleri", + "Ağız ve Diş Sağlığı Merkezleri" +]; + +export const CITIES_LIST = [ + "Adana", "Adıyaman", "Afyonkarahisar", "Aksaray", "Amasya", "Ankara", "Antalya", "Ardahan", "Artvin", + "Aydın", "Balıkesir", "Bolu", "Bursa", "Çanakkale", "Denizli", "Diyarbakır", "Edirne", "Eskişehir", + "Gaziantep", "Giresun", "Isparta", "İstanbul", "İzmir", "Kahramanmaraş", "Kars", "Kastamonu", "Kayseri", + "Kocaeli", "Konya", "Kütahya", "Malatya", "Manisa", "Mardin", "Muğla", "Ordu", "Rize", "Sakarya", + "Samsun", "Sivas", "Şanlıurfa", "Tekirdağ", "Trabzon", "Van", "Zonguldak" +]; + +export const COMPETITOR_DATA = [ + { name: "Tanrıverdi Medikal & Hijyen Ltd.", winCount: 24, totalVolume: "4.850.000 TL", share: 32 }, + { name: "Atlas Büro & Kırtasiye A.Ş.", winCount: 19, totalVolume: "3.200.000 TL", share: 24 }, + { name: "ProTek Bilişim ve Sistemler", winCount: 15, totalVolume: "6.750.000 TL", share: 22 }, + { name: "Özkan Sağlık Hizmetleri", winCount: 11, totalVolume: "2.100.000 TL", share: 14 }, + { name: "Diğer Tedarikçiler", winCount: 8, totalVolume: "1.400.000 TL", share: 8 } +]; diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..71f2c56 --- /dev/null +++ b/src/index.css @@ -0,0 +1,45 @@ +@import "tailwindcss"; + +@layer base { + body { + background-color: #ebedf2; + color: #1e293b; + font-family: 'Inter', system-ui, -apple-system, sans-serif; + } +} + +/* Custom Scrollbars */ +::-webkit-scrollbar { + width: 6px; + height: 6px; +} +::-webkit-scrollbar-track { + background: #f1f5f9; +} +::-webkit-scrollbar-thumb { + background: #cbd5e1; + border-radius: 9999px; +} +::-webkit-scrollbar-thumb:hover { + background: #94a3b8; +} + +/* Animations */ +@keyframes fadeIn { + from { opacity: 0; transform: translateY(4px); } + to { opacity: 1; transform: translateY(0); } +} + +.animate-fade-in { + animation: fadeIn 0.2s ease-out forwards; +} + +/* Pulse badge animation */ +@keyframes pulseGlow { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.85; transform: scale(1.03); } +} + +.pulse-glow { + animation: pulseGlow 2s infinite ease-in-out; +} diff --git a/src/main.jsx b/src/main.jsx new file mode 100644 index 0000000..54b39dd --- /dev/null +++ b/src/main.jsx @@ -0,0 +1,10 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.jsx' +import './index.css' + +ReactDOM.createRoot(document.getElementById('root')).render( + + + , +) diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..b62324f --- /dev/null +++ b/vite.config.js @@ -0,0 +1,11 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import tailwindcss from '@tailwindcss/vite' + +export default defineConfig({ + plugins: [react(), tailwindcss()], + server: { + port: 3000, + host: true + } +})