修改论坛、促销、登录,增加测试
Change-Id: I71883fc1da46a94db47f90a4cd61474c274a5b2c
diff --git a/.env.development b/.env.development
index 9a9d66e..32e9bf1 100644
--- a/.env.development
+++ b/.env.development
@@ -1 +1,2 @@
-REACT_APP_API_BASE=http://127.0.0.1:4523/m1/6139971-5831803-default
+# REACT_APP_API_BASE=http://127.0.0.1:4523/m1/6139971-5831803-default
+REACT_APP_API_BASE=http://localhost:8080
diff --git a/.env.test b/.env.test
new file mode 100644
index 0000000..b6cee00
--- /dev/null
+++ b/.env.test
@@ -0,0 +1 @@
+REACT_APP_API_BASE=http://localhost:8080
diff --git a/package-lock.json b/package-lock.json
index 9e114d7..39431d4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,18 +11,22 @@
"@icon-park/react": "^1.4.2",
"@testing-library/dom": "^10.4.0",
"@testing-library/user-event": "^13.5.0",
- "axios": "^1.8.4",
+ "axios": "^0.27.2",
+ "crypto-js": "^4.2.0",
"quill": "^2.0.3",
"react": "^19.1.0",
"react-dom": "^19.1.0",
- "react-router-dom": "^7.5.0",
+ "react-router-dom": "^7.6.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4",
"wouter": "^3.6.0"
},
"devDependencies": {
+ "@babel/preset-env": "^7.27.2",
+ "@babel/preset-react": "^7.27.1",
"@testing-library/jest-dom": "^6.6.3",
- "@testing-library/react": "^16.3.0"
+ "@testing-library/react": "^16.3.0",
+ "babel-jest": "^30.0.0-beta.3"
}
},
"node_modules/@adobe/css-tools": {
@@ -58,23 +62,23 @@
}
},
"node_modules/@babel/code-frame": {
- "version": "7.26.2",
- "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.26.2.tgz",
- "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
"license": "MIT",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.27.1",
"js-tokens": "^4.0.0",
- "picocolors": "^1.0.0"
+ "picocolors": "^1.1.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/compat-data": {
- "version": "7.26.8",
- "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.26.8.tgz",
- "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==",
+ "version": "7.27.3",
+ "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.27.3.tgz",
+ "integrity": "sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -156,13 +160,13 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.27.0",
- "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.27.0.tgz",
- "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==",
+ "version": "7.27.3",
+ "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.27.3.tgz",
+ "integrity": "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==",
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.27.0",
- "@babel/types": "^7.27.0",
+ "@babel/parser": "^7.27.3",
+ "@babel/types": "^7.27.3",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^3.0.2"
@@ -172,25 +176,25 @@
}
},
"node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
- "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
+ "version": "7.27.3",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz",
+ "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.9"
+ "@babel/types": "^7.27.3"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-compilation-targets": {
- "version": "7.27.0",
- "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz",
- "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==",
+ "version": "7.27.2",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
+ "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
"license": "MIT",
"dependencies": {
- "@babel/compat-data": "^7.26.8",
- "@babel/helper-validator-option": "^7.25.9",
+ "@babel/compat-data": "^7.27.2",
+ "@babel/helper-validator-option": "^7.27.1",
"browserslist": "^4.24.0",
"lru-cache": "^5.1.1",
"semver": "^6.3.1"
@@ -209,17 +213,17 @@
}
},
"node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.27.0",
- "resolved": "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz",
- "integrity": "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz",
+ "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==",
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.25.9",
- "@babel/helper-member-expression-to-functions": "^7.25.9",
- "@babel/helper-optimise-call-expression": "^7.25.9",
- "@babel/helper-replace-supers": "^7.26.5",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
- "@babel/traverse": "^7.27.0",
+ "@babel/helper-annotate-as-pure": "^7.27.1",
+ "@babel/helper-member-expression-to-functions": "^7.27.1",
+ "@babel/helper-optimise-call-expression": "^7.27.1",
+ "@babel/helper-replace-supers": "^7.27.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
+ "@babel/traverse": "^7.27.1",
"semver": "^6.3.1"
},
"engines": {
@@ -239,12 +243,12 @@
}
},
"node_modules/@babel/helper-create-regexp-features-plugin": {
- "version": "7.27.0",
- "resolved": "https://registry.npmmirror.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.0.tgz",
- "integrity": "sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz",
+ "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-annotate-as-pure": "^7.27.1",
"regexpu-core": "^6.2.0",
"semver": "^6.3.1"
},
@@ -281,40 +285,40 @@
}
},
"node_modules/@babel/helper-member-expression-to-functions": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz",
- "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz",
+ "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==",
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-imports": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
- "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.26.0",
- "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz",
- "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==",
+ "version": "7.27.3",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz",
+ "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==",
"license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9",
- "@babel/traverse": "^7.25.9"
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "@babel/traverse": "^7.27.3"
},
"engines": {
"node": ">=6.9.0"
@@ -324,35 +328,35 @@
}
},
"node_modules/@babel/helper-optimise-call-expression": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz",
- "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz",
+ "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.25.9"
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-plugin-utils": {
- "version": "7.26.5",
- "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz",
- "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
+ "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-remap-async-to-generator": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz",
- "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz",
+ "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.25.9",
- "@babel/helper-wrap-function": "^7.25.9",
- "@babel/traverse": "^7.25.9"
+ "@babel/helper-annotate-as-pure": "^7.27.1",
+ "@babel/helper-wrap-function": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -362,14 +366,14 @@
}
},
"node_modules/@babel/helper-replace-supers": {
- "version": "7.26.5",
- "resolved": "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz",
- "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz",
+ "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-member-expression-to-functions": "^7.25.9",
- "@babel/helper-optimise-call-expression": "^7.25.9",
- "@babel/traverse": "^7.26.5"
+ "@babel/helper-member-expression-to-functions": "^7.27.1",
+ "@babel/helper-optimise-call-expression": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -379,54 +383,54 @@
}
},
"node_modules/@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz",
- "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz",
+ "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==",
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
- "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
- "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
+ "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-option": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
- "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-wrap-function": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz",
- "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz",
+ "integrity": "sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==",
"license": "MIT",
"dependencies": {
- "@babel/template": "^7.25.9",
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/template": "^7.27.1",
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -446,12 +450,12 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.27.0",
- "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.27.0.tgz",
- "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
+ "version": "7.27.3",
+ "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.27.3.tgz",
+ "integrity": "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==",
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.27.0"
+ "@babel/types": "^7.27.3"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -461,13 +465,13 @@
}
},
"node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz",
- "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz",
+ "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/traverse": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -477,12 +481,12 @@
}
},
"node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz",
- "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz",
+ "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -492,12 +496,12 @@
}
},
"node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz",
- "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz",
+ "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -507,14 +511,14 @@
}
},
"node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz",
- "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz",
+ "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
- "@babel/plugin-transform-optional-chaining": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
+ "@babel/plugin-transform-optional-chaining": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -524,13 +528,13 @@
}
},
"node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz",
- "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.27.1.tgz",
+ "integrity": "sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/traverse": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -736,12 +740,12 @@
}
},
"node_modules/@babel/plugin-syntax-import-assertions": {
- "version": "7.26.0",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz",
- "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz",
+ "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -751,12 +755,12 @@
}
},
"node_modules/@babel/plugin-syntax-import-attributes": {
- "version": "7.26.0",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz",
- "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz",
+ "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -790,12 +794,12 @@
}
},
"node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz",
- "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz",
+ "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -938,12 +942,12 @@
}
},
"node_modules/@babel/plugin-transform-arrow-functions": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz",
- "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz",
+ "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -953,14 +957,14 @@
}
},
"node_modules/@babel/plugin-transform-async-generator-functions": {
- "version": "7.26.8",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz",
- "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.27.1.tgz",
+ "integrity": "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.26.5",
- "@babel/helper-remap-async-to-generator": "^7.25.9",
- "@babel/traverse": "^7.26.8"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-remap-async-to-generator": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -970,14 +974,14 @@
}
},
"node_modules/@babel/plugin-transform-async-to-generator": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz",
- "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz",
+ "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-remap-async-to-generator": "^7.25.9"
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-remap-async-to-generator": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -987,12 +991,12 @@
}
},
"node_modules/@babel/plugin-transform-block-scoped-functions": {
- "version": "7.26.5",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz",
- "integrity": "sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz",
+ "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.26.5"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1002,12 +1006,12 @@
}
},
"node_modules/@babel/plugin-transform-block-scoping": {
- "version": "7.27.0",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.0.tgz",
- "integrity": "sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ==",
+ "version": "7.27.3",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.3.tgz",
+ "integrity": "sha512-+F8CnfhuLhwUACIJMLWnjz6zvzYM2r0yeIHKlbgfw7ml8rOMJsXNXV/hyRcb3nb493gRs4WvYpQAndWj/qQmkQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.26.5"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1017,13 +1021,13 @@
}
},
"node_modules/@babel/plugin-transform-class-properties": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz",
- "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz",
+ "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-create-class-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1033,13 +1037,13 @@
}
},
"node_modules/@babel/plugin-transform-class-static-block": {
- "version": "7.26.0",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz",
- "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.27.1.tgz",
+ "integrity": "sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-create-class-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1049,16 +1053,16 @@
}
},
"node_modules/@babel/plugin-transform-classes": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz",
- "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.27.1.tgz",
+ "integrity": "sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.25.9",
- "@babel/helper-compilation-targets": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-replace-supers": "^7.25.9",
- "@babel/traverse": "^7.25.9",
+ "@babel/helper-annotate-as-pure": "^7.27.1",
+ "@babel/helper-compilation-targets": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-replace-supers": "^7.27.1",
+ "@babel/traverse": "^7.27.1",
"globals": "^11.1.0"
},
"engines": {
@@ -1069,13 +1073,13 @@
}
},
"node_modules/@babel/plugin-transform-computed-properties": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz",
- "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz",
+ "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/template": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/template": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1085,12 +1089,12 @@
}
},
"node_modules/@babel/plugin-transform-destructuring": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz",
- "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==",
+ "version": "7.27.3",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.3.tgz",
+ "integrity": "sha512-s4Jrok82JpiaIprtY2nHsYmrThKvvwgHwjgd7UMiYhZaN0asdXNLr0y+NjTfkA7SyQE5i2Fb7eawUOZmLvyqOA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1100,13 +1104,13 @@
}
},
"node_modules/@babel/plugin-transform-dotall-regex": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz",
- "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz",
+ "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1116,12 +1120,12 @@
}
},
"node_modules/@babel/plugin-transform-duplicate-keys": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz",
- "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz",
+ "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1131,13 +1135,13 @@
}
},
"node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz",
- "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz",
+ "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1147,12 +1151,12 @@
}
},
"node_modules/@babel/plugin-transform-dynamic-import": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz",
- "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz",
+ "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1162,12 +1166,12 @@
}
},
"node_modules/@babel/plugin-transform-exponentiation-operator": {
- "version": "7.26.3",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz",
- "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz",
+ "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1177,12 +1181,12 @@
}
},
"node_modules/@babel/plugin-transform-export-namespace-from": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz",
- "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz",
+ "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1208,13 +1212,13 @@
}
},
"node_modules/@babel/plugin-transform-for-of": {
- "version": "7.26.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz",
- "integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz",
+ "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.26.5",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1224,14 +1228,14 @@
}
},
"node_modules/@babel/plugin-transform-function-name": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz",
- "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz",
+ "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-compilation-targets": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/traverse": "^7.25.9"
+ "@babel/helper-compilation-targets": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1241,12 +1245,12 @@
}
},
"node_modules/@babel/plugin-transform-json-strings": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz",
- "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz",
+ "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1256,12 +1260,12 @@
}
},
"node_modules/@babel/plugin-transform-literals": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz",
- "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz",
+ "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1271,12 +1275,12 @@
}
},
"node_modules/@babel/plugin-transform-logical-assignment-operators": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz",
- "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz",
+ "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1286,12 +1290,12 @@
}
},
"node_modules/@babel/plugin-transform-member-expression-literals": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz",
- "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz",
+ "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1301,13 +1305,13 @@
}
},
"node_modules/@babel/plugin-transform-modules-amd": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz",
- "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz",
+ "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-module-transforms": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-module-transforms": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1317,13 +1321,13 @@
}
},
"node_modules/@babel/plugin-transform-modules-commonjs": {
- "version": "7.26.3",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz",
- "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz",
+ "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-module-transforms": "^7.26.0",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-module-transforms": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1333,15 +1337,15 @@
}
},
"node_modules/@babel/plugin-transform-modules-systemjs": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz",
- "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz",
+ "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-module-transforms": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9",
- "@babel/traverse": "^7.25.9"
+ "@babel/helper-module-transforms": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1351,13 +1355,13 @@
}
},
"node_modules/@babel/plugin-transform-modules-umd": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz",
- "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz",
+ "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==",
"license": "MIT",
"dependencies": {
- "@babel/helper-module-transforms": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-module-transforms": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1367,13 +1371,13 @@
}
},
"node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz",
- "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz",
+ "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==",
"license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1383,12 +1387,12 @@
}
},
"node_modules/@babel/plugin-transform-new-target": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz",
- "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz",
+ "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1398,12 +1402,12 @@
}
},
"node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
- "version": "7.26.6",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz",
- "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz",
+ "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.26.5"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1413,12 +1417,12 @@
}
},
"node_modules/@babel/plugin-transform-numeric-separator": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz",
- "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz",
+ "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1428,14 +1432,15 @@
}
},
"node_modules/@babel/plugin-transform-object-rest-spread": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz",
- "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==",
+ "version": "7.27.3",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.3.tgz",
+ "integrity": "sha512-7ZZtznF9g4l2JCImCo5LNKFHB5eXnN39lLtLY5Tg+VkR0jwOt7TBciMckuiQIOIW7L5tkQOCh3bVGYeXgMx52Q==",
"license": "MIT",
"dependencies": {
- "@babel/helper-compilation-targets": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/plugin-transform-parameters": "^7.25.9"
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/plugin-transform-destructuring": "^7.27.3",
+ "@babel/plugin-transform-parameters": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1445,13 +1450,13 @@
}
},
"node_modules/@babel/plugin-transform-object-super": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz",
- "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz",
+ "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-replace-supers": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-replace-supers": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1461,12 +1466,12 @@
}
},
"node_modules/@babel/plugin-transform-optional-catch-binding": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz",
- "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz",
+ "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1476,13 +1481,13 @@
}
},
"node_modules/@babel/plugin-transform-optional-chaining": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz",
- "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz",
+ "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1492,12 +1497,12 @@
}
},
"node_modules/@babel/plugin-transform-parameters": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz",
- "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.1.tgz",
+ "integrity": "sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1507,13 +1512,13 @@
}
},
"node_modules/@babel/plugin-transform-private-methods": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz",
- "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz",
+ "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-create-class-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1523,14 +1528,14 @@
}
},
"node_modules/@babel/plugin-transform-private-property-in-object": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz",
- "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz",
+ "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.25.9",
- "@babel/helper-create-class-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-annotate-as-pure": "^7.27.1",
+ "@babel/helper-create-class-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1540,12 +1545,12 @@
}
},
"node_modules/@babel/plugin-transform-property-literals": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz",
- "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz",
+ "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1570,12 +1575,12 @@
}
},
"node_modules/@babel/plugin-transform-react-display-name": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz",
- "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.27.1.tgz",
+ "integrity": "sha512-p9+Vl3yuHPmkirRrg021XiP+EETmPMQTLr6Ayjj85RLNEbb3Eya/4VI0vAdzQG9SEAl2Lnt7fy5lZyMzjYoZQQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1585,16 +1590,16 @@
}
},
"node_modules/@babel/plugin-transform-react-jsx": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz",
- "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz",
+ "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.25.9",
- "@babel/helper-module-imports": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/plugin-syntax-jsx": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/helper-annotate-as-pure": "^7.27.1",
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/plugin-syntax-jsx": "^7.27.1",
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1604,12 +1609,12 @@
}
},
"node_modules/@babel/plugin-transform-react-jsx-development": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz",
- "integrity": "sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz",
+ "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==",
"license": "MIT",
"dependencies": {
- "@babel/plugin-transform-react-jsx": "^7.25.9"
+ "@babel/plugin-transform-react-jsx": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1619,13 +1624,13 @@
}
},
"node_modules/@babel/plugin-transform-react-pure-annotations": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz",
- "integrity": "sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz",
+ "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-annotate-as-pure": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1635,13 +1640,12 @@
}
},
"node_modules/@babel/plugin-transform-regenerator": {
- "version": "7.27.0",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.0.tgz",
- "integrity": "sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.1.tgz",
+ "integrity": "sha512-B19lbbL7PMrKr52BNPjCqg1IyNUIjTcxKj8uX9zHO+PmWN93s19NDr/f69mIkEp2x9nmDJ08a7lgHaTTzvW7mw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.26.5",
- "regenerator-transform": "^0.15.2"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1651,13 +1655,13 @@
}
},
"node_modules/@babel/plugin-transform-regexp-modifiers": {
- "version": "7.26.0",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz",
- "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz",
+ "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1667,12 +1671,12 @@
}
},
"node_modules/@babel/plugin-transform-reserved-words": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz",
- "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz",
+ "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1711,12 +1715,12 @@
}
},
"node_modules/@babel/plugin-transform-shorthand-properties": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz",
- "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz",
+ "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1726,13 +1730,13 @@
}
},
"node_modules/@babel/plugin-transform-spread": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz",
- "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz",
+ "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1742,12 +1746,12 @@
}
},
"node_modules/@babel/plugin-transform-sticky-regex": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz",
- "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz",
+ "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1757,12 +1761,12 @@
}
},
"node_modules/@babel/plugin-transform-template-literals": {
- "version": "7.26.8",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz",
- "integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz",
+ "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.26.5"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1772,12 +1776,12 @@
}
},
"node_modules/@babel/plugin-transform-typeof-symbol": {
- "version": "7.27.0",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.0.tgz",
- "integrity": "sha512-+LLkxA9rKJpNoGsbLnAgOCdESl73vwYn+V6b+5wHbrE7OGKVDPHIQvbFSzqE6rwqaCw2RE+zdJrlLkcf8YOA0w==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz",
+ "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.26.5"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1806,12 +1810,12 @@
}
},
"node_modules/@babel/plugin-transform-unicode-escapes": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz",
- "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz",
+ "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1821,13 +1825,13 @@
}
},
"node_modules/@babel/plugin-transform-unicode-property-regex": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz",
- "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz",
+ "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==",
"license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1837,13 +1841,13 @@
}
},
"node_modules/@babel/plugin-transform-unicode-regex": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz",
- "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz",
+ "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1853,13 +1857,13 @@
}
},
"node_modules/@babel/plugin-transform-unicode-sets-regex": {
- "version": "7.25.9",
- "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz",
- "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz",
+ "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.25.9",
- "@babel/helper-plugin-utils": "^7.25.9"
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1869,74 +1873,74 @@
}
},
"node_modules/@babel/preset-env": {
- "version": "7.26.9",
- "resolved": "https://registry.npmmirror.com/@babel/preset-env/-/preset-env-7.26.9.tgz",
- "integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==",
+ "version": "7.27.2",
+ "resolved": "https://registry.npmmirror.com/@babel/preset-env/-/preset-env-7.27.2.tgz",
+ "integrity": "sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==",
"license": "MIT",
"dependencies": {
- "@babel/compat-data": "^7.26.8",
- "@babel/helper-compilation-targets": "^7.26.5",
- "@babel/helper-plugin-utils": "^7.26.5",
- "@babel/helper-validator-option": "^7.25.9",
- "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9",
- "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9",
- "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9",
- "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9",
- "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9",
+ "@babel/compat-data": "^7.27.2",
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-validator-option": "^7.27.1",
+ "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.27.1",
+ "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1",
+ "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.27.1",
"@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
- "@babel/plugin-syntax-import-assertions": "^7.26.0",
- "@babel/plugin-syntax-import-attributes": "^7.26.0",
+ "@babel/plugin-syntax-import-assertions": "^7.27.1",
+ "@babel/plugin-syntax-import-attributes": "^7.27.1",
"@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
- "@babel/plugin-transform-arrow-functions": "^7.25.9",
- "@babel/plugin-transform-async-generator-functions": "^7.26.8",
- "@babel/plugin-transform-async-to-generator": "^7.25.9",
- "@babel/plugin-transform-block-scoped-functions": "^7.26.5",
- "@babel/plugin-transform-block-scoping": "^7.25.9",
- "@babel/plugin-transform-class-properties": "^7.25.9",
- "@babel/plugin-transform-class-static-block": "^7.26.0",
- "@babel/plugin-transform-classes": "^7.25.9",
- "@babel/plugin-transform-computed-properties": "^7.25.9",
- "@babel/plugin-transform-destructuring": "^7.25.9",
- "@babel/plugin-transform-dotall-regex": "^7.25.9",
- "@babel/plugin-transform-duplicate-keys": "^7.25.9",
- "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9",
- "@babel/plugin-transform-dynamic-import": "^7.25.9",
- "@babel/plugin-transform-exponentiation-operator": "^7.26.3",
- "@babel/plugin-transform-export-namespace-from": "^7.25.9",
- "@babel/plugin-transform-for-of": "^7.26.9",
- "@babel/plugin-transform-function-name": "^7.25.9",
- "@babel/plugin-transform-json-strings": "^7.25.9",
- "@babel/plugin-transform-literals": "^7.25.9",
- "@babel/plugin-transform-logical-assignment-operators": "^7.25.9",
- "@babel/plugin-transform-member-expression-literals": "^7.25.9",
- "@babel/plugin-transform-modules-amd": "^7.25.9",
- "@babel/plugin-transform-modules-commonjs": "^7.26.3",
- "@babel/plugin-transform-modules-systemjs": "^7.25.9",
- "@babel/plugin-transform-modules-umd": "^7.25.9",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9",
- "@babel/plugin-transform-new-target": "^7.25.9",
- "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6",
- "@babel/plugin-transform-numeric-separator": "^7.25.9",
- "@babel/plugin-transform-object-rest-spread": "^7.25.9",
- "@babel/plugin-transform-object-super": "^7.25.9",
- "@babel/plugin-transform-optional-catch-binding": "^7.25.9",
- "@babel/plugin-transform-optional-chaining": "^7.25.9",
- "@babel/plugin-transform-parameters": "^7.25.9",
- "@babel/plugin-transform-private-methods": "^7.25.9",
- "@babel/plugin-transform-private-property-in-object": "^7.25.9",
- "@babel/plugin-transform-property-literals": "^7.25.9",
- "@babel/plugin-transform-regenerator": "^7.25.9",
- "@babel/plugin-transform-regexp-modifiers": "^7.26.0",
- "@babel/plugin-transform-reserved-words": "^7.25.9",
- "@babel/plugin-transform-shorthand-properties": "^7.25.9",
- "@babel/plugin-transform-spread": "^7.25.9",
- "@babel/plugin-transform-sticky-regex": "^7.25.9",
- "@babel/plugin-transform-template-literals": "^7.26.8",
- "@babel/plugin-transform-typeof-symbol": "^7.26.7",
- "@babel/plugin-transform-unicode-escapes": "^7.25.9",
- "@babel/plugin-transform-unicode-property-regex": "^7.25.9",
- "@babel/plugin-transform-unicode-regex": "^7.25.9",
- "@babel/plugin-transform-unicode-sets-regex": "^7.25.9",
+ "@babel/plugin-transform-arrow-functions": "^7.27.1",
+ "@babel/plugin-transform-async-generator-functions": "^7.27.1",
+ "@babel/plugin-transform-async-to-generator": "^7.27.1",
+ "@babel/plugin-transform-block-scoped-functions": "^7.27.1",
+ "@babel/plugin-transform-block-scoping": "^7.27.1",
+ "@babel/plugin-transform-class-properties": "^7.27.1",
+ "@babel/plugin-transform-class-static-block": "^7.27.1",
+ "@babel/plugin-transform-classes": "^7.27.1",
+ "@babel/plugin-transform-computed-properties": "^7.27.1",
+ "@babel/plugin-transform-destructuring": "^7.27.1",
+ "@babel/plugin-transform-dotall-regex": "^7.27.1",
+ "@babel/plugin-transform-duplicate-keys": "^7.27.1",
+ "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1",
+ "@babel/plugin-transform-dynamic-import": "^7.27.1",
+ "@babel/plugin-transform-exponentiation-operator": "^7.27.1",
+ "@babel/plugin-transform-export-namespace-from": "^7.27.1",
+ "@babel/plugin-transform-for-of": "^7.27.1",
+ "@babel/plugin-transform-function-name": "^7.27.1",
+ "@babel/plugin-transform-json-strings": "^7.27.1",
+ "@babel/plugin-transform-literals": "^7.27.1",
+ "@babel/plugin-transform-logical-assignment-operators": "^7.27.1",
+ "@babel/plugin-transform-member-expression-literals": "^7.27.1",
+ "@babel/plugin-transform-modules-amd": "^7.27.1",
+ "@babel/plugin-transform-modules-commonjs": "^7.27.1",
+ "@babel/plugin-transform-modules-systemjs": "^7.27.1",
+ "@babel/plugin-transform-modules-umd": "^7.27.1",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1",
+ "@babel/plugin-transform-new-target": "^7.27.1",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1",
+ "@babel/plugin-transform-numeric-separator": "^7.27.1",
+ "@babel/plugin-transform-object-rest-spread": "^7.27.2",
+ "@babel/plugin-transform-object-super": "^7.27.1",
+ "@babel/plugin-transform-optional-catch-binding": "^7.27.1",
+ "@babel/plugin-transform-optional-chaining": "^7.27.1",
+ "@babel/plugin-transform-parameters": "^7.27.1",
+ "@babel/plugin-transform-private-methods": "^7.27.1",
+ "@babel/plugin-transform-private-property-in-object": "^7.27.1",
+ "@babel/plugin-transform-property-literals": "^7.27.1",
+ "@babel/plugin-transform-regenerator": "^7.27.1",
+ "@babel/plugin-transform-regexp-modifiers": "^7.27.1",
+ "@babel/plugin-transform-reserved-words": "^7.27.1",
+ "@babel/plugin-transform-shorthand-properties": "^7.27.1",
+ "@babel/plugin-transform-spread": "^7.27.1",
+ "@babel/plugin-transform-sticky-regex": "^7.27.1",
+ "@babel/plugin-transform-template-literals": "^7.27.1",
+ "@babel/plugin-transform-typeof-symbol": "^7.27.1",
+ "@babel/plugin-transform-unicode-escapes": "^7.27.1",
+ "@babel/plugin-transform-unicode-property-regex": "^7.27.1",
+ "@babel/plugin-transform-unicode-regex": "^7.27.1",
+ "@babel/plugin-transform-unicode-sets-regex": "^7.27.1",
"@babel/preset-modules": "0.1.6-no-external-plugins",
"babel-plugin-polyfill-corejs2": "^0.4.10",
"babel-plugin-polyfill-corejs3": "^0.11.0",
@@ -1975,17 +1979,17 @@
}
},
"node_modules/@babel/preset-react": {
- "version": "7.26.3",
- "resolved": "https://registry.npmmirror.com/@babel/preset-react/-/preset-react-7.26.3.tgz",
- "integrity": "sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/preset-react/-/preset-react-7.27.1.tgz",
+ "integrity": "sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==",
"license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.25.9",
- "@babel/helper-validator-option": "^7.25.9",
- "@babel/plugin-transform-react-display-name": "^7.25.9",
- "@babel/plugin-transform-react-jsx": "^7.25.9",
- "@babel/plugin-transform-react-jsx-development": "^7.25.9",
- "@babel/plugin-transform-react-pure-annotations": "^7.25.9"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-validator-option": "^7.27.1",
+ "@babel/plugin-transform-react-display-name": "^7.27.1",
+ "@babel/plugin-transform-react-jsx": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-development": "^7.27.1",
+ "@babel/plugin-transform-react-pure-annotations": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -2026,30 +2030,30 @@
}
},
"node_modules/@babel/template": {
- "version": "7.27.0",
- "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.27.0.tgz",
- "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==",
+ "version": "7.27.2",
+ "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.27.2.tgz",
+ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.26.2",
- "@babel/parser": "^7.27.0",
- "@babel/types": "^7.27.0"
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.2",
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.27.0",
- "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.27.0.tgz",
- "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==",
+ "version": "7.27.3",
+ "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.27.3.tgz",
+ "integrity": "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ==",
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.26.2",
- "@babel/generator": "^7.27.0",
- "@babel/parser": "^7.27.0",
- "@babel/template": "^7.27.0",
- "@babel/types": "^7.27.0",
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.27.3",
+ "@babel/parser": "^7.27.3",
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.27.3",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@@ -2058,13 +2062,13 @@
}
},
"node_modules/@babel/types": {
- "version": "7.27.0",
- "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.27.0.tgz",
- "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
+ "version": "7.27.3",
+ "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.27.3.tgz",
+ "integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==",
"license": "MIT",
"dependencies": {
- "@babel/helper-string-parser": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9"
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -2749,6 +2753,30 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
+ "node_modules/@jest/pattern": {
+ "version": "30.0.0-beta.3",
+ "resolved": "https://registry.npmmirror.com/@jest/pattern/-/pattern-30.0.0-beta.3.tgz",
+ "integrity": "sha512-IuB9mweyJI5ToVBRdptKb2w97LGnNHFI+V9/cGaYeFareL7BYD6KiUH022OC51K1841c6YzgYjyQmJHFxELZSQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "jest-regex-util": "30.0.0-beta.3"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || >=22.0.0"
+ }
+ },
+ "node_modules/@jest/pattern/node_modules/jest-regex-util": {
+ "version": "30.0.0-beta.3",
+ "resolved": "https://registry.npmmirror.com/jest-regex-util/-/jest-regex-util-30.0.0-beta.3.tgz",
+ "integrity": "sha512-kiDaZ35ogPivxgLEGJ1jNW2KBtvmPwGlPjy5ASHiVE3kjn3g80galEIcWC0hZV6g5BtTx15VKzSyfOTiKXPnxQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || >=22.0.0"
+ }
+ },
"node_modules/@jest/reporters": {
"version": "27.5.1",
"resolved": "https://registry.npmmirror.com/@jest/reporters/-/reporters-27.5.1.tgz",
@@ -3668,12 +3696,6 @@
"@types/node": "*"
}
},
- "node_modules/@types/cookie": {
- "version": "0.6.0",
- "resolved": "https://registry.npmmirror.com/@types/cookie/-/cookie-0.6.0.tgz",
- "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
- "license": "MIT"
- },
"node_modules/@types/eslint": {
"version": "8.56.12",
"resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.56.12.tgz",
@@ -4921,14 +4943,13 @@
}
},
"node_modules/axios": {
- "version": "1.8.4",
- "resolved": "https://registry.npmmirror.com/axios/-/axios-1.8.4.tgz",
- "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==",
+ "version": "0.27.2",
+ "resolved": "https://registry.npmmirror.com/axios/-/axios-0.27.2.tgz",
+ "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
"license": "MIT",
"dependencies": {
- "follow-redirects": "^1.15.6",
- "form-data": "^4.0.0",
- "proxy-from-env": "^1.1.0"
+ "follow-redirects": "^1.14.9",
+ "form-data": "^4.0.0"
}
},
"node_modules/axios/node_modules/form-data": {
@@ -4956,25 +4977,277 @@
}
},
"node_modules/babel-jest": {
- "version": "27.5.1",
- "resolved": "https://registry.npmmirror.com/babel-jest/-/babel-jest-27.5.1.tgz",
- "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==",
+ "version": "30.0.0-beta.3",
+ "resolved": "https://registry.npmmirror.com/babel-jest/-/babel-jest-30.0.0-beta.3.tgz",
+ "integrity": "sha512-h7VooBet0MbW4KuDxLY38sD3VrX6ugyePeA6vKnAx0ncYDRJwGfa/ZFZtl0e4JQ7jyby4qPV9c8BMfsKOR1Big==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@jest/transform": "^27.5.1",
- "@jest/types": "^27.5.1",
+ "@jest/transform": "30.0.0-beta.3",
"@types/babel__core": "^7.1.14",
- "babel-plugin-istanbul": "^6.1.1",
- "babel-preset-jest": "^27.5.1",
+ "babel-plugin-istanbul": "^7.0.0",
+ "babel-preset-jest": "30.0.0-beta.3",
"chalk": "^4.0.0",
"graceful-fs": "^4.2.9",
"slash": "^3.0.0"
},
"engines": {
- "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ "node": "^18.14.0 || ^20.0.0 || >=22.0.0"
},
"peerDependencies": {
- "@babel/core": "^7.8.0"
+ "@babel/core": "^7.11.0"
+ }
+ },
+ "node_modules/babel-jest/node_modules/@jest/schemas": {
+ "version": "30.0.0-beta.3",
+ "resolved": "https://registry.npmmirror.com/@jest/schemas/-/schemas-30.0.0-beta.3.tgz",
+ "integrity": "sha512-tiT79EKOlJGT5v8fYr9UKLSyjlA3Ek+nk0cVZwJGnRqVp26EQSOTYXBCzj0dGMegkgnPTt3f7wP1kGGI8q/e0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.34.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || >=22.0.0"
+ }
+ },
+ "node_modules/babel-jest/node_modules/@jest/transform": {
+ "version": "30.0.0-beta.3",
+ "resolved": "https://registry.npmmirror.com/@jest/transform/-/transform-30.0.0-beta.3.tgz",
+ "integrity": "sha512-2gixxaYdRh3MQaRsEenHejw0qBIW72DfwG1q9HPLXpnLkm5TKZlTOvOS33S00PGEoa4UG1Iq9tNHh7fxOJAGwQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "30.0.0-beta.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^7.0.0",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "30.0.0-beta.3",
+ "jest-regex-util": "30.0.0-beta.3",
+ "jest-util": "30.0.0-beta.3",
+ "micromatch": "^4.0.8",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^5.0.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || >=22.0.0"
+ }
+ },
+ "node_modules/babel-jest/node_modules/@jest/types": {
+ "version": "30.0.0-beta.3",
+ "resolved": "https://registry.npmmirror.com/@jest/types/-/types-30.0.0-beta.3.tgz",
+ "integrity": "sha512-x7GyHD8rxZ4Ygmp4rea3uPDIPZ6Jglcglaav8wQNqXsVUAByapDwLF52Cp3wEYMPMnvH4BicEj56j8fqZx5jng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/pattern": "30.0.0-beta.3",
+ "@jest/schemas": "30.0.0-beta.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || >=22.0.0"
+ }
+ },
+ "node_modules/babel-jest/node_modules/@sinclair/typebox": {
+ "version": "0.34.33",
+ "resolved": "https://registry.npmmirror.com/@sinclair/typebox/-/typebox-0.34.33.tgz",
+ "integrity": "sha512-5HAV9exOMcXRUxo+9iYB5n09XxzCXnfy4VTNW4xnDv+FgjzAGY989C28BIdljKqmF+ZltUwujE3aossvcVtq6g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/babel-jest/node_modules/@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmmirror.com/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/babel-jest/node_modules/babel-plugin-istanbul": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmmirror.com/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz",
+ "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-instrument": "^6.0.2",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/babel-jest/node_modules/ci-info": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmmirror.com/ci-info/-/ci-info-4.2.0.tgz",
+ "integrity": "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-jest/node_modules/istanbul-lib-instrument": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmmirror.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.23.9",
+ "@babel/parser": "^7.23.9",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/babel-jest/node_modules/jest-haste-map": {
+ "version": "30.0.0-beta.3",
+ "resolved": "https://registry.npmmirror.com/jest-haste-map/-/jest-haste-map-30.0.0-beta.3.tgz",
+ "integrity": "sha512-MafsVPIca9E4HR3Fp9gYX+AET4YZmU/VtyLcnRJ9QHdVqHSCzOaElxX30BlyNf5Nw6ZcCafkbB0RGXqSwwsjxw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "30.0.0-beta.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "30.0.0-beta.3",
+ "jest-util": "30.0.0-beta.3",
+ "jest-worker": "30.0.0-beta.3",
+ "micromatch": "^4.0.8",
+ "walker": "^1.0.8"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || >=22.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
+ }
+ },
+ "node_modules/babel-jest/node_modules/jest-regex-util": {
+ "version": "30.0.0-beta.3",
+ "resolved": "https://registry.npmmirror.com/jest-regex-util/-/jest-regex-util-30.0.0-beta.3.tgz",
+ "integrity": "sha512-kiDaZ35ogPivxgLEGJ1jNW2KBtvmPwGlPjy5ASHiVE3kjn3g80galEIcWC0hZV6g5BtTx15VKzSyfOTiKXPnxQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || >=22.0.0"
+ }
+ },
+ "node_modules/babel-jest/node_modules/jest-util": {
+ "version": "30.0.0-beta.3",
+ "resolved": "https://registry.npmmirror.com/jest-util/-/jest-util-30.0.0-beta.3.tgz",
+ "integrity": "sha512-kob8YNaO1UPrG0TgGdH5l0ciNGuXDX93Yn2b2VCkALuqOXbqzT2xCr6O7dBuwhM7tmzBbpM6CkcK7Qyf/JmLZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "30.0.0-beta.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^4.0.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || >=22.0.0"
+ }
+ },
+ "node_modules/babel-jest/node_modules/jest-worker": {
+ "version": "30.0.0-beta.3",
+ "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-30.0.0-beta.3.tgz",
+ "integrity": "sha512-v17y4Jg9geh3tDm8aU2snuwr8oCJtFefuuPrMRqmC6Ew8K+sLfOcuB3moJ15PHoe4MjTGgsC1oO2PK/GaF1vTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@ungap/structured-clone": "^1.2.0",
+ "jest-util": "30.0.0-beta.3",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || >=22.0.0"
+ }
+ },
+ "node_modules/babel-jest/node_modules/picomatch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.2.tgz",
+ "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/babel-jest/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/babel-jest/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/babel-jest/node_modules/write-file-atomic": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmmirror.com/write-file-atomic/-/write-file-atomic-5.0.1.tgz",
+ "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/babel-loader": {
@@ -5031,18 +5304,18 @@
}
},
"node_modules/babel-plugin-jest-hoist": {
- "version": "27.5.1",
- "resolved": "https://registry.npmmirror.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz",
- "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==",
+ "version": "30.0.0-beta.3",
+ "resolved": "https://registry.npmmirror.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.0.0-beta.3.tgz",
+ "integrity": "sha512-phSBX46tzCw+6KB9lUuYzyjq16nCRYntYvsDNOx5ZXSGPBcEGbe1mQI+CgdmKUKDD4+o/NDYlvDaQSB3UaSVSw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@babel/template": "^7.3.3",
"@babel/types": "^7.3.3",
- "@types/babel__core": "^7.0.0",
- "@types/babel__traverse": "^7.0.6"
+ "@types/babel__core": "^7.1.14"
},
"engines": {
- "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ "node": "^18.14.0 || ^20.0.0 || >=22.0.0"
}
},
"node_modules/babel-plugin-macros": {
@@ -5150,19 +5423,20 @@
}
},
"node_modules/babel-preset-jest": {
- "version": "27.5.1",
- "resolved": "https://registry.npmmirror.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz",
- "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==",
+ "version": "30.0.0-beta.3",
+ "resolved": "https://registry.npmmirror.com/babel-preset-jest/-/babel-preset-jest-30.0.0-beta.3.tgz",
+ "integrity": "sha512-2/Oy4J/MxFwNszlwYPO4L7Z+XI7CNCbiz5HZwrsfWnEEDBxJZBJzblfc8TP9lzeiQ4v+Vvem7BMS6B2dVCfzOg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "babel-plugin-jest-hoist": "^27.5.1",
+ "babel-plugin-jest-hoist": "30.0.0-beta.3",
"babel-preset-current-node-syntax": "^1.0.0"
},
"engines": {
- "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ "node": "^18.14.0 || ^20.0.0 || >=22.0.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0"
+ "@babel/core": "^7.11.0"
}
},
"node_modules/babel-preset-react-app": {
@@ -6030,6 +6304,12 @@
"node": ">= 8"
}
},
+ "node_modules/crypto-js": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz",
+ "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==",
+ "license": "MIT"
+ },
"node_modules/crypto-random-string": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
@@ -10155,6 +10435,59 @@
}
}
},
+ "node_modules/jest-config/node_modules/babel-jest": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmmirror.com/babel-jest/-/babel-jest-27.5.1.tgz",
+ "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/transform": "^27.5.1",
+ "@jest/types": "^27.5.1",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^27.5.1",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/jest-config/node_modules/babel-plugin-jest-hoist": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmmirror.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz",
+ "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.0.0",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ }
+ },
+ "node_modules/jest-config/node_modules/babel-preset-jest": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmmirror.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz",
+ "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==",
+ "license": "MIT",
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^27.5.1",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
"node_modules/jest-diff": {
"version": "27.5.1",
"resolved": "https://registry.npmmirror.com/jest-diff/-/jest-diff-27.5.1.tgz",
@@ -13736,12 +14069,6 @@
"node": ">= 0.10"
}
},
- "node_modules/proxy-from-env": {
- "version": "1.1.0",
- "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
- "license": "MIT"
- },
"node_modules/psl": {
"version": "1.15.0",
"resolved": "https://registry.npmmirror.com/psl/-/psl-1.15.0.tgz",
@@ -14075,15 +14402,13 @@
}
},
"node_modules/react-router": {
- "version": "7.5.0",
- "resolved": "https://registry.npmmirror.com/react-router/-/react-router-7.5.0.tgz",
- "integrity": "sha512-estOHrRlDMKdlQa6Mj32gIks4J+AxNsYoE0DbTTxiMy2mPzZuWSDU+N85/r1IlNR7kGfznF3VCUlvc5IUO+B9g==",
+ "version": "7.6.1",
+ "resolved": "https://registry.npmmirror.com/react-router/-/react-router-7.6.1.tgz",
+ "integrity": "sha512-hPJXXxHJZEsPFNVbtATH7+MMX43UDeOauz+EAU4cgqTn7ojdI9qQORqS8Z0qmDlL1TclO/6jLRYUEtbWidtdHQ==",
"license": "MIT",
"dependencies": {
- "@types/cookie": "^0.6.0",
"cookie": "^1.0.1",
- "set-cookie-parser": "^2.6.0",
- "turbo-stream": "2.4.0"
+ "set-cookie-parser": "^2.6.0"
},
"engines": {
"node": ">=20.0.0"
@@ -14099,12 +14424,12 @@
}
},
"node_modules/react-router-dom": {
- "version": "7.5.0",
- "resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-7.5.0.tgz",
- "integrity": "sha512-fFhGFCULy4vIseTtH5PNcY/VvDJK5gvOWcwJVHQp8JQcWVr85ENhJ3UpuF/zP1tQOIFYNRJHzXtyhU1Bdgw0RA==",
+ "version": "7.6.1",
+ "resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-7.6.1.tgz",
+ "integrity": "sha512-vxU7ei//UfPYQ3iZvHuO1D/5fX3/JOqhNTbRR+WjSBWxf9bIvpWK+ftjmdfJHzPOuMQKe2fiEdG+dZX6E8uUpA==",
"license": "MIT",
"dependencies": {
- "react-router": "7.5.0"
+ "react-router": "7.6.1"
},
"engines": {
"node": ">=20.0.0"
@@ -14187,6 +14512,59 @@
}
}
},
+ "node_modules/react-scripts/node_modules/babel-jest": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmmirror.com/babel-jest/-/babel-jest-27.5.1.tgz",
+ "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==",
+ "license": "MIT",
+ "dependencies": {
+ "@jest/transform": "^27.5.1",
+ "@jest/types": "^27.5.1",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^27.5.1",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/react-scripts/node_modules/babel-plugin-jest-hoist": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmmirror.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz",
+ "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.0.0",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ }
+ },
+ "node_modules/react-scripts/node_modules/babel-preset-jest": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmmirror.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz",
+ "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==",
+ "license": "MIT",
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^27.5.1",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/read-cache/-/read-cache-1.0.0.tgz",
@@ -14294,15 +14672,6 @@
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
"license": "MIT"
},
- "node_modules/regenerator-transform": {
- "version": "0.15.2",
- "resolved": "https://registry.npmmirror.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz",
- "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.8.4"
- }
- },
"node_modules/regex-parser": {
"version": "2.3.1",
"resolved": "https://registry.npmmirror.com/regex-parser/-/regex-parser-2.3.1.tgz",
@@ -16424,12 +16793,6 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"license": "0BSD"
},
- "node_modules/turbo-stream": {
- "version": "2.4.0",
- "resolved": "https://registry.npmmirror.com/turbo-stream/-/turbo-stream-2.4.0.tgz",
- "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==",
- "license": "ISC"
- },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz",
diff --git a/package.json b/package.json
index 5747deb..32849de 100644
--- a/package.json
+++ b/package.json
@@ -6,11 +6,12 @@
"@icon-park/react": "^1.4.2",
"@testing-library/dom": "^10.4.0",
"@testing-library/user-event": "^13.5.0",
- "axios": "^1.8.4",
+ "axios": "^0.27.2",
+ "crypto-js": "^4.2.0",
"quill": "^2.0.3",
"react": "^19.1.0",
"react-dom": "^19.1.0",
- "react-router-dom": "^7.5.0",
+ "react-router-dom": "^7.6.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4",
"wouter": "^3.6.0"
@@ -40,8 +41,11 @@
]
},
"devDependencies": {
+ "@babel/preset-env": "^7.27.2",
+ "@babel/preset-react": "^7.27.1",
"@testing-library/jest-dom": "^6.6.3",
- "@testing-library/react": "^16.3.0"
+ "@testing-library/react": "^16.3.0",
+ "babel-jest": "^30.0.0-beta.3"
},
"jest": {
"transformIgnorePatterns": [
diff --git a/src/App.js b/src/App.js
index af9f809..27775b1 100644
--- a/src/App.js
+++ b/src/App.js
@@ -13,7 +13,7 @@
import CreatePostPage from './pages/Forum/posts-create/CreatePostPage';
import MessagePage from './pages/MessagePage/MessagePage';
import CreateMoment from './pages/FriendMoments/CreateMoment';
-
+import PromotionsPage from './pages/PromotionsPage/PromotionsPage';
function App() {
return (
@@ -32,6 +32,7 @@
<Route path="/interest-groups" component={InterestGroup}/>
<Route path="/user/profile" component={UserProfile}/>
<Route path="/messages" component={MessagePage}/>
+ <Route path="/promotions" component={PromotionsPage}/>
</>
</UserProvider>
);
diff --git a/src/__tests__/CreatePost.test.js b/src/__tests__/CreatePost.test.js
new file mode 100644
index 0000000..2695c5e
--- /dev/null
+++ b/src/__tests__/CreatePost.test.js
@@ -0,0 +1,106 @@
+
+import React from 'react';
+import { render, screen, fireEvent, waitFor } from '@testing-library/react';
+import CreatePost from '../pages/Forum/posts-create/CreatePost';
+import axios from 'axios';
+
+// mock axios
+jest.mock('axios');
+
+describe('CreatePost Component', () => {
+ const mockUserId = 123;
+
+ beforeEach(() => {
+ axios.post.mockClear();
+ });
+
+ test('renders form inputs and button', () => {
+ render(<CreatePost user_id={mockUserId} />);
+
+ expect(screen.getByLabelText(/标题/)).toBeInTheDocument();
+ expect(screen.getByLabelText(/内容/)).toBeInTheDocument();
+ expect(screen.getByLabelText(/图片链接/)).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: '发布' })).toBeInTheDocument();
+ });
+
+ test('shows error when title and content are empty', async () => {
+ render(<CreatePost user_id={mockUserId} />);
+
+ fireEvent.click(screen.getByRole('button', { name: '发布' }));
+
+ expect(await screen.findByText('标题和内容不能为空')).toBeInTheDocument();
+ });
+
+ test('submits post and shows success message', async () => {
+ axios.post.mockResolvedValueOnce({
+ data: { post_id: 456 },
+ });
+
+ render(<CreatePost user_id={mockUserId} />);
+
+ fireEvent.change(screen.getByLabelText(/标题/), {
+ target: { value: '测试标题' },
+ });
+ fireEvent.change(screen.getByLabelText(/内容/), {
+ target: { value: '测试内容' },
+ });
+ fireEvent.change(screen.getByLabelText(/图片链接/), {
+ target: { value: 'http://example.com/image.jpg' },
+ });
+
+ fireEvent.click(screen.getByRole('button', { name: '发布' }));
+
+ await waitFor(() =>
+ expect(axios.post).toHaveBeenCalledWith(
+ `http://localhost:8080/echo/forum/posts/${mockUserId}/createPost`,
+ {
+ title: '测试标题',
+ post_content: '测试内容',
+ image_url: 'http://example.com/image.jpg',
+ }
+ )
+ );
+
+ expect(await screen.findByText(/发帖成功,帖子ID:456/)).toBeInTheDocument();
+ });
+
+ test('shows error message on submission failure', async () => {
+ axios.post.mockRejectedValueOnce({
+ response: {
+ data: {
+ error: '服务器内部错误',
+ },
+ },
+ });
+
+ render(<CreatePost user_id={mockUserId} />);
+
+ fireEvent.change(screen.getByLabelText(/标题/), {
+ target: { value: '测试标题' },
+ });
+ fireEvent.change(screen.getByLabelText(/内容/), {
+ target: { value: '测试内容' },
+ });
+
+ fireEvent.click(screen.getByRole('button', { name: '发布' }));
+
+ expect(await screen.findByText('服务器内部错误')).toBeInTheDocument();
+ });
+
+ test('shows fallback error message when no response', async () => {
+ axios.post.mockRejectedValueOnce(new Error('Network error'));
+
+ render(<CreatePost user_id={mockUserId} />);
+
+ fireEvent.change(screen.getByLabelText(/标题/), {
+ target: { value: '测试标题' },
+ });
+ fireEvent.change(screen.getByLabelText(/内容/), {
+ target: { value: '测试内容' },
+ });
+
+ fireEvent.click(screen.getByRole('button', { name: '发布' }));
+
+ expect(await screen.findByText('发帖失败,请稍后重试')).toBeInTheDocument();
+ });
+});
diff --git a/src/components/Auth/Login.jsx b/src/components/Auth/Login.jsx
index 2f43619..d635223 100644
--- a/src/components/Auth/Login.jsx
+++ b/src/components/Auth/Login.jsx
@@ -1,95 +1,213 @@
-import React, { useState } from 'react';
-import '../../pages/AuthPage/AuthPage.css';
-import image from './logo.svg'; // 引入图片
-const Login = ({ onRegisterClick }) => {
- const [formData, setFormData] = useState({
- username: '',
- password: ''
- });
+// import React, { useState } from 'react';
+// import '../../pages/AuthPage/AuthPage.css';
+// import image from './logo.svg'; // 引入图片
+// const Login = ({ onRegisterClick }) => {
+// const [formData, setFormData] = useState({
+// username: '',
+// password: ''
+// });
- const handleChange = (e) => {
- const { name, value } = e.target;
- setFormData(prev => ({ ...prev, [name]: value }));
- };
+// const handleChange = (e) => {
+// const { name, value } = e.target;
+// setFormData(prev => ({ ...prev, [name]: value }));
+// };
- const handleSubmit = async (e) => {
- e.preventDefault();
- try {
- const response = await fetch('http://localhost:8080/user/login', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(formData),
- });
+// const handleSubmit = async (e) => {
+// e.preventDefault();
+// try {
+// const response = await fetch('http://localhost:8080/user/login', {
+// method: 'POST',
+// headers: {
+// 'Content-Type': 'application/json',
+// },
+// body: JSON.stringify(formData),
+// });
- const result = await response.json();
- if (response.ok && result.code === "0") {
- console.log('登录成功:', result);
- // 处理成功逻辑
- } else {
- console.error('登录失败:', result);
- // 处理失败逻辑
- }
- } catch (error) {
- console.error('请求错误:', error);
- // 处理请求错误
- }
- };
+// const result = await response.json();
+// if (response.ok && result.code === "0") {
+// console.log('登录成功:', result);
+// // 处理成功逻辑
+// } else {
+// console.error('登录失败:', result);
+// // 处理失败逻辑
+// }
+// } catch (error) {
+// console.error('请求错误:', error);
+// // 处理请求错误
+// }
+// };
- return (
- <div className="auth-container">
- <img
- src={image}
- alt="描述"
- style={{ width: '30%', height: 'auto'}}
- />
- <div className="auth-form-section">
- {/* <h3>欢迎来到EchoTorent !</h3> */}
- <h3>用户登录</h3>
- <form onSubmit={handleSubmit}>
- <div className="form-group">
- <label>用户名</label>
- <input
- type="text"
- name="username"
- placeholder="请输入用户名"
- value={formData.username}
- onChange={handleChange}
- className="form-input"
- />
- </div>
- <div className="form-group">
- <label>密码</label>
- <input
- type="password"
- name="password"
- placeholder="请输入密码"
- value={formData.password}
- onChange={handleChange}
- className="form-input"
- />
- <button
- type="button"
- className="link-button forgot-password"
- onClick={() => console.log('跳转到忘记密码页面')}
- >
- 忘记密码?
- </button>
- </div>
- <button type="submit" className="auth-button">
- 登录
- </button>
- <p className="register-link">
- 没有账号?
- <button onClick={onRegisterClick} className="link-button">
- 点击注册
- </button>
- </p>
- </form>
- </div>
- </div>
- );
-};
+// return (
+// <div className="auth-container">
+// <img
+// src={image}
+// alt="描述"
+// style={{ width: '30%', height: 'auto'}}
+// />
+// <div className="auth-form-section">
+// {/* <h3>欢迎来到EchoTorent !</h3> */}
+// <h3>用户登录</h3>
+// <form onSubmit={handleSubmit}>
+// <div className="form-group">
+// <label>用户名</label>
+// <input
+// type="text"
+// name="username"
+// placeholder="请输入用户名"
+// value={formData.username}
+// onChange={handleChange}
+// className="form-input"
+// />
+// </div>
+// <div className="form-group">
+// <label>密码</label>
+// <input
+// type="password"
+// name="password"
+// placeholder="请输入密码"
+// value={formData.password}
+// onChange={handleChange}
+// className="form-input"
+// />
+// <button
+// type="button"
+// className="link-button forgot-password"
+// onClick={() => console.log('跳转到忘记密码页面')}
+// >
+// 忘记密码?
+// </button>
+// </div>
+// <button type="submit" className="auth-button">
+// 登录
+// </button>
+// <p className="register-link">
+// 没有账号?
+// <button onClick={onRegisterClick} className="link-button">
+// 点击注册
+// </button>
+// </p>
+// </form>
+// </div>
+// </div>
+// );
+// };
-export default Login;
\ No newline at end of file
+// export default Login;
+
+
+// import React, { useState } from 'react';
+// import '../../pages/AuthPage/AuthPage.css';
+// import image from './logo.svg';
+
+// const API_BASE = process.env.REACT_APP_API_BASE;
+
+// const Login = ({ onRegisterClick }) => {
+// const [formData, setFormData] = useState({
+// username: '',
+// password: ''
+// });
+// const [error, setError] = useState('');
+// const [isSubmitting, setIsSubmitting] = useState(false);
+
+// const handleSubmit = async (e) => {
+// e.preventDefault();
+// setIsSubmitting(true);
+// setError('');
+
+// try {
+// const response = await fetch(`${API_BASE}/user/login`, {
+// method: 'POST',
+// headers: {
+// 'Content-Type': 'application/json',
+// },
+// body: JSON.stringify(formData),
+// });
+
+// const result = await response.json();
+
+// if (!response.ok) {
+// throw new Error(result.message || '登录失败');
+// }
+
+// console.log('登录成功:', result);
+// // 这里可以添加登录成功后的跳转逻辑
+// alert('登录成功!');
+// } catch (error) {
+// console.error('登录错误:', error);
+// setError(error.message || '登录过程中出现错误');
+// } finally {
+// setIsSubmitting(false);
+// }
+// };
+
+// const handleChange = (e) => {
+// const { name, value } = e.target;
+// setFormData(prev => ({ ...prev, [name]: value }));
+// };
+
+// return (
+// <div className="auth-container">
+// <img
+// src={image}
+// alt="网站Logo"
+// style={{ width: '30%', height: 'auto' }}
+// />
+// <div className="auth-form-section">
+// <h3>用户登录</h3>
+// {error && <div className="error-message">{error}</div>}
+// <form onSubmit={handleSubmit}>
+// <div className="form-group">
+// <label>用户名</label>
+// <input
+// type="text"
+// name="username"
+// placeholder="请输入用户名"
+// value={formData.username}
+// onChange={handleChange}
+// className="form-input"
+// required
+// />
+// </div>
+// <div className="form-group">
+// <label>密码</label>
+// <input
+// type="password"
+// name="password"
+// placeholder="请输入密码"
+// value={formData.password}
+// onChange={handleChange}
+// className="form-input"
+// required
+// />
+// <button
+// type="button"
+// className="link-button forgot-password"
+// onClick={() => console.log('跳转到忘记密码页面')}
+// >
+// 忘记密码?
+// </button>
+// </div>
+// <button
+// type="submit"
+// className="auth-button"
+// disabled={isSubmitting}
+// >
+// {isSubmitting ? '登录中...' : '登录'}
+// </button>
+// <p className="register-link">
+// 没有账号?{' '}
+// <button
+// type="button"
+// onClick={onRegisterClick}
+// className="link-button"
+// >
+// 点击注册
+// </button>
+// </p>
+// </form>
+// </div>
+// </div>
+// );
+// };
+
+// export default Login;
\ No newline at end of file
diff --git a/src/components/Auth/Login.test.jsx b/src/components/Auth/Login.test.jsx
deleted file mode 100644
index 6da7659..0000000
--- a/src/components/Auth/Login.test.jsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import React from 'react';
-import { render, screen, fireEvent } from '@testing-library/react';
-import Login from './Login';
-
-describe('Login component', () => {
- test('renders login form', () => {
- const onRegisterClick = jest.fn();
- render(<Login onRegisterClick={onRegisterClick} />);
-
- const usernameInput = screen.getByPlaceholderText('请输入用户名');
- const passwordInput = screen.getByPlaceholderText('请输入密码');
- const loginButton = screen.getByText('登录');
-
- expect(usernameInput).toBeInTheDocument();
- expect(passwordInput).toBeInTheDocument();
- expect(loginButton).toBeInTheDocument();
- });
-
- test('calls onRegisterClick when "点击注册" is clicked', () => {
- const onRegisterClick = jest.fn();
- render(<Login onRegisterClick={onRegisterClick} />);
-
- const registerButton = screen.getByText('点击注册');
- fireEvent.click(registerButton);
-
- expect(onRegisterClick).toHaveBeenCalled();
- });
-});
\ No newline at end of file
diff --git a/src/components/Auth/Login.test.jsx.txt b/src/components/Auth/Login.test.jsx.txt
new file mode 100644
index 0000000..4631a5f
--- /dev/null
+++ b/src/components/Auth/Login.test.jsx.txt
@@ -0,0 +1,28 @@
+// import React from 'react';
+// import { render, screen, fireEvent } from '@testing-library/react';
+// import Login from './Login';
+
+// describe('Login component', () => {
+// test('renders login form', () => {
+// const onRegisterClick = jest.fn();
+// render(<Login onRegisterClick={onRegisterClick} />);
+
+// const usernameInput = screen.getByPlaceholderText('请输入用户名');
+// const passwordInput = screen.getByPlaceholderText('请输入密码');
+// const loginButton = screen.getByText('登录');
+
+// expect(usernameInput).toBeInTheDocument();
+// expect(passwordInput).toBeInTheDocument();
+// expect(loginButton).toBeInTheDocument();
+// });
+
+// test('calls onRegisterClick when "点击注册" is clicked', () => {
+// const onRegisterClick = jest.fn();
+// render(<Login onRegisterClick={onRegisterClick} />);
+
+// const registerButton = screen.getByText('点击注册');
+// fireEvent.click(registerButton);
+
+// expect(onRegisterClick).toHaveBeenCalled();
+// });
+// });
\ No newline at end of file
diff --git a/src/components/Auth/Register.jsx b/src/components/Auth/Register.jsx
index de32cc2..16b2313 100644
--- a/src/components/Auth/Register.jsx
+++ b/src/components/Auth/Register.jsx
@@ -1,121 +1,261 @@
-import React, { useState } from 'react';
-import '../../pages/AuthPage/AuthPage.css';
-import image from './logo.svg'; // 引入图片
+// import React, { useState } from 'react';
+// import '../../pages/AuthPage/AuthPage.css';
+// import image from './logo.svg'; // 引入图片
-const Register = ({ onLoginClick }) => {
- const [formData, setFormData] = useState({
- username: '',
- password: '',
- email: ''
- });
- const [verificationCode, setVerificationCode] = useState('');
+// const Register = ({ onLoginClick }) => {
+// const [formData, setFormData] = useState({
+// username: '',
+// password: '',
+// email: ''
+// });
+// const [verificationCode, setVerificationCode] = useState('');
- const handleSubmit = async (e) => {
- e.preventDefault();
- // 注册逻辑
- };
+// const handleSubmit = async (e) => {
+// e.preventDefault();
+// // 注册逻辑
+// };
- const verifyEmailCode = async () => {
- try {
- const response = await fetch('http://localhost:8080/user/verify-code', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- email: formData.email,
- code: verificationCode,
- }),
- });
+// const verifyEmailCode = async () => {
+// try {
+// const response = await fetch('http://localhost:8080/user/verify-code', {
+// method: 'POST',
+// headers: {
+// 'Content-Type': 'application/json',
+// },
+// body: JSON.stringify({
+// email: formData.email,
+// code: verificationCode,
+// }),
+// });
- const result = await response.json();
- if (response.ok && result.code === "0") {
- console.log('邮箱验证成功:', result.msg);
- // 处理成功逻辑
- } else {
- console.error('邮箱验证失败:', result.msg);
- // 处理失败逻辑
- }
- } catch (error) {
- console.error('请求错误:', error);
- // 处理请求错误
- }
- };
+// const result = await response.json();
+// if (response.ok && result.code === "0") {
+// console.log('邮箱验证成功:', result.msg);
+// // 处理成功逻辑
+// } else {
+// console.error('邮箱验证失败:', result.msg);
+// // 处理失败逻辑
+// }
+// } catch (error) {
+// console.error('请求错误:', error);
+// // 处理请求错误
+// }
+// };
- return (
- <div className="auth-container">
- <img
- src={image}
- alt="描述"
- style={{ width: '30%', height: 'auto'}}
- />
- <div className="auth-form-section">
- <h3>用户注册</h3>
- <form onSubmit={handleSubmit}>
- <div className="form-group">
- <label>用户名</label>
- <input
- type="text"
- className="form-input"
- placeholder="请输入用户名"
- value={formData.username}
- onChange={(e) => setFormData({ ...formData, username: e.target.value })}
- required
- />
- </div>
- <div className="form-group">
- <label>密码</label>
- <input
- type="password"
- className="form-input"
- placeholder="请输入密码"
- value={formData.password}
- onChange={(e) => setFormData({ ...formData, password: e.target.value })}
- required
- />
- </div>
- <div className="form-group">
- <label>邮箱</label>
- <div style={{ display: 'flex', alignItems: 'center' }}>
- <input
- type="email"
- className="form-input"
- placeholder="请输入邮箱"
- value={formData.email}
- onChange={(e) => setFormData({ ...formData, email: e.target.value })}
- required
- style={{ flex: 1, marginRight: '10px' }}
- />
- <button type="button" onClick={verifyEmailCode} className="verify-button">
- 验证邮箱
- </button>
- </div>
- </div>
- <div className="form-group">
- <label>验证码</label>
- <input
- type="text"
- className="form-input"
- placeholder="请输入邮箱验证码"
- value={verificationCode}
- onChange={(e) => setVerificationCode(e.target.value)}
- required
- />
- </div>
- <button type="submit" className="auth-button">
- 注册
- </button>
- <p className="login-link">
- 已有账号?
- <button onClick={onLoginClick} className="link-button">
- 点击登录
- </button>
- </p>
- </form>
- </div>
- </div>
- );
-};
+// return (
+// <div className="auth-container">
+// <img
+// src={image}
+// alt="描述"
+// style={{ width: '30%', height: 'auto'}}
+// />
+// <div className="auth-form-section">
+// <h3>用户注册</h3>
+// <form onSubmit={handleSubmit}>
+// <div className="form-group">
+// <label>用户名</label>
+// <input
+// type="text"
+// className="form-input"
+// placeholder="请输入用户名"
+// value={formData.username}
+// onChange={(e) => setFormData({ ...formData, username: e.target.value })}
+// required
+// />
+// </div>
+// <div className="form-group">
+// <label>密码</label>
+// <input
+// type="password"
+// className="form-input"
+// placeholder="请输入密码"
+// value={formData.password}
+// onChange={(e) => setFormData({ ...formData, password: e.target.value })}
+// required
+// />
+// </div>
+// <div className="form-group">
+// <label>邮箱</label>
+// <div style={{ display: 'flex', alignItems: 'center' }}>
+// <input
+// type="email"
+// className="form-input"
+// placeholder="请输入邮箱"
+// value={formData.email}
+// onChange={(e) => setFormData({ ...formData, email: e.target.value })}
+// required
+// style={{ flex: 1, marginRight: '10px' }}
+// />
+// <button type="button" onClick={verifyEmailCode} className="verify-button">
+// 验证邮箱
+// </button>
+// </div>
+// </div>
+// <div className="form-group">
+// <label>验证码</label>
+// <input
+// type="text"
+// className="form-input"
+// placeholder="请输入邮箱验证码"
+// value={verificationCode}
+// onChange={(e) => setVerificationCode(e.target.value)}
+// required
+// />
+// </div>
+// <button type="submit" className="auth-button">
+// 注册
+// </button>
+// <p className="login-link">
+// 已有账号?
+// <button onClick={onLoginClick} className="link-button">
+// 点击登录
+// </button>
+// </p>
+// </form>
+// </div>
+// </div>
+// );
+// };
-export default Register;
\ No newline at end of file
+// export default Register;
+
+// import React, { useState } from 'react';
+// import '../../pages/AuthPage/AuthPage.css';
+// import image from './logo.svg';
+
+// const API_BASE = process.env.REACT_APP_API_BASE || '/echo';
+
+// const Register = ({ onLoginClick }) => {
+// const [formData, setFormData] = useState({
+// username: '',
+// email: '',
+// password: '',
+// role: 'user',
+// inviteCode: ''
+// });
+// const [error, setError] = useState('');
+// const [isSubmitting, setIsSubmitting] = useState(false);
+
+// const handleSubmit = async (e) => {
+// e.preventDefault();
+// setIsSubmitting(true);
+// setError('');
+
+// try {
+// const response = await fetch(`${API_BASE}/user/register`, {
+// method: 'POST',
+// headers: {
+// 'Content-Type': 'application/json',
+// },
+// body: JSON.stringify(formData),
+// });
+
+// const result = await response.json();
+
+// if (!response.ok) {
+// throw new Error(result.message || '注册失败');
+// }
+
+// console.log('注册成功:', result);
+// // 这里可以添加注册成功后的跳转逻辑
+// alert('注册成功!');
+// } catch (error) {
+// console.error('注册错误:', error);
+// setError(error.message || '注册过程中出现错误');
+// } finally {
+// setIsSubmitting(false);
+// }
+// };
+
+// const handleChange = (e) => {
+// const { name, value } = e.target;
+// setFormData(prev => ({ ...prev, [name]: value }));
+// };
+
+// return (
+// <div className="auth-container">
+// <img
+// src={image}
+// alt="网站Logo"
+// style={{ width: '30%', height: 'auto' }}
+// />
+// <div className="auth-form-section">
+// <h3>用户注册</h3>
+// {error && <div className="error-message">{error}</div>}
+// <form onSubmit={handleSubmit}>
+// <div className="form-group">
+// <label>用户名</label>
+// <input
+// type="text"
+// name="username"
+// className="form-input"
+// placeholder="请输入用户名"
+// value={formData.username}
+// onChange={handleChange}
+// required
+// minLength="3"
+// maxLength="20"
+// />
+// </div>
+// <div className="form-group">
+// <label>邮箱</label>
+// <input
+// type="email"
+// name="email"
+// className="form-input"
+// placeholder="请输入邮箱"
+// value={formData.email}
+// onChange={handleChange}
+// required
+// />
+// </div>
+// <div className="form-group">
+// <label>密码</label>
+// <input
+// type="password"
+// name="password"
+// className="form-input"
+// placeholder="请输入密码"
+// value={formData.password}
+// onChange={handleChange}
+// required
+// minLength="6"
+// />
+// </div>
+// <div className="form-group">
+// <label>邀请码</label>
+// <input
+// type="text"
+// name="inviteCode"
+// className="form-input"
+// placeholder="请输入邀请码"
+// value={formData.inviteCode}
+// onChange={handleChange}
+// required
+// />
+// </div>
+// <button
+// type="submit"
+// className="auth-button"
+// disabled={isSubmitting}
+// >
+// {isSubmitting ? '注册中...' : '注册'}
+// </button>
+// <p className="login-link">
+// 已有账号?{' '}
+// <button
+// type="button"
+// onClick={onLoginClick}
+// className="link-button"
+// >
+// 点击登录
+// </button>
+// </p>
+// </form>
+// </div>
+// </div>
+// );
+// };
+
+// export default Register;
\ No newline at end of file
diff --git a/src/components/Auth/Register.test.jsx b/src/components/Auth/Register.test.jsx
deleted file mode 100644
index 969e464..0000000
--- a/src/components/Auth/Register.test.jsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import React from 'react';
-import { render, screen, fireEvent } from '@testing-library/react';
-import Register from './Register';
-
-describe('Register component', () => {
- test('renders register form', () => {
- const onLoginClick = jest.fn();
- render(<Register onLoginClick={onLoginClick} />);
-
- const usernameInput = screen.getByPlaceholderText('请输入用户名');
- const passwordInput = screen.getByPlaceholderText('请输入密码');
- const emailInput = screen.getByPlaceholderText('请输入邮箱');
- const verifyButton = screen.getByText('验证邮箱');
- const registerButton = screen.getByText('注册');
-
- expect(usernameInput).toBeInTheDocument();
- expect(passwordInput).toBeInTheDocument();
- expect(emailInput).toBeInTheDocument();
- expect(verifyButton).toBeInTheDocument();
- expect(registerButton).toBeInTheDocument();
- });
-
- test('calls onLoginClick when "点击登录" is clicked', () => {
- const onLoginClick = jest.fn();
- render(<Register onLoginClick={onLoginClick} />);
-
- const loginButton = screen.getByText('点击登录');
- fireEvent.click(loginButton);
-
- expect(onLoginClick).toHaveBeenCalled();
- });
-});
\ No newline at end of file
diff --git a/src/components/Auth/Register.test.jsx.txt b/src/components/Auth/Register.test.jsx.txt
new file mode 100644
index 0000000..356fadd
--- /dev/null
+++ b/src/components/Auth/Register.test.jsx.txt
@@ -0,0 +1,32 @@
+// import React from 'react';
+// import { render, screen, fireEvent } from '@testing-library/react';
+// import Register from './Register';
+
+// describe('Register component', () => {
+// test('renders register form', () => {
+// const onLoginClick = jest.fn();
+// render(<Register onLoginClick={onLoginClick} />);
+
+// const usernameInput = screen.getByPlaceholderText('请输入用户名');
+// const passwordInput = screen.getByPlaceholderText('请输入密码');
+// const emailInput = screen.getByPlaceholderText('请输入邮箱');
+// const verifyButton = screen.getByText('验证邮箱');
+// const registerButton = screen.getByText('注册');
+
+// expect(usernameInput).toBeInTheDocument();
+// expect(passwordInput).toBeInTheDocument();
+// expect(emailInput).toBeInTheDocument();
+// expect(verifyButton).toBeInTheDocument();
+// expect(registerButton).toBeInTheDocument();
+// });
+
+// test('calls onLoginClick when "点击登录" is clicked', () => {
+// const onLoginClick = jest.fn();
+// render(<Register onLoginClick={onLoginClick} />);
+
+// const loginButton = screen.getByText('点击登录');
+// fireEvent.click(loginButton);
+
+// expect(onLoginClick).toHaveBeenCalled();
+// });
+// });
\ No newline at end of file
diff --git a/src/pages/AuthPage/AuthPage.css b/src/pages/AuthPage/AuthPage.css
index cb9e470..98e5532 100644
--- a/src/pages/AuthPage/AuthPage.css
+++ b/src/pages/AuthPage/AuthPage.css
@@ -1,11 +1,11 @@
-.auth-container {
+/* .auth-container {
display: flex;
align-items: center;
- justify-content: flex-end; /* 使卡片靠右 */
+ justify-content: flex-end;
min-height: 100vh;
font-family: Arial, sans-serif;
- background: linear-gradient(180deg, #5F4437, #823c3c);
- padding: 0 2rem; /* 添加左右内边距 */
+ background: #333;
+ padding: 0 2rem;
}
.auth-container img {
@@ -13,13 +13,13 @@
}
.auth-form-section {
- background: #E4D8C9; /* 米白色 */
+ background: #E4D8C9;
padding: 2rem;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
width: 300px;
margin: 0 auto;
- max-width: 400px; /* 限制卡片最大宽度 */
+ max-width: 400px;
}
.form-group {
@@ -32,7 +32,7 @@
display: block;
font-size: 0.9rem;
margin-bottom: 0.5rem;
- color: #4A3B34; /* 棕色 */
+ color: #4A3B34;
}
.form-input {
@@ -46,8 +46,8 @@
.auth-button {
padding: 0.8rem 8.4rem;
- background: #BA929A; /* 粉色 */
- color: #4A3B34; /* 棕色 */
+ background: #BA929A;
+ color: #4A3B34;
border: none;
border-radius: 5px;
cursor: pointer;
@@ -56,21 +56,20 @@
}
.verify-button {
- padding: 0.5rem 1rem; /* 更小的内边距 */
- background: #BA929A; /* 粉色 */
- color: #4A3B34; /* 棕色 */
+ padding: 0.5rem 1rem;
+ background: #BA929A;
+ color: #4A3B34;
border: none;
border-radius: 5px;
cursor: pointer;
- font-size: 0.8rem; /* 更小的字体 */
+ font-size: 0.8rem;
display: inline-block;
}
.link-button {
background: none;
border: none;
- color: #4A3B34; /* 棕色 */
- /* text-decoration: underline; */
+ color: #4A3B34;
cursor: pointer;
font-size: 0.8rem;
padding: 0;
@@ -78,19 +77,251 @@
.forgot-password {
position: absolute;
- right: 10px; /* 让按钮靠右 */
- bottom: 5px; /* 调整到底部 */
+ right: 10px;
+ bottom: 5px;
font-size: 12px;
background: none;
border: none;
- color: #4A3B34; /* 颜色与 "点击注册" 一致 */
+ color: #4A3B34;
cursor: pointer;
text-decoration: underline;
}
-
.register-link, .login-link {
text-align: center;
font-size: 0.8rem;
margin-top: 1rem;
-}
\ No newline at end of file
+} */
+
+
+ .auth-container {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end; /* 使卡片靠右 */
+ min-height: 100vh;
+ font-family: Arial, sans-serif;
+ background: #333;
+ /* background: linear-gradient(180deg, #5F4437, #823c3c) */
+ padding: 0 2rem; /* 添加左右内边距 */
+}
+
+ .auth-card {
+ width: 100%;
+ max-width: 480px;
+ background-color: #E4D8C9;
+ border-radius: 8px;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+ overflow: hidden;
+ }
+
+ .auth-header {
+ display: flex;
+ border-bottom: 1px solid #eee;
+ }
+
+ .auth-tab {
+ flex: 1;
+ padding: 16px;
+ text-align: center;
+ font-size: 18px;
+ font-weight: 500;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ }
+
+ .auth-tab.active {
+ color: #BA929A;
+ border-bottom: 2px solid #BA929A;
+ }
+
+ .auth-tab:not(.active) {
+ color: #888;
+ }
+
+ .auth-tab:hover:not(.active) {
+ background-color: #f9f9f9;
+ }
+
+ .auth-content {
+ padding: 30px;
+ }
+
+ .auth-form {
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+ }
+
+ .form-group {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ }
+
+ .form-group label {
+ font-weight: 500;
+ color: #333;
+ text-align: left;
+ align-self: flex-start;
+ }
+
+ .form-group input[type="text"],
+ .form-group input[type="email"],
+ .form-group input[type="password"] {
+ padding: 12px 16px;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ font-size: 16px;
+ transition: border-color 0.3s;
+ }
+
+ .form-group input:focus {
+ border-color: #BA929A;
+ outline: none;
+ }
+
+ .form-group-inline {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+
+ .checkbox-container {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ }
+
+ .checkbox-container input[type="checkbox"] {
+ width: 18px;
+ height: 18px;
+ cursor: pointer;
+ }
+
+ .forgot-password {
+ color: #BA929A;
+ text-decoration: none;
+ font-size: 14px;
+ }
+
+ .forgot-password:hover {
+ text-decoration: underline;
+ }
+
+ .auth-button {
+ background-color: #BA929A;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ padding: 14px;
+ font-size: 16px;
+ font-weight: 500;
+ cursor: pointer;
+ transition: background-color 0.3s;
+ }
+
+ .auth-button:hover {
+ background-color: #BA929A;
+ }
+
+ .social-login {
+ margin-top: 20px;
+ text-align: center;
+ }
+
+ .social-login p {
+ color: #666;
+ margin-bottom: 15px;
+ position: relative;
+ }
+
+ .social-login p::before,
+ .social-login p::after {
+ content: "";
+ position: absolute;
+ top: 50%;
+ width: 30%;
+ height: 1px;
+ background-color: #ddd;
+ }
+
+ .social-login p::before {
+ left: 0;
+ }
+
+ .social-login p::after {
+ right: 0;
+ }
+
+ .social-icons {
+ display: flex;
+ justify-content: center;
+ gap: 20px;
+ }
+
+ .social-icon {
+ width: 40px;
+ height: 40px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: white;
+ font-size: 12px;
+ cursor: pointer;
+ }
+
+ .social-icon.wechat {
+ background-color: #07c160;
+ }
+
+ .social-icon.weibo {
+ background-color: #e6162d;
+ }
+
+ .social-icon.qq {
+ background-color: #12b7f5;
+ }
+
+ .terms-container {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+
+ .terms-link {
+ color: #BA929A;
+ text-decoration: none;
+ }
+
+ .terms-link:hover {
+ text-decoration: underline;
+ }
+
+ .error-message {
+ color: #e53e3e;
+ font-size: 14px;
+ margin-top: 4px;
+ }
+
+ /* Responsive adjustments */
+ @media (max-width: 576px) {
+ .auth-card {
+ box-shadow: none;
+ border-radius: 0;
+ }
+
+ .auth-content {
+ padding: 20px;
+ }
+
+ .form-group-inline {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 10px;
+ }
+
+ .social-icons {
+ flex-wrap: wrap;
+ }
+ }
+
\ No newline at end of file
diff --git a/src/pages/AuthPage/AuthPage.jsx b/src/pages/AuthPage/AuthPage.jsx
index 4238214..bfc8e43 100644
--- a/src/pages/AuthPage/AuthPage.jsx
+++ b/src/pages/AuthPage/AuthPage.jsx
@@ -1,19 +1,342 @@
-import React, { useState } from 'react';
-import Login from '../../components/Auth/Login';
-import Register from '../../components/Auth/Register';
+// import React, { useState } from 'react';
+// import Login from '../../components/Auth/Login';
+// import Register from '../../components/Auth/Register';
-const AuthPage = () => {
- const [isRegister, setIsRegister] = useState(false);
+// const AuthPage = () => {
+// const [isRegister, setIsRegister] = useState(false);
+
+// return (
+// <div>
+// {isRegister ? (
+// <Register onLoginClick={() => setIsRegister(false)} />
+// ) : (
+// <Login onRegisterClick={() => setIsRegister(true)} />
+// )}
+// </div>
+// );
+// };
+
+// export default AuthPage;
+
+
+
+import { useState } from "react";
+import { Link } from "wouter";
+import "./AuthPage.css";
+import CryptoJS from "crypto-js";
+
+const API_BASE = process.env.REACT_APP_API_BASE;
+function AuthPage() {
+ const [activeTab, setActiveTab] = useState("login");
+
+ // Login form state
+ const [loginData, setLoginData] = useState({
+ username: "",
+ password: "",
+ rememberMe: false,
+ });
+
+ // Register form state
+ const [registerData, setRegisterData] = useState({
+ username: "",
+ email: "",
+ password: "",
+ confirmPassword: "",
+ inviteCode: "",
+ agreeTerms: false,
+ });
+
+ // Form errors
+ const [errors, setErrors] = useState({
+ login: {},
+ register: {},
+ });
+
+ const hashPassword = (password) => {
+ return CryptoJS.SHA256(password).toString(CryptoJS.enc.Hex);
+ };
+
+ // Handle login form submission
+ const handleLogin = async (e) => {
+ e.preventDefault();
+
+ // 客户端验证
+ const newErrors = {};
+ if (!loginData.username) {
+ newErrors.username = "请输入用户名或邮箱";
+ }
+ if (!loginData.password) {
+ newErrors.password = "请输入密码";
+ }
+
+ if (Object.keys(newErrors).length > 0) {
+ setErrors((prev) => ({ ...prev, login: newErrors }));
+ return;
+ }
+
+ // 加密密码
+ const hashedPassword = hashPassword(loginData.password);
+
+ try {
+ const response = await fetch(`${API_BASE}/echo/user/login`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ username: loginData.username,
+ password: hashedPassword,
+ }),
+ });
+
+ if (!response.ok) {
+ throw new Error('登录失败');
+ }
+
+ const data = await response.json();
+
+ if (data.code !== 0 || !data.result) {
+ throw new Error(data.msg || '登录失败');
+ }
+
+ console.log('登录成功:', data);
+ localStorage.setItem('token', data.rows.token);
+ localStorage.setItem('userId', data.rows.userId);
+ window.location.href = '/';
+ } catch (error) {
+ console.error('登录错误:', error.message);
+ setErrors((prev) => ({
+ ...prev,
+ login: { message: error.message },
+ }));
+ throw error;
+ }
+ };
+
+ // Handle register form submission
+ const handleRegister = async (e) => {
+ e.preventDefault();
+
+ // 客户端验证
+ const newErrors = {};
+ if (!registerData.username) {
+ newErrors.username = "请输入用户名";
+ }
+ if (!registerData.email) {
+ newErrors.email = "请输入邮箱";
+ } else if (!/\S+@\S+\.\S+/.test(registerData.email)) {
+ newErrors.email = "邮箱格式不正确";
+ }
+ if (!registerData.password) {
+ newErrors.password = "请输入密码";
+ } else if (registerData.password.length < 6) {
+ newErrors.password = "密码长度至少为6位";
+ }
+ if (registerData.password !== registerData.confirmPassword) {
+ newErrors.confirmPassword = "两次输入的密码不一致";
+ }
+ if (!registerData.agreeTerms) {
+ newErrors.agreeTerms = "请同意用户协议和隐私政策";
+ }
+
+ if (Object.keys(newErrors).length > 0) {
+ setErrors({ ...errors, register: newErrors });
+ return;
+ }
+
+ // 加密密码
+ const hashedPassword = hashPassword(registerData.password);
+
+ try {
+ const response = await fetch(`${API_BASE}/echo/user/register`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ username: registerData.username,
+ email: registerData.email,
+ password: hashedPassword,
+ inviteCode: registerData.inviteCode,
+ }),
+ });
+
+ if (!response.ok) {
+ throw new Error('注册失败');
+ }
+
+ const data = await response.json();
+ if (data.code !== 0 || !data.result) {
+ throw new Error(data.msg || '注册失败');
+ }
+
+ console.log('注册成功:', data);
+ setActiveTab('login');
+ alert('注册成功,请登录!');
+ } catch (error) {
+ console.error('注册错误:', error.message);
+ setErrors((prev) => ({
+ ...prev,
+ register: { message: error.message },
+ }));
+ }
+ };
+
+ // Update login form data
+ const updateLoginData = (field, value) => {
+ setLoginData({
+ ...loginData,
+ [field]: value,
+ });
+ };
+
+ // Update register form data
+ const updateRegisterData = (field, value) => {
+ setRegisterData({
+ ...registerData,
+ [field]: value,
+ });
+ };
return (
- <div>
- {isRegister ? (
- <Register onLoginClick={() => setIsRegister(false)} />
- ) : (
- <Login onRegisterClick={() => setIsRegister(true)} />
- )}
+ <div className="auth-container">
+ <div className="auth-card">
+ <div className="auth-header">
+ <div className={`auth-tab ${activeTab === "login" ? "active" : ""}`} onClick={() => setActiveTab("login")}>
+ 登录
+ </div>
+ <div className={`auth-tab ${activeTab === "register" ? "active" : ""}`} onClick={() => setActiveTab("register")}>
+ 注册
+ </div>
+ </div>
+
+ <div className="auth-content">
+ {activeTab === "login" ? (
+ <form className="auth-form" onSubmit={handleLogin}>
+ {errors.login.message && <div className="error-message">{errors.login.message}</div>}
+ <div className="form-group">
+ <label htmlFor="login-username">用户名/邮箱</label>
+ <input
+ type="text"
+ id="login-username"
+ value={loginData.username}
+ onChange={(e) => updateLoginData("username", e.target.value)}
+ placeholder="请输入用户名或邮箱"
+ required
+ />
+ {errors.login.username && <div className="error-message">{errors.login.username}</div>}
+ </div>
+
+ <div className="form-group">
+ <label htmlFor="login-password">密码</label>
+ <input
+ type="password"
+ id="login-password"
+ value={loginData.password}
+ onChange={(e) => updateLoginData("password", e.target.value)}
+ placeholder="请输入密码"
+ required
+ />
+ {errors.login.password && <div className="error-message">{errors.login.password}</div>}
+ </div>
+
+ <div className="form-group-inline">
+ <div className="checkbox-container">
+ <input
+ type="checkbox"
+ id="remember-me"
+ checked={loginData.rememberMe}
+ onChange={(e) => updateLoginData("rememberMe", e.target.checked)}
+ />
+ <label htmlFor="remember-me">记住我</label>
+ </div>
+ <Link to="/forgot-password" className="forgot-password">
+ 忘记密码?
+ </Link>
+ </div>
+
+ <button type="submit" className="auth-button">
+ 登录
+ </button>
+ </form>
+ ) : (
+ <form className="auth-form" onSubmit={handleRegister}>
+ {errors.register.message && <div className="error-message">{errors.register.message}</div>}
+ <div className="form-group">
+ <label htmlFor="register-username">用户名</label>
+ <input
+ type="text"
+ id="register-username"
+ value={registerData.username}
+ onChange={(e) => updateRegisterData("username", e.target.value)}
+ placeholder="请输入用户名"
+ required
+ />
+ {errors.register.username && <div className="error-message">{errors.register.username}</div>}
+ </div>
+
+ <div className="form-group">
+ <label htmlFor="register-email">邮箱</label>
+ <input
+ type="email"
+ id="register-email"
+ value={registerData.email}
+ onChange={(e) => updateRegisterData("email", e.target.value)}
+ placeholder="请输入邮箱"
+ required
+ />
+ {errors.register.email && <div className="error-message">{errors.register.email}</div>}
+ </div>
+
+ <div className="form-group">
+ <label htmlFor="register-password">密码</label>
+ <input
+ type="password"
+ id="register-password"
+ value={registerData.password}
+ onChange={(e) => updateRegisterData("password", e.target.value)}
+ placeholder="请输入密码"
+ required
+ />
+ {errors.register.password && <div className="error-message">{errors.register.password}</div>}
+ </div>
+
+ <div className="form-group">
+ <label htmlFor="register-confirm-password">确认密码</label>
+ <input
+ type="password"
+ id="register-confirm-password"
+ value={registerData.confirmPassword}
+ onChange={(e) => updateRegisterData("confirmPassword", e.target.value)}
+ placeholder="请再次输入密码"
+ required
+ />
+ {errors.register.confirmPassword && (
+ <div className="error-message">{errors.register.confirmPassword}</div>
+ )}
+ </div>
+
+ <div className="form-group">
+ <label htmlFor="register-inviteCode">邀请码</label>
+ <input
+ type="text"
+ id="register-inviteCode"
+ value={registerData.inviteCode}
+ onChange={(e) => updateRegisterData("inviteCode", e.target.value)}
+ placeholder="请输入邀请码"
+ />
+ {errors.register.inviteCode && <div className="error-message">{errors.register.inviteCode}</div>}
+ </div>
+
+ <button type="submit" className="auth-button">
+ 注册
+ </button>
+ </form>
+ )}
+ </div>
+ </div>
</div>
);
-};
+}
export default AuthPage;
\ No newline at end of file
diff --git a/src/pages/AuthPage/AuthPage.test.jsx b/src/pages/AuthPage/AuthPage.test.jsx
deleted file mode 100644
index e398536..0000000
--- a/src/pages/AuthPage/AuthPage.test.jsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import React from 'react';
-import { render, screen, fireEvent } from '@testing-library/react';
-import AuthPage from './AuthPage';
-
-describe('AuthPage component', () => {
- test('switches between login and register forms', () => {
- render(<AuthPage />);
-
- const registerButton = screen.getByText('点击注册');
- fireEvent.click(registerButton);
-
- const usernameInput = screen.getByPlaceholderText('请输入用户名');
- const passwordInput = screen.getByPlaceholderText('请输入密码');
- const emailInput = screen.getByPlaceholderText('请输入邮箱');
-
- expect(usernameInput).toBeInTheDocument();
- expect(passwordInput).toBeInTheDocument();
- expect(emailInput).toBeInTheDocument();
-
- const loginButton = screen.getByText('点击登录');
- fireEvent.click(loginButton);
-
- const loginUsernameInput = screen.getByPlaceholderText('请输入用户名');
- const loginPasswordInput = screen.getByPlaceholderText('请输入密码');
- const loginSubmitButton = screen.getByText('登录');
-
- expect(loginUsernameInput).toBeInTheDocument();
- expect(loginPasswordInput).toBeInTheDocument();
- expect(loginSubmitButton).toBeInTheDocument();
- });
-});
\ No newline at end of file
diff --git a/src/pages/AuthPage/AuthPage.test.jsx.txt b/src/pages/AuthPage/AuthPage.test.jsx.txt
new file mode 100644
index 0000000..a622c13
--- /dev/null
+++ b/src/pages/AuthPage/AuthPage.test.jsx.txt
@@ -0,0 +1,31 @@
+// import React from 'react';
+// import { render, screen, fireEvent } from '@testing-library/react';
+// import AuthPage from './AuthPage';
+
+// describe('AuthPage component', () => {
+// test('switches between login and register forms', () => {
+// render(<AuthPage />);
+
+// const registerButton = screen.getByText('点击注册');
+// fireEvent.click(registerButton);
+
+// const usernameInput = screen.getByPlaceholderText('请输入用户名');
+// const passwordInput = screen.getByPlaceholderText('请输入密码');
+// const emailInput = screen.getByPlaceholderText('请输入邮箱');
+
+// expect(usernameInput).toBeInTheDocument();
+// expect(passwordInput).toBeInTheDocument();
+// expect(emailInput).toBeInTheDocument();
+
+// const loginButton = screen.getByText('点击登录');
+// fireEvent.click(loginButton);
+
+// const loginUsernameInput = screen.getByPlaceholderText('请输入用户名');
+// const loginPasswordInput = screen.getByPlaceholderText('请输入密码');
+// const loginSubmitButton = screen.getByText('登录');
+
+// expect(loginUsernameInput).toBeInTheDocument();
+// expect(loginPasswordInput).toBeInTheDocument();
+// expect(loginSubmitButton).toBeInTheDocument();
+// });
+// });
\ No newline at end of file
diff --git a/src/pages/Forum/posts-create/CreatePost.jsx b/src/pages/Forum/posts-create/CreatePost.jsx
index e38c29a..b8e8c2a 100644
--- a/src/pages/Forum/posts-create/CreatePost.jsx
+++ b/src/pages/Forum/posts-create/CreatePost.jsx
@@ -1,89 +1,78 @@
-// // src/pages/Forum/CreatePost.jsx
// import React, { useState } from 'react';
// import axios from 'axios';
+// import './CreatePost.css'; // 如果你打算加样式
// const API_BASE = process.env.REACT_APP_API_BASE;
-// const CreatePost = ({ userId }) => {
+// const CreatePost = ({ user_id }) => {
// const [title, setTitle] = useState('');
// const [content, setContent] = useState('');
-// const [imgUrl, setImageUrl] = useState('');
-// const [isAnonymous, setIsAnonymous] = useState(false);
+// const [imageUrl, setImageUrl] = useState('');
+// const [message, setMessage] = useState('');
+// const [error, setError] = useState('');
// const handleSubmit = async (e) => {
// e.preventDefault();
+// setMessage('');
+// setError('');
+
+// if (!title.trim() || !content.trim()) {
+// setError('标题和内容不能为空');
+// return;
+// }
// try {
-// const postData = {
+// const res = await axios.post(`${API_BASE}/echo/forum/posts/${user_id}/createPost`, {
// title,
-// postContent: content,
-// postType: isAnonymous,
-// };
+// post_content: content,
+// image_url: imageUrl
+// });
-// if (imgUrl.trim()) {
-// postData.imgUrl = imgUrl;
-// }
-
-// const response = await axios.post(
-// `${API_BASE}/echo/forum/posts/${userId}/createPost`,
-// postData
-// );
-
-
-// if (response.status === 201) {
-// alert('帖子创建成功!');
-// setTitle('');
-// setContent('');
-// setImageUrl('');
-// setIsAnonymous(false);
-// }
-// } catch (error) {
-// console.error('帖子创建失败:', error.response?.data || error.message);
-// alert('创建失败,请重试');
-// }
+// setMessage(`发帖成功,帖子ID:${res.data.post_id}`);
+// setTitle('');
+// setContent('');
+// setImageUrl('');
+// } catch (err) {
+// console.error(err);
+// setError(err.response?.data?.error || '发帖失败,请稍后重试');
+// }
// };
// return (
-// <div className="create-post">
-// <h2>创建新帖子</h2>
-// <form onSubmit={handleSubmit}>
-// <div>
+// <div className="create-post-container">
+// <h2>发表新帖子</h2>
+// <form onSubmit={handleSubmit} className="create-post-form">
+// <div className="form-group">
// <label>标题:</label>
// <input
// type="text"
// value={title}
// onChange={(e) => setTitle(e.target.value)}
-// required
+// placeholder="输入帖子标题"
// />
// </div>
-// <div>
+// <div className="form-group">
// <label>内容:</label>
// <textarea
// value={content}
// onChange={(e) => setContent(e.target.value)}
-// required
+// placeholder="输入帖子内容"
// />
// </div>
-// <div>
-// <label>图片 URL(可选):</label>
+// <div className="form-group">
+// <label>图片链接(可选):</label>
// <input
// type="text"
-// value={imgUrl}
+// value={imageUrl}
// onChange={(e) => setImageUrl(e.target.value)}
+// placeholder="例如:https://example.com/img.jpg"
// />
// </div>
-// <div>
-// <label>
-// <input
-// type="checkbox"
-// checked={isAnonymous}
-// onChange={(e) => setIsAnonymous(e.target.checked)}
-// />
-// 匿名发布
-// </label>
-// </div>
// <button type="submit">发布</button>
// </form>
+
+// {message && <p className="success-text">{message}</p>}
+// {error && <p className="error-text">{error}</p>}
// </div>
// );
// };
@@ -96,7 +85,7 @@
const API_BASE = process.env.REACT_APP_API_BASE;
-const CreatePost = ({ userId }) => {
+const CreatePost = ({ user_id }) => {
const [title, setTitle] = useState('');
const [content, setContent] = useState('');
const [imageUrl, setImageUrl] = useState('');
@@ -114,7 +103,7 @@
}
try {
- const res = await axios.post(`${API_BASE}/echo/forum/posts/${userId}/createPost`, {
+ const res = await axios.post(`${API_BASE}/echo/forum/posts/${user_id}/createPost`, {
title,
post_content: content,
image_url: imageUrl
@@ -135,8 +124,10 @@
<h2>发表新帖子</h2>
<form onSubmit={handleSubmit} className="create-post-form">
<div className="form-group">
- <label>标题:</label>
+ {/* 这里加上htmlFor,并给input加id */}
+ <label htmlFor="title">标题:</label>
<input
+ id="title" // 加id
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
@@ -144,16 +135,20 @@
/>
</div>
<div className="form-group">
- <label>内容:</label>
+ {/* 同理,内容 */}
+ <label htmlFor="content">内容:</label>
<textarea
+ id="content" // 加id
value={content}
onChange={(e) => setContent(e.target.value)}
placeholder="输入帖子内容"
/>
</div>
<div className="form-group">
- <label>图片链接(可选):</label>
+ {/* 图片链接 */}
+ <label htmlFor="imageUrl">图片链接(可选):</label>
<input
+ id="imageUrl" // 加id
type="text"
value={imageUrl}
onChange={(e) => setImageUrl(e.target.value)}
diff --git a/src/pages/Forum/posts-detail/PostDetailPage.css b/src/pages/Forum/posts-detail/PostDetailPage.css
index 780492b..570b65f 100644
--- a/src/pages/Forum/posts-detail/PostDetailPage.css
+++ b/src/pages/Forum/posts-detail/PostDetailPage.css
@@ -1,5 +1,5 @@
.post-detail-page {
- background: linear-gradient(180deg, #5F4437, #823c3c);
+ background: #333;
font-family: 'Helvetica Neue', sans-serif;
color: #333;
}
diff --git a/src/pages/Forum/posts-detail/PostDetailPage.jsx b/src/pages/Forum/posts-detail/PostDetailPage.jsx
index 01e1648..c58ed33 100644
--- a/src/pages/Forum/posts-detail/PostDetailPage.jsx
+++ b/src/pages/Forum/posts-detail/PostDetailPage.jsx
@@ -1,7 +1,288 @@
+// import React, { useEffect, useState } from 'react';
+// import { useParams } from 'wouter';
+// import { GoodTwo, Star } from '@icon-park/react';
+// import { getPostDetail, getPostComments, likePost, unlikePost, addCommentToPost, collectPost } from './api'; // 引入你的 API 函数
+// import './PostDetailPage.css';
+// import { useUser } from '../../../context/UserContext'; // 注意路径
+// import Header from '../../../components/Header';
+
+// const PostDetailPage = () => {
+// const { postId } = useParams(); // 获取帖子ID
+// const [postDetail, setPostDetail] = useState(null);
+// const [comments, setComments] = useState([]);
+// const [loading, setLoading] = useState(true);
+// const [errorMsg, setErrorMsg] = useState('');
+// const [newComment, setNewComment] = useState(''); // 新评论内容
+// const [isAnonymous, setIsAnonymous] = useState(false); // 是否匿名
+// const [isLiked, setIsLiked] = useState(false); // 是否已点赞
+// const [isCollected, setIsCollected] = useState(false); // 是否已收藏
+// const [replyToCommentId, setReplyToCommentId] = useState(null); // 回复的评论ID
+
+// // 获取当前用户ID(假设从上下文中获取)
+// const { user } = useUser(); // 你需要从用户上下文获取用户 ID
+
+// useEffect(() => {
+// const fetchPostDetail = async () => {
+// setLoading(true);
+// setErrorMsg('');
+// try {
+// // 获取帖子详情
+// const postData = await getPostDetail(postId);
+// setPostDetail(postData);
+
+// // 获取帖子评论
+// const commentsData = await getPostComments(postId);
+// setComments(commentsData);
+
+// // 设置是否已经点赞
+// if (postData.likedByUser) {
+// setIsLiked(true);
+// } else {
+// setIsLiked(false);
+// }
+
+// // 设置是否已经收藏
+// if (postData.collectedByUser) {
+// setIsCollected(true);
+// } else {
+// setIsCollected(false);
+// }
+// } catch (err) {
+// console.error('加载失败:', err);
+// setErrorMsg('加载失败,请稍后重试');
+// } finally {
+// setLoading(false);
+// }
+// };
+
+// fetchPostDetail();
+// }, [postId]);
+
+// // 点赞功能
+// const toggleLike = async () => {
+// if (!user) {
+// alert('请先登录');
+// return;
+// }
+
+// try {
+// if (isLiked) {
+// // 取消点赞
+// await unlikePost(postId, user.id);
+// setIsLiked(false);
+// setPostDetail((prev) => ({
+// ...prev,
+// postLikeNum: prev.postLikeNum - 1,
+// }));
+// } else {
+// // 点赞
+// await likePost(postId, user.id);
+// setIsLiked(true);
+// setPostDetail((prev) => ({
+// ...prev,
+// postLikeNum: prev.postLikeNum + 1,
+// }));
+// }
+// } catch (err) {
+// console.error('点赞失败:', err);
+// alert('点赞失败,请稍后再试');
+// }
+// };
+
+// // 收藏功能
+// const toggleCollect = async () => {
+// if (!user) {
+// alert('请先登录');
+// return;
+// }
+
+// try {
+// const action = isCollected ? 'cancel' : 'collect';
+// // 调用收藏 API
+// await collectPost(postId, user.id, action);
+// setIsCollected(!isCollected);
+// setPostDetail((prev) => ({
+// ...prev,
+// postCollectNum: isCollected ? prev.postCollectNum - 1 : prev.postCollectNum + 1,
+// }));
+// } catch (err) {
+// console.error('收藏失败:', err);
+// alert('收藏失败,请稍后再试');
+// }
+// };
+
+// // 添加评论
+// const handleAddComment = async () => {
+// if (!newComment.trim()) {
+// alert('评论内容不能为空');
+// return;
+// }
+
+// try {
+// // 调用 API 添加评论,若为回复评论则传递父评论ID(com_comment_id)
+// const commentData = await addCommentToPost(postId, user.id, newComment, isAnonymous, replyToCommentId);
+// // 更新评论列表
+// setComments((prev) => [
+// ...prev,
+// {
+// commentId: commentData.commentId,
+// post_id: postId,
+// userId: user.id,
+// content: newComment,
+// isAnonymous,
+// commentTime: new Date().toISOString(),
+// comCommentId: replyToCommentId, // 回复评论时传递父评论ID
+// },
+// ]);
+// // 清空评论框和回复状态
+// setNewComment('');
+// setReplyToCommentId(null);
+// } catch (err) {
+// console.error('评论添加失败:', err);
+// alert('评论失败,请稍后再试');
+// }
+// };
+
+// // 回复评论
+// const handleReply = (commentId) => {
+// setReplyToCommentId(commentId); // 设置父评论ID为当前评论的ID
+// };
+
+// return (
+// <div className="post-detail-page">
+// <Header />
+// {loading ? (
+// <p>加载中...</p>
+// ) : errorMsg ? (
+// <p className="error-text">{errorMsg}</p>
+// ) : postDetail ? (
+// <div className="post-detail">
+// <h1>{postDetail.title}</h1>
+// <div className="post-meta">
+// <span className="post-user">用户ID: {postDetail.user_id}</span>
+// <span className="post-time">
+// 发布时间:{new Date(postDetail.postTime).toLocaleString()}
+// </span>
+// </div>
+// <div className="post-content">
+// <p>{postDetail.postContent}</p>
+// {Array.isArray(postDetail.imgUrl) ? (
+// <div className="post-images">
+// {postDetail.imgUrl.map((url, idx) => (
+// <img key={idx} src={url} alt={`图片${idx}`} />
+// ))}
+// </div>
+// ) : (
+// postDetail.imgUrl && (
+// <img className="post-image" src={postDetail.imgUrl} alt="帖子图片" />
+// )
+// )}
+
+// </div>
+
+// {/* 点赞和收藏 */}
+// <div className="post-actions">
+// <button
+// className="icon-btn"
+// onClick={toggleLike} // 点赞操作
+// >
+// <GoodTwo
+// theme="outline"
+// size="20"
+// fill={isLiked ? '#f00' : '#ccc'} // 如果已点赞,显示红色
+// />
+// <span>{postDetail.postLikeNum}</span>
+// </button>
+// <button
+// className="icon-btn"
+// onClick={toggleCollect} // 收藏操作
+// >
+// <Star
+// theme="outline"
+// size="20"
+// fill={isCollected ? '#ffd700' : '#ccc'} // 如果已收藏,显示金色
+// />
+// <span>{postDetail.postCollectNum}</span>
+// </button>
+// </div>
+
+// <hr className="divider" />
+// {/* 评论部分 */}
+// <h3>评论区</h3>
+// <div className="comments-section">
+// {comments.length ? (
+// comments.map((comment) => (
+// <div key={comment.commentId} className="comment">
+// <div className="comment-header">
+// <span className="comment-user">用户 ID: {comment.userId}</span>
+// <button className="reply-btn" onClick={() => handleReply(comment.commentId)}>回复</button>
+// </div>
+// <p className="comment-content">{comment.content}</p>
+// <div className="comment-time">
+// {new Date(comment.commentTime).toLocaleString()}
+// </div>
+
+// {/* 回复框,只有在当前评论是正在回复的评论时显示 */}
+// {replyToCommentId === comment.commentId && (
+// <div className="reply-form">
+// <textarea
+// placeholder="输入你的回复..."
+// value={newComment}
+// onChange={(e) => setNewComment(e.target.value)}
+// />
+// <div className="comment-options">
+// <label>
+// <input
+// type="checkbox"
+// checked={isAnonymous}
+// onChange={() => setIsAnonymous(!isAnonymous)}
+// />
+// 匿名评论
+// </label>
+// <button onClick={handleAddComment}>发布回复</button>
+// </div>
+// </div>
+// )}
+// </div>
+// ))
+// ) : (
+// <p>暂无评论</p>
+// )}
+
+// {/* 添加评论表单 */}
+// <div className="add-comment-form">
+// <textarea
+// placeholder="输入你的评论..."
+// value={newComment}
+// onChange={(e) => setNewComment(e.target.value)}
+// />
+// <div className="comment-options">
+// <label>
+// <input
+// type="checkbox"
+// checked={isAnonymous}
+// onChange={() => setIsAnonymous(!isAnonymous)}
+// />
+// 匿名评论
+// </label>
+// <button onClick={handleAddComment}>发布评论</button>
+// </div>
+// </div>
+// </div>
+// </div>
+// ) : (
+// <p>帖子不存在</p>
+// )}
+// </div>
+// );
+// };
+
+// export default PostDetailPage;
+
import React, { useEffect, useState } from 'react';
import { useParams } from 'wouter';
import { GoodTwo, Star } from '@icon-park/react';
-import { getPostDetail, getPostComments, likePost, unlikePost, addCommentToPost, collectPost } from './api'; // 引入你的 API 函数
+import { getPostDetail, getPostComments, likePost, unlikePost, addCommentToPost, collectPost, uncollectPost } from './api'; // 引入你的 API 函数
import './PostDetailPage.css';
import { useUser } from '../../../context/UserContext'; // 注意路径
import Header from '../../../components/Header';
@@ -13,7 +294,7 @@
const [loading, setLoading] = useState(true);
const [errorMsg, setErrorMsg] = useState('');
const [newComment, setNewComment] = useState(''); // 新评论内容
- const [isAnonymous, setIsAnonymous] = useState(false); // 是否匿名
+ // const [isAnonymous, setIsAnonymous] = useState(false); // 是否匿名
const [isLiked, setIsLiked] = useState(false); // 是否已点赞
const [isCollected, setIsCollected] = useState(false); // 是否已收藏
const [replyToCommentId, setReplyToCommentId] = useState(null); // 回复的评论ID
@@ -89,27 +370,36 @@
}
};
- // 收藏功能
- const toggleCollect = async () => {
+// 收藏功能
+const toggleCollect = async () => {
if (!user) {
- alert('请先登录');
- return;
+ alert('请先登录');
+ return;
}
try {
- const action = isCollected ? 'cancel' : 'collect';
- // 调用收藏 API
- await collectPost(postId, user.id, action);
- setIsCollected(!isCollected);
- setPostDetail((prev) => ({
- ...prev,
- postCollectNum: isCollected ? prev.postCollectNum - 1 : prev.postCollectNum + 1,
- }));
+ if (isCollected) {
+ // 取消收藏 - 使用原有的collectPost函数,传递action: "cancel"
+ await collectPost(postId, user.id, "cancel");
+ setIsCollected(false);
+ setPostDetail((prev) => ({
+ ...prev,
+ postCollectNum: prev.postCollectNum - 1,
+ }));
+ } else {
+ // 收藏
+ await collectPost(postId, user.id, "collect");
+ setIsCollected(true);
+ setPostDetail((prev) => ({
+ ...prev,
+ postCollectNum: prev.postCollectNum + 1,
+ }));
+ }
} catch (err) {
- console.error('收藏失败:', err);
- alert('收藏失败,请稍后再试');
+ console.error('收藏操作失败:', err);
+ alert('收藏操作失败,请稍后再试');
}
- };
+};
// 添加评论
const handleAddComment = async () => {
@@ -120,7 +410,7 @@
try {
// 调用 API 添加评论,若为回复评论则传递父评论ID(com_comment_id)
- const commentData = await addCommentToPost(postId, user.id, newComment, isAnonymous, replyToCommentId);
+ const commentData = await addCommentToPost(postId, user.id, newComment, replyToCommentId);
// 更新评论列表
setComments((prev) => [
...prev,
@@ -129,7 +419,7 @@
post_id: postId,
userId: user.id,
content: newComment,
- isAnonymous,
+ // isAnonymous,
commentTime: new Date().toISOString(),
comCommentId: replyToCommentId, // 回复评论时传递父评论ID
},
@@ -231,14 +521,14 @@
onChange={(e) => setNewComment(e.target.value)}
/>
<div className="comment-options">
- <label>
- <input
- type="checkbox"
- checked={isAnonymous}
- onChange={() => setIsAnonymous(!isAnonymous)}
- />
- 匿名评论
- </label>
+ {/* <label> */}
+ {/* <input */}
+ {/* type="checkbox" */}
+ {/* checked={isAnonymous} */}
+ {/* onChange={() => setIsAnonymous(!isAnonymous)} */}
+ {/* /> */}
+ {/* 匿名评论 */}
+ {/* </label> */}
<button onClick={handleAddComment}>发布回复</button>
</div>
</div>
@@ -257,14 +547,14 @@
onChange={(e) => setNewComment(e.target.value)}
/>
<div className="comment-options">
- <label>
+ {/* <label>
<input
type="checkbox"
checked={isAnonymous}
onChange={() => setIsAnonymous(!isAnonymous)}
/>
匿名评论
- </label>
+ </label> */}
<button onClick={handleAddComment}>发布评论</button>
</div>
</div>
@@ -277,4 +567,4 @@
);
};
-export default PostDetailPage;
+export default PostDetailPage;
\ No newline at end of file
diff --git a/src/pages/Forum/posts-detail/api.js b/src/pages/Forum/posts-detail/api.js
index d05f148..27c3a18 100644
--- a/src/pages/Forum/posts-detail/api.js
+++ b/src/pages/Forum/posts-detail/api.js
@@ -2,22 +2,23 @@
const API_BASE = process.env.REACT_APP_API_BASE;
+
// 获取帖子详情
-export const getPostDetail = async (postId) => {
- const response = await axios.get(`${API_BASE}/echo/forum/posts/${postId}/getPost`);
+export const getPostDetail = async (post_id) => {
+ const response = await axios.get(`${API_BASE}/echo/forum/posts/${post_id}/getPost`);
return response.data;
};
// 获取帖子评论
-export const getPostComments = async (postId) => {
- const response = await axios.get(`${API_BASE}/echo/forum/posts/${postId}/getAllComments`);
+export const getPostComments = async (post_id) => {
+ const response = await axios.get(`${API_BASE}/echo/forum/posts/${post_id}/getAllComments`);
return response.data;
};
// 点赞帖子
-export const likePost = async (postId, userId) => {
+export const likePost = async (post_id, userId) => {
try {
- const response = await axios.post(`${API_BASE}/echo/forum/posts/${postId}/like`, {
+ const response = await axios.post(`${API_BASE}/echo/forum/posts/${post_id}/like`, {
user_id: userId, // 用户 ID
});
return response.data;
@@ -27,15 +28,15 @@
};
// 取消点赞帖子
-export const unlikePost = async (postId) => {
- const response = await axios.delete(`${API_BASE}/echo/forum/posts/${postId}/unlike`);
+export const unlikePost = async (post_id) => {
+ const response = await axios.delete(`${API_BASE}/echo/forum/posts/${post_id}/unlike`);
return response.data;
};
// 添加评论
-export const addCommentToPost = async (postId, userId, content, isAnonymous, comCommentId = null) => {
+export const addCommentToPost = async (post_id, userId, content, isAnonymous, comCommentId = null) => {
try {
- const response = await axios.post(`${API_BASE}/echo/forum/posts/${postId}/comments`, {
+ const response = await axios.post(`${API_BASE}/echo/forum/posts/${post_id}/comments`, {
content,
user_id: userId,
is_anonymous: isAnonymous,
@@ -60,9 +61,9 @@
};
// 收藏帖子
-export const collectPost = async (postId, userId, action) => {
+export const collectPost = async (post_id, userId, action) => {
try {
- const response = await axios.post(`${API_BASE}/echo/forum/posts/${postId}/collect`, {
+ const response = await axios.post(`${API_BASE}/echo/forum/posts/${post_id}/collect`, {
user_id: userId,
action: action, // "collect" 或 "cancel"
});
@@ -72,6 +73,14 @@
}
};
+// // 取消收藏帖子
+// export const uncollectPost = async (post_id, userId) => {
+// const response = await axios.post(`${API_BASE}/echo/forum/posts/${post_id}/uncollect`, {
+// user_id: userId, // 用户 ID
+// });
+// return response.data;
+// };
+
// 获取用户信息
export const getUserInfo = async (userId) => {
const response = await axios.get(`${API_BASE}/user/${userId}/info`);
diff --git a/src/pages/Forum/posts-main/ForumPage.css b/src/pages/Forum/posts-main/ForumPage.css
index 8a7ae4c..5fd64a2 100644
--- a/src/pages/Forum/posts-main/ForumPage.css
+++ b/src/pages/Forum/posts-main/ForumPage.css
@@ -2,7 +2,7 @@
color: #fff;
/* background-color: #5F4437; */
/* background: linear-gradient(180deg, #5F4437, #9c737b); */
- background: linear-gradient(180deg, #5F4437, #823c3c);
+ background: #333;
/* background-color: #5F4437; */
min-height: 100vh;
font-family: Arial, sans-serif;
diff --git a/src/pages/Forum/posts-main/components/CreatePostButton.jsx b/src/pages/Forum/posts-main/components/CreatePostButton.jsx
index 0390ee7..4f7d7b1 100644
--- a/src/pages/Forum/posts-main/components/CreatePostButton.jsx
+++ b/src/pages/Forum/posts-main/components/CreatePostButton.jsx
@@ -4,7 +4,7 @@
import './CreatePostButton.css';
const API_BASE = process.env.REACT_APP_API_BASE;
-const USER_ID = 456;
+const user_id = 456;
const CreatePostButton = () => {
const [showModal, setShowModal] = useState(false);
@@ -49,7 +49,7 @@
try {
await axios.post(
- `${API_BASE}/echo/forum/posts/${USER_ID}/createPost`,
+ `${API_BASE}/echo/forum/posts/${user_id}/createPost`,
{
title: title.trim(),
post_content: content.trim(),
diff --git a/src/pages/Forum/posts-main/components/PostList.jsx b/src/pages/Forum/posts-main/components/PostList.jsx
index 3eba6f8..707ff15 100644
--- a/src/pages/Forum/posts-main/components/PostList.jsx
+++ b/src/pages/Forum/posts-main/components/PostList.jsx
@@ -1,175 +1,8 @@
-// import React, { useEffect, useState } from 'react';
-// import axios from 'axios';
-// import { Link } from 'wouter';
-// import { GoodTwo, Comment, Star } from '@icon-park/react';
-// import { likePost, unlikePost, collectPost } from '../../posts-detail/api';
-// import './PostList.css';
-
-// const API_BASE = process.env.REACT_APP_API_BASE;
-
-// const PostList = ({ search }) => {
-// const [posts, setPosts] = useState([]);
-// const [page, setPage] = useState(1);
-// const [total, setTotal] = useState(0);
-// const [loading, setLoading] = useState(true);
-// const [errorMsg, setErrorMsg] = useState('');
-
-// const size = 10; // 每页条数
-// const totalPages = Math.ceil(total / size);
-
-// useEffect(() => {
-// const fetchPosts = async () => {
-// setLoading(true);
-// setErrorMsg('');
-// try {
-// const res = await axios.get(`${API_BASE}/echo/forum/posts`, {
-// params: {
-// page: page,
-// pageSize: size,
-// sortBy: 'createdAt', // 按时间排序
-// order: 'desc' // 按降序排序
-// }
-// });
-
-// const postsData = res.data.posts || [];
-// const userIds = [...new Set(postsData.map(p => p.user_id))];
-
-// // 获取用户信息
-// const profiles = await Promise.all(userIds.map(async id => {
-// try {
-// const r = await axios.get(`${API_BASE}/echo/user/profile`, {
-// params: { user_id: id }
-// });
-// return { id, profile: r.data };
-// } catch {
-// return { id, profile: { nickname: '未知用户', avatar_url: 'default-avatar.png' } };
-// }
-// }));
-
-// const userMap = {};
-// profiles.forEach(({ id, profile }) => { userMap[id] = profile; });
-
-// // 更新帖子数据
-// const postsWithProfiles = postsData
-// .filter(post => post.title.includes(search))
-// .map(post => ({
-// ...post,
-// userProfile: userMap[post.user_id] || {}
-// }));
-
-// setPosts(postsWithProfiles);
-// setTotal(res.data.total || 0);
-// } catch (err) {
-// console.error('加载失败:', err);
-// setErrorMsg('加载失败,请稍后重试');
-// } finally {
-// setLoading(false);
-// }
-// };
-
-// fetchPosts();
-// }, [page, search]);
-
-// // 点赞/取消点赞操作
-// const toggleLike = async (postId, liked, userId) => {
-// try {
-// if (liked) {
-// await unlikePost(postId); // 取消点赞
-// } else {
-// await likePost(postId, userId); // 点赞
-// }
-
-// setPosts(posts =>
-// posts.map(post =>
-// post.id === postId
-// ? { ...post, liked: !liked, likeCount: liked ? post.likeCount - 1 : post.likeCount + 1 }
-// : post
-// )
-// );
-// } catch (err) {
-// console.error('点赞失败:', err);
-// }
-// };
-
-// // 收藏/取消收藏操作
-// const toggleCollect = async (postId, collected, userId) => {
-// try {
-// const action = collected ? 'cancel' : 'collect';
-// await collectPost(postId, userId, action);
-
-// setPosts(posts =>
-// posts.map(post =>
-// post.id === postId
-// ? { ...post, collected: !collected, collectCount: collected ? post.collectCount - 1 : post.collectCount + 1 }
-// : post
-// )
-// );
-// } catch (err) {
-// console.error('收藏失败:', err);
-// }
-// };
-
-// return (
-// <div className="post-list">
-// {loading ? <p>加载中...</p> :
-// errorMsg ? <p className="error-text">{errorMsg}</p> :
-// posts.length === 0 ? <p>暂无帖子。</p> :
-// posts.map(post => (
-// <Link
-// key={post.id}
-// href={`/forum/post/${post.id}`}
-// className="post-card"
-// style={{ backgroundColor: '#e9ded2' }}
-// >
-// <div className="user-info">
-// <img className="avatar" src={post.userProfile.avatar_url} alt="头像" />
-// <span className="nickname" style={{ color: '#755e50' }}>{post.userProfile.nickname}</span>
-// </div>
-// {post.cover_image_url && (
-// <img className="cover-image" src={post.cover_image_url} alt="封面" />
-// )}
-// <h3 style={{ color: '#000000' }}>{post.title}</h3>
-// <div className="post-meta">
-// <span>发布时间:{new Date(post.createdAt).toLocaleString()}</span>
-// <div className="post-actions">
-// {/* 点赞按钮 */}
-// <button className="icon-btn" onClick={(e) => { e.stopPropagation(); toggleLike(post.id, post.liked, post.user_id); }}>
-// <GoodTwo theme="outline" size="24" fill={post.liked ? '#f00' : '#fff'} />
-// <span>{post.likeCount}</span>
-// </button>
-
-// {/* 收藏按钮 */}
-// <button className="icon-btn" onClick={(e) => { e.stopPropagation(); toggleCollect(post.id, post.collected, post.user_id); }}>
-// <Star theme="outline" size="24" fill={post.collected ? '#ffd700' : '#fff'} />
-// <span>{post.collectCount}</span>
-// </button>
-
-// <Link href={`/forum/post/${post.id}`} className="icon-btn" onClick={(e) => e.stopPropagation()}>
-// <Comment theme="outline" size="24" fill="#fff" />
-// <span>{post.commentCount}</span>
-// </Link>
-// </div>
-// </div>
-// </Link>
-// ))
-// }
-
-// <div className="pagination">
-// <button disabled={page === 1} onClick={() => setPage(page - 1)}>上一页</button>
-// <span>第 {page} 页 / 共 {totalPages} 页</span>
-// <button disabled={page === totalPages} onClick={() => setPage(page + 1)}>下一页</button>
-// </div>
-// </div>
-// );
-// };
-
-// export default PostList;
-
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import { Link } from 'wouter';
-import { GoodTwo, Comment, Star } from '@icon-park/react';
-import { likePost, unlikePost, collectPost } from '../../posts-detail/api';
+import { GoodTwo, Comment, Star, Delete } from '@icon-park/react';
+import { likePost, unlikePost } from '../../posts-detail/api';
import './PostList.css';
const API_BASE = process.env.REACT_APP_API_BASE;
@@ -200,10 +33,8 @@
const postsData = res.data.posts || [];
- // 收集所有 user_id
const userIds = [...new Set(postsData.map(post => post.user_id))];
- // 批量请求用户资料
const profiles = await Promise.all(userIds.map(async id => {
try {
const r = await axios.get(`${API_BASE}/echo/user/profile`, {
@@ -215,13 +46,11 @@
}
}));
- // 创建 user_id -> profile 映射
const userMap = {};
profiles.forEach(({ id, profile }) => {
userMap[id] = profile;
});
- // 过滤并补充 profile
const postsWithProfiles = postsData
.filter(post => post.title.toLowerCase().includes(search.toLowerCase()))
.map(post => ({
@@ -265,10 +94,20 @@
}
};
+ // 收藏帖子
const toggleCollect = async (postId, collected, userId) => {
try {
- const action = collected ? 'cancel' : 'collect';
- await collectPost(postId, userId, action);
+ if (collected) {
+ // 取消收藏
+ await axios.get(`${API_BASE}/echo/forum/posts/${postId}/uncollect`, {
+ data: { user_id: userId }
+ });
+ } else {
+ // 收藏帖子
+ await axios.post(`${API_BASE}/echo/forum/posts/${postId}/collect`, {
+ user_id: userId
+ });
+ }
setPosts(posts =>
posts.map(post =>
@@ -278,7 +117,27 @@
)
);
} catch (err) {
- console.error('收藏失败:', err);
+ console.error('收藏操作失败:', err);
+ }
+ };
+
+ // 删除帖子
+ const handleDeletePost = async (postId) => {
+ if (window.confirm('确定要删除这篇帖子吗?')) {
+ try {
+ await axios.delete(`${API_BASE}/echo/forum/posts/${postId}/deletePost`);
+
+ // 从列表中移除已删除的帖子
+ setPosts(posts => posts.filter(post => post.postNo !== postId));
+
+ // 如果删除后当前页没有帖子了,尝试加载上一页
+ if (posts.length === 1 && page > 1) {
+ setPage(page - 1);
+ }
+ } catch (err) {
+ console.error('删除帖子失败:', err);
+ alert('删除帖子失败,请稍后再试');
+ }
}
};
@@ -288,9 +147,8 @@
errorMsg ? <p className="error-text">{errorMsg}</p> :
posts.length === 0 ? <p>暂无帖子。</p> :
posts.map(post => (
- <Link
+ <div
key={post.postNo}
- href={`/forum/post/${post.postNo}`}
className="post-card"
style={{ backgroundColor: '#e9ded2' }}
>
@@ -305,23 +163,30 @@
<div className="post-meta">
<span>发布时间:{new Date(post.createdAt).toLocaleString()}</span>
<div className="post-actions">
- <button className="icon-btn" onClick={(e) => { e.stopPropagation(); toggleLike(post.postNo, post.liked, post.user_id); }}>
+ <button className="icon-btn" onClick={() => toggleLike(post.postNo, post.liked, post.user_id)}>
<GoodTwo theme="outline" size="24" fill={post.liked ? '#f00' : '#fff'} />
<span>{post.likeCount}</span>
</button>
- <button className="icon-btn" onClick={(e) => { e.stopPropagation(); toggleCollect(post.postNo, post.collected, post.user_id); }}>
+ <button className="icon-btn" onClick={() => toggleCollect(post.postNo, post.collected, post.user_id)}>
<Star theme="outline" size="24" fill={post.collected ? '#ffd700' : '#fff'} />
<span>{post.collectCount}</span>
</button>
- <Link href={`/forum/post/${post.postNo}`} className="icon-btn" onClick={(e) => e.stopPropagation()}>
+ <div className="icon-btn">
<Comment theme="outline" size="24" fill="#fff" />
<span>{post.commentCount}</span>
- </Link>
+ </div>
+
+ <button className="icon-btn" onClick={() => handleDeletePost(post.postNo)}>
+ <Delete theme="outline" size="24" fill="#333" />
+ </button>
</div>
</div>
- </Link>
+ <div className="detail-button-wrapper">
+ <Link href={`/forum/post/${post.postNo}`} className="detail-button">查看详情</Link>
+ </div>
+ </div>
))
}
@@ -334,4 +199,4 @@
);
};
-export default PostList;
+export default PostList;
\ No newline at end of file
diff --git a/src/pages/FriendMoments/FriendMoments.css b/src/pages/FriendMoments/FriendMoments.css
index a69d919..1059f10 100644
--- a/src/pages/FriendMoments/FriendMoments.css
+++ b/src/pages/FriendMoments/FriendMoments.css
@@ -1,6 +1,6 @@
.friend-moments-container {
margin: 0 auto;
- background: linear-gradient(180deg, #5F4437, #823c3c);
+ background: #333;
padding-bottom: 40px;
}
diff --git a/src/pages/InterestGroup/InterestGroup.css b/src/pages/InterestGroup/InterestGroup.css
index 35d3c4d..91b21da 100644
--- a/src/pages/InterestGroup/InterestGroup.css
+++ b/src/pages/InterestGroup/InterestGroup.css
@@ -1,6 +1,6 @@
/* 设置整个兴趣小组页面的背景色和布局 */
.interest-group-container {
- background: linear-gradient(180deg, #5F4437, #823c3c);
+ background: #333;
width: 100%;
height: 2000px;
}
diff --git a/src/pages/PromotionsPage/PromotionsPage.css b/src/pages/PromotionsPage/PromotionsPage.css
new file mode 100644
index 0000000..6752c69
--- /dev/null
+++ b/src/pages/PromotionsPage/PromotionsPage.css
@@ -0,0 +1,206 @@
+.promotions-page {
+ padding: 20px;
+ font-family: Arial, sans-serif;
+}
+
+.promotions-container {
+ max-width: 1200px;
+ margin: 0 auto;
+ background-color: #fff;
+ border-radius: 8px;
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+ padding: 20px;
+}
+
+h1, h2, h3 {
+ color: #333;
+}
+
+.admin-actions {
+ margin-bottom: 20px;
+}
+
+.create-button, .submit-button, .delete-button {
+ background-color: #4CAF50;
+ color: white;
+ border: none;
+ padding: 10px 15px;
+ border-radius: 4px;
+ cursor: pointer;
+ font-size: 14px;
+ transition: background-color 0.3s;
+}
+
+.create-button:hover, .submit-button:hover {
+ background-color: #45a049;
+}
+
+.delete-button {
+ background-color: #f44336;
+ margin-top: 10px;
+}
+
+.delete-button:hover {
+ background-color: #d32f2f;
+}
+
+.create-promotion-form {
+ background-color: #f9f9f9;
+ padding: 20px;
+ border-radius: 8px;
+ margin-bottom: 20px;
+}
+
+.form-group {
+ margin-bottom: 15px;
+}
+
+.form-row {
+ display: flex;
+ gap: 20px;
+}
+
+.form-row .form-group {
+ flex: 1;
+}
+
+label {
+ display: block;
+ margin-bottom: 5px;
+ font-weight: bold;
+}
+
+input, select {
+ width: 100%;
+ padding: 8px;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ box-sizing: border-box;
+}
+
+.error-message {
+ color: #f44336;
+ margin-bottom: 15px;
+ padding: 10px;
+ background-color: #ffebee;
+ border-radius: 4px;
+}
+
+.promotions-grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 20px;
+}
+
+.promotions-list {
+ border-right: 1px solid #eee;
+ padding-right: 20px;
+}
+
+.promotion-items {
+ max-height: 600px;
+ overflow-y: auto;
+}
+
+.promotion-item {
+ background-color: #f9f9f9;
+ padding: 15px;
+ border-radius: 8px;
+ margin-bottom: 15px;
+ cursor: pointer;
+ transition: background-color 0.3s;
+}
+
+.promotion-item:hover {
+ background-color: #f0f0f0;
+}
+
+.promotion-item.active {
+ background-color: #e3f2fd;
+ border-left: 4px solid #2196F3;
+}
+
+.promotion-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 10px;
+}
+
+.promotion-type {
+ background-color: #2196F3;
+ color: white;
+ padding: 3px 8px;
+ border-radius: 12px;
+ font-size: 12px;
+}
+
+.promotion-dates {
+ color: #666;
+ font-size: 14px;
+ margin-bottom: 10px;
+}
+
+.promotion-coeffs {
+ display: flex;
+ gap: 15px;
+ font-weight: bold;
+}
+
+.promotion-coeffs span {
+ background-color: #e3f2fd;
+ padding: 3px 8px;
+ border-radius: 4px;
+}
+
+.promotion-details {
+ padding: 0 20px;
+}
+
+.detail-item {
+ margin-bottom: 15px;
+}
+
+.detail-item label {
+ font-weight: bold;
+ color: #555;
+}
+
+.detail-item span {
+ display: block;
+ margin-top: 5px;
+ padding: 8px;
+ background-color: #f5f5f5;
+ border-radius: 4px;
+}
+
+.no-promotions, .no-selection, .loading {
+ text-align: center;
+ padding: 40px;
+ color: #888;
+}
+
+.pagination {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 15px;
+ margin-top: 20px;
+}
+
+.pagination button {
+ padding: 5px 10px;
+ background-color: #f0f0f0;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ cursor: pointer;
+}
+
+.pagination button:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+
+.pagination span {
+ font-size: 14px;
+}
\ No newline at end of file
diff --git a/src/pages/PromotionsPage/PromotionsPage.jsx b/src/pages/PromotionsPage/PromotionsPage.jsx
new file mode 100644
index 0000000..bb50d72
--- /dev/null
+++ b/src/pages/PromotionsPage/PromotionsPage.jsx
@@ -0,0 +1,435 @@
+import React, { useState, useEffect } from 'react';
+import './PromotionsPage.css';
+
+const API_BASE = process.env.REACT_APP_API_BASE;
+function PromotionsPage() {
+ const [promotions, setPromotions] = useState([]);
+ const [currentPromotion, setCurrentPromotion] = useState(null);
+ const [isAdmin, setIsAdmin] = useState(false);
+ const [isLoading, setIsLoading] = useState(false);
+ const [error, setError] = useState(null);
+ const [formData, setFormData] = useState({
+ name: '',
+ uploadCoeff: 1,
+ downloadCoeff: 1,
+ timeRange: 0,
+ criteria: 1,
+ pStartTime: '',
+ pEndTime: ''
+ });
+ const [isCreating, setIsCreating] = useState(false);
+ const [currentPage, setCurrentPage] = useState(1);
+ const [perPage] = useState(10);
+ const [totalPromotions, setTotalPromotions] = useState(0);
+
+ const getAuthHeaders = () => {
+ const token = localStorage.getItem('token');
+ return {
+ 'Authorization': token ? `Bearer ${token}` : '',
+ 'Content-Type': 'application/json'
+ };
+ };
+
+ const fetchPromotions = async (page = 1) => {
+ setIsLoading(true);
+ try {
+ const response = await fetch(`${API_BASE}/promotions/list?page=${page}&per_page=${perPage}`, {
+ headers: getAuthHeaders()
+ });
+
+ if (!response.ok) {
+ throw new Error('获取促销活动失败');
+ }
+
+ const data = await response.json();
+ if (data.code === 0 && data.result) {
+ setPromotions(data.rows || []);
+ setTotalPromotions(data.total || 0);
+ } else {
+ throw new Error(data.msg || '获取促销活动失败');
+ }
+ } catch (err) {
+ console.error('获取促销活动错误:', err);
+ setError(err.message);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ const fetchPromotionDetails = async (promoId) => {
+ setIsLoading(true);
+ try {
+ const response = await fetch(`${API_BASE}/promotions/${promoId}`, {
+ headers: getAuthHeaders()
+ });
+
+ if (!response.ok) {
+ throw new Error('获取促销详情失败');
+ }
+
+ const data = await response.json();
+ if (data.code === 0 && data.result) {
+ setCurrentPromotion(data.rows);
+ } else {
+ throw new Error(data.msg || '获取促销详情失败');
+ }
+ } catch (err) {
+ console.error('获取促销详情错误:', err);
+ setError(err.message);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ const createPromotion = async () => {
+ if (!formData.name || !formData.pStartTime || !formData.pEndTime) {
+ alert('请填写完整活动信息');
+ return;
+ }
+
+ if (new Date(formData.pStartTime) >= new Date(formData.pEndTime)) {
+ alert('活动时间设置不正确,请重新设定');
+ return;
+ }
+
+ setIsLoading(true);
+ try {
+ const response = await fetch('${API_BASE}/promotions/add', {
+ method: 'POST',
+ headers: getAuthHeaders(),
+ body: JSON.stringify(formData)
+ });
+
+ if (!response.ok) {
+ throw new Error('创建促销活动失败');
+ }
+
+ const data = await response.json();
+ if (data.code === 0 && data.result) {
+ alert(`活动创建成功!活动ID: ${data.msg}`);
+ setIsCreating(false);
+ setFormData({
+ name: '',
+ uploadCoeff: 1,
+ downloadCoeff: 1,
+ timeRange: 0,
+ criteria: 1,
+ pStartTime: '',
+ pEndTime: ''
+ });
+ fetchPromotions();
+ } else {
+ throw new Error(data.msg || '创建促销活动失败');
+ }
+ } catch (err) {
+ console.error('创建促销活动错误:', err);
+ alert(err.message);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ const deletePromotion = async (promoId) => {
+ if (!window.confirm('确定要删除这个促销活动吗?')) {
+ return;
+ }
+
+ setIsLoading(true);
+ try {
+ const response = await fetch(`${API_BASE}/promotions/delete/${promoId}`, {
+ method: 'DELETE',
+ headers: getAuthHeaders()
+ });
+
+ if (!response.ok) {
+ throw new Error('删除促销活动失败');
+ }
+
+ const data = await response.json();
+ if (data.code === 0 && data.result) {
+ alert('促销活动删除成功');
+ fetchPromotions();
+ if (currentPromotion && currentPromotion.promoId === promoId) {
+ setCurrentPromotion(null);
+ }
+ } else {
+ throw new Error(data.msg || '删除促销活动失败');
+ }
+ } catch (err) {
+ console.error('删除促销活动错误:', err);
+ alert(err.message);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ const checkAdminStatus = () => {
+ const role = localStorage.getItem('role');
+ setIsAdmin(role === 'admin');
+ };
+
+ useEffect(() => {
+ checkAdminStatus();
+ fetchPromotions();
+ }, []);
+
+ const handleInputChange = (e) => {
+ const { name, value } = e.target;
+ setFormData(prev => ({
+ ...prev,
+ [name]: name === 'uploadCoeff' || name === 'downloadCoeff' || name === 'timeRange' || name === 'criteria'
+ ? parseFloat(value)
+ : value
+ }));
+ };
+
+ const handlePageChange = (newPage) => {
+ setCurrentPage(newPage);
+ fetchPromotions(newPage);
+ };
+
+ const getPromotionType = (promo) => {
+ if (promo.downloadCoeff === 0 && promo.uploadCoeff > 1) {
+ return '免费';
+ } else if (promo.downloadCoeff < 1 && promo.uploadCoeff > 1) {
+ return '折扣+上传奖励';
+ } else if (promo.downloadCoeff < 1) {
+ return '折扣';
+ } else if (promo.uploadCoeff > 1) {
+ return '上传奖励';
+ }
+ return '普通';
+ };
+
+ return (
+ <div className="promotions-page">
+ <div className="promotions-container">
+ <h1>促销活动</h1>
+
+ {isAdmin && (
+ <div className="admin-actions">
+ <button
+ className="create-button"
+ onClick={() => setIsCreating(!isCreating)}
+ >
+ {isCreating ? '取消创建' : '创建新活动'}
+ </button>
+ </div>
+ )}
+
+ {isCreating && isAdmin && (
+ <div className="create-promotion-form">
+ <h2>创建新促销活动</h2>
+ <div className="form-group">
+ <label>活动名称</label>
+ <input
+ type="text"
+ name="name"
+ value={formData.name}
+ onChange={handleInputChange}
+ placeholder="例如: 春节特惠"
+ />
+ </div>
+
+ <div className="form-row">
+ <div className="form-group">
+ <label>上传量系数</label>
+ <input
+ type="number"
+ name="uploadCoeff"
+ min="0"
+ step="0.1"
+ value={formData.uploadCoeff}
+ onChange={handleInputChange}
+ />
+ </div>
+
+ <div className="form-group">
+ <label>下载量系数</label>
+ <input
+ type="number"
+ name="downloadCoeff"
+ min="0"
+ step="0.1"
+ value={formData.downloadCoeff}
+ onChange={handleInputChange}
+ />
+ </div>
+ </div>
+
+ <div className="form-row">
+ <div className="form-group">
+ <label>资源时间范围</label>
+ <select
+ name="timeRange"
+ value={formData.timeRange}
+ onChange={handleInputChange}
+ >
+ <option value="0">全站资源</option>
+ <option value="1">当天上传</option>
+ <option value="2">最近两天</option>
+ <option value="7">最近一周</option>
+ <option value="30">最近一个月</option>
+ </select>
+ </div>
+
+ <div className="form-group">
+ <label>最低用户等级</label>
+ <input
+ type="number"
+ name="criteria"
+ min="1"
+ value={formData.criteria}
+ onChange={handleInputChange}
+ />
+ </div>
+ </div>
+
+ <div className="form-row">
+ <div className="form-group">
+ <label>开始时间</label>
+ <input
+ type="datetime-local"
+ name="pStartTime"
+ value={formData.pStartTime}
+ onChange={handleInputChange}
+ />
+ </div>
+
+ <div className="form-group">
+ <label>结束时间</label>
+ <input
+ type="datetime-local"
+ name="pEndTime"
+ value={formData.pEndTime}
+ onChange={handleInputChange}
+ />
+ </div>
+ </div>
+
+ <button
+ className="submit-button"
+ onClick={createPromotion}
+ disabled={isLoading}
+ >
+ {isLoading ? '创建中...' : '提交创建'}
+ </button>
+ </div>
+ )}
+
+ {error && <div className="error-message">{error}</div>}
+
+ <div className="promotions-grid">
+ {/* 促销活动列表 */}
+ <div className="promotions-list">
+ <h2>当前促销活动</h2>
+ {isLoading && promotions.length === 0 ? (
+ <div className="loading">加载中...</div>
+ ) : promotions.length === 0 ? (
+ <div className="no-promotions">暂无促销活动</div>
+ ) : (
+ <div className="promotion-items">
+ {promotions.map(promo => (
+ <div
+ key={promo.promoId}
+ className={`promotion-item ${currentPromotion && currentPromotion.promoId === promo.promoId ? 'active' : ''}`}
+ onClick={() => fetchPromotionDetails(promo.promoId)}
+ >
+ <div className="promotion-header">
+ <h3>{promo.name}</h3>
+ <span className="promotion-type">{getPromotionType(promo)}</span>
+ </div>
+ <div className="promotion-dates">
+ {new Date(promo.pStartTime).toLocaleString()} - {new Date(promo.pEndTime).toLocaleString()}
+ </div>
+ <div className="promotion-coeffs">
+ <span>上传: {promo.uploadCoeff}x</span>
+ <span>下载: {promo.downloadCoeff}x</span>
+ </div>
+ {isAdmin && (
+ <button
+ className="delete-button"
+ onClick={(e) => {
+ e.stopPropagation();
+ deletePromotion(promo.promoId);
+ }}
+ disabled={isLoading}
+ >
+ 删除
+ </button>
+ )}
+ </div>
+ ))}
+ </div>
+ )}
+
+ {totalPromotions > perPage && (
+ <div className="pagination">
+ <button
+ disabled={currentPage === 1}
+ onClick={() => handlePageChange(currentPage - 1)}
+ >
+ 上一页
+ </button>
+ <span>第 {currentPage} 页</span>
+ <button
+ disabled={currentPage * perPage >= totalPromotions}
+ onClick={() => handlePageChange(currentPage + 1)}
+ >
+ 下一页
+ </button>
+ </div>
+ )}
+ </div>
+
+ {/* 促销活动详情 */}
+ <div className="promotion-details">
+ {currentPromotion ? (
+ <>
+ <h2>{currentPromotion.name}</h2>
+ <div className="detail-item">
+ <label>活动ID:</label>
+ <span>{currentPromotion.promoId}</span>
+ </div>
+ <div className="detail-item">
+ <label>活动时间:</label>
+ <span>
+ {new Date(currentPromotion.pStartTime).toLocaleString()} - {new Date(currentPromotion.pEndTime).toLocaleString()}
+ </span>
+ </div>
+ <div className="detail-item">
+ <label>促销类型:</label>
+ <span>{getPromotionType(currentPromotion)}</span>
+ </div>
+ <div className="detail-item">
+ <label>上传量系数:</label>
+ <span>{currentPromotion.uploadCoeff}x</span>
+ </div>
+ <div className="detail-item">
+ <label>下载量系数:</label>
+ <span>{currentPromotion.downloadCoeff}x</span>
+ </div>
+ <div className="detail-item">
+ <label>适用资源:</label>
+ <span>
+ {currentPromotion.timeRange === 0
+ ? '全站资源'
+ : `最近${currentPromotion.timeRange}天内上传的资源`}
+ </span>
+ </div>
+ <div className="detail-item">
+ <label>参与条件:</label>
+ <span>用户等级 ≥ {currentPromotion.criteria}</span>
+ </div>
+ </>
+ ) : (
+ <div className="no-selection">请从左侧选择一个促销活动查看详情</div>
+ )}
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+}
+
+export default PromotionsPage;
\ No newline at end of file
diff --git a/src/pages/PublishSeed/PublishSeed.css b/src/pages/PublishSeed/PublishSeed.css
index 1cc4804..3c53352 100644
--- a/src/pages/PublishSeed/PublishSeed.css
+++ b/src/pages/PublishSeed/PublishSeed.css
@@ -70,7 +70,7 @@
}
.publish-seed-container {
- background: linear-gradient(180deg, #5F4437, #823c3c);
+ background: #333;
color: white;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
diff --git a/src/pages/SeedList/SeedDetail/SeedDetail.css b/src/pages/SeedList/SeedDetail/SeedDetail.css
index 641a4be..594cb8e 100644
--- a/src/pages/SeedList/SeedDetail/SeedDetail.css
+++ b/src/pages/SeedList/SeedDetail/SeedDetail.css
@@ -1,5 +1,5 @@
.seed-detail-page {
- background: linear-gradient(180deg, #5F4437, #823c3c);
+ background: #333;
font-family: 'Helvetica Neue', sans-serif;
color: #333;
}
diff --git a/src/pages/SeedList/SeedList.css b/src/pages/SeedList/SeedList.css
index aff93c3..f53a9a3 100644
--- a/src/pages/SeedList/SeedList.css
+++ b/src/pages/SeedList/SeedList.css
@@ -1,6 +1,6 @@
.seed-list-container {
- background: linear-gradient(180deg, #5F4437, #823c3c);
+ background: #333;
}
/* 搜索、排序控件 */
diff --git a/src/pages/UserCenter/UserProfile.css b/src/pages/UserCenter/UserProfile.css
index bcb1a2d..b63c408 100644
--- a/src/pages/UserCenter/UserProfile.css
+++ b/src/pages/UserCenter/UserProfile.css
@@ -4,7 +4,7 @@
font-family: Arial, sans-serif;
display: flex;
gap: 10%;
- background: linear-gradient(180deg, #5F4437, #823c3c);
+ background: #333;
}