add lint js
This commit is contained in:
@@ -4,7 +4,12 @@
|
|||||||
"es2021": true
|
"es2021": true
|
||||||
},
|
},
|
||||||
"extends": [
|
"extends": [
|
||||||
"plugin:react/recommended"
|
"eslint:recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"plugin:@typescript-eslint/stylistic",
|
||||||
|
"plugin:react/recommended",
|
||||||
|
"plugin:react-hooks/recommended",
|
||||||
|
"plugin:tailwindcss/recommended"
|
||||||
],
|
],
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaFeatures": {
|
"ecmaFeatures": {
|
||||||
@@ -19,30 +24,25 @@
|
|||||||
"tailwindcss"
|
"tailwindcss"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"react-hooks/rules-of-hooks": "error",
|
"no-undef": ["error", {"typeof": true}],
|
||||||
|
"react-hooks/exhaustive-deps": "off",
|
||||||
"react/react-in-jsx-scope": "off",
|
"react/react-in-jsx-scope": "off",
|
||||||
"react/button-has-type": "error",
|
|
||||||
"react/prop-types": "error",
|
|
||||||
"react/require-default-props": "off",
|
"react/require-default-props": "off",
|
||||||
"react/no-array-index-key": "error",
|
|
||||||
"react/jsx-uses-react": "error",
|
|
||||||
"react/display-name": "error",
|
|
||||||
"react/no-danger-with-children": "error",
|
|
||||||
// "react-hooks/exhaustive-deps": "warn",
|
|
||||||
// "react/jsx-no-bind": "error",
|
|
||||||
"react/jsx-uses-vars": "error",
|
|
||||||
"no-restricted-syntax": ["warn", {
|
|
||||||
"selector": "CallExpression[callee.object.name='console'][callee.property.name!=/^(warn|info)$/]",
|
|
||||||
"message": "Unexpected property on console object was called"
|
|
||||||
}],
|
|
||||||
"semi": [2, "never"],
|
"semi": [2, "never"],
|
||||||
"tailwindcss/classnames-order": "warn",
|
"tailwindcss/no-custom-classname": ["warn", {
|
||||||
|
"cssFiles": ["resources/css/app.css"],
|
||||||
|
"whitelist": []
|
||||||
|
}],
|
||||||
"tailwindcss/enforces-negative-arbitrary-values": "warn",
|
"tailwindcss/enforces-negative-arbitrary-values": "warn",
|
||||||
"tailwindcss/enforces-shorthand": "warn",
|
"tailwindcss/enforces-shorthand": "warn",
|
||||||
"tailwindcss/migration-from-tailwind-2": "warn",
|
"tailwindcss/migration-from-tailwind-2": "warn",
|
||||||
"tailwindcss/no-arbitrary-value": "off",
|
// "tailwindcss/no-arbitrary-value": "off",
|
||||||
|
// "tailwindcss/no-arbitrary-value": "error",
|
||||||
"tailwindcss/no-contradicting-classname": "error"
|
"tailwindcss/no-contradicting-classname": "error"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"react": {
|
||||||
|
"version": "18.2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dev.to/logrocket/12-essential-eslint-rules-for-react-5doc
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"@types/d3": "^7.4.3",
|
"@types/d3": "^7.4.3",
|
||||||
"@types/react": "^18.2.58",
|
"@types/react": "^18.2.58",
|
||||||
"@types/react-dom": "^18.2.19",
|
"@types/react-dom": "^18.2.19",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^7.1.1",
|
||||||
"@vite-pwa/assets-generator": "^0.0.11",
|
"@vite-pwa/assets-generator": "^0.0.11",
|
||||||
"@vitejs/plugin-react": "^4.2.1",
|
"@vitejs/plugin-react": "^4.2.1",
|
||||||
"autoprefixer": "^10.4.17",
|
"autoprefixer": "^10.4.17",
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"d3": "^7.8.5",
|
"d3": "^7.8.5",
|
||||||
|
"echarts": "^5.5.0",
|
||||||
"react-router-dom": "^6.22.1",
|
"react-router-dom": "^6.22.1",
|
||||||
"vite-plugin-pwa": "^0.17.5"
|
"vite-plugin-pwa": "^0.17.5"
|
||||||
}
|
}
|
||||||
|
|||||||
184
pnpm-lock.yaml
generated
184
pnpm-lock.yaml
generated
@@ -8,6 +8,9 @@ dependencies:
|
|||||||
d3:
|
d3:
|
||||||
specifier: ^7.8.5
|
specifier: ^7.8.5
|
||||||
version: 7.8.5
|
version: 7.8.5
|
||||||
|
echarts:
|
||||||
|
specifier: ^5.5.0
|
||||||
|
version: 5.5.0
|
||||||
react-router-dom:
|
react-router-dom:
|
||||||
specifier: ^6.22.1
|
specifier: ^6.22.1
|
||||||
version: 6.22.1(react-dom@18.2.0)(react@18.2.0)
|
version: 6.22.1(react-dom@18.2.0)(react@18.2.0)
|
||||||
@@ -28,6 +31,9 @@ devDependencies:
|
|||||||
'@types/react-dom':
|
'@types/react-dom':
|
||||||
specifier: ^18.2.19
|
specifier: ^18.2.19
|
||||||
version: 18.2.19
|
version: 18.2.19
|
||||||
|
'@typescript-eslint/eslint-plugin':
|
||||||
|
specifier: ^7.1.1
|
||||||
|
version: 7.1.1(@typescript-eslint/parser@7.1.1)(eslint@8.57.0)(typescript@5.3.3)
|
||||||
'@vite-pwa/assets-generator':
|
'@vite-pwa/assets-generator':
|
||||||
specifier: ^0.0.11
|
specifier: ^0.0.11
|
||||||
version: 0.0.11
|
version: 0.0.11
|
||||||
@@ -1887,6 +1893,10 @@ packages:
|
|||||||
'@types/node': 20.11.20
|
'@types/node': 20.11.20
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/json-schema@7.0.15:
|
||||||
|
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/minimatch@5.1.2:
|
/@types/minimatch@5.1.2:
|
||||||
resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==}
|
resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -1924,10 +1934,146 @@ packages:
|
|||||||
resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==}
|
resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/semver@7.5.8:
|
||||||
|
resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/trusted-types@2.0.7:
|
/@types/trusted-types@2.0.7:
|
||||||
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
|
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@typescript-eslint/eslint-plugin@7.1.1(@typescript-eslint/parser@7.1.1)(eslint@8.57.0)(typescript@5.3.3):
|
||||||
|
resolution: {integrity: sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==}
|
||||||
|
engines: {node: ^16.0.0 || >=18.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
'@typescript-eslint/parser': ^7.0.0
|
||||||
|
eslint: ^8.56.0
|
||||||
|
typescript: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@eslint-community/regexpp': 4.10.0
|
||||||
|
'@typescript-eslint/parser': 7.1.1(eslint@8.57.0)(typescript@5.3.3)
|
||||||
|
'@typescript-eslint/scope-manager': 7.1.1
|
||||||
|
'@typescript-eslint/type-utils': 7.1.1(eslint@8.57.0)(typescript@5.3.3)
|
||||||
|
'@typescript-eslint/utils': 7.1.1(eslint@8.57.0)(typescript@5.3.3)
|
||||||
|
'@typescript-eslint/visitor-keys': 7.1.1
|
||||||
|
debug: 4.3.4
|
||||||
|
eslint: 8.57.0
|
||||||
|
graphemer: 1.4.0
|
||||||
|
ignore: 5.3.1
|
||||||
|
natural-compare: 1.4.0
|
||||||
|
semver: 7.6.0
|
||||||
|
ts-api-utils: 1.2.1(typescript@5.3.3)
|
||||||
|
typescript: 5.3.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/parser@7.1.1(eslint@8.57.0)(typescript@5.3.3):
|
||||||
|
resolution: {integrity: sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==}
|
||||||
|
engines: {node: ^16.0.0 || >=18.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
eslint: ^8.56.0
|
||||||
|
typescript: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@typescript-eslint/scope-manager': 7.1.1
|
||||||
|
'@typescript-eslint/types': 7.1.1
|
||||||
|
'@typescript-eslint/typescript-estree': 7.1.1(typescript@5.3.3)
|
||||||
|
'@typescript-eslint/visitor-keys': 7.1.1
|
||||||
|
debug: 4.3.4
|
||||||
|
eslint: 8.57.0
|
||||||
|
typescript: 5.3.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/scope-manager@7.1.1:
|
||||||
|
resolution: {integrity: sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==}
|
||||||
|
engines: {node: ^16.0.0 || >=18.0.0}
|
||||||
|
dependencies:
|
||||||
|
'@typescript-eslint/types': 7.1.1
|
||||||
|
'@typescript-eslint/visitor-keys': 7.1.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/type-utils@7.1.1(eslint@8.57.0)(typescript@5.3.3):
|
||||||
|
resolution: {integrity: sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==}
|
||||||
|
engines: {node: ^16.0.0 || >=18.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
eslint: ^8.56.0
|
||||||
|
typescript: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@typescript-eslint/typescript-estree': 7.1.1(typescript@5.3.3)
|
||||||
|
'@typescript-eslint/utils': 7.1.1(eslint@8.57.0)(typescript@5.3.3)
|
||||||
|
debug: 4.3.4
|
||||||
|
eslint: 8.57.0
|
||||||
|
ts-api-utils: 1.2.1(typescript@5.3.3)
|
||||||
|
typescript: 5.3.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/types@7.1.1:
|
||||||
|
resolution: {integrity: sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==}
|
||||||
|
engines: {node: ^16.0.0 || >=18.0.0}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/typescript-estree@7.1.1(typescript@5.3.3):
|
||||||
|
resolution: {integrity: sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==}
|
||||||
|
engines: {node: ^16.0.0 || >=18.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
typescript: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@typescript-eslint/types': 7.1.1
|
||||||
|
'@typescript-eslint/visitor-keys': 7.1.1
|
||||||
|
debug: 4.3.4
|
||||||
|
globby: 11.1.0
|
||||||
|
is-glob: 4.0.3
|
||||||
|
minimatch: 9.0.3
|
||||||
|
semver: 7.6.0
|
||||||
|
ts-api-utils: 1.2.1(typescript@5.3.3)
|
||||||
|
typescript: 5.3.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/utils@7.1.1(eslint@8.57.0)(typescript@5.3.3):
|
||||||
|
resolution: {integrity: sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==}
|
||||||
|
engines: {node: ^16.0.0 || >=18.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
eslint: ^8.56.0
|
||||||
|
dependencies:
|
||||||
|
'@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
|
||||||
|
'@types/json-schema': 7.0.15
|
||||||
|
'@types/semver': 7.5.8
|
||||||
|
'@typescript-eslint/scope-manager': 7.1.1
|
||||||
|
'@typescript-eslint/types': 7.1.1
|
||||||
|
'@typescript-eslint/typescript-estree': 7.1.1(typescript@5.3.3)
|
||||||
|
eslint: 8.57.0
|
||||||
|
semver: 7.6.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
- typescript
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/visitor-keys@7.1.1:
|
||||||
|
resolution: {integrity: sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==}
|
||||||
|
engines: {node: ^16.0.0 || >=18.0.0}
|
||||||
|
dependencies:
|
||||||
|
'@typescript-eslint/types': 7.1.1
|
||||||
|
eslint-visitor-keys: 3.4.3
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@ungap/structured-clone@1.2.0:
|
/@ungap/structured-clone@1.2.0:
|
||||||
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
|
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -2825,6 +2971,13 @@ packages:
|
|||||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/echarts@5.5.0:
|
||||||
|
resolution: {integrity: sha512-rNYnNCzqDAPCr4m/fqyUFv7fD9qIsd50S6GDFgO1DxZhncCsNsG7IfUlAlvZe5oSEQxtsjnHiUuppzccry93Xw==}
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.3.0
|
||||||
|
zrender: 5.5.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/ejs@3.1.9:
|
/ejs@3.1.9:
|
||||||
resolution: {integrity: sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==}
|
resolution: {integrity: sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -3386,6 +3539,18 @@ packages:
|
|||||||
slash: 3.0.0
|
slash: 3.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/globby@11.1.0:
|
||||||
|
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
dependencies:
|
||||||
|
array-union: 2.1.0
|
||||||
|
dir-glob: 3.0.1
|
||||||
|
fast-glob: 3.3.2
|
||||||
|
ignore: 5.3.1
|
||||||
|
merge2: 1.4.1
|
||||||
|
slash: 3.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/gopd@1.0.1:
|
/gopd@1.0.1:
|
||||||
resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
|
resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4993,10 +5158,23 @@ packages:
|
|||||||
punycode: 2.3.1
|
punycode: 2.3.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/ts-api-utils@1.2.1(typescript@5.3.3):
|
||||||
|
resolution: {integrity: sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==}
|
||||||
|
engines: {node: '>=16'}
|
||||||
|
peerDependencies:
|
||||||
|
typescript: '>=4.2.0'
|
||||||
|
dependencies:
|
||||||
|
typescript: 5.3.3
|
||||||
|
dev: true
|
||||||
|
|
||||||
/ts-interface-checker@0.1.13:
|
/ts-interface-checker@0.1.13:
|
||||||
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
|
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/tslib@2.3.0:
|
||||||
|
resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/tunnel-agent@0.6.0:
|
/tunnel-agent@0.6.0:
|
||||||
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
|
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -5462,3 +5640,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/zrender@5.5.0:
|
||||||
|
resolution: {integrity: sha512-O3MilSi/9mwoovx77m6ROZM7sXShR/O/JIanvzTwjN3FORfLSr81PsUGd7jlaYOeds9d8tw82oP44+3YucVo+w==}
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.3.0
|
||||||
|
dev: false
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React, {FC} from "react";
|
import React, {FC} from "react"
|
||||||
import {PropsWithChildren} from "react";
|
import {PropsWithChildren} from "react"
|
||||||
|
|
||||||
const Card: FC<PropsWithChildren<CardProps>> = ({children, className = ''}) => {
|
const Card: FC<PropsWithChildren<CardProps>> = ({children, className = ''}) => {
|
||||||
|
|
||||||
return <div className={`${className} border m-1 rounded py-1 px-2`}>
|
return <div className={`${className} m-1 rounded border px-2 py-1`}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const Field: FC<FieldProps> = ({children, type = 'text', className = '', ...prop
|
|||||||
htmlFor={props.id ?? undefined}>
|
htmlFor={props.id ?? undefined}>
|
||||||
{children}
|
{children}
|
||||||
</label>}
|
</label>}
|
||||||
<input className={`${className} w-full mt-2 rounded dark:bg-gray-700`}
|
<input className={`${className} mt-2 w-full rounded dark:bg-gray-700`}
|
||||||
type={type}
|
type={type}
|
||||||
{...props}/>
|
{...props}/>
|
||||||
<div className={`error-message`} />
|
<div className={`error-message`} />
|
||||||
@@ -24,7 +24,7 @@ interface FieldProps {
|
|||||||
type?: HTMLInputTypeAttribute,
|
type?: HTMLInputTypeAttribute,
|
||||||
name: string,
|
name: string,
|
||||||
id?: string,
|
id?: string,
|
||||||
value: any,
|
value?: string|number|undefined,
|
||||||
placeholder?: string,
|
placeholder?: string,
|
||||||
autoFocus?: boolean,
|
autoFocus?: boolean,
|
||||||
className?: string,
|
className?: string,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const Header = () => {
|
|||||||
const {authUser} = useAuthUser()
|
const {authUser} = useAuthUser()
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
|
|
||||||
return <header className="flex justify-between py-3 px-5 bg-blue-700 text-white text-xl">
|
return <header className="flex justify-between bg-blue-700 px-5 py-3 text-xl text-white">
|
||||||
<div>
|
<div>
|
||||||
<Link to="/">Bermite</Link>
|
<Link to="/">Bermite</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, {FC} from "react";
|
import React, {FC} from "react"
|
||||||
|
|
||||||
const Img: FC<{src: string, alt: string, width: string}> = ({src, alt, width, ...props}) => {
|
const Img: FC<{src: string, alt: string, width: string}> = ({src, alt, width, ...props}) => {
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, {Dispatch, FC, FormEvent, SetStateAction, useState} from "react"
|
import React, {Dispatch, FC, FormEvent, SetStateAction, useState} from "react"
|
||||||
import useAxiosTools from "../../hooks/AxiosTools";
|
import useAxiosTools from "../../hooks/AxiosTools"
|
||||||
import Field from "../Field";
|
import Field from "../Field"
|
||||||
import Card from "../Card";
|
import Card from "../Card"
|
||||||
|
|
||||||
const AddRainfall: FC<AddRainfallProps> = ({reload}) => {
|
const AddRainfall: FC<AddRainfallProps> = ({reload}) => {
|
||||||
|
|
||||||
@@ -23,12 +23,12 @@ const AddRainfall: FC<AddRainfallProps> = ({reload}) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Card className="min-w-[300px] overflow-hidden self-start w-full md:w-auto">
|
return <Card className="w-full min-w-[300px] self-start overflow-hidden md:w-auto">
|
||||||
<h2 className="text-center bg-blue-500 text-white -mx-2 -mt-1 text-lg font-bold px-2 py-1">
|
<h2 className="-mx-2 -mt-1 bg-blue-500 px-2 py-1 text-center text-lg font-bold text-white">
|
||||||
Ajout d'une mesure
|
Ajout d'une mesure
|
||||||
</h2>
|
</h2>
|
||||||
{errorLabel()}
|
{errorLabel()}
|
||||||
<form onSubmit={handleSubmit} className="p-2 flex flex-col gap-2">
|
<form onSubmit={handleSubmit} className="flex flex-col gap-2 p-2">
|
||||||
<Field type="date"
|
<Field type="date"
|
||||||
name="date"
|
name="date"
|
||||||
value={data.date}
|
value={data.date}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React, {FC, useEffect, useState} from "react"
|
import React, {FC, useEffect, useState} from "react"
|
||||||
import useAxiosTools from "../../hooks/AxiosTools";
|
import useAxiosTools from "../../hooks/AxiosTools"
|
||||||
import {rainfall} from "../../types";
|
import {rainfall} from "../../types"
|
||||||
import {AxiosError} from "axios";
|
import {AxiosError} from "axios"
|
||||||
import Card from "../Card";
|
import Card from "../Card"
|
||||||
import {Link} from "react-router-dom";
|
import {Link} from "react-router-dom"
|
||||||
|
|
||||||
const LastFiveMesure: FC<LastFiveMesureProps> = ({loadedAt}) => {
|
const LastFiveMesure: FC<LastFiveMesureProps> = ({loadedAt}) => {
|
||||||
|
|
||||||
@@ -27,14 +27,14 @@ const LastFiveMesure: FC<LastFiveMesureProps> = ({loadedAt}) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Card className="min-w-[300px] overflow-hidden self-start w-full md:w-auto">
|
return <Card className="w-full min-w-[300px] self-start overflow-hidden md:w-auto">
|
||||||
<h1 className="text-center bg-blue-500 text-white -mx-2 -mt-1 text-lg font-bold px-2 py-1">5 dernières mesures</h1>
|
<h1 className="-mx-2 -mt-1 bg-blue-500 px-2 py-1 text-center text-lg font-bold text-white">5 dernières mesures</h1>
|
||||||
{errorLabel()}
|
{errorLabel()}
|
||||||
<table className="w-full text-center">
|
<table className="w-full text-center">
|
||||||
<tbody>
|
<tbody>
|
||||||
{data.map(line => <tr key={line.id} className="">
|
{data.map(line => <tr key={line.id} className="">
|
||||||
<td>{(new Date(line.date)).toLocaleDateString()}</td>
|
<td>{(new Date(line.date)).toLocaleDateString()}</td>
|
||||||
<td className="text-right px-2">{line.value}</td>
|
<td className="px-2 text-right">{line.value}</td>
|
||||||
</tr>)}
|
</tr>)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
122
resources/js/components/rainfall/RainFallEcharts.tsx
Normal file
122
resources/js/components/rainfall/RainFallEcharts.tsx
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
import React, {FC, useEffect, useRef, useState} from "react"
|
||||||
|
import {rainfallGraphData} from "../../types"
|
||||||
|
import {init, getInstanceByDom} from 'echarts'
|
||||||
|
import type {ECharts } from "echarts"
|
||||||
|
|
||||||
|
const RainFallEcharts: FC<RainFallEchartsProps> = ({width, height, data, loading}) => {
|
||||||
|
|
||||||
|
// https://dev.to/manufac/using-apache-echarts-with-react-and-typescript-353k
|
||||||
|
const chartRef = useRef<HTMLDivElement>(null)
|
||||||
|
const [option, setOption] = useState({
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
data: data.map(d => d.label),
|
||||||
|
axisTick: {
|
||||||
|
alignWithLabel: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Pluviométrie',
|
||||||
|
type: 'bar',
|
||||||
|
color: ['steelblue'],
|
||||||
|
barWidth: '80%',
|
||||||
|
data: data.map(d => d.value)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let chart: ECharts | undefined
|
||||||
|
console.log('in', width, height)
|
||||||
|
if (chartRef.current !== null) {
|
||||||
|
chart = init(chartRef.current)
|
||||||
|
}
|
||||||
|
|
||||||
|
function resizeChart() {
|
||||||
|
chart?.resize()
|
||||||
|
}
|
||||||
|
window.addEventListener("resize", resizeChart)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
chart?.dispose()
|
||||||
|
window.removeEventListener("resize", resizeChart)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('data')
|
||||||
|
if (chartRef.current !== null) {
|
||||||
|
console.log('data', data)
|
||||||
|
const chart = getInstanceByDom(chartRef.current)
|
||||||
|
chart?.setOption(option)
|
||||||
|
}
|
||||||
|
}, [option, data])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setOption({...option,
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
data: data.map(d => d.label),
|
||||||
|
axisTick: {
|
||||||
|
alignWithLabel: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Pluviométrie',
|
||||||
|
type: 'bar',
|
||||||
|
color: ['steelblue'],
|
||||||
|
barWidth: '80%',
|
||||||
|
data: data.map(d => d.value)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}, [data])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (chartRef.current !== null) {
|
||||||
|
const chart = getInstanceByDom(chartRef.current)
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||||
|
loading === true ? chart?.showLoading() : chart?.hideLoading()
|
||||||
|
}
|
||||||
|
}, [loading])
|
||||||
|
|
||||||
|
return <div className="relative">
|
||||||
|
<div ref={chartRef} style={{width: "100%", height}} />
|
||||||
|
<div id="tooltip" className="absolute left-10 top-3 rounded border p-2" style={{opacity: 0}}></div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RainFallEcharts
|
||||||
|
|
||||||
|
interface RainFallEchartsProps {
|
||||||
|
width: number,
|
||||||
|
height: number,
|
||||||
|
data: rainfallGraphData[],
|
||||||
|
loading: boolean,
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as d3 from "d3"
|
import * as d3 from "d3"
|
||||||
import React, {FC, LegacyRef, useEffect, useRef} from "react"
|
import React, {FC, useEffect, useRef} from "react"
|
||||||
import {rainfall, rainfallGraphData} from "../../types";
|
import {rainfallGraphData} from "../../types"
|
||||||
|
|
||||||
const RainfallGraph: FC<RainfallGraphProps> = ({width, height, data, start_date, end_date}) => {
|
const RainfallGraph: FC<RainfallGraphProps> = ({width, height, data, start_date, end_date}) => {
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ const RainfallGraph: FC<RainfallGraphProps> = ({width, height, data, start_date,
|
|||||||
.call(d3.axisBottom(x)
|
.call(d3.axisBottom(x)
|
||||||
.ticks(8)
|
.ticks(8)
|
||||||
.tickFormat(
|
.tickFormat(
|
||||||
// @ts-ignore
|
// @ts-expect-error change time format
|
||||||
d3.timeFormat("%d/%m/%Y")
|
d3.timeFormat("%d/%m/%Y")
|
||||||
)
|
)
|
||||||
, 0)
|
, 0)
|
||||||
@@ -101,7 +101,7 @@ const RainfallGraph: FC<RainfallGraphProps> = ({width, height, data, start_date,
|
|||||||
|
|
||||||
return <div className="relative">
|
return <div className="relative">
|
||||||
<svg ref={svgRef} />
|
<svg ref={svgRef} />
|
||||||
<div id="tooltip" className="absolute px-2 py-2 top-3 left-10 rounded border" style={{opacity: 0}}></div>
|
<div id="tooltip" className="absolute left-10 top-3 rounded border p-2" style={{opacity: 0}}></div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const weekDays = ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi']
|
const weekDays = ['dimanche', 'lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi']
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
interface Date {
|
interface Date {
|
||||||
getWeekDay(): string,
|
getWeekDay(): string,
|
||||||
toSQLDate(): string,
|
toSQLDate(): string,
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import React, {
|
|||||||
useContext,
|
useContext,
|
||||||
useEffect,
|
useEffect,
|
||||||
useState
|
useState
|
||||||
} from "react";
|
} from "react"
|
||||||
import axios from "axios";
|
import axios from "axios"
|
||||||
|
|
||||||
const AuthUserContext = createContext<AuthUserProps|undefined>(undefined)
|
const AuthUserContext = createContext<AuthUserProps|undefined>(undefined)
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ export const AuthUserProvider = ({children}: PropsWithChildren) => {
|
|||||||
const res = await axios.get('/api/user')
|
const res = await axios.get('/api/user')
|
||||||
setAuthUser(res.data)
|
setAuthUser(res.data)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// @ts-ignore
|
// @ts-expect-error check axios response status
|
||||||
if (e.response.status === 401) {
|
if (e.response.status === 401) {
|
||||||
console.info('no user login')
|
console.info('no user login')
|
||||||
if (window.location.pathname !== '/connexion') {
|
if (window.location.pathname !== '/connexion') {
|
||||||
@@ -44,7 +44,7 @@ export const AuthUserProvider = ({children}: PropsWithChildren) => {
|
|||||||
const logout = async () => {
|
const logout = async () => {
|
||||||
try {
|
try {
|
||||||
setLoadingAuthUser(false)
|
setLoadingAuthUser(false)
|
||||||
const res = await axios.delete('/api/logout')
|
await axios.delete('/api/logout')
|
||||||
setAuthUser(null)
|
setAuthUser(null)
|
||||||
window.location.replace('/')
|
window.location.replace('/')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -1,29 +1,31 @@
|
|||||||
import {useState} from "react";
|
import {useState} from "react"
|
||||||
import axios from "axios";
|
import axios, {AxiosError} from "axios"
|
||||||
import React from "react";
|
import React from "react"
|
||||||
import {cleanErrorsForm, displayFormErrors} from "../utilities/form";
|
import {cleanErrorsForm, displayFormErrors, ValidationErrors} from "../utilities/form"
|
||||||
|
|
||||||
const useAxiosTools = () => {
|
const useAxiosTools = () => {
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [error, setError] = useState<string|null>(null)
|
const [error, setError] = useState<string|null|undefined>(null)
|
||||||
|
|
||||||
const axiosGet = axios.get
|
const axiosGet = axios.get
|
||||||
const axiosPost = axios.post
|
const axiosPost = axios.post
|
||||||
const axiosPut = axios.put
|
const axiosPut = axios.put
|
||||||
const axiosDelete = axios.delete
|
const axiosDelete = axios.delete
|
||||||
|
|
||||||
const errorCatch = (error: any) => {
|
const errorCatch = (error: Error|AxiosError|unknown) => {
|
||||||
if (error.response && error.response.status === 422) {
|
if (axios.isAxiosError(error)) {
|
||||||
displayFormErrors(error)
|
(error.response?.status === 422)
|
||||||
} else {
|
? displayFormErrors(error)
|
||||||
setError(error.response?.data.message || error.message)
|
: setError(error.response?.data.message || error.message)
|
||||||
|
} else if (error instanceof Error) {
|
||||||
|
setError(error.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const errorLabel = () => {
|
const errorLabel = () => {
|
||||||
|
|
||||||
return error ? <div className="bg-red-600 rounded m-2 text-center text-white px-2 py-1 mx-auto">{error}</div>: null
|
return error ? <div className="m-2 mx-auto rounded bg-red-600 px-2 py-1 text-center text-white">{error}</div>: null
|
||||||
}
|
}
|
||||||
|
|
||||||
const cleanErrors = () => {
|
const cleanErrors = () => {
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ const useDimension = () => {
|
|||||||
|
|
||||||
const RESET_TIMEOUT = 300
|
const RESET_TIMEOUT = 300
|
||||||
let movement_timer: number|undefined = undefined
|
let movement_timer: number|undefined = undefined
|
||||||
const targetRef = useRef<any>()
|
const targetRef = useRef<HTMLDivElement>()
|
||||||
const [dimensions, setDimensions] = useState({ width:0, height: 0 })
|
const [dimensions, setDimensions] = useState({ width:0, height: 0 })
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener('resize', ()=>{
|
window.addEventListener('resize', ()=>{
|
||||||
clearInterval(movement_timer)
|
clearInterval(movement_timer)
|
||||||
|
// @ts-expect-error setTimeout defined in var
|
||||||
movement_timer = setTimeout(testDimensions, RESET_TIMEOUT)
|
movement_timer = setTimeout(testDimensions, RESET_TIMEOUT)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
import React, {FormEvent, SyntheticEvent, useState} from "react"
|
import React, {FormEvent, useState} from "react"
|
||||||
import Field from "../../components/Field";
|
import Field from "../../components/Field"
|
||||||
import axios from "axios";
|
import useAxiosTools from "../../hooks/AxiosTools"
|
||||||
import {useNavigate} from "react-router-dom";
|
|
||||||
import useAuthUser from "../../hooks/AuthUser";
|
|
||||||
import useAxiosTools from "../../hooks/AxiosTools";
|
|
||||||
|
|
||||||
const ForgotPassword = () => {
|
const ForgotPassword = () => {
|
||||||
|
|
||||||
@@ -16,15 +13,15 @@ const ForgotPassword = () => {
|
|||||||
try {
|
try {
|
||||||
cleanErrors()
|
cleanErrors()
|
||||||
await axiosGet('/sanctum/csrf-cookie')
|
await axiosGet('/sanctum/csrf-cookie')
|
||||||
const res = await axiosPost('/api/forgot', {email})
|
await axiosPost('/api/forgot', {email})
|
||||||
setMessage(true)
|
setMessage(true)
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
errorCatch(e)
|
errorCatch(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<form onSubmit={handleSubmit} className="w-96 mx-auto mt-10 border shadow p-3">
|
<form onSubmit={handleSubmit} className="mx-auto mt-10 w-96 border p-3 shadow">
|
||||||
<h1 className="text-center">Mot de passe oublié</h1>
|
<h1 className="text-center">Mot de passe oublié</h1>
|
||||||
|
|
||||||
{message && <p className="bg-green-600">Un email vous a été envoyé pour modifier le mot de passe.</p>}
|
{message && <p className="bg-green-600">Un email vous a été envoyé pour modifier le mot de passe.</p>}
|
||||||
@@ -37,7 +34,7 @@ const ForgotPassword = () => {
|
|||||||
value={email}
|
value={email}
|
||||||
onChange={event => setEmail(event.target.value)}
|
onChange={event => setEmail(event.target.value)}
|
||||||
autoFocus>Email</Field>
|
autoFocus>Email</Field>
|
||||||
<button type="submit" className="mt-5 btn-primary w-full block text-lg">Valider</button>
|
<button type="submit" className="btn-primary mt-5 block w-full text-lg">Valider</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import React, {FormEvent, SyntheticEvent, useState} from "react"
|
import React, {FormEvent, useState} from "react"
|
||||||
import Field from "../../components/Field";
|
import Field from "../../components/Field"
|
||||||
import axios from "axios";
|
import {Link, useNavigate} from "react-router-dom"
|
||||||
import {Link, useNavigate} from "react-router-dom";
|
import useAuthUser from "../../hooks/AuthUser"
|
||||||
import useAuthUser from "../../hooks/AuthUser";
|
import Card from "../../components/Card"
|
||||||
import Card from "../../components/Card";
|
import useAxiosTools from "../../hooks/AxiosTools"
|
||||||
import useAxiosTools from "../../hooks/AxiosTools";
|
|
||||||
|
|
||||||
const Login = () => {
|
const Login = () => {
|
||||||
|
|
||||||
@@ -22,15 +21,15 @@ const Login = () => {
|
|||||||
const res = await axiosPost('/api/login', {email, password})
|
const res = await axiosPost('/api/login', {email, password})
|
||||||
setAuthUser(res.data.user)
|
setAuthUser(res.data.user)
|
||||||
navigate('/')
|
navigate('/')
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
errorCatch(e)
|
errorCatch(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<Card className="w-96 mx-auto mt-10 p-2 overflow-hidden">
|
<Card className="mx-auto mt-10 w-96 overflow-hidden p-2">
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<h1 className="text-center bg-blue-500 -mx-2 -mt-1 text-lg font-bold px-2 py-1 mb-2">
|
<h1 className="-mx-2 -mt-1 mb-2 bg-blue-500 px-2 py-1 text-center text-lg font-bold">
|
||||||
Connexion
|
Connexion
|
||||||
</h1>
|
</h1>
|
||||||
{errorLabel()}
|
{errorLabel()}
|
||||||
@@ -46,7 +45,7 @@ const Login = () => {
|
|||||||
placeholder="******"
|
placeholder="******"
|
||||||
value={password}
|
value={password}
|
||||||
onChange={event => setPassword(event.target.value)}>Mot de passe</Field>
|
onChange={event => setPassword(event.target.value)}>Mot de passe</Field>
|
||||||
<button type="submit" className="mt-5 btn-primary w-full block text-lg">Valider</button>
|
<button type="submit" className="btn-primary mt-5 block w-full text-lg">Valider</button>
|
||||||
<Link to="/mot-de-passe-oubliee" className="mt-2 inline-block">Mot de passe oublié ?</Link>
|
<Link to="/mot-de-passe-oubliee" className="mt-2 inline-block">Mot de passe oublié ?</Link>
|
||||||
</form>
|
</form>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React, {FormEvent, useState} from "react"
|
import React, {FormEvent, useState} from "react"
|
||||||
import useAuthUser from "../../hooks/AuthUser"
|
import useAuthUser from "../../hooks/AuthUser"
|
||||||
import PageLayout from "../../components/PageLayout"
|
import PageLayout from "../../components/PageLayout"
|
||||||
import Card from "../../components/Card";
|
import Card from "../../components/Card"
|
||||||
import Field from "../../components/Field";
|
import Field from "../../components/Field"
|
||||||
import useAxiosTools from "../../hooks/AxiosTools";
|
import useAxiosTools from "../../hooks/AxiosTools"
|
||||||
|
|
||||||
const Profile = () => {
|
const Profile = () => {
|
||||||
|
|
||||||
@@ -18,8 +18,8 @@ const Profile = () => {
|
|||||||
try {
|
try {
|
||||||
const res = await axiosPost(`/api/locations`, {latitude, longitude})
|
const res = await axiosPost(`/api/locations`, {latitude, longitude})
|
||||||
setAuthUser(res.data)
|
setAuthUser(res.data)
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
errorCatch(e)
|
errorCatch(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ const Profile = () => {
|
|||||||
Longitude
|
Longitude
|
||||||
</Field>
|
</Field>
|
||||||
<div className="self-end">
|
<div className="self-end">
|
||||||
<button type="submit" className="btn-primary w-24 h-10">Valider</button>
|
<button type="submit" className="btn-primary h-10 w-24">Valider</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>}
|
</form>}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React, {ChangeEvent, FormEvent, SyntheticEvent, useState} from "react"
|
import React, {FormEvent, useState} from "react"
|
||||||
import Field from "../../components/Field";
|
import Field from "../../components/Field"
|
||||||
import axios from "axios";
|
import axios from "axios"
|
||||||
import {useNavigate} from "react-router-dom";
|
import {useNavigate} from "react-router-dom"
|
||||||
import Card from "../../components/Card";
|
import Card from "../../components/Card"
|
||||||
|
|
||||||
const Register = () => {
|
const Register = () => {
|
||||||
|
|
||||||
@@ -15,18 +15,18 @@ const Register = () => {
|
|||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
try {
|
try {
|
||||||
await axios.get('/sanctum/csrf-cookie')
|
await axios.get('/sanctum/csrf-cookie')
|
||||||
const res = await axios.post('/api/register', {name, email, password})
|
await axios.post('/api/register', {name, email, password})
|
||||||
navigate('/')
|
navigate('/')
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
console.error(e)
|
console.error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<Card className="w-96 mx-auto mt-10 p-2 overflow-hidden">
|
<Card className="mx-auto mt-10 w-96 overflow-hidden p-2">
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<h1 className="text-center bg-blue-500 -mx-2 -mt-1 text-lg font-bold px-2 py-1 mb-2">
|
<h1 className="-mx-2 -mt-1 mb-2 bg-blue-500 px-2 py-1 text-center text-lg font-bold">
|
||||||
S'inscrire
|
S'inscrire
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<Field placeholder="Nom"
|
<Field placeholder="Nom"
|
||||||
@@ -46,7 +46,7 @@ const Register = () => {
|
|||||||
value={password}
|
value={password}
|
||||||
onChange={event => setPassword(event.target.value)}
|
onChange={event => setPassword(event.target.value)}
|
||||||
autoFocus>Mot de passe</Field>
|
autoFocus>Mot de passe</Field>
|
||||||
<button type="submit" className="mt-5 btn-primary w-full block text-lg">Valider</button>
|
<button type="submit" className="btn-primary mt-5 block w-full text-lg">Valider</button>
|
||||||
</form>
|
</form>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
import PageLayout from "../../components/PageLayout";
|
import Field from "../../components/Field"
|
||||||
import Field from "../../components/Field";
|
import React, {FormEvent, useState} from "react"
|
||||||
import React, {FormEvent, useState} from "react";
|
import {useNavigate, useParams} from "react-router-dom"
|
||||||
import {useNavigate, useParams} from "react-router-dom";
|
import useAuthUser from "../../hooks/AuthUser"
|
||||||
import useAuthUser from "../../hooks/AuthUser";
|
import useAxiosTools from "../../hooks/AxiosTools"
|
||||||
import axios from "axios";
|
|
||||||
import useAxiosTools from "../../hooks/AxiosTools";
|
|
||||||
|
|
||||||
const Reset = () => {
|
const Reset = () => {
|
||||||
|
|
||||||
let {token} = useParams()
|
const {token} = useParams()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const {setAuthUser} = useAuthUser()
|
const {setAuthUser} = useAuthUser()
|
||||||
const [email, setEmail] = useState('')
|
const [email, setEmail] = useState('')
|
||||||
@@ -24,13 +22,13 @@ const Reset = () => {
|
|||||||
const res = await axiosPost('/api/reset', {email, token, password, samePassword})
|
const res = await axiosPost('/api/reset', {email, token, password, samePassword})
|
||||||
setAuthUser(res.data.user)
|
setAuthUser(res.data.user)
|
||||||
navigate('/connexion')
|
navigate('/connexion')
|
||||||
} catch (e) {
|
} catch (error) {
|
||||||
errorCatch(e)
|
errorCatch(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<form onSubmit={handleSubmit} className="w-96 mx-auto mt-10 border shadow p-3">
|
<form onSubmit={handleSubmit} className="mx-auto mt-10 w-96 border p-3 shadow">
|
||||||
<h1 className="text-center">Modifier voter mot de passe</h1>
|
<h1 className="text-center">Modifier voter mot de passe</h1>
|
||||||
|
|
||||||
{errorLabel()}
|
{errorLabel()}
|
||||||
@@ -51,7 +49,7 @@ const Reset = () => {
|
|||||||
placeholder="******"
|
placeholder="******"
|
||||||
value={samePassword}
|
value={samePassword}
|
||||||
onChange={event => setSamePassword(event.target.value)}>Confirmation du mot de passe</Field>
|
onChange={event => setSamePassword(event.target.value)}>Confirmation du mot de passe</Field>
|
||||||
<button type="submit" className="mt-5 btn-primary w-full block text-lg">Valider</button>
|
<button type="submit" className="btn-primary mt-5 block w-full text-lg">Valider</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import React, {useEffect, useState} from "react"
|
import React, {useEffect, useState} from "react"
|
||||||
import PageLayout from "../components/PageLayout";
|
import PageLayout from "../components/PageLayout"
|
||||||
import LastFiveMesure from "../components/rainfall/LastFiveMesure";
|
import LastFiveMesure from "../components/rainfall/LastFiveMesure"
|
||||||
import AddRainfall from "../components/rainfall/AddRainfall";
|
import AddRainfall from "../components/rainfall/AddRainfall"
|
||||||
import RainfallGraph from "../components/rainfall/RainfallGraph";
|
import useAxiosTools from "../hooks/AxiosTools"
|
||||||
import useAxiosTools from "../hooks/AxiosTools";
|
import {rainfallGraphData} from "../types"
|
||||||
import {rainfall, rainfallGraphData} from "../types";
|
import Field from "../components/Field"
|
||||||
import Field from "../components/Field";
|
import useDimension from "../hooks/DimensionHook"
|
||||||
import useDimension from "../hooks/DimensionHook";
|
import RainFallEcharts from "../components/rainfall/RainFallEcharts"
|
||||||
|
|
||||||
const Rainfall = () => {
|
const Rainfall = () => {
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ const Rainfall = () => {
|
|||||||
end_date: (new Date()).toSQLDate(),
|
end_date: (new Date()).toSQLDate(),
|
||||||
period: 'day',
|
period: 'day',
|
||||||
})
|
})
|
||||||
const {errorCatch, errorLabel, axiosGet} = useAxiosTools()
|
const {loading, setLoading, errorCatch, errorLabel, axiosGet} = useAxiosTools()
|
||||||
const {targetRef, dimensions} = useDimension()
|
const {targetRef, dimensions} = useDimension()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -26,22 +26,25 @@ const Rainfall = () => {
|
|||||||
|
|
||||||
const fetchGraphData = async () => {
|
const fetchGraphData = async () => {
|
||||||
try {
|
try {
|
||||||
|
setLoading(true)
|
||||||
const params = `start=${graphDetails.start_date}&end=${graphDetails.end_date}&period=${graphDetails.period}`
|
const params = `start=${graphDetails.start_date}&end=${graphDetails.end_date}&period=${graphDetails.period}`
|
||||||
const res = await axiosGet(`/api/rainfalls/graph?${params}`)
|
const res = await axiosGet(`/api/rainfalls/graph?${params}`)
|
||||||
setGraphData(res.data)
|
setGraphData(res.data)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
errorCatch(error)
|
errorCatch(error)
|
||||||
|
} finally {
|
||||||
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <PageLayout>
|
return <PageLayout>
|
||||||
<div className="flex flex-wrap gap-2 justify-between">
|
<div className="flex flex-wrap justify-between gap-2">
|
||||||
<LastFiveMesure loadedAt={loadedAt} />
|
<LastFiveMesure loadedAt={loadedAt} />
|
||||||
<AddRainfall reload={reload} />
|
<AddRainfall reload={reload} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{errorLabel()}
|
{errorLabel()}
|
||||||
<form className="flex mb-2 mx-5 gap-2 flex-wrap">
|
<form className="mx-5 mb-2 flex flex-wrap gap-2">
|
||||||
<Field name="start_date"
|
<Field name="start_date"
|
||||||
type="date"
|
type="date"
|
||||||
value={graphDetails.start_date}
|
value={graphDetails.start_date}
|
||||||
@@ -51,7 +54,7 @@ const Rainfall = () => {
|
|||||||
value={graphDetails.end_date}
|
value={graphDetails.end_date}
|
||||||
onChange={e => setGraphDetails({...graphDetails, end_date: (new Date(e.target.value)).toSQLDate()})} />
|
onChange={e => setGraphDetails({...graphDetails, end_date: (new Date(e.target.value)).toSQLDate()})} />
|
||||||
<div className="form-control">
|
<div className="form-control">
|
||||||
<select className={` w-full mt-2 rounded dark:bg-gray-700`}
|
<select className={` mt-2 w-full rounded dark:bg-gray-700`}
|
||||||
value={graphDetails.period}
|
value={graphDetails.period}
|
||||||
onChange={e => setGraphDetails({...graphDetails, period: e.target.value})}>
|
onChange={e => setGraphDetails({...graphDetails, period: e.target.value})}>
|
||||||
<option value="day">Jour</option>
|
<option value="day">Jour</option>
|
||||||
@@ -61,11 +64,15 @@ const Rainfall = () => {
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div ref={targetRef} className="mb-20">
|
<div ref={targetRef} className="mb-20 min-h-96">
|
||||||
<RainfallGraph width={dimensions.width}
|
<RainFallEcharts width={dimensions.width}
|
||||||
height={500}
|
height={500}
|
||||||
data={graphData} start_date={graphDetails.start_date}
|
data={graphData}
|
||||||
end_date={graphDetails.end_date} />
|
loading={loading} />
|
||||||
|
{/*<RainfallGraph width={dimensions.width}*/}
|
||||||
|
{/* height={500}*/}
|
||||||
|
{/* data={graphData} start_date={graphDetails.start_date}*/}
|
||||||
|
{/* end_date={graphDetails.end_date} />*/}
|
||||||
</div>
|
</div>
|
||||||
</PageLayout>
|
</PageLayout>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, {useEffect, useState} from "react";
|
import React, {useEffect, useState} from "react"
|
||||||
import PageLayout from "../../components/PageLayout";
|
import PageLayout from "../../components/PageLayout"
|
||||||
import useAxiosTools from "../../hooks/AxiosTools";
|
import useAxiosTools from "../../hooks/AxiosTools"
|
||||||
import {rainfall} from "../../types";
|
import {rainfall} from "../../types"
|
||||||
|
|
||||||
const RainfallIndex = () => {
|
const RainfallIndex = () => {
|
||||||
|
|
||||||
@@ -24,13 +24,9 @@ const RainfallIndex = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleEdit = (rainfall: rainfall) => {
|
|
||||||
console.log(rainfall)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDelete = async (rainfall: rainfall) => {
|
const handleDelete = async (rainfall: rainfall) => {
|
||||||
try {
|
try {
|
||||||
const res = await axiosDelete(`/api/rainfalls/${rainfall.id}`)
|
await axiosDelete(`/api/rainfalls/${rainfall.id}`)
|
||||||
setRainfalls(rainfalls.filter(r => r.id !== rainfall.id))
|
setRainfalls(rainfalls.filter(r => r.id !== rainfall.id))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
errorCatch(error)
|
errorCatch(error)
|
||||||
@@ -39,7 +35,7 @@ const RainfallIndex = () => {
|
|||||||
|
|
||||||
return <PageLayout>
|
return <PageLayout>
|
||||||
{errorLabel()}
|
{errorLabel()}
|
||||||
<table className="border w-96 text-center mx-auto">
|
<table className="mx-auto w-96 border text-center">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Date</th>
|
<th>Date</th>
|
||||||
|
|||||||
@@ -8,14 +8,13 @@ const ForgotPassword = lazy(() => import('./Auth/ForgotPassword'))
|
|||||||
const Home = lazy(() => import('./Home'))
|
const Home = lazy(() => import('./Home'))
|
||||||
const Login = lazy(() => import('./Auth/Login'))
|
const Login = lazy(() => import('./Auth/Login'))
|
||||||
const Profile = lazy(() => import('./Auth/Profile'))
|
const Profile = lazy(() => import('./Auth/Profile'))
|
||||||
const Register = lazy(() => import('./Auth/Register'))
|
|
||||||
const Reset = lazy(() => import('./Auth/Reset'))
|
const Reset = lazy(() => import('./Auth/Reset'))
|
||||||
const Rainfall = lazy(() => import('./Rainfall'))
|
const Rainfall = lazy(() => import('./Rainfall'))
|
||||||
const RainfallIndex = lazy(() => import('./Rainfall/RainfallIndex'))
|
const RainfallIndex = lazy(() => import('./Rainfall/RainfallIndex'))
|
||||||
|
|
||||||
const Router = () => {
|
const Router = () => {
|
||||||
|
|
||||||
const {authUser, loadingAuthUser, logout} = useAuthUser()
|
const {loadingAuthUser} = useAuthUser()
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
{loadingAuthUser ? '...loading'
|
{loadingAuthUser ? '...loading'
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ const Weather = () => {
|
|||||||
|
|
||||||
const [currentWeather, setCurrentWeather] = useState<WeatherValue|null>(null)
|
const [currentWeather, setCurrentWeather] = useState<WeatherValue|null>(null)
|
||||||
const [fetchTime, setFetchTime] = useState(0)
|
const [fetchTime, setFetchTime] = useState(0)
|
||||||
const [count, setCount] = useState(0)
|
|
||||||
const [weatherDays, setWeatherDays] = useState<[string, WeatherValue[]][]|null>(null)
|
const [weatherDays, setWeatherDays] = useState<[string, WeatherValue[]][]|null>(null)
|
||||||
const {loading, setLoading, errorLabel, errorCatch, cleanErrors, axiosGet} = useAxiosTools()
|
const {loading, setLoading, errorLabel, errorCatch, cleanErrors, axiosGet} = useAxiosTools()
|
||||||
|
|
||||||
@@ -31,9 +30,9 @@ const Weather = () => {
|
|||||||
const res = await axiosGet(`/api/weather`)
|
const res = await axiosGet(`/api/weather`)
|
||||||
const currentWeather = res.data.list[0]
|
const currentWeather = res.data.list[0]
|
||||||
|
|
||||||
let weatherDays: [string, WeatherValue[]][] = []
|
const weatherDays: [string, WeatherValue[]][] = []
|
||||||
let objectEntries = {index: -1, date: ''}
|
let objectEntries = {index: -1, date: ''}
|
||||||
res.data.list.forEach((item: WeatherValue, index: number) => {
|
res.data.list.forEach((item: WeatherValue) => {
|
||||||
const date = item.dt_txt.split(' ')[0]
|
const date = item.dt_txt.split(' ')[0]
|
||||||
|
|
||||||
if (date === (new Date).toSQLDate()) {
|
if (date === (new Date).toSQLDate()) {
|
||||||
@@ -70,7 +69,7 @@ const Weather = () => {
|
|||||||
{errorLabel()}
|
{errorLabel()}
|
||||||
|
|
||||||
<Card className="flex justify-between">
|
<Card className="flex justify-between">
|
||||||
<div className="flex flex-col m-2 justify-between">
|
<div className="m-2 flex flex-col justify-between">
|
||||||
<span className="text-6xl">{currentWeather?.main.temp.toFixed()} °C</span>
|
<span className="text-6xl">{currentWeather?.main.temp.toFixed()} °C</span>
|
||||||
<span className="text-secondary dark:text-secondary-ligth">{currentWeather?.weather[0].description}</span>
|
<span className="text-secondary dark:text-secondary-ligth">{currentWeather?.weather[0].description}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -81,9 +80,9 @@ const Weather = () => {
|
|||||||
{currentWeather && <Img src={`images/icons/${currentWeather?.weather[0].icon}.svg`}
|
{currentWeather && <Img src={`images/icons/${currentWeather?.weather[0].icon}.svg`}
|
||||||
alt={currentWeather?.weather[0].main} width="120px" />}
|
alt={currentWeather?.weather[0].main} width="120px" />}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-1 flex-col">
|
<div className="flex flex-col gap-1">
|
||||||
<span className="text-4xl pt-5">{currentWeather?.main.temp_max.toFixed()} <span className="text-2xl">°C</span></span>
|
<span className="pt-5 text-4xl">{currentWeather?.main.temp_max.toFixed()} <span className="text-2xl">°C</span></span>
|
||||||
<span className="text-secondary text-2xl mt-2 dark:text-secondary-ligth">{currentWeather?.main.temp_min.toFixed()} °C</span>
|
<span className="mt-2 text-2xl text-secondary dark:text-secondary-ligth">{currentWeather?.main.temp_min.toFixed()} °C</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -108,7 +107,7 @@ const WeatherCard: FC<{date: string, values: WeatherValue[]}> = ({date, values=
|
|||||||
icon: '',
|
icon: '',
|
||||||
description: '',
|
description: '',
|
||||||
}
|
}
|
||||||
const result: {[k: string]: number} = {}
|
const result: Record<string, number> = {}
|
||||||
values.forEach(value => {
|
values.forEach(value => {
|
||||||
if (value.main.temp_min < weatherState.min) {
|
if (value.main.temp_min < weatherState.min) {
|
||||||
weatherState.min = value.main.temp_min
|
weatherState.min = value.main.temp_min
|
||||||
@@ -144,17 +143,17 @@ const WeatherCard: FC<{date: string, values: WeatherValue[]}> = ({date, values=
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return <div className="flex gap-5">
|
return <div className="flex gap-5">
|
||||||
<div className="flex flex-col gap-2 flex-1 h-full">
|
<div className="flex h-full flex-1 flex-col gap-2">
|
||||||
<span className="font-bold text-lg" title={(new Date(date)).toLocaleDateString()}>{(new Date(date)).getWeekDay()}</span>
|
<span className="text-lg font-bold" title={(new Date(date)).toLocaleDateString()}>{(new Date(date)).getWeekDay()}</span>
|
||||||
<span className="text-secondary dark:text-secondary-ligth">{weatherState?.description}</span>
|
<span className="text-secondary dark:text-secondary-ligth">{weatherState?.description}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center -mt-1.5">
|
<div className="-mt-1.5 flex items-center">
|
||||||
<Img src={`images/icons/${weatherState?.icon}.svg`}
|
<Img src={`images/icons/${weatherState?.icon}.svg`}
|
||||||
alt={weatherState?.main + ' ' + weatherState?.icon}
|
alt={weatherState?.main + ' ' + weatherState?.icon}
|
||||||
width="80px" />
|
width="80px" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-1 flex-col">
|
<div className="flex flex-col gap-1">
|
||||||
<span className="text-lg">{weatherState?.max.toFixed()} °C</span>
|
<span className="text-lg">{weatherState?.max.toFixed()} °C</span>
|
||||||
<span className="text-secondary dark:text-secondary-ligth">{weatherState?.min.toFixed()} °C</span>
|
<span className="text-secondary dark:text-secondary-ligth">{weatherState?.min.toFixed()} °C</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -38,7 +38,3 @@ export interface WeatherTime {
|
|||||||
icon: string,
|
icon: string,
|
||||||
main: 'Rain',
|
main: 'Rain',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WeatherCompilation {
|
|
||||||
[k: string]: WeatherValue[]
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,14 +1,27 @@
|
|||||||
|
import {AxiosError} from "axios"
|
||||||
|
|
||||||
export function displayFormErrors(error: any, form: HTMLElement|null = null) {
|
export function displayFormErrors(error: AxiosError, form: HTMLElement|null = null) {
|
||||||
if (error.response && error.response.status === 422) {
|
if (error.response && error.response.status === 422) {
|
||||||
let errors = error.response.data.errors
|
// @ts-expect-error test axios error
|
||||||
|
const errors = error.response.data.errors
|
||||||
const formBase = (form) ? form : document.body
|
const formBase = (form) ? form : document.body
|
||||||
Object.keys(errors).forEach(key => {
|
Object.entries(errors).forEach(([key, value]) => {
|
||||||
displayError(key, errors[key], formBase)
|
displayError(key, value, formBase)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ValidationErrors {
|
||||||
|
response: {
|
||||||
|
status: number,
|
||||||
|
data: {
|
||||||
|
errors: object
|
||||||
|
message?: string,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
message?: string,
|
||||||
|
}
|
||||||
|
|
||||||
export function displayError(key: string, message: string, form: HTMLElement|null = null) {
|
export function displayError(key: string, message: string, form: HTMLElement|null = null) {
|
||||||
const formBase = (form) ? form : document
|
const formBase = (form) ? form : document
|
||||||
const input = formBase.querySelector(`input[name="${key}"], select[name="${key}"], textarea[name="${key}"]`)
|
const input = formBase.querySelector(`input[name="${key}"], select[name="${key}"], textarea[name="${key}"]`)
|
||||||
|
|||||||
Reference in New Issue
Block a user