diff --git a/.env.template b/.env.template
index 04e93cbd..38986c0c 100644
--- a/.env.template
+++ b/.env.template
@@ -1,2 +1,5 @@
NEXT_TELEMETRY_DISABLED=1
NEXT_PUBLIC_DEBUG=true
+# if link change dont forget to chage the test for sideNav to check if the link is correct
+NEXT_PUBLIC_REPORT_ISSUE_URL="https://forms.office.com/Pages/ResponsePage.aspx?id=7aW1GIYd00GUoLwn2uMqsn9SKTgKSYtCg4t0B9x4uyJURE5HSkFCTkZHUEQyWkxJVElMODdFQ09HUCQlQCN0PWcu&r5a19e9d47d9f4ac497fb974c192da4b3=%22Fertiscan%22"
+NEXT_PUBLIC_ALERT_BANNER_AUTO_DISMISS_TIME=5000
diff --git a/package-lock.json b/package-lock.json
index e5f4e5aa..ca92c306 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,7 +11,7 @@
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.5",
"@mui/icons-material": "^6.1.4",
- "@mui/material": "^6.1.4",
+ "@mui/material": "^6.1.8",
"@mui/material-nextjs": "^6.1.4",
"dotenv": "^16.4.5",
"i18next": "^23.16.5",
@@ -33,7 +33,7 @@
"devDependencies": {
"@jest/types": "^29.6.3",
"@testing-library/dom": "^10.4.0",
- "@testing-library/jest-dom": "^6.6.2",
+ "@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.14",
@@ -41,7 +41,7 @@
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.1",
"eslint": "^8",
- "eslint-config-next": "14.2.15",
+ "eslint-config-next": "15.0.3",
"jest": "^29.7.0",
"postcss": "^8",
"prettier": "^3.3.3",
@@ -660,10 +660,9 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.25.7",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz",
- "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==",
- "license": "MIT",
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
+ "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@@ -1560,10 +1559,9 @@
}
},
"node_modules/@mui/core-downloads-tracker": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.1.4.tgz",
- "integrity": "sha512-jCRsB9NDJJatVCHvwWSTfYUzuTQ7E0Km6tAQWz2Md1SLHIbVj5visC9yHbf/Cv2IDcG6XdHRv3e7Bt1rIburNw==",
- "license": "MIT",
+ "version": "6.1.8",
+ "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.1.8.tgz",
+ "integrity": "sha512-TGAvzwUg9hybDacwfIGFjI2bXYXrIqky+vMfaeay8rvT56/PNAlvIDUJ54kpT5KRc9AWAihOvtDI7/LJOThOmQ==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
@@ -1596,16 +1594,15 @@
}
},
"node_modules/@mui/material": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.1.4.tgz",
- "integrity": "sha512-mIVdjzDYU4U/XYzf8pPEz3zDZFS4Wbyr0cjfgeGiT/s60EvtEresXXQy8XUA0bpJDJjgic1Hl5AIRcqWDyi2eg==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.25.7",
- "@mui/core-downloads-tracker": "^6.1.4",
- "@mui/system": "^6.1.4",
- "@mui/types": "^7.2.18",
- "@mui/utils": "^6.1.4",
+ "version": "6.1.8",
+ "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.1.8.tgz",
+ "integrity": "sha512-QZdQFnXct+7NXIzHgT3qt+sQiO7HYGZU2vymP9Xl9tUMXEOA/S1mZMMb7+WGZrk5TzNlU/kP/85K0da5V1jXoQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.26.0",
+ "@mui/core-downloads-tracker": "^6.1.8",
+ "@mui/system": "^6.1.8",
+ "@mui/types": "^7.2.19",
+ "@mui/utils": "^6.1.8",
"@popperjs/core": "^2.11.8",
"@types/react-transition-group": "^4.4.11",
"clsx": "^2.1.1",
@@ -1624,7 +1621,7 @@
"peerDependencies": {
"@emotion/react": "^11.5.0",
"@emotion/styled": "^11.3.0",
- "@mui/material-pigment-css": "^6.1.4",
+ "@mui/material-pigment-css": "^6.1.8",
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
@@ -1686,13 +1683,12 @@
"license": "MIT"
},
"node_modules/@mui/private-theming": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.1.4.tgz",
- "integrity": "sha512-FPa+W5BSrRM/1QI5Gf/GwJinJ2WsrKPpJB6xMmmXMXSUIp31YioIVT04i28DQUXFFB3yZY12ukcZi51iLvPljw==",
- "license": "MIT",
+ "version": "6.1.8",
+ "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.1.8.tgz",
+ "integrity": "sha512-TuKl7msynCNCVvhX3c0ef1sF0Qb3VHcPs8XOGB/8bdOGBr/ynmIG1yTMjZeiFQXk8yN9fzK/FDEKMFxILNn3wg==",
"dependencies": {
- "@babel/runtime": "^7.25.7",
- "@mui/utils": "^6.1.4",
+ "@babel/runtime": "^7.26.0",
+ "@mui/utils": "^6.1.8",
"prop-types": "^15.8.1"
},
"engines": {
@@ -1713,12 +1709,11 @@
}
},
"node_modules/@mui/styled-engine": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.1.4.tgz",
- "integrity": "sha512-D+aiIDtJsU9OVJ7dgayhCDABJHT7jTlnz1FKyxa5mNVHsxjjeG1M4OpLsRQvx4dcvJfDywnU2cE+nFm4Ln2aFQ==",
- "license": "MIT",
+ "version": "6.1.8",
+ "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.1.8.tgz",
+ "integrity": "sha512-ZvEoT0U2nPLSLI+B4by4cVjaZnPT2f20f4JUPkyHdwLv65ZzuoHiTlwyhqX1Ch63p8bcJzKTHQVGisEoMK6PGA==",
"dependencies": {
- "@babel/runtime": "^7.25.7",
+ "@babel/runtime": "^7.26.0",
"@emotion/cache": "^11.13.1",
"@emotion/serialize": "^1.3.2",
"@emotion/sheet": "^1.4.0",
@@ -1747,16 +1742,15 @@
}
},
"node_modules/@mui/system": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.1.4.tgz",
- "integrity": "sha512-lCveY/UtDhYwMg1WnLc3wEEuGymLi6YI79VOwFV9zfZT5Et+XEw/e1It26fiKwUZ+mB1+v1iTYMpJnwnsrn2aQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.25.7",
- "@mui/private-theming": "^6.1.4",
- "@mui/styled-engine": "^6.1.4",
- "@mui/types": "^7.2.18",
- "@mui/utils": "^6.1.4",
+ "version": "6.1.8",
+ "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.1.8.tgz",
+ "integrity": "sha512-i1kLfQoWxzFpXTBQIuPoA3xKnAnP3en4I2T8xIolovSolGQX5k8vGjw1JaydQS40td++cFsgCdEU458HDNTGUA==",
+ "dependencies": {
+ "@babel/runtime": "^7.26.0",
+ "@mui/private-theming": "^6.1.8",
+ "@mui/styled-engine": "^6.1.8",
+ "@mui/types": "^7.2.19",
+ "@mui/utils": "^6.1.8",
"clsx": "^2.1.1",
"csstype": "^3.1.3",
"prop-types": "^15.8.1"
@@ -1787,10 +1781,9 @@
}
},
"node_modules/@mui/types": {
- "version": "7.2.18",
- "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.18.tgz",
- "integrity": "sha512-uvK9dWeyCJl/3ocVnTOS6nlji/Knj8/tVqVX03UVTpdmTJYu/s4jtDd9Kvv0nRGE0CUSNW1UYAci7PYypjealg==",
- "license": "MIT",
+ "version": "7.2.19",
+ "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.19.tgz",
+ "integrity": "sha512-6XpZEM/Q3epK9RN8ENoXuygnqUQxE+siN/6rGRi2iwJPgBUR25mphYQ9ZI87plGh58YoZ5pp40bFvKYOCDJ3tA==",
"peerDependencies": {
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
@@ -1801,13 +1794,12 @@
}
},
"node_modules/@mui/utils": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.4.tgz",
- "integrity": "sha512-v0wXkyh3/Hpw48ivlNvgs4ZT6M8BIEAMdLgvct59rQBggYFhoAVKyliKDzdj37CnIlYau3DYIn7x5bHlRYFBow==",
- "license": "MIT",
+ "version": "6.1.8",
+ "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.8.tgz",
+ "integrity": "sha512-O2DWb1kz8hiANVcR7Z4gOB3SvPPsSQGUmStpyBDzde6dJIfBzgV9PbEQOBZd3EBsd1pB+Uv1z5LAJAbymmawrA==",
"dependencies": {
- "@babel/runtime": "^7.25.7",
- "@mui/types": "^7.2.18",
+ "@babel/runtime": "^7.26.0",
+ "@mui/types": "^7.2.19",
"@types/prop-types": "^15.7.13",
"clsx": "^2.1.1",
"prop-types": "^15.8.1",
@@ -1833,8 +1825,7 @@
"node_modules/@mui/utils/node_modules/react-is": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
- "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
- "license": "MIT"
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
},
"node_modules/@next/env": {
"version": "14.2.15",
@@ -1843,13 +1834,160 @@
"license": "MIT"
},
"node_modules/@next/eslint-plugin-next": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.15.tgz",
- "integrity": "sha512-pKU0iqKRBlFB/ocOI1Ip2CkKePZpYpnw5bEItEkuZ/Nr9FQP1+p7VDWr4VfOdff4i9bFmrOaeaU1bFEyAcxiMQ==",
+ "version": "15.0.3",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.0.3.tgz",
+ "integrity": "sha512-3Ln/nHq2V+v8uIaxCR6YfYo7ceRgZNXfTd3yW1ukTaFbO+/I8jNakrjYWODvG9BuR2v5kgVtH/C8r0i11quOgw==",
"dev": true,
- "license": "MIT",
"dependencies": {
- "glob": "10.3.10"
+ "fast-glob": "3.3.1"
+ }
+ },
+ "node_modules/@next/eslint-plugin-next/node_modules/fast-glob": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+ "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/@next/eslint-plugin-next/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.15.tgz",
+ "integrity": "sha512-Rvh7KU9hOUBnZ9TJ28n2Oa7dD9cvDBKua9IKx7cfQQ0GoYUwg9ig31O2oMwH3wm+pE3IkAQ67ZobPfEgurPZIA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-x64": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.15.tgz",
+ "integrity": "sha512-5TGyjFcf8ampZP3e+FyCax5zFVHi+Oe7sZyaKOngsqyaNEpOgkKB3sqmymkZfowy3ufGA/tUgDPPxpQx931lHg==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.15.tgz",
+ "integrity": "sha512-3Bwv4oc08ONiQ3FiOLKT72Q+ndEMyLNsc/D3qnLMbtUYTQAmkx9E/JRu0DBpHxNddBmNT5hxz1mYBphJ3mfrrw==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.15.tgz",
+ "integrity": "sha512-k5xf/tg1FBv/M4CMd8S+JL3uV9BnnRmoe7F+GWC3DxkTCD9aewFRH1s5rJ1zkzDa+Do4zyN8qD0N8c84Hu96FQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.15.tgz",
+ "integrity": "sha512-kE6q38hbrRbKEkkVn62reLXhThLRh6/TvgSP56GkFNhU22TbIrQDEMrO7j0IcQHcew2wfykq8lZyHFabz0oBrA==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.15.tgz",
+ "integrity": "sha512-PZ5YE9ouy/IdO7QVJeIcyLn/Rc4ml9M2G4y3kCM9MNf1YKvFY4heg3pVa/jQbMro+tP6yc4G2o9LjAz1zxD7tQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.15.tgz",
+ "integrity": "sha512-2raR16703kBvYEQD9HNLyb0/394yfqzmIeyp2nDzcPV4yPjqNUG3ohX6jX00WryXz6s1FXpVhsCo3i+g4RUX+g==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-ia32-msvc": {
+ "version": "14.2.15",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.15.tgz",
+ "integrity": "sha512-fyTE8cklgkyR1p03kJa5zXEaZ9El+kDNM5A+66+8evQS5e/6v0Gk28LqA0Jet8gKSOyP+OTm/tJHzMlGdQerdQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
}
},
"node_modules/@next/swc-darwin-arm64": {
@@ -2142,11 +2280,10 @@
}
},
"node_modules/@testing-library/jest-dom": {
- "version": "6.6.2",
- "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.2.tgz",
- "integrity": "sha512-P6GJD4yqc9jZLbe98j/EkyQDTPgqftohZF5FBkHY5BUERZmcf4HeO2k0XaefEg329ux2p21i1A1DmyQ1kKw2Jw==",
+ "version": "6.6.3",
+ "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz",
+ "integrity": "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@adobe/css-tools": "^4.4.0",
"aria-query": "^5.0.0",
@@ -3572,7 +3709,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
- "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -4458,25 +4594,24 @@
}
},
"node_modules/eslint-config-next": {
- "version": "14.2.15",
- "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.15.tgz",
- "integrity": "sha512-mKg+NC/8a4JKLZRIOBplxXNdStgxy7lzWuedUaCc8tev+Al9mwDUTujQH6W6qXDH9kycWiVo28tADWGvpBsZcQ==",
+ "version": "15.0.3",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.0.3.tgz",
+ "integrity": "sha512-IGP2DdQQrgjcr4mwFPve4DrCqo7CVVez1WoYY47XwKSrYO4hC0Dlb+iJA60i0YfICOzgNADIb8r28BpQ5Zs0wg==",
"dev": true,
- "license": "MIT",
"dependencies": {
- "@next/eslint-plugin-next": "14.2.15",
- "@rushstack/eslint-patch": "^1.3.3",
+ "@next/eslint-plugin-next": "15.0.3",
+ "@rushstack/eslint-patch": "^1.10.3",
"@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
"@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
"eslint-import-resolver-node": "^0.3.6",
"eslint-import-resolver-typescript": "^3.5.2",
- "eslint-plugin-import": "^2.28.1",
- "eslint-plugin-jsx-a11y": "^6.7.1",
- "eslint-plugin-react": "^7.33.2",
- "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705"
+ "eslint-plugin-import": "^2.31.0",
+ "eslint-plugin-jsx-a11y": "^6.10.0",
+ "eslint-plugin-react": "^7.35.0",
+ "eslint-plugin-react-hooks": "^5.0.0"
},
"peerDependencies": {
- "eslint": "^7.23.0 || ^8.0.0",
+ "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0",
"typescript": ">=3.3.1"
},
"peerDependenciesMeta": {
@@ -4703,16 +4838,15 @@
}
},
"node_modules/eslint-plugin-react-hooks": {
- "version": "5.0.0-canary-7118f5dd7-20230705",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz",
- "integrity": "sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz",
+ "integrity": "sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==",
"dev": true,
- "license": "MIT",
"engines": {
"node": ">=10"
},
"peerDependencies": {
- "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
}
},
"node_modules/eslint-plugin-react/node_modules/doctrine": {
@@ -8336,9 +8470,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.47",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
- "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
+ "version": "8.4.49",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
+ "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
"dev": true,
"funding": [
{
@@ -8354,10 +8488,9 @@
"url": "https://github.com/sponsors/ai"
}
],
- "license": "MIT",
"dependencies": {
"nanoid": "^3.3.7",
- "picocolors": "^1.1.0",
+ "picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
"engines": {
diff --git a/package.json b/package.json
index 0fa9668e..1dbe5368 100644
--- a/package.json
+++ b/package.json
@@ -25,7 +25,7 @@
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.5",
"@mui/icons-material": "^6.1.4",
- "@mui/material": "^6.1.4",
+ "@mui/material": "^6.1.8",
"@mui/material-nextjs": "^6.1.4",
"dotenv": "^16.4.5",
"i18next": "^23.16.5",
@@ -47,7 +47,7 @@
"devDependencies": {
"@jest/types": "^29.6.3",
"@testing-library/dom": "^10.4.0",
- "@testing-library/jest-dom": "^6.6.2",
+ "@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.14",
@@ -55,7 +55,7 @@
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.1",
"eslint": "^8",
- "eslint-config-next": "14.2.15",
+ "eslint-config-next": "15.0.3",
"jest": "^29.7.0",
"postcss": "^8",
"prettier": "^3.3.3",
diff --git a/public/locales/en/labelDataValidationPage.json b/public/locales/en/labelDataValidationPage.json
new file mode 100644
index 00000000..c545a1d1
--- /dev/null
+++ b/public/locales/en/labelDataValidationPage.json
@@ -0,0 +1,103 @@
+{
+ "baseInformation": {
+ "stepTitle": "Base Information",
+ "fields": {
+ "name": {
+ "label": "Name",
+ "placeholder": "Enter name"
+ },
+ "registrationNumber": {
+ "label": "Registration Number",
+ "placeholder": "Enter registration number"
+ },
+ "lotNumber": {
+ "label": "Lot Number",
+ "placeholder": "Enter lot number"
+ },
+ "npk": {
+ "label": "NPK",
+ "placeholder": "Enter NPK"
+ },
+ "weight": {
+ "label": "Weight"
+ },
+ "density": {
+ "label": "Density"
+ },
+ "volume": {
+ "label": "Volume"
+ }
+ }
+ },
+ "organizations": {
+ "stepTitle": "Organizations"
+ },
+ "cautions": {
+ "stepTitle": "Cautions"
+ },
+ "instructions": {
+ "stepTitle": "Instructions"
+ },
+ "verifiedQuantityMultiInput": {
+ "deleteRow": "Delete this row",
+ "defaultPlaceholder": "Enter value",
+ "addRow": "Add Row",
+ "removeRow": "Remove",
+ "verify": "Mark as Verified",
+ "unverify": "Mark as Unverified",
+ "errors": {
+ "numbersOnly": "Numbers only",
+ "minValue": "Minimum value is 0",
+ "duplicateUnit": "Duplicate unit"
+ },
+ "units": {
+ "kg": "kg",
+ "g": "g",
+ "lb": "lb",
+ "tonne": "tonne",
+ "L": "L",
+ "mL": "mL",
+ "gal": "gal",
+ "ft³": "ft³",
+ "lb/ft³": "lb/ft³",
+ "g/cm³": "g/cm³",
+ "kg/m³": "kg/m³",
+ "lb/gal": "lb/gal"
+ },
+ "accessibility": {
+ "deleteRowButton": "Button to delete this row",
+ "addRowButton": "Button to add a new row",
+ "valueInput": "Input field for numeric value",
+ "unitDropdown": "Dropdown to select a unit of measurement",
+ "verifyToggleButton": "Button to toggle verification status",
+ "fieldsContainer": "Container for all input fields",
+ "row": "Row containing inputs for unit and value",
+ "errorIcon": "Icon indicating a validation error"
+ }
+ },
+ "verifiedBilingualTable": {
+ "english": "English",
+ "french": "French",
+ "actions": "Actions",
+ "placeholders": {
+ "english": "Enter English text",
+ "french": "Enter French text"
+ },
+ "addRow": "Add Row",
+ "delete": "Delete Row",
+ "verify": "Mark as Verified",
+ "unverify": "Mark as Unverified",
+ "verifyAll": "Mark All as Verified",
+ "unverifyAll": "Mark All as Unverified",
+ "accessibility": {
+ "englishInput": "English text input for row {{row}}",
+ "frenchInput": "French text input for row {{row}}",
+ "deleteButton": "Button to delete this row",
+ "addRowButton": "Button to add a new row",
+ "verifyButton": "Button to mark this row as Verified",
+ "unverifyButton": "Button to mark this row as Unverified",
+ "verifyAllButton": "Button to mark all rows as Verified",
+ "unverifyAllButton": "Button to mark all rows as Unverified"
+ }
+ }
+}
diff --git a/public/locales/fr/labelDataValidationPage.json b/public/locales/fr/labelDataValidationPage.json
new file mode 100644
index 00000000..6eaf6ff9
--- /dev/null
+++ b/public/locales/fr/labelDataValidationPage.json
@@ -0,0 +1,103 @@
+{
+ "baseInformation": {
+ "stepTitle": "Informations de base sur l'engrais",
+ "fields": {
+ "name": {
+ "label": "Nom",
+ "placeholder": "Entrez le nom"
+ },
+ "registrationNumber": {
+ "label": "Numéro d'enregistrement",
+ "placeholder": "Entrez le numéro d'enregistrement"
+ },
+ "lotNumber": {
+ "label": "Numéro de lot",
+ "placeholder": "Entrez le numéro de lot"
+ },
+ "npk": {
+ "label": "NPK",
+ "placeholder": "Entrez le NPK"
+ },
+ "weight": {
+ "label": "Poids"
+ },
+ "density": {
+ "label": "Densité"
+ },
+ "volume": {
+ "label": "Volume"
+ }
+ }
+ },
+ "organizations": {
+ "stepTitle": "Organisations"
+ },
+ "cautions": {
+ "stepTitle": "Mises en garde"
+ },
+ "instructions": {
+ "stepTitle": "Instructions"
+ },
+ "verifiedQuantityMultiInput": {
+ "deleteRow": "Supprimer cette ligne",
+ "defaultPlaceholder": "Entrez une valeur",
+ "addRow": "Ajouter une ligne",
+ "removeRow": "Supprimer",
+ "verify": "Marquer comme vérifiés",
+ "unverify": "Marquer comme non vérifiés",
+ "errors": {
+ "numbersOnly": "Uniquement des nombres",
+ "minValue": "La valeur minimale est 0",
+ "duplicateUnit": "Unité dupliquée"
+ },
+ "units": {
+ "kg": "kg",
+ "g": "g",
+ "lb": "lb",
+ "tonne": "tonne",
+ "L": "L",
+ "mL": "mL",
+ "gal": "gal",
+ "ft³": "pi³",
+ "lb/ft³": "lb/pi³",
+ "g/cm³": "g/cm³",
+ "kg/m³": "kg/m³",
+ "lb/gal": "lb/gal"
+ },
+ "accessibility": {
+ "deleteRowButton": "Bouton pour supprimer cette ligne",
+ "addRowButton": "Bouton pour ajouter une nouvelle ligne",
+ "valueInput": "Champ de saisie pour une valeur numérique",
+ "unitDropdown": "Menu déroulant pour sélectionner une unité de mesure",
+ "verifyToggleButton": "Bouton pour basculer l'état de vérification",
+ "fieldsContainer": "Conteneur pour tous les champs de saisie",
+ "row": "Ligne contenant les champs pour l'unité et la valeur",
+ "errorIcon": "Icône indiquant une erreur de validation"
+ }
+ },
+ "verifiedBilingualTable": {
+ "english": "Anglais",
+ "french": "Français",
+ "actions": "Actions",
+ "placeholders": {
+ "english": "Entrez le texte en anglais",
+ "french": "Entrez le texte en français"
+ },
+ "addRow": "Ajouter une ligne",
+ "delete": "Supprimer cette ligne",
+ "verify": "Marquer comme vérifié",
+ "unverify": "Marquer comme non vérifié",
+ "verifyAll": "Tout marquer comme vérifié",
+ "unverifyAll": "Tout marquer comme non vérifié",
+ "accessibility": {
+ "englishInput": "Zone de texte en anglais pour la ligne {{row}}",
+ "frenchInput": "Zone de texte en français pour la ligne {{row}}",
+ "deleteButton": "Bouton pour supprimer cette ligne",
+ "addRowButton": "Bouton pour ajouter une nouvelle ligne",
+ "verifyButton": "Bouton pour marquer cette ligne comme vérifiée",
+ "unverifyButton": "Bouton pour marquer cette ligne comme non vérifiée",
+ "verifyAllButton": "Bouton pour tout marquer comme vérifié",
+ "unverifyAllButton": "Bouton pour tout marquer comme non vérifié"
+ }
+ }
+}
diff --git a/src/app/label-data-validation/__tests__/page.test.tsx b/src/app/label-data-validation/__tests__/page.test.tsx
index e4d30bcc..c37a1c91 100644
--- a/src/app/label-data-validation/__tests__/page.test.tsx
+++ b/src/app/label-data-validation/__tests__/page.test.tsx
@@ -1,4 +1,4 @@
-import { fireEvent, render, screen } from "@testing-library/react";
+import { act, fireEvent, render, screen } from "@testing-library/react";
import LabelDataValidationPage from "../page";
jest.mock("@/components/ImageViewer", () => ({
@@ -20,8 +20,8 @@ describe("LabelDataValidationPage Rendering", () => {
it("renders the correct step component initially", () => {
render();
- expect(screen.getByTestId("organizations-form")).toBeInTheDocument();
- expect(screen.queryByTestId("Dummy Step")).not.toBeInTheDocument();
+ expect(screen.getByTestId("base-information-form")).toBeInTheDocument();
+ expect(screen.queryByTestId("organizations-form")).not.toBeInTheDocument();
});
});
@@ -32,14 +32,16 @@ describe("LabelDataValidationPage Functionality", () => {
const nextButton = screen.getByText("Next");
fireEvent.click(nextButton);
- expect(screen.queryByTestId("organizations-form")).not.toBeInTheDocument();
- expect(screen.getByTestId("Dummy Step")).toBeInTheDocument();
+ expect(
+ screen.queryByTestId("base-information-form"),
+ ).not.toBeInTheDocument();
+ expect(screen.getByTestId("organizations-form")).toBeInTheDocument();
const backButton = screen.getByText("Back");
fireEvent.click(backButton);
- expect(screen.getByTestId("organizations-form")).toBeInTheDocument();
- expect(screen.queryByTestId("Dummy Step")).not.toBeInTheDocument();
+ expect(screen.getByTestId("base-information-form")).toBeInTheDocument();
+ expect(screen.queryByTestId("organizations-form")).not.toBeInTheDocument();
});
it("does not navigate beyond the first or last step", () => {
@@ -49,11 +51,12 @@ describe("LabelDataValidationPage Functionality", () => {
const backButton = screen.getByText("Back");
fireEvent.click(backButton);
- expect(screen.getByTestId("organizations-form")).toBeInTheDocument();
+ expect(screen.getByTestId("base-information-form")).toBeInTheDocument();
fireEvent.click(nextButton);
fireEvent.click(nextButton);
- expect(screen.getByTestId("Dummy Step")).toBeInTheDocument();
+ fireEvent.click(nextButton);
+ expect(screen.getByTestId("instructions-form")).toBeInTheDocument();
});
it("renders the mocked Image Viewer", () => {
@@ -64,11 +67,13 @@ describe("LabelDataValidationPage Functionality", () => {
});
});
-describe("LabelDataValidationPage and OrganizationsForm Integration", () => {
- it("marks the Organizations step as Completed when all organizations are Verified", () => {
+describe("LabelDataValidationPage and Forms Integration", () => {
+ it("marks the Organizations step as Completed or Incomplete when fields are Verified", () => {
render();
- const spans = screen.getAllByText("Organizations", { exact: true });
+ const spans = screen.getAllByText("organizations.stepTitle", {
+ exact: true,
+ });
const targetSpan = spans.find((span) =>
span.classList.contains("MuiStepLabel-label"),
);
@@ -79,28 +84,116 @@ describe("LabelDataValidationPage and OrganizationsForm Integration", () => {
const verifyAllButton = screen.getByTestId("verify-all-btn-0");
fireEvent.click(verifyAllButton);
expect(targetSpan).toHaveClass("Mui-completed");
+
+ fireEvent.click(
+ screen.getByTestId("verified-icon-organizations.0.address.verified"),
+ );
+
+ expect(targetSpan).not.toHaveClass("Mui-completed");
});
- it("keeps the Organizations step as Incomplete when at least one organization is not Verified", () => {
+ it("marks the Base Information step as Completed or Incomplete when fields are Verified", async () => {
render();
- const spans = screen.getAllByText("Organizations", { exact: true });
+ const spans = screen.getAllByText("baseInformation.stepTitle", {
+ exact: true,
+ });
const targetSpan = spans.find((span) =>
span.classList.contains("MuiStepLabel-label"),
);
expect(targetSpan).not.toHaveClass("Mui-completed");
const button = targetSpan!.closest("button");
- fireEvent.click(button!);
+ await act(async () => {
+ fireEvent.click(button!);
+ });
+
+ const verifyButtons = screen.getAllByTestId(
+ /verified-icon-baseInformation/,
+ );
+ expect(verifyButtons.length).toBeGreaterThanOrEqual(7);
+
+ for (const button of verifyButtons) {
+ await act(async () => {
+ fireEvent.click(button);
+ });
+ }
+
+ expect(targetSpan).toHaveClass("Mui-completed");
+
+ await act(async () => {
+ fireEvent.click(verifyButtons[0]);
+ });
+
+ expect(targetSpan).not.toHaveClass("Mui-completed");
+ });
+
+ it("marks the Cautions step as Completed or Incomplete when fields are Verified", async () => {
+ render();
+
+ const spans = screen.getAllByText("cautions.stepTitle", {
+ exact: true,
+ });
+ const targetSpan = spans.find((span) =>
+ span.classList.contains("MuiStepLabel-label"),
+ );
+ expect(targetSpan).not.toHaveClass("Mui-completed");
+
+ const button = targetSpan!.closest("button");
+ await act(async () => {
+ fireEvent.click(button!);
+ });
+
+ const verifyButtons = screen.getAllByTestId(/verify-row-btn-cautions-\d+/);
+ expect(verifyButtons.length).toBeGreaterThanOrEqual(1);
+
+ for (const button of verifyButtons) {
+ await act(async () => {
+ fireEvent.click(button);
+ });
+ }
- const verifyAllButton = screen.getByTestId("verify-all-btn-0");
- fireEvent.click(verifyAllButton);
expect(targetSpan).toHaveClass("Mui-completed");
- const toggleStatusButton = screen.getByTestId(
- "toggle-status-btn-organizations.0.name.status",
+ await act(async () => {
+ fireEvent.click(verifyButtons[0]);
+ });
+
+ expect(targetSpan).not.toHaveClass("Mui-completed");
+ });
+
+ it("marks the Instructions step as Completed or Incomplete when fields are Verified", async () => {
+ render();
+
+ const spans = screen.getAllByText("instructions.stepTitle", {
+ exact: true,
+ });
+ const targetSpan = spans.find((span) =>
+ span.classList.contains("MuiStepLabel-label"),
);
- fireEvent.click(toggleStatusButton);
+ expect(targetSpan).not.toHaveClass("Mui-completed");
+
+ const button = targetSpan!.closest("button");
+ await act(async () => {
+ fireEvent.click(button!);
+ });
+
+ const verifyButtons = screen.getAllByTestId(
+ /verify-row-btn-instructions-\d+/,
+ );
+ expect(verifyButtons.length).toBeGreaterThanOrEqual(1);
+
+ for (const button of verifyButtons) {
+ await act(async () => {
+ fireEvent.click(button);
+ });
+ }
+
+ expect(targetSpan).toHaveClass("Mui-completed");
+
+ await act(async () => {
+ fireEvent.click(verifyButtons[0]);
+ });
expect(targetSpan).not.toHaveClass("Mui-completed");
});
diff --git a/src/app/label-data-validation/page.tsx b/src/app/label-data-validation/page.tsx
index 52a9d4d3..7e4af082 100644
--- a/src/app/label-data-validation/page.tsx
+++ b/src/app/label-data-validation/page.tsx
@@ -1,24 +1,28 @@
"use client";
-import DummyStepComponent from "@/components/DummyStepComponent";
+import BaseInformationForm from "@/components/BaseInformationForm";
+import CautionsForm from "@/components/CautionsForm";
import ImageViewer from "@/components/ImageViewer";
+import InstructionsForm from "@/components/InstructionsForm";
import OrganizationsForm from "@/components/OrganizationsForm";
import {
HorizontalNonLinearStepper,
StepperControls,
StepStatus,
} from "@/components/stepper";
+import useAlertStore from "@/stores/alertStore";
import {
- checkOrganizationStatus,
DEFAULT_LABEL_DATA,
- FieldStatus,
FormComponentProps,
+ isVerified,
LabelData,
} from "@/types/types";
import useBreakpoints from "@/utils/useBreakpoints";
-import { Box, Button, Container } from "@mui/material";
+import { Box, Button, Container, Typography } from "@mui/material";
import { useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
function LabelDataValidationPage() {
+ const { t } = useTranslation("labelDataValidationPage");
const [imageFiles, setImageFiles] = useState([]);
const { isDownXs, isBetweenXsSm, isBetweenSmMd, isBetweenMdLg } =
useBreakpoints();
@@ -28,9 +32,14 @@ function LabelDataValidationPage() {
const [activeStep, setActiveStep] = useState(0);
const [organizationsStepStatus, setOrganizationsStepStatus] =
useState(StepStatus.Incomplete);
- const [dummyStepStatus, setDummyStepStatus] = useState(
+ const [baseInformationStepStatus, setBaseInformationStepStatus] =
+ useState(StepStatus.Incomplete);
+ const [cautionsStepStatus, setCautionsStepStatus] = useState(
StepStatus.Incomplete,
);
+ const [instructionsStepStatus, setInstructionsStepStatus] =
+ useState(StepStatus.Incomplete);
+ const { showAlert } = useAlertStore();
const createStep = (
title: string,
@@ -43,27 +52,35 @@ function LabelDataValidationPage() {
stepStatus: stepStatus,
setStepStatus: setStepStatusState,
render: () => (
-
+
),
};
};
const steps = [
createStep(
- "Organizations",
+ t("baseInformation.stepTitle"),
+ BaseInformationForm,
+ baseInformationStepStatus,
+ setBaseInformationStepStatus,
+ ),
+ createStep(
+ t("organizations.stepTitle"),
OrganizationsForm,
organizationsStepStatus,
setOrganizationsStepStatus,
),
createStep(
- "Dummy Step",
- DummyStepComponent,
- dummyStepStatus,
- setDummyStepStatus,
+ t("cautions.stepTitle"),
+ CautionsForm,
+ cautionsStepStatus,
+ setCautionsStepStatus,
+ ),
+ createStep(
+ t("instructions.stepTitle"),
+ InstructionsForm,
+ instructionsStepStatus,
+ setInstructionsStepStatus,
),
];
@@ -78,17 +95,38 @@ function LabelDataValidationPage() {
};
useEffect(() => {
- const verified = labelData.organizations.every((org) =>
- checkOrganizationStatus(org, FieldStatus.Verified),
- );
+ const verified = labelData.organizations.every((org) => isVerified(org));
setOrganizationsStepStatus(
verified ? StepStatus.Completed : StepStatus.Incomplete,
);
}, [labelData.organizations, setOrganizationsStepStatus]);
+ useEffect(() => {
+ const verified = isVerified(labelData.baseInformation);
+ setBaseInformationStepStatus(
+ verified ? StepStatus.Completed : StepStatus.Incomplete,
+ );
+ }, [labelData.baseInformation, setBaseInformationStepStatus]);
+
+ useEffect(() => {
+ const verified = labelData.cautions.every((caution) => caution.verified);
+ setCautionsStepStatus(
+ verified ? StepStatus.Completed : StepStatus.Incomplete,
+ );
+ }, [labelData.cautions, setCautionsStepStatus]);
+
+ useEffect(() => {
+ const verified = labelData.instructions.every(
+ (instruction) => instruction.verified,
+ );
+ setInstructionsStepStatus(
+ verified ? StepStatus.Completed : StepStatus.Incomplete,
+ );
+ }, [labelData.instructions, setInstructionsStepStatus]);
+
return (
@@ -104,12 +142,12 @@ function LabelDataValidationPage() {
)}
@@ -126,18 +164,26 @@ function LabelDataValidationPage() {
)}
-
- {steps[activeStep].render()}
- step.title)}
- stepStatuses={steps.map((step) => step.stepStatus)}
- activeStep={activeStep}
- setActiveStep={setActiveStep}
- />
+
+ {steps[activeStep].title}
+
+ {/* */}
+
+ {steps[activeStep].render()}
+ step.title)}
+ stepStatuses={steps.map((step) => step.stepStatus)}
+ activeStep={activeStep}
+ setActiveStep={setActiveStep}
+ />
@@ -153,6 +199,7 @@ function LabelDataValidationPage() {
style={{ display: "none" }}
onChange={handleFileChange}
/>
+
);
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index dd1bb27f..181d0db6 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,15 +1,16 @@
"use client";
import Header from "@/components/Header";
import SideNav from "@/components/Sidenav";
+import useAlertStore from "@/stores/alertStore";
+import { Box } from "@mui/material";
import { AppRouterCacheProvider } from "@mui/material-nextjs/v14-appRouter";
import { ThemeProvider } from "@mui/material/styles";
+import "dotenv/config";
import { useState } from "react";
+import { useTranslation } from "react-i18next";
import "./globals.css";
-import theme from "./theme";
-import "dotenv/config";
import "./i18n";
-import useAlertStore from "@/stores/alertStore";
-import { useTranslation } from "react-i18next";
+import theme from "./theme";
export default function RootLayout({
children,
@@ -17,10 +18,10 @@ export default function RootLayout({
const [sideNavOpen, setSideNavOpen] = useState(false);
const { showAlert } = useAlertStore();
const { t, i18n } = useTranslation(["alertBanner", "translation"]);
- const debugMode = process.env.NEXT_PUBLIC_DEBUG === 'true';
+ const debugMode = process.env.NEXT_PUBLIC_DEBUG === "true";
if (debugMode) {
- console.log(t("debugMessage"));
+ console.log(t("debugMessage"));
}
const handleDrawerClose = () => {
@@ -40,7 +41,7 @@ export default function RootLayout({
- {children}
+ {children}