diff --git a/package-lock.json b/package-lock.json
index 1356826..a6500ae 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,10 +11,15 @@
"@reduxjs/toolkit": "^1.9.5",
"autoprefixer": "^10.4.14",
"axios": "^1.4.0",
+ "csvtojson": "^2.0.10",
+ "i18next": "^23.6.0",
+ "i18next-browser-languagedetector": "^7.1.0",
"jquery": "^3.7.0",
"postcss": "^8.4.23",
"react": "^18.2.0",
+ "react-csv": "^2.2.2",
"react-dom": "^18.2.0",
+ "react-i18next": "^13.3.1",
"react-icons": "^4.8.0",
"react-redux": "^8.0.5",
"react-router-dom": "^6.10.0",
@@ -23,6 +28,7 @@
"devDependencies": {
"@types/jquery": "^3.5.16",
"@types/react": "^18.0.28",
+ "@types/react-csv": "^1.1.7",
"@types/react-dom": "^18.0.11",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1",
@@ -361,11 +367,11 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.22.3",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.3.tgz",
- "integrity": "sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ==",
+ "version": "7.23.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz",
+ "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==",
"dependencies": {
- "regenerator-runtime": "^0.13.11"
+ "regenerator-runtime": "^0.14.0"
},
"engines": {
"node": ">=6.9.0"
@@ -1035,6 +1041,15 @@
"csstype": "^3.0.2"
}
},
+ "node_modules/@types/react-csv": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@types/react-csv/-/react-csv-1.1.7.tgz",
+ "integrity": "sha512-MOXBoBrLm3Bz0xxQ1I367PhioZRxjBwmMsSUgckPP04UJw6iHbije37Auct9v+EAHGih2v1eYxchCaoqgJ8idQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/react-dom": {
"version": "18.2.1",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.1.tgz",
@@ -1432,6 +1447,11 @@
"node": ">=8"
}
},
+ "node_modules/bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+ },
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -1665,6 +1685,22 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
},
+ "node_modules/csvtojson": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/csvtojson/-/csvtojson-2.0.10.tgz",
+ "integrity": "sha512-lUWFxGKyhraKCW8Qghz6Z0f2l/PqB1W3AO0HKJzGIQ5JRSlR651ekJDiGJbBT4sRNNv5ddnSGVEnsxP9XRCVpQ==",
+ "dependencies": {
+ "bluebird": "^3.5.1",
+ "lodash": "^4.17.3",
+ "strip-bom": "^2.0.0"
+ },
+ "bin": {
+ "csvtojson": "bin/csvtojson"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
"node_modules/daisyui": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-3.1.1.tgz",
@@ -2415,6 +2451,44 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
+ "node_modules/html-parse-stringify": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
+ "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
+ "dependencies": {
+ "void-elements": "3.1.0"
+ }
+ },
+ "node_modules/i18next": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.6.0.tgz",
+ "integrity": "sha512-z0Cxr0MGkt+kli306WS4nNNM++9cgt2b2VCMprY92j+AIab/oclgPxdwtTZVLP1zn5t5uo8M6uLsZmYrcjr3HA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://locize.com"
+ },
+ {
+ "type": "individual",
+ "url": "https://locize.com/i18next.html"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
+ }
+ ],
+ "dependencies": {
+ "@babel/runtime": "^7.22.5"
+ }
+ },
+ "node_modules/i18next-browser-languagedetector": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.1.0.tgz",
+ "integrity": "sha512-cr2k7u1XJJ4HTOjM9GyOMtbOA47RtUoWRAtt52z43r3AoMs2StYKyjS3URPhzHaf+mn10hY9dZWamga5WPQjhA==",
+ "dependencies": {
+ "@babel/runtime": "^7.19.4"
+ }
+ },
"node_modules/ignore": {
"version": "5.2.4",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
@@ -2537,6 +2611,11 @@
"node": ">=8"
}
},
+ "node_modules/is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q=="
+ },
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -2663,6 +2742,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@@ -3171,6 +3255,11 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-csv": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/react-csv/-/react-csv-2.2.2.tgz",
+ "integrity": "sha512-RG5hOcZKZFigIGE8LxIEV/OgS1vigFQT4EkaHeKgyuCbUAu9Nbd/1RYq++bJcJJ9VOqO/n9TZRADsXNDR4VEpw=="
+ },
"node_modules/react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
@@ -3183,6 +3272,27 @@
"react": "^18.2.0"
}
},
+ "node_modules/react-i18next": {
+ "version": "13.3.1",
+ "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-13.3.1.tgz",
+ "integrity": "sha512-JAtYREK879JXaN9GdzfBI4yJeo/XyLeXWUsRABvYXiFUakhZJ40l+kaTo+i+A/3cKIED41kS/HAbZ5BzFtq/Og==",
+ "dependencies": {
+ "@babel/runtime": "^7.22.5",
+ "html-parse-stringify": "^3.0.1"
+ },
+ "peerDependencies": {
+ "i18next": ">= 23.2.3",
+ "react": ">= 16.8.0"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ }
+ }
+ },
"node_modules/react-icons": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.8.0.tgz",
@@ -3311,9 +3421,9 @@
}
},
"node_modules/regenerator-runtime": {
- "version": "0.13.11",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
- "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
+ "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
},
"node_modules/reselect": {
"version": "4.1.8",
@@ -3501,6 +3611,17 @@
"node": ">=8"
}
},
+ "node_modules/strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==",
+ "dependencies": {
+ "is-utf8": "^0.2.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -3829,6 +3950,14 @@
}
}
},
+ "node_modules/void-elements": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
+ "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -4122,11 +4251,11 @@
}
},
"@babel/runtime": {
- "version": "7.22.3",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.3.tgz",
- "integrity": "sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ==",
+ "version": "7.23.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz",
+ "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==",
"requires": {
- "regenerator-runtime": "^0.13.11"
+ "regenerator-runtime": "^0.14.0"
}
},
"@babel/template": {
@@ -4523,6 +4652,15 @@
"csstype": "^3.0.2"
}
},
+ "@types/react-csv": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@types/react-csv/-/react-csv-1.1.7.tgz",
+ "integrity": "sha512-MOXBoBrLm3Bz0xxQ1I367PhioZRxjBwmMsSUgckPP04UJw6iHbije37Auct9v+EAHGih2v1eYxchCaoqgJ8idQ==",
+ "dev": true,
+ "requires": {
+ "@types/react": "*"
+ }
+ },
"@types/react-dom": {
"version": "18.2.1",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.1.tgz",
@@ -4779,6 +4917,11 @@
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"dev": true
},
+ "bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+ },
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -4943,6 +5086,16 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
},
+ "csvtojson": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/csvtojson/-/csvtojson-2.0.10.tgz",
+ "integrity": "sha512-lUWFxGKyhraKCW8Qghz6Z0f2l/PqB1W3AO0HKJzGIQ5JRSlR651ekJDiGJbBT4sRNNv5ddnSGVEnsxP9XRCVpQ==",
+ "requires": {
+ "bluebird": "^3.5.1",
+ "lodash": "^4.17.3",
+ "strip-bom": "^2.0.0"
+ }
+ },
"daisyui": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-3.1.1.tgz",
@@ -5493,6 +5646,30 @@
}
}
},
+ "html-parse-stringify": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
+ "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
+ "requires": {
+ "void-elements": "3.1.0"
+ }
+ },
+ "i18next": {
+ "version": "23.6.0",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.6.0.tgz",
+ "integrity": "sha512-z0Cxr0MGkt+kli306WS4nNNM++9cgt2b2VCMprY92j+AIab/oclgPxdwtTZVLP1zn5t5uo8M6uLsZmYrcjr3HA==",
+ "requires": {
+ "@babel/runtime": "^7.22.5"
+ }
+ },
+ "i18next-browser-languagedetector": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.1.0.tgz",
+ "integrity": "sha512-cr2k7u1XJJ4HTOjM9GyOMtbOA47RtUoWRAtt52z43r3AoMs2StYKyjS3URPhzHaf+mn10hY9dZWamga5WPQjhA==",
+ "requires": {
+ "@babel/runtime": "^7.19.4"
+ }
+ },
"ignore": {
"version": "5.2.4",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
@@ -5581,6 +5758,11 @@
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
"dev": true
},
+ "is-utf8": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
+ "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q=="
+ },
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -5673,6 +5855,11 @@
"p-locate": "^5.0.0"
}
},
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
"lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@@ -6000,6 +6187,11 @@
"loose-envify": "^1.1.0"
}
},
+ "react-csv": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/react-csv/-/react-csv-2.2.2.tgz",
+ "integrity": "sha512-RG5hOcZKZFigIGE8LxIEV/OgS1vigFQT4EkaHeKgyuCbUAu9Nbd/1RYq++bJcJJ9VOqO/n9TZRADsXNDR4VEpw=="
+ },
"react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
@@ -6009,6 +6201,15 @@
"scheduler": "^0.23.0"
}
},
+ "react-i18next": {
+ "version": "13.3.1",
+ "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-13.3.1.tgz",
+ "integrity": "sha512-JAtYREK879JXaN9GdzfBI4yJeo/XyLeXWUsRABvYXiFUakhZJ40l+kaTo+i+A/3cKIED41kS/HAbZ5BzFtq/Og==",
+ "requires": {
+ "@babel/runtime": "^7.22.5",
+ "html-parse-stringify": "^3.0.1"
+ }
+ },
"react-icons": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.8.0.tgz",
@@ -6089,9 +6290,9 @@
"requires": {}
},
"regenerator-runtime": {
- "version": "0.13.11",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
- "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
+ "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA=="
},
"reselect": {
"version": "4.1.8",
@@ -6217,6 +6418,14 @@
"ansi-regex": "^5.0.1"
}
},
+ "strip-bom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
+ "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==",
+ "requires": {
+ "is-utf8": "^0.2.0"
+ }
+ },
"strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -6423,6 +6632,11 @@
"rollup": "^3.21.0"
}
},
+ "void-elements": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
+ "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w=="
+ },
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
diff --git a/package.json b/package.json
index 61a4650..ae2d49b 100644
--- a/package.json
+++ b/package.json
@@ -13,10 +13,15 @@
"@reduxjs/toolkit": "^1.9.5",
"autoprefixer": "^10.4.14",
"axios": "^1.4.0",
+ "csvtojson": "^2.0.10",
+ "i18next": "^23.6.0",
+ "i18next-browser-languagedetector": "^7.1.0",
"jquery": "^3.7.0",
"postcss": "^8.4.23",
"react": "^18.2.0",
+ "react-csv": "^2.2.2",
"react-dom": "^18.2.0",
+ "react-i18next": "^13.3.1",
"react-icons": "^4.8.0",
"react-redux": "^8.0.5",
"react-router-dom": "^6.10.0",
@@ -25,6 +30,7 @@
"devDependencies": {
"@types/jquery": "^3.5.16",
"@types/react": "^18.0.28",
+ "@types/react-csv": "^1.1.7",
"@types/react-dom": "^18.0.11",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1",
diff --git a/src/components/BackOfficeComponent.tsx b/src/components/BackOfficeComponent.tsx
index 9e1ce24..821c75a 100644
--- a/src/components/BackOfficeComponent.tsx
+++ b/src/components/BackOfficeComponent.tsx
@@ -6,9 +6,11 @@ import ProjectsComponent from "./apps/ProjectsComponent";
import menu from "../assets/img/menu.png";
import { AdminButtons } from "./faqs/faqsAdminView/AdminButtons";
import BackOfficeUserSendCode from "./BackOfficeUserSendCode";
+import { useTranslation } from "react-i18next";
function ViewBackOffice({ setIsLogged, dispatch }: { readonly setIsLogged: any; readonly dispatch: any }) {
-
+ const [t] = useTranslation();
+
const [state, setState] = useState({
faqs: false,
projectsComponent: false,
@@ -54,21 +56,21 @@ function ViewBackOffice({ setIsLogged, dispatch }: { readonly setIsLogged: any;
handleClickNav('faqs')}>
- FAQs
+ {t("backofficePage.navbarComponent.faqs")}
handleClickNav('apps')}>
- Apps
+ {t("backofficePage.navbarComponent.apps")}
handleClickNav('users')}>
- Usuari@s
+ {t("backofficePage.navbarComponent.users")}
dispatch(setIsLogged(false))} className="flex py-2 px-3 my-4 ml-2">
- Logout
+ {t("backofficePage.navbarComponent.logoutButton")}
diff --git a/src/components/BackOfficeUserSendCode.tsx b/src/components/BackOfficeUserSendCode.tsx
index 20e7864..8adbcff 100644
--- a/src/components/BackOfficeUserSendCode.tsx
+++ b/src/components/BackOfficeUserSendCode.tsx
@@ -7,9 +7,10 @@ import { useDispatch, useSelector } from "react-redux";
import { RootState } from "../store/store";
import { createToken } from "../interfaces/interfaces";
import { AdminButtons } from "./faqs/faqsAdminView/AdminButtons";
+import { useTranslation } from "react-i18next";
const BackOfficeUserSendCode = () => {
-
+ const [t] = useTranslation();
const dispatch = useDispatch()
const { acces_token }: createToken = useSelector(
@@ -89,13 +90,13 @@ const BackOfficeUserSendCode = () => {
-
Invitar nuev@ admin
+
{t("backofficePage.usersComponent.title")}
handleResetEmail('no-reset-email')}
- placeholder="Dirección de email"
+ placeholder={t("backofficePage.usersComponent.emailInput")}
className={`flex my-8 input input-bordered ${colorInput} w-2/3 max-w-xs`}
value={email}
onChange={(e) => setEmail(e.target.value)}
@@ -103,18 +104,18 @@ const BackOfficeUserSendCode = () => {
{error === '' ? (
- Invitar
+ {t("backofficePage.usersComponent.buttonTitle")}
) : error === "ERROR" ? (
- Email inválido
+ {t("backofficePage.usersComponent.emailIncorrect")}
) : showAlert === true && requestStatus==='200' ? (
-
Email enviado
+
{t("backofficePage.usersComponent.emailSendIt")}
) : showAlert === true && requestStatus!=='200' ? (
-
Email no enviado
+
{t("backofficePage.usersComponent.emailNotSendIt")}
) :
(
diff --git a/src/components/Collaborators.tsx b/src/components/Collaborators.tsx
index bd197a7..ae3b6bc 100644
--- a/src/components/Collaborators.tsx
+++ b/src/components/Collaborators.tsx
@@ -1,11 +1,13 @@
import { useState } from "react";
import Card from "./CollaboratorsCard";
import CollaboratorsModal from "./CollaboratorsModal";
+import { useTranslation } from "react-i18next";
function Collaborators() {
+ const [t] = useTranslation();
const [active, setActive] = useState("AngularCard");
// Aconsejo quitarlo, debajo está el resultado solo con el useState de arriba const [selectedItem, setSelectedItem] = useState(1);
- const VT = "Ver Todos >";
+ const VT = t("landingPage.collaboratorsComponent.buttonViewAll");
const btnActive =
" px-6 lg:mb-0 mb-5 ml-2 btn btn-ghost text-sm normal-case rounded-3xl bg-pink-it text-white ";
const btnInactive =
@@ -15,7 +17,7 @@ function Collaborators() {
- Colaboradores de proyectos
+ {t("landingPage.collaboratorsComponent.title")}
diff --git a/src/components/FooterComponent.tsx b/src/components/FooterComponent.tsx
index 4a0badf..94def65 100644
--- a/src/components/FooterComponent.tsx
+++ b/src/components/FooterComponent.tsx
@@ -1,7 +1,11 @@
//import NormativaModal from "../../pages/landingPage/Modals/NormativaModal";
import ImgLogoFooter from '../assets/img/ITA_Logo.png'
-const Footer = () => (
-
+import { useTranslation } from "react-i18next";
+
+const Footer = () => {
+ const [t] = useTranslation();
+ return (
+
-);
+ )
+}
-export default Footer;
+export default Footer
\ No newline at end of file
diff --git a/src/components/HeaderComponent.tsx b/src/components/HeaderComponent.tsx
index 93e6308..c199d5f 100644
--- a/src/components/HeaderComponent.tsx
+++ b/src/components/HeaderComponent.tsx
@@ -8,17 +8,28 @@ import menu from "../assets/img/menu.png";
import LoginComponent from "./LoginComponent";
import RegisterComponent from "./Registercomponent";
import PasswordReminderComponent from "./PasswordReminderComponent";
+import { useTranslation } from "react-i18next";
const Header = () => {
+ const [t, i18n] = useTranslation();
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const [IsDropdownEnterButton, setIsDropdownEnterButton] =
useState(false);
const [isDropdownCuenta, setisDropdownCuenta] = useState(false);
const [isPasswordReminder, setIsPasswordReminder] = useState(false);
+ const [languageSelected, setLanguageSelected] = useState('catala');
+
+ const handleChangeLanguageOfTheWebsite = (lang:string):void => {
+ setLanguageSelected(lang)
+ i18n.changeLanguage(lang)
+ }
const toggleDropdown = (): void => {
setIsDropdownOpen(!isDropdownOpen);
};
+
+ console.log(i18n.language)
+
return (
{/* Logo */}
@@ -36,7 +47,7 @@ const Header = () => {
onClick={toggleDropdown}
>
-
Castellano
+
{t(`landingPage.languagesSwitcher.${languageSelected}`)}
{
isDropdownOpen ? "" : "hidden"
}`}
>
-
+ handleChangeLanguageOfTheWebsite('catala')}>
- Català
+ {t('landingPage.languagesSwitcher.catala')}
{
className="h-53 w-53 scale-90 ml-4 flex-none"
/>
-
+ handleChangeLanguageOfTheWebsite('espanol')}>
- Castellano
+ {t('landingPage.languagesSwitcher.espanol')}
{
className="h-53 w-53 scale-90 ml-4 flex-none"
/>
-
+ handleChangeLanguageOfTheWebsite('english')}>
- English
+ {t('landingPage.languagesSwitcher.english')}
{
- Entrar
+ {t('landingPage.loginModal.login')}
@@ -184,8 +195,7 @@ const Header = () => {
/>
- {" "}
- Castellano{" "}
+ Castellano
@@ -197,7 +207,6 @@ const Header = () => {
/>
- {" "}
English
diff --git a/src/components/LoginComponent.tsx b/src/components/LoginComponent.tsx
index 4e538a1..a135dc7 100644
--- a/src/components/LoginComponent.tsx
+++ b/src/components/LoginComponent.tsx
@@ -12,12 +12,15 @@ import {
ApiPostRegisterState,
FormDataEvent,
} from "../interfaces/interfaces";
+import { useTranslation } from "react-i18next";
+
export default function LoginComponent({
setIsDropdownEnterButton,
setisDropdownCuenta,
setIsPasswordReminder,
}: ChildComponentProps) {
+ const [t] = useTranslation();
const navegador = useNavigate();
const dispatch = useDispatch();
@@ -43,20 +46,20 @@ export default function LoginComponent({
/>
diff --git a/src/components/Registercomponent.tsx b/src/components/Registercomponent.tsx
index 1b9dbb6..97e3a4e 100644
--- a/src/components/Registercomponent.tsx
+++ b/src/components/Registercomponent.tsx
@@ -10,6 +10,7 @@ import {
RootState,
ApiPostRegisterState,
} from "../interfaces/interfaces";
+import { useTranslation } from "react-i18next";
//componente//
@@ -17,6 +18,7 @@ export default function RegisterComponent({
setIsDropdownEnterButton,
setisDropdownCuenta,
}: ChildComponentProps) {
+ const [t] = useTranslation();
const dispatch = useDispatch();
const { messageError, isLoadingMessageError }: ApiPostRegisterState =
useSelector((state: RootState) => state.apiPostRegister);
@@ -39,50 +41,50 @@ export default function RegisterComponent({
/>
-
Registro
+ {t("landingPage.registerModal.title")}
@@ -103,7 +105,7 @@ export default function RegisterComponent({
}}
className="border-b-2 border-black"
>
- ¿Tienes cuenta? acceder
+ {t("landingPage.registerModal.messageLogin")}
diff --git a/src/components/SloganComponent.tsx b/src/components/SloganComponent.tsx
index fc4a654..baf7299 100644
--- a/src/components/SloganComponent.tsx
+++ b/src/components/SloganComponent.tsx
@@ -11,10 +11,16 @@ import nodejsLogo from "../assets/img/nodejs.png";
import gitLogo from "../assets/img/git.png";
import itacademyLogo from "../assets/img/itacademylogo.png";
import HeaderComponent from "./HeaderComponent";
+import selector from "../assets/img/sel_right.png";
+import { useTranslation } from "react-i18next";
+
+
+
const SloganComponent = () => {
const [isPopupOpen, setIsPopupOpen] = useState(false);
-
+ const [t] = useTranslation();
+
const openPopup = () => {
setIsPopupOpen(true);
};
@@ -30,7 +36,7 @@ const SloganComponent = () => {
-
Gana y valida experiencia como programador
+
{t("landingPage.title")}
@@ -69,8 +75,7 @@ const SloganComponent = () => {
- La falta de experiencia te dificulta conseguir trabajo?
- Trabaja en equipo y ponte a prueba con nuestros proyectos
+ {t("landingPage.descriptionHeader")}
@@ -133,6 +138,8 @@ const SloganComponent = () => {
{isPopupOpen &&
}
>
-);
-};
-export default SloganComponent;
\ No newline at end of file
+ )
+}
+
+export default SloganComponent
+
diff --git a/src/components/TeamSectionComponent.tsx b/src/components/TeamSectionComponent.tsx
index 777bc69..68d212e 100644
--- a/src/components/TeamSectionComponent.tsx
+++ b/src/components/TeamSectionComponent.tsx
@@ -6,20 +6,22 @@ import reactLogo from "../assets/img/react.png";
import nodejsLogo from "../assets/img/nodejs.png";
import CardComponent from "./CardComponent";
import ImgVector from "../assets/img/curved-arrow.png";
+import { useTranslation } from "react-i18next";
-const TeamsectionComponent = () => (
-
+const TeamSectionComponent = () => {
+ const [t] = useTranslation();
+ return (
+
- Equipos de trabajo
+ {t("landingPage.teamComponent.title")}
- Los proyectos son realizados por equipos que combinan las siguientes
- tecnologías
+ {t("landingPage.teamComponent.description")}
@@ -60,6 +62,7 @@ const TeamsectionComponent = () => (
/>
-);
+ )
+}
-export default TeamsectionComponent;
+export default TeamSectionComponent
diff --git a/src/components/apps/Apps.tsx b/src/components/apps/Apps.tsx
index 4647cfc..c4ef570 100644
--- a/src/components/apps/Apps.tsx
+++ b/src/components/apps/Apps.tsx
@@ -7,6 +7,8 @@ import { useDispatch, useSelector } from "react-redux";
import ModalApps from "./appsAdminView/modalApps";
import trashIcon from "../../assets/img/icon-delete-faq-backoffice.png"
import githubLogo from "../../assets/img/githubLogo.svg"
+import { useTranslation } from "react-i18next";
+
declare global {
interface Window {
@@ -17,14 +19,15 @@ declare global {
}
const Apps = () => {
- const { acces_token }: createToken = useSelector(
- (state: RootState) => state.apiPostRegister
+ const { acces_token }: createToken = useSelector(
+ (state: RootState) => state.apiPostRegister
);
-
+
const { apps }: ApiStateApps = useSelector(
- (state: RootState) => state.appsCallApiFunctionality
- );
-
+ (state: RootState) => state.appsCallApiFunctionality
+ );
+
+ const [t] = useTranslation();
const handleSendApiInfo = (id: number) => {
apiCallAppsInfo(dispatch, id, acces_token);
};
@@ -57,7 +60,7 @@ const Apps = () => {
>
{window.location.pathname === "/backoffice" && (
);
diff --git a/src/components/apps/appsAdminView/CreateApp.tsx b/src/components/apps/appsAdminView/CreateApp.tsx
index 4196c88..5644847 100644
--- a/src/components/apps/appsAdminView/CreateApp.tsx
+++ b/src/components/apps/appsAdminView/CreateApp.tsx
@@ -5,8 +5,11 @@ import { createToken } from "../../../interfaces/interfaces";
import { useState } from "react";
import ModalsAddApps from "./ModalsAddApps";
import plusIcon from "../../../assets/img/plus.svg"
+import { useTranslation } from "react-i18next";
+
+
declare global {
- interface Window {
+ interface Window {
my_modal_2: {
showModal: () => void;
};
@@ -14,6 +17,7 @@ declare global {
}
const CreateApp = () => {
+ const [t] = useTranslation();
const dispatch = useDispatch();
@@ -44,7 +48,7 @@ const CreateApp = () => {
className="flex w-full h-56 md:h-full justify-center items-center rounded-xl border-dashed border-2 border-[#7e7e7e]"
>
-
Crear nueva app
+
{t("backofficePage.appsComponent.createButton.createButtonTitle")}
diff --git a/src/components/apps/appsAdminView/ModalsAddApps.tsx b/src/components/apps/appsAdminView/ModalsAddApps.tsx
index cd32964..50f222a 100644
--- a/src/components/apps/appsAdminView/ModalsAddApps.tsx
+++ b/src/components/apps/appsAdminView/ModalsAddApps.tsx
@@ -1,4 +1,6 @@
import Cross from "../../../assets/img/cross.png";
+import { useTranslation } from "react-i18next";
+
export default function ModalsAddApps({
newInfoApps,
setNewInfoApps,
@@ -8,7 +10,7 @@ export default function ModalsAddApps({
setNewInfoApps: any;
sendInfo: any;
}) {
-
+ const [t] = useTranslation();
return (
<>
@@ -18,7 +20,7 @@ export default function ModalsAddApps({
setNewInfoApps({ ...newInfoApps, title: e.target.value })
}
@@ -35,9 +37,9 @@ export default function ModalsAddApps({
/>
-
Url del proyecto
+ {t("backofficePage.appsComponent.createButton.urlProjectTitle")}
setNewInfoApps({ ...newInfoApps, url: e.target.value })
}
@@ -47,9 +49,9 @@ export default function ModalsAddApps({
-
Url del repositorio de GitHub
+ {t("backofficePage.appsComponent.createButton.urlGitHubTitle")}
setNewInfoApps({ ...newInfoApps, github: e.target.value })
}
@@ -58,7 +60,7 @@ export default function ModalsAddApps({
/>
- Estado
+ {t("backofficePage.appsComponent.createButton.state")}
{ setNewInfoApps({ ...newInfoApps, state: "COMPLETED" })}}
@@ -68,7 +70,7 @@ export default function ModalsAddApps({
: "cursor-pointer p-3"
} text-sm`}
>
- Completada
+ {t("backofficePage.appsComponent.createButton.status.finished")}
{setNewInfoApps({ ...newInfoApps, state: "IN PROGRESS" })}}
@@ -78,7 +80,7 @@ export default function ModalsAddApps({
: "cursor-pointer p-3 ml-2"
} text-sm`}
>
- En progreso
+ {t("backofficePage.appsComponent.createButton.status.construction")}
{setNewInfoApps({ ...newInfoApps, state: "SOON" })}}
@@ -88,13 +90,13 @@ export default function ModalsAddApps({
: "cursor-pointer p-3 ml-2"
} text-sm`}
>
- Próximamente
+ {t("backofficePage.appsComponent.createButton.status.soon")}
- Cancelar
- Crear
+ {t("backofficePage.appsComponent.createButton.closeButton")}
+ {t("backofficePage.appsComponent.createButton.saveButton")}
diff --git a/src/components/apps/appsAdminView/modalApps.tsx b/src/components/apps/appsAdminView/modalApps.tsx
index 8a7efb7..37e4a89 100644
--- a/src/components/apps/appsAdminView/modalApps.tsx
+++ b/src/components/apps/appsAdminView/modalApps.tsx
@@ -4,6 +4,8 @@ import { RootState } from "../../../store/store";
import { putApiApps } from "../../../store/reducers/appsCall/appsCallApiFunctionality";
import Cross from "../../../assets/img/cross.png";
import { createToken } from "../../../interfaces/interfaces";
+import { useTranslation } from "react-i18next";
+
export default function ModalApps({
newInfoApps,
setNewInfoApps,
@@ -11,6 +13,7 @@ export default function ModalApps({
newInfoApps: any;
setNewInfoApps: React.Dispatch>;
}) {
+ const [t] = useTranslation();
const dispatch = useDispatch();
const { acces_token }: createToken = useSelector(
(state: RootState) => state.apiPostRegister
@@ -60,9 +63,9 @@ export default function ModalApps({
/>
-
Url del proyecto
+ {t("backofficePage.appsComponent.editButton.urlProjectTitle")}
setNewInfoApps({ ...newInfoApps, url: e.target.value })
@@ -73,9 +76,9 @@ export default function ModalApps({
-
Url del repositorio de GitHub
+ {t("backofficePage.appsComponent.editButton.urlGitHubTitle")}
setNewInfoApps({ ...newInfoApps, github: e.target.value })
@@ -85,7 +88,7 @@ export default function ModalApps({
/>
- Estado
+ {t("backofficePage.appsComponent.editButton.state")}
{
@@ -97,7 +100,7 @@ export default function ModalApps({
: "cursor-pointer p-3"
} text-sm`}
>
- Completada
+ {t("backofficePage.appsComponent.editButton.status.finished")}
{
@@ -109,7 +112,7 @@ export default function ModalApps({
: "cursor-pointer p-3 ml-2"
} text-sm`}
>
- En progreso
+ {t("backofficePage.appsComponent.editButton.status.construction")}
{
@@ -121,18 +124,18 @@ export default function ModalApps({
: "cursor-pointer p-3 ml-2"
} text-sm`}
>
- Próximamente
+ {t("backofficePage.appsComponent.editButton.status.soon")}
- Cancelar
+ {t("backofficePage.appsComponent.editButton.closeButton")}
putApiApps(newInfoApps, acces_token, dispatch, appsInfo.id)
}
>
- Guardar
+ {t("backofficePage.appsComponent.editButton.saveButton")}
diff --git a/src/components/apps/appsHomepageView/TasksProcess.tsx b/src/components/apps/appsHomepageView/TasksProcess.tsx
index 2d296c1..f7644da 100644
--- a/src/components/apps/appsHomepageView/TasksProcess.tsx
+++ b/src/components/apps/appsHomepageView/TasksProcess.tsx
@@ -1,7 +1,9 @@
import { FaRegCircle } from "react-icons/fa";
import { IconContext } from "react-icons";
+import { useTranslation } from "react-i18next";
const TasksProcess = () => {
+ const [t] = useTranslation();
return (
@@ -9,14 +11,15 @@ const TasksProcess = () => {
value={{ color: "#bedfc8", className: "global-class-name" }}
>
- Terminadas
+ {t("landingPage.appsComponent.status.finished")}
- En construcción
+
+ {t("landingPage.appsComponent.status.construction")}
@@ -24,7 +27,7 @@ const TasksProcess = () => {
value={{ color: "#f7cbc4", className: "global-class-name" }}
>
- Próximamente
+ {t("landingPage.appsComponent.status.soon")}
diff --git a/src/components/apps/appsHomepageView/TitleApps.tsx b/src/components/apps/appsHomepageView/TitleApps.tsx
index 73a5489..5bcac53 100644
--- a/src/components/apps/appsHomepageView/TitleApps.tsx
+++ b/src/components/apps/appsHomepageView/TitleApps.tsx
@@ -1,6 +1,8 @@
import curvedArrow from "../../../assets/img/curvedArrow.svg";
+import { useTranslation } from "react-i18next";
const TitleApps = () => {
+ const [t] = useTranslation();
return (
{
>
- Directorio de aplicaciones IT Academy
+ {t("landingPage.appsComponent.title")}
);
diff --git a/src/components/faqs/FAQsComponent.tsx b/src/components/faqs/FAQsComponent.tsx
index 6ec4001..ccf4547 100644
--- a/src/components/faqs/FAQsComponent.tsx
+++ b/src/components/faqs/FAQsComponent.tsx
@@ -6,6 +6,7 @@ import { apiCall, putApiFaqs } from "../../store/reducers/faqsCall/faqsReducer";
import deleteFaqIcon from "../../assets/img/icon-delete-faq-backoffice.png";
import DeleteFaqModal from "./Modals/DeleteFaqModal";
import { AdminButtons } from "./faqsAdminView/AdminButtons";
+import { useTranslation } from "react-i18next";
const FAQs = () => {
//Interfaces//
@@ -45,20 +46,15 @@ const FAQs = () => {
setFaqClone(faqs);
}, [faqs]);
+ const [t] = useTranslation();
const [faqsClone, setFaqClone] = useState(faqs); // Clone Faqs
-
const [selectedFaqId, setSelectedFaqId] = useState(null); // FaqId selected
-
const [deleteModal, setDeleteModal] = useState(false); // DeleteModal
-
const [titleButtons, setTitleButtons] = useState(true); // Editar & Eliminar buttons
const [descriptionButtons, setDescriptionButtons] = useState(false); // Cancelar & Guardar buttons
-
const [isContentEditing, setIsContentIsEditing] = useState(false); // Title & Description editable
-
const [inputNewTitleValue, setInputNewTitleValue] = useState(""); // New Title input
const [inputNewDescriptionValue, setInputNewDescriptionValue] = useState(""); // New Description input
-
const [positionIndex, setPositionIndex] = useState("");
const displayInput = (index: number, faq: any) => {
@@ -127,7 +123,7 @@ const FAQs = () => {
{window.location.pathname === "/" && (
- Preguntas frecuentes
+ {t("landingPage.faqsComponent.title")}
)}
@@ -167,7 +163,7 @@ const FAQs = () => {
className="mx-4 px-4 border-gray-500 h-[30px] self-center"
onClick={() => displayInput(index, faqsClone[index])}
>
- Editar
+ {t("backofficePage.faqsComponent.editButton.editButtonTitle")}
{
className="mr-5 xl:px-7 btn btn-outline-primary border-gray-600 bg-transparent text-gray-600"
onClick={() => cancelEditing(index, faqsClone[index])}
>
- Cancelar
+ {t("backofficePage.faqsComponent.editButton.closeButton")}
saveEditingFaq(index)}
>
- Guardar
+ {t("backofficePage.faqsComponent.editButton.saveButton")}
)}
diff --git a/src/components/faqs/Modals/DeleteFaqModal.tsx b/src/components/faqs/Modals/DeleteFaqModal.tsx
index 1a72cbc..5aa8baf 100644
--- a/src/components/faqs/Modals/DeleteFaqModal.tsx
+++ b/src/components/faqs/Modals/DeleteFaqModal.tsx
@@ -1,6 +1,7 @@
import { deleteApiFaqs } from "../../../store/reducers/faqsCall/faqsReducer";
import locker from '../../../assets/img/locker.png';
import { Dispatch } from "@reduxjs/toolkit";
+import { useTranslation } from "react-i18next";
interface DeleteFaqModalProps{
deleteModal: (flag: boolean) => void;
faqId: number;
@@ -9,7 +10,7 @@ interface DeleteFaqModalProps{
}
function DeleteFaqModal({ deleteModal, faqId, acces_token, dispatch }: DeleteFaqModalProps) {
- console.log(faqId)
+ const [t] = useTranslation();
return (
@@ -18,12 +19,12 @@ function DeleteFaqModal({ deleteModal, faqId, acces_token, dispatch }: DeleteFaq
-
¿Estás segur@?
-
Esta acción eliminará el elemento seleccionado
+
{t("backofficePage.faqsComponent.deleteButton.deleteButtonTitle")}
+
{t("backofficePage.faqsComponent.deleteButton.text")}
-
deleteApiFaqs(faqId, acces_token, dispatch)}> Eliminar
+
deleteApiFaqs(faqId, acces_token, dispatch)}> {t("backofficePage.faqsComponent.deleteButton.saveButton")}
-
deleteModal(false)}> Cancelar
+
deleteModal(false)}> {t("backofficePage.faqsComponent.deleteButton.closeButton")}
diff --git a/src/components/faqs/faqsAdminView/FaqsModified.tsx b/src/components/faqs/faqsAdminView/FaqsModified.tsx
index 4e4f22a..fd6dd67 100644
--- a/src/components/faqs/faqsAdminView/FaqsModified.tsx
+++ b/src/components/faqs/faqsAdminView/FaqsModified.tsx
@@ -3,6 +3,9 @@ import { useDispatch, useSelector } from "react-redux";
import { useState } from "react";
import { postApiFaqs } from "../../../store/reducers/faqsCall/faqsReducer";
import { createToken } from "../../../interfaces/interfaces";
+import { useTranslation } from "react-i18next";
+
+
export default function FaqsModified() {
const { acces_token }: createToken = useSelector(
(state: RootState) => state.apiPostRegister
@@ -10,6 +13,7 @@ export default function FaqsModified() {
//constantes para el set //
const dispatch = useDispatch();
+ const [t] = useTranslation();
const [faqsContent, setFaqsContent] = useState<{
title: string;
description: string;
@@ -34,13 +38,13 @@ export default function FaqsModified() {
setIsOpen(true)} />
- {isOpen ?
setFaqsContent({ ...faqsContent, title: e.target.value })} value={faqsContent.title}/> :
Crear nueva pregunta
}
+ {isOpen ?
setFaqsContent({ ...faqsContent, title: e.target.value })} value={faqsContent.title}/> :
{t("backofficePage.faqsComponent.createNewQuestion.createNewQuestionTitle")}
}
-
+
- Cancelar
- Crear
+ {t("backofficePage.faqsComponent.createNewQuestion.closeButton")}
+ {t("backofficePage.faqsComponent.createNewQuestion.saveButton")}
diff --git a/src/main.tsx b/src/main.tsx
index 839e10b..0586185 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -6,13 +6,17 @@ import "./styles/tailwind.css";
import { BrowserRouter } from "react-router-dom";
import { Provider } from "react-redux";
import { store } from "./store/store.tsx";
+import { I18nextProvider } from "react-i18next";
+import i18n from "../src/translation/i18n.ts";
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
-
+
+
+
diff --git a/src/translation/CsvToJsonConverter.tsx b/src/translation/CsvToJsonConverter.tsx
new file mode 100644
index 0000000..63dfeb9
--- /dev/null
+++ b/src/translation/CsvToJsonConverter.tsx
@@ -0,0 +1,58 @@
+import React, { useState } from "react";
+import * as csv from "csvtojson";
+
+const CSVtoJSONConverter: React.FC = () => {
+ const [jsonContent, setJSONContent] = useState(null);
+
+ const handleFileChange = async (e: React.ChangeEvent) => {
+ const file = e.target.files?.[0];
+
+ if (file) {
+ const reader = new FileReader();
+ reader.onload = async (event) => {
+ const csvData = event.target?.result as string;
+ const jsonArray = await convertCSVtoJSON(csvData);
+ setJSONContent(JSON.stringify(jsonArray, null, 2));
+ };
+ reader.readAsText(file);
+ }
+ };
+
+ const convertCSVtoJSON = async (csvData: string) => {
+ try {
+ const jsonArray = await csv().fromString(csvData);
+ return jsonArray;
+ } catch (error) {
+ console.error("Error converting CSV to JSON:", error);
+ return [];
+ }
+ };
+
+ const handleDownloadJSON = () => {
+ if (jsonContent) {
+ const blob = new Blob([jsonContent], { type: "application/json" });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = "data.json";
+ a.click();
+ URL.revokeObjectURL(url);
+ }
+ };
+
+ return (
+
+
CSV to JSON Converter
+
+ {jsonContent && (
+
+
Download JSON
+
JSON Output:
+
{jsonContent}
+
+ )}
+
+ );
+};
+
+export default CSVtoJSONConverter;
diff --git a/src/translation/JsonToCsvConverter.tsx b/src/translation/JsonToCsvConverter.tsx
new file mode 100644
index 0000000..bf74450
--- /dev/null
+++ b/src/translation/JsonToCsvConverter.tsx
@@ -0,0 +1,35 @@
+import { CSVLink } from "react-csv"
+
+const headers = [
+ { label: "First Name", key: "firstName" },
+ { label: "Last Name", key: "lastName" },
+ { label: "Email", key: "email" },
+];
+
+const data = [
+ {
+ firstName: "Naruto",
+ lastName: "Uzumaki",
+ email: "dasdas@gmail.com"
+ },
+ {
+ firstName: "Albert",
+ lastName: "Lanza",
+ email: "ladskdaskdma@gmail.com"
+ },
+ {
+ firstName: "Maria",
+ lastName: "Perez",
+ email: "maria@gmail.com"
+ }
+]
+
+const JsonToCsvConverter = () => {
+ return (
+
+
+
+ )
+}
+
+export default JsonToCsvConverter
\ No newline at end of file
diff --git a/src/translation/files_csv/catala.csv b/src/translation/files_csv/catala.csv
new file mode 100644
index 0000000..e69de29
diff --git a/src/translation/files_csv/english.csv b/src/translation/files_csv/english.csv
new file mode 100644
index 0000000..e69de29
diff --git a/src/translation/files_csv/espanol.csv b/src/translation/files_csv/espanol.csv
new file mode 100644
index 0000000..e69de29
diff --git a/src/translation/i18n.d.ts b/src/translation/i18n.d.ts
new file mode 100644
index 0000000..a7afe7f
--- /dev/null
+++ b/src/translation/i18n.d.ts
@@ -0,0 +1,14 @@
+import catala from "../translation/languages/catala.json";
+import english from "../translation/languages/english.json";
+import espanol from "../translation/languages/espanol.json";
+
+declare module "i18next" {
+ interface CustomTypeOptions {
+ defaultNS: "ca";
+ resources: {
+ ca: typeof catala;
+ es: typeof espanol;
+ en: typeof english;
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/translation/i18n.ts b/src/translation/i18n.ts
new file mode 100644
index 0000000..9048fba
--- /dev/null
+++ b/src/translation/i18n.ts
@@ -0,0 +1,26 @@
+import i18next from 'i18next';
+import catala from "../translation/languages/catala.json";
+import english from "../translation/languages/english.json";
+import espanol from "../translation/languages/espanol.json";
+export const defaultNS = 'ns1';
+export const fallbackNS = 'fallback';
+
+i18next.init({
+ debug: true,
+ fallbackLng: 'catala',
+ defaultNS,
+ fallbackNS,
+ resources: {
+ catala: {
+ ns1: catala
+ },
+ espanol: {
+ ns1: espanol
+ },
+ english: {
+ ns1: english
+ }
+ },
+});
+
+export default i18next;
\ No newline at end of file
diff --git a/src/translation/languages/catala.json b/src/translation/languages/catala.json
new file mode 100644
index 0000000..cd4a5a2
--- /dev/null
+++ b/src/translation/languages/catala.json
@@ -0,0 +1,127 @@
+{
+ "landingPage": {
+ "title": "Guanya i valida experiència com a programador",
+ "buttonCollaborate": "Com col·laborar?",
+ "descriptionHeader": "La falta d'experiència et dificulta conseguir treball? Treballa en equip i posat a prova amb els nostre projectes",
+ "languagesSwitcher": {
+ "catala": "Català",
+ "espanol": "Castellà",
+ "english": "Anglès"
+ },
+ "loginModal": {
+ "login": "Iniciar sessió",
+ "dniInput": "DNI o NIE",
+ "passwordInput": "Constrasenya",
+ "changePassword": "Recordar/Canviar contrasenya",
+ "registerMessage": "No tens ningún compte? Crea'n un!"
+ },
+ "registerModal": {
+ "title": "Registre",
+ "dniInput": "DNI o NIE",
+ "emailInput": "Email",
+ "passwordInput": "Constrasenya",
+ "passwordRepeatInput": "Repeteix contrasenya",
+ "nameInput": "Nom",
+ "codeInput": "Codi de confirmació",
+ "titleButton": "Registrat",
+ "messageLogin": "Tens compte? Inicia sessió"
+ },
+ "appsComponent": {
+ "title": "Directori d'aplicacions IT Academy",
+ "status": {
+ "finished": "Acabades",
+ "construction": "En construcció",
+ "soon": "Pròximament"
+ }
+ },
+ "teamComponent": {
+ "title": "Equips de treball",
+ "description": "Els projectes son realitzats per equips que combinen les següents tecnologies"
+ },
+ "collaboratorsComponent": {
+ "title": "Col·laboradors de projectes",
+ "buttonViewAll": "Veure tots >"
+ },
+ "faqsComponent": {
+ "title": "Preguntes freqüents"
+ },
+ "footer": {
+ "institution": "Barcelona Activa",
+ "academy": "IT Academy",
+ "buttonCollaborate": "Com col·laborar?",
+ "normative": "Normativa",
+ "terms": "Termes",
+ "privacity": "Privacitat",
+ "cookies": "Galetes"
+ }
+ },
+ "backofficePage": {
+ "navbarComponent": {
+ "faqs": "FAQs",
+ "apps": "Apps",
+ "users": "Usuaris",
+ "logoutButton": "Sortir"
+ },
+ "faqsComponent": {
+ "title": "FAQs",
+ "createNewQuestion": {
+ "createNewQuestionTitle": "Crear nova pregunta",
+ "textareaInput": "Resposta",
+ "closeButton": "Cancel·lar",
+ "saveButton": "Guardar"
+ },
+ "editButton": {
+ "editButtonTitle": "Editar",
+ "closeButton": "Cancel·lar",
+ "saveButton": "Guardar"
+ },
+ "deleteButton": {
+ "deleteButtonTitle": "Estàs segur?",
+ "text": "Aquesta acció eliminarà l'element seleccionat",
+ "closeButton": "Cancel·lar",
+ "saveButton": "Guardar"
+ }
+ },
+ "appsComponent": {
+ "title": "Apps",
+ "appLink": "Anar a l'app",
+ "editButton": {
+ "editButtonTitle": "Editar",
+ "urlProjectTitle": "Url del projecte",
+ "urlGitHubTitle": "Url del repositori de GitHub",
+ "inputText": "Escriu aquí",
+ "state": "Estat",
+ "status": {
+ "finished": "Acabada",
+ "construction": "En construcció",
+ "soon": "Pròximament"
+ },
+ "closeButton": "Cancel·lar",
+ "saveButton": "Guardar"
+ },
+ "createButton": {
+ "createButtonTitle": "Crear nova aplicació",
+ "titleInput": "Escriu aquí el título",
+ "urlProjectTitle": "Url del projecte",
+ "urlGitHubTitle": "Url del repositori de GitHub",
+ "inputText": "Escriu aquí",
+ "state": "Estat",
+ "status": {
+ "finished": "Acabada",
+ "construction": "En construcció",
+ "soon": "Pròximament"
+ },
+ "closeButton": "Cancel·lar",
+ "saveButton": "Crear"
+ }
+ },
+ "usersComponent": {
+ "title": "Invitar nou/nova admin",
+ "emailInput": "Direcció d'email",
+ "emailIncorrect": "Email invàlid",
+ "emailSendIt": "Email enviat",
+ "emailNotSendIt": "Email no enviat",
+ "buttonTitle": "Invitar"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/translation/languages/english.json b/src/translation/languages/english.json
new file mode 100644
index 0000000..a713979
--- /dev/null
+++ b/src/translation/languages/english.json
@@ -0,0 +1,127 @@
+{
+ "landingPage": {
+ "title": "Gain and validate experience as a programmer",
+ "buttonCollaborate": "How to collaborate?",
+ "descriptionHeader": "Does lack of experience make it difficult for you to find a job? Work as a team and challenge yourself with our projects.",
+ "languagesSwitcher": {
+ "catala": "Catalan",
+ "espanol": "Spanish",
+ "english": "English"
+ },
+ "loginModal": {
+ "login": "Log In",
+ "dniInput": "DNI or NIE",
+ "passwordInput": "Password",
+ "changePassword": "Remember/Change password",
+ "registerMessage": "Don't have an account? Create one!"
+ },
+ "registerModal": {
+ "title": "Registration",
+ "dniInput": "DNI or NIE",
+ "emailInput": "Email",
+ "passwordInput": "Password",
+ "passwordRepeatInput": "Repeat password",
+ "nameInput": "Name",
+ "codeInput": "Confirmation code",
+ "titleButton": "Register",
+ "messageLogin": "Do you have an account? Log in"
+ },
+ "appsComponent": {
+ "title": "IT Academy Applications Directory",
+ "status": {
+ "finished": "Finished",
+ "construction": "Under construction",
+ "soon": "Coming soon"
+ }
+ },
+ "teamComponent": {
+ "title": "Work teams",
+ "description": "The projects are carried out by teams that combine the following technologies"
+ },
+ "collaboratorsComponent": {
+ "title": "Project collaborators",
+ "buttonViewAll": "View all >"
+ },
+ "faqsComponent": {
+ "title": "Frequently questions"
+ },
+ "footer": {
+ "institution": "Barcelona Activa",
+ "academy": "IT Academy",
+ "buttonCollaborate": "How to collaborate?",
+ "normative": "Regulations",
+ "terms": "Terms",
+ "privacity": "Privacity",
+ "cookies": "Cookies"
+ }
+ },
+ "backofficePage": {
+ "navbarComponent": {
+ "faqs": "FAQs",
+ "apps": "Apps",
+ "users": "Users",
+ "logoutButton": "Log out"
+ },
+ "faqsComponent": {
+ "title": "FAQs",
+ "createNewQuestion": {
+ "createNewQuestionTitle": "Create new question",
+ "textareaInput": "Response",
+ "closeButton": "Cancel",
+ "saveButton": "Save"
+ },
+ "editButton": {
+ "editButtonTitle": "Edit",
+ "closeButton": "Cancel",
+ "saveButton": "Save"
+ },
+ "deleteButton": {
+ "deleteButtonTitle": "Are you sure?",
+ "text": "This action will delete the selected item",
+ "closeButton": "Cancel",
+ "saveButton": "Save"
+ }
+ },
+ "appsComponent": {
+ "title": "Apps",
+ "appLink": "Go to the app",
+ "editButton": {
+ "editButtonTitle": "Edit",
+ "urlProjectTitle": "Project url",
+ "urlGitHubTitle": "GitHub repository url",
+ "inputText": "Write here",
+ "state": "Status",
+ "status": {
+ "finished": "Finished",
+ "construction": "Under construction",
+ "soon": "Coming soon"
+ },
+ "closeButton": "Cancel",
+ "saveButton": "Save"
+ },
+ "createButton": {
+ "createButtonTitle": "Create new app",
+ "titleInput": "Write the title here",
+ "urlProjectTitle": "Project url",
+ "urlGitHubTitle": "GitHub repository url",
+ "inputText": "Write here",
+ "state": "Status",
+ "status": {
+ "finished": "Finished",
+ "construction": "Under construction",
+ "soon": "Coming soon"
+ },
+ "closeButton": "Cancel",
+ "saveButton": "Create"
+ }
+ },
+ "usersComponent": {
+ "title": "Invite new admin",
+ "emailInput": "Email adress",
+ "emailIncorrect": "Invalid email",
+ "emailSendIt": "Email send",
+ "emailNotSendIt": "Email not send",
+ "buttonTitle": "Invite"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/translation/languages/espanol.json b/src/translation/languages/espanol.json
new file mode 100644
index 0000000..ea325a4
--- /dev/null
+++ b/src/translation/languages/espanol.json
@@ -0,0 +1,127 @@
+{
+ "landingPage": {
+ "title": "Gana y valida experiencia como programador",
+ "buttonCollaborate": "¿Cómo colaborar?",
+ "descriptionHeader": "¿La falta de experiencia te dificulta conseguir trabajo? Trabaja en equipo y ponte a prueba con nuestros proyectos",
+ "languagesSwitcher": {
+ "catala": "Catalán",
+ "espanol": "Castellano",
+ "english": "Inglés"
+ },
+ "loginModal": {
+ "login": "Iniciar sessión",
+ "dniInput": "DNI o NIE",
+ "passwordInput": "Contraseña",
+ "changePassword": "Recordar/Cambiar contraseña",
+ "registerMessage": "No tienes ninguna cuenta? Crea una!"
+ },
+ "registerModal": {
+ "title": "Registro",
+ "dniInput": "DNI o NIE",
+ "emailInput": "Email",
+ "passwordInput": "Constraseña",
+ "passwordRepeatInput": "Repite contraseña",
+ "nameInput": "Nombre",
+ "codeInput": "Código de confirmación",
+ "titleButton": "Registrate",
+ "messageLogin": "¿Tienes cuenta? Inicia sessión"
+ },
+ "appsComponent": {
+ "title": "Directorio de aplicaciones IT Academy",
+ "status": {
+ "finished": "Finalizadas",
+ "construction": "En construcción",
+ "soon": "Próximamente"
+ }
+ },
+ "teamComponent": {
+ "title": "Equipos de trabajo",
+ "description": "Los proyectos son realizados por equipos que combinan las siguientes tecnologías"
+ },
+ "collaboratorsComponent": {
+ "title": "Colaboradores de proyectos",
+ "buttonViewAll": "Ver todos >"
+ },
+ "faqsComponent": {
+ "title": "Preguntas frecuentes"
+ },
+ "footer": {
+ "institution": "Barcelona Activa",
+ "academy": "IT Academy",
+ "buttonCollaborate": "¿Cómo colaborar?",
+ "normative": "Normativa",
+ "terms": "Términos",
+ "privacity": "Privacidad",
+ "cookies": "Galletas"
+ }
+ },
+ "backofficePage": {
+ "navbarComponent": {
+ "faqs": "FAQs",
+ "apps": "Apps",
+ "users": "Usuarios",
+ "logoutButton": "Salir"
+ },
+ "faqsComponent": {
+ "title": "FAQs",
+ "createNewQuestion": {
+ "createNewQuestionTitle": "Crear nueva pregunta",
+ "textareaInput": "Respuesta",
+ "closeButton": "Cancelar",
+ "saveButton": "Guardar"
+ },
+ "editButton": {
+ "editButtonTitle": "Editar",
+ "closeButton": "Cancelar",
+ "saveButton": "Guardar"
+ },
+ "deleteButton": {
+ "deleteButtonTitle": "¿Estás seguro?",
+ "text": "Esta acción eliminará el elemento seleccionado",
+ "closeButton": "Cancelar",
+ "saveButton": "Guardar"
+ }
+ },
+ "appsComponent": {
+ "title": "Apps",
+ "appLink": "Ir a la app",
+ "editButton": {
+ "editButtonTitle": "Editar",
+ "urlProjectTitle": "Url del proyecto",
+ "urlGitHubTitle": "Url del repositorio de GitHub",
+ "inputText": "Escribe aquí",
+ "state": "Estado",
+ "status": {
+ "finished": "Acabada",
+ "construction": "En construcción",
+ "soon": "Próximamente"
+ },
+ "closeButton": "Cancelar",
+ "saveButton": "Guardar"
+ },
+ "createButton": {
+ "createButtonTitle": "Crear nueva aplicación",
+ "titleInput": "Escribe aquí el título",
+ "urlProjectTitle": "Url del proyecto",
+ "urlGitHubTitle": "Url del repositorio de GitHub",
+ "inputText": "Escribe aquí",
+ "state": "Estado",
+ "status": {
+ "finished": "Acabada",
+ "construction": "En construcción",
+ "soon": "Próximamente"
+ },
+ "closeButton": "Cancelar",
+ "saveButton": "Crear"
+ }
+ },
+ "usersComponent": {
+ "title": "Invitar nuevo/nueva admin",
+ "emailInput": "Dirección de email",
+ "emailIncorrect": "Email inválido",
+ "emailSendIt": "Email enviado",
+ "emailNotSendIt": "Email no enviado",
+ "buttonTitle": "Invitar"
+ }
+ }
+}
\ No newline at end of file