dev #105

Merged
Thibaut merged 8 commits from dev into master 2026-01-23 15:49:25 +00:00
4 changed files with 83 additions and 45 deletions
Showing only changes of commit 3d8597869d - Show all commits

View File

@ -18,7 +18,7 @@
"@fortawesome/react-fontawesome": "^3.1.1", "@fortawesome/react-fontawesome": "^3.1.1",
"axios": "^1.13.2", "axios": "^1.13.2",
"browser-image-compression": "^2.0.2", "browser-image-compression": "^2.0.2",
"i18next": "^25.7.4", "i18next": "^25.8.0",
"i18next-browser-languagedetector": "^8.2.0", "i18next-browser-languagedetector": "^8.2.0",
"i18next-http-backend": "^3.0.2", "i18next-http-backend": "^3.0.2",
"jszip": "^3.10.1", "jszip": "^3.10.1",
@ -33,12 +33,12 @@
"react-loader-spinner": "^8.0.2", "react-loader-spinner": "^8.0.2",
"react-router-dom": "^7.12.0", "react-router-dom": "^7.12.0",
"react-toastify": "^11.0.5", "react-toastify": "^11.0.5",
"recharts": "^3.6.0", "recharts": "^3.7.0",
"xlsx": "^0.18.5", "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
"xlsx-js-style": "^1.2.0" "xlsx-js-style": "^1.2.0"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^19.2.8", "@types/react": "^19.2.9",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.2", "@vitejs/plugin-react": "^5.1.2",
"eslint": "^9.39.2", "eslint": "^9.39.2",
@ -1606,9 +1606,9 @@
"dev": true "dev": true
}, },
"node_modules/@types/react": { "node_modules/@types/react": {
"version": "19.2.8", "version": "19.2.9",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.8.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.9.tgz",
"integrity": "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==", "integrity": "sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA==",
"devOptional": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"peer": true, "peer": true,
@ -2048,14 +2048,6 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/codepage": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/combined-stream": { "node_modules/combined-stream": {
"version": "1.0.8", "version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@ -3357,9 +3349,9 @@
} }
}, },
"node_modules/i18next": { "node_modules/i18next": {
"version": "25.7.4", "version": "25.8.0",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.7.4.tgz", "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.0.tgz",
"integrity": "sha512-hRkpEblXXcXSNbw8mBNq9042OEetgyB/ahc/X17uV/khPwzV+uB8RHceHh3qavyrkPJvmXFKXME2Sy1E0KjAfw==", "integrity": "sha512-urrg4HMFFMQZ2bbKRK7IZ8/CTE7D8H4JRlAwqA2ZwDRFfdd0K/4cdbNNLgfn9mo+I/h9wJu61qJzH7jCFAhUZQ==",
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@ -3374,6 +3366,7 @@
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
} }
], ],
"license": "MIT",
"peer": true, "peer": true,
"dependencies": { "dependencies": {
"@babel/runtime": "^7.28.4" "@babel/runtime": "^7.28.4"
@ -4674,9 +4667,13 @@
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
}, },
"node_modules/recharts": { "node_modules/recharts": {
"version": "3.6.0", "version": "3.7.0",
"resolved": "https://registry.npmjs.org/recharts/-/recharts-3.6.0.tgz", "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.7.0.tgz",
"integrity": "sha512-L5bjxvQRAe26RlToBAziKUB7whaGKEwD3znoM6fz3DrTowCIC/FnJYnuq1GEzB8Zv2kdTfaxQfi5GoH0tBinyg==", "integrity": "sha512-l2VCsy3XXeraxIID9fx23eCb6iCBsxUQDnE8tWm6DFdszVAO7WVY/ChAD9wVit01y6B2PMupYiMmQwhgPHc9Ew==",
"license": "MIT",
"workspaces": [
"www"
],
"dependencies": { "dependencies": {
"@reduxjs/toolkit": "1.x.x || 2.x.x", "@reduxjs/toolkit": "1.x.x || 2.x.x",
"clsx": "^2.1.1", "clsx": "^2.1.1",
@ -5735,18 +5732,10 @@
} }
}, },
"node_modules/xlsx": { "node_modules/xlsx": {
"version": "0.18.5", "version": "0.20.3",
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", "resolved": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
"integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", "integrity": "sha512-oLDq3jw7AcLqKWH2AhCpVTZl8mf6X2YReP+Neh0SJUzV/BdZYjth94tG5toiMB1PPrYtxOCfaoUCkvtuH+3AJA==",
"dependencies": { "license": "Apache-2.0",
"adler-32": "~1.3.0",
"cfb": "~1.2.1",
"codepage": "~1.15.0",
"crc-32": "~1.2.1",
"ssf": "~0.11.2",
"wmf": "~1.0.1",
"word": "~0.3.0"
},
"bin": { "bin": {
"xlsx": "bin/xlsx.njs" "xlsx": "bin/xlsx.njs"
}, },

View File

@ -20,7 +20,7 @@
"@fortawesome/react-fontawesome": "^3.1.1", "@fortawesome/react-fontawesome": "^3.1.1",
"axios": "^1.13.2", "axios": "^1.13.2",
"browser-image-compression": "^2.0.2", "browser-image-compression": "^2.0.2",
"i18next": "^25.7.4", "i18next": "^25.8.0",
"i18next-browser-languagedetector": "^8.2.0", "i18next-browser-languagedetector": "^8.2.0",
"i18next-http-backend": "^3.0.2", "i18next-http-backend": "^3.0.2",
"jszip": "^3.10.1", "jszip": "^3.10.1",
@ -35,12 +35,12 @@
"react-loader-spinner": "^8.0.2", "react-loader-spinner": "^8.0.2",
"react-router-dom": "^7.12.0", "react-router-dom": "^7.12.0",
"react-toastify": "^11.0.5", "react-toastify": "^11.0.5",
"recharts": "^3.6.0", "recharts": "^3.7.0",
"xlsx": "^0.18.5", "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
"xlsx-js-style": "^1.2.0" "xlsx-js-style": "^1.2.0"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^19.2.8", "@types/react": "^19.2.9",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.2", "@vitejs/plugin-react": "^5.1.2",
"eslint": "^9.39.2", "eslint": "^9.39.2",

View File

@ -173,7 +173,7 @@
"comp.error1": "La date de fin doit être postérieure à la date de début.", "comp.error1": "La date de fin doit être postérieure à la date de début.",
"comp.error2": "Veuillez renseigner les dates de début et de fin d'inscription.", "comp.error2": "Veuillez renseigner les dates de début et de fin d'inscription.",
"comp.error3": "La date de fin d'inscription doit être postérieure à la date de début d'inscription.", "comp.error3": "La date de fin d'inscription doit être postérieure à la date de début d'inscription.",
"comp.exporterLesInscription": "Exporter les inscription", "comp.exporterLesInscription": "Exporter les inscriptions",
"comp.ha.emailDeRéceptionDesInscriptionséchoué": "Email de réception des inscriptions échoué", "comp.ha.emailDeRéceptionDesInscriptionséchoué": "Email de réception des inscriptions échoué",
"comp.ha.error1": "Veuillez renseigner l'URL de la billetterie HelloAsso et les tarifs associés.", "comp.ha.error1": "Veuillez renseigner l'URL de la billetterie HelloAsso et les tarifs associés.",
"comp.ha.error2": "L'URL de la billetterie HelloAsso n'est pas valide. Veuillez vérifier le format de l'URL.", "comp.ha.error2": "L'URL de la billetterie HelloAsso n'est pas valide. Veuillez vérifier le format de l'URL.",

View File

@ -98,7 +98,7 @@ export function CompetitionRegisterAdmin({source}) {
filterNotWeight={filterNotWeight} setFilterNotWeight={setFilterNotWeight} source={source}/> filterNotWeight={filterNotWeight} setFilterNotWeight={setFilterNotWeight} source={source}/>
</div> </div>
</div> </div>
{source === "admin" && <FileOutput data={data}/>} {source === "admin" && <FileOutput data={data} data2={data2}/>}
</div> </div>
</div> </div>
@ -721,29 +721,78 @@ function MakeCentralPanel({data, data2, data3, dispatch, id, setModalState, sour
</> </>
} }
function FileOutput({data}) { function FileOutput({data, data2}) {
const {t} = useTranslation(); const {t} = useTranslation();
const handleFileDownload = () => { const handleFileDownload = () => {
const catColumns = {}
for (const cat of data2) {
catColumns[cat.id] = ""
}
const columnOrder = [
"licence", "pays", "nom", "prenom", "genre", "weight",
"categorie", "overCategory", "categorie2", "club",
...Object.keys(catColumns)
];
const dataOut = [] const dataOut = []
for (const e of data) { for (const e of data) {
const tmp = { const tmp = {
licence: e.licence, licence: e.licence,
pays: e.country,
nom: e.lname, nom: e.lname,
prenom: e.fname, prenom: e.fname,
genre: e.genre, genre: e.genre,
weight: e.weight, weight: e.weightReal ? e.weightReal : e.weight,
categorie: e.categorie, categorie: getCatName(e.categorie),
overCategory: e.overCategory, overCategory: e.overCategory,
categorie2: getCatName(applyOverCategory(e.categorie, e.overCategory)),
club: e.club ? e.club.name : '', club: e.club ? e.club.name : '',
...catColumns
}
for (const c of e.categoriesInscrites) {
tmp[c] = "X"
} }
dataOut.push(tmp) dataOut.push(tmp)
} }
dataOut.sort((a, b) => a.prenom.localeCompare(b.prenom) || a.nom.localeCompare(b.nom));
const secondHeaders = [
"Licence", "Pays", "Nom", "Prénom", "Genre", "Poids",
"Catégorie normalizer", "Surclassement", "Catégorie d'inscription", "Club",
...Object.keys(catColumns).map(id => data2.find(p => p.id === Number(id))?.name)
];
const headers = [
"", "", "", "", "", "", "", "", "", "", "Catégories",
...Object.keys(catColumns).map(() => "")
];
const orderedData = dataOut.map(row => columnOrder.map(col => row[col]));
const wb = XLSX.utils.book_new(); const wb = XLSX.utils.book_new();
const ws = XLSX.utils.json_to_sheet(dataOut); const ws = XLSX.utils.json_to_sheet([], {skipHeader: true});
XLSX.utils.sheet_add_aoa(ws, [["Licence", "Nom", "Prénom", "Genre", "Poids", "Catégorie normalizer", "Surclassement", "Club"]], {origin: 'A1'});
ws["!cols"] = [{wch: 7}, {wch: 16}, {wch: 16}, {wch: 6}, {wch: 6}, {wch: 10}, {wch: 10}, {wch: 60}] XLSX.utils.sheet_add_aoa(ws, [headers, secondHeaders, ...orderedData], {origin: "A1"});
// Fusionner les cellules pour le titre "Catégories"
const mergeStart = XLSX.utils.encode_cell({r: 0, c: 10}); // Ligne 1, colonne K (index 10)
const mergeEnd = XLSX.utils.encode_cell({r: 0, c: 10 + Object.keys(catColumns).length - 1});
ws["!merges"] = [{s: mergeStart, e: mergeEnd}];
// 10. Appliquer une rotation de 45° aux en-têtes
const headerRow = ws["!rows"] || (ws["!rows"] = {});
headerRow[1] = {hpt: 70}; // Hauteur de la première ligne
for (let i = 0; i < headers.length; i++) {
const cellRef = XLSX.utils.encode_cell({r: 1, c: i});
if (!ws[cellRef]) ws[cellRef] = {};
ws[cellRef].s = {
alignment: {textRotation: 45, vertical: "bottom", wrapText: true}
};
}
ws["!cols"] = [{wch: 5}, {wch: 4}, {wch: 16}, {wch: 16}, {wch: 4}, {wch: 4}, {wch: 10}, {wch: 4}, {wch: 10}, {wch: 60},
...Object.keys(catColumns).map(() => ({wch: 2}))]
XLSX.utils.book_append_sheet(wb, ws, "Feuille 1"); XLSX.utils.book_append_sheet(wb, ws, "Feuille 1");
XLSX.writeFile(wb, "output.xlsx"); XLSX.writeFile(wb, "output.xlsx");