From 2273b816f10f9b1472f3f439ba193a18d405ee07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Poncin?= Date: Wed, 24 Jun 2026 17:55:15 +0200 Subject: [PATCH 1/5] refactor:challenge creation & invalidation --- .../AdminChallenge/adminChalengeList.tsx | 21 +- .../AdminChallenge/adminChallengeEditor.tsx | 12 +- .../adminChallengeValidatedList.tsx | 242 +++++++++++++++--- 3 files changed, 230 insertions(+), 45 deletions(-) diff --git a/frontend/src/components/Admin/AdminChallenge/adminChalengeList.tsx b/frontend/src/components/Admin/AdminChallenge/adminChalengeList.tsx index 2b1661d..27fe698 100644 --- a/frontend/src/components/Admin/AdminChallenge/adminChalengeList.tsx +++ b/frontend/src/components/Admin/AdminChallenge/adminChalengeList.tsx @@ -1,6 +1,6 @@ import { CheckCircle2, Edit, Search, Trash2 } from "lucide-react"; import { useMemo, useState } from "react"; -import Select, { type SingleValue } from "react-select"; +import Select from "react-select"; import Swal from "sweetalert2"; import { type Challenge } from "../../../interfaces/challenge.interface"; @@ -62,6 +62,11 @@ const AdminChallengeList = ({ challenges, refreshChallenges, onEdit, teams, fact } }; + const handleValidationCLick = async (c: Challenge) => { + setShowValidationFormForId(c.id); + setValidationType(c.category.toLowerCase() as ValidationTarget); + } + const handleValidate = async () => { if (!showValidationFormForId || !validationType || !selectedTargetId) return; @@ -145,7 +150,7 @@ const AdminChallengeList = ({ challenges, refreshChallenges, onEdit, teams, fact Supprimer + {showUnvalidationFormForId === group.challenge_id && ( + + + +

❌ Invalider le challenge

+ + setSelectedTargetId(Number(option?.value))} + onChange={(options) => setSelectedTargetIds(options.map((o) => Number(o.value)))} options={users.map((u: User) => ({ value: u.userId, label: `${u.firstName} ${u.lastName}`, @@ -176,8 +179,9 @@ const AdminChallengeList = ({ challenges, refreshChallenges, onEdit, teams, fact {validationType === "team" && ( setSelectedTargetId(Number(option?.value))} + onChange={(options) => setSelectedTargetIds(options.map((o) => Number(o.value)))} options={factions.map((f: Faction) => ({ value: f.factionId, label: f.name, @@ -207,7 +212,7 @@ const AdminChallengeList = ({ challenges, refreshChallenges, onEdit, teams, fact onClick={() => { setShowValidationFormForId(null); setValidationType(null); - setSelectedTargetId(null); + setSelectedTargetIds([]); }} className="bg-gray-400 hover:bg-gray-500 text-white" > diff --git a/frontend/src/components/Admin/AdminChallenge/adminChallengeAddPointsForm.tsx b/frontend/src/components/Admin/AdminChallenge/adminChallengeAddPointsForm.tsx index 1fa1e03..6a27268 100644 --- a/frontend/src/components/Admin/AdminChallenge/adminChallengeAddPointsForm.tsx +++ b/frontend/src/components/Admin/AdminChallenge/adminChallengeAddPointsForm.tsx @@ -67,7 +67,7 @@ export const AdminChallengeAddPointsForm = () => { return (
- + 🎯 Ajouter des points à une faction diff --git a/frontend/src/components/Admin/AdminChallenge/adminChallengeEditor.tsx b/frontend/src/components/Admin/AdminChallenge/adminChallengeEditor.tsx index 73dd80b..b1d5a84 100644 --- a/frontend/src/components/Admin/AdminChallenge/adminChallengeEditor.tsx +++ b/frontend/src/components/Admin/AdminChallenge/adminChallengeEditor.tsx @@ -72,7 +72,7 @@ const ChallengeEditor = ({ editingChallenge, setEditingChallenge, refreshChallen }; return ( - + {editingChallenge ? "✏️ Modifier Challenge" : "🛠️ Créer Challenge"} diff --git a/frontend/src/components/Admin/AdminChallenge/adminChallengeValidatedList.tsx b/frontend/src/components/Admin/AdminChallenge/adminChallengeValidatedList.tsx index c49e727..7420b64 100644 --- a/frontend/src/components/Admin/AdminChallenge/adminChallengeValidatedList.tsx +++ b/frontend/src/components/Admin/AdminChallenge/adminChallengeValidatedList.tsx @@ -1,6 +1,6 @@ -import { Search } from "lucide-react"; +import { Search, Trash2, X } from "lucide-react"; import { useMemo, useState } from "react"; -import Select from "react-select"; +import Select from "react-select"; import Swal from "sweetalert2"; import { type ValidatedChallenge } from "../../../interfaces/challenge.interface"; @@ -205,7 +205,7 @@ export const AdminValidatedChallengesList = ({ }; return ( -
+
@@ -226,94 +226,88 @@ export const AdminValidatedChallengesList = ({
{/* Grille */} - {filtered.length === 0 ? ( -

Aucun challenge validé trouvé.

- ) : ( -
- {groupedValidatedChallenges.map((group) => ( -
-
-

{group.challenge_name}

-

{group.challenge_categorie}

-

{group.challenge_description}

-
+
+ {filtered.length > 0 ? ( + groupedValidatedChallenges.map((group) => ( + + +
+

{group.challenge_name}

+

{group.challenge_description}

+

Catégorie : {group.challenge_categorie}

+

Points : {group.points}

+

Validé le : {new Date(group.validated_at).toLocaleDateString()}

+
-
-

Points : {group.points}

-

- Validé le : {new Date(group.validated_at).toLocaleDateString()} -

-
+
+

Destinataires :

+ {group.recipients.length > 0 ? ( +
    + {group.recipients.map((recipient) => ( +
  • {recipient.label}
  • + ))} +
+ ) : ( +

Aucun destinataire connu.

+ )} +
-
-

Destinataires :

- {group.recipients.length > 0 ? ( -
    - {group.recipients.map((recipient) => ( -
  • {recipient.label}
  • - ))} -
- ) : ( -

Aucun destinataire connu.

- )} -
- - - {showUnvalidationFormForId === group.challenge_id && ( - - - -

❌ Invalider le challenge

+
+ +
- + setSelectedUnvalidationTargetIds(options.map((o) => Number(o.value))) + } + options={group.recipients.map((recipient) => ({ + value: recipient.id, + label: recipient.label, + }))} + /> - - - -
- - - )} -
- ))} -
- )} +
+ + + +
+ + + )} + + + )) + ) : ( +

Aucun challenge validé trouvé.

+ )} +
From bf1234df48d059b6706d3810a7d7389ce58431fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Poncin?= Date: Thu, 25 Jun 2026 10:57:35 +0200 Subject: [PATCH 3/5] =?UTF-8?q?fix:=20"d=C3=A9valider=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/controllers/tent.controller.ts | 4 +-- backend/src/services/tent.service.ts | 2 +- backend/src/utils/emailtemplates.ts | 2 +- .../adminChallengeValidatedList.tsx | 26 +++++++++---------- frontend/src/components/Admin/adminTent.tsx | 6 ++--- .../src/services/requests/tent.service.ts | 2 +- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/backend/src/controllers/tent.controller.ts b/backend/src/controllers/tent.controller.ts index 5dd067b..2f87a81 100644 --- a/backend/src/controllers/tent.controller.ts +++ b/backend/src/controllers/tent.controller.ts @@ -90,7 +90,7 @@ export const toggleTentConfirmation = async (req: Request, res: Response) => { to: [user1.email, user2.email], subject: confirmed ? "🎉 Votre tente a été validée !" - : "⛺ Votre tente a été dévalidée", + : "⛺ Votre tente a été invalidée", text: "", // optionnel html: htmlEmail, }; @@ -101,7 +101,7 @@ export const toggleTentConfirmation = async (req: Request, res: Response) => { Ok(res, { msg: confirmed ? "Tente validée et email envoyé." - : "Tente dévalidée et email envoyé.", + : "Tente invalidée et email envoyé.", }); } catch (err: any) { console.error(err); diff --git a/backend/src/services/tent.service.ts b/backend/src/services/tent.service.ts index ed9b32b..5f02fce 100644 --- a/backend/src/services/tent.service.ts +++ b/backend/src/services/tent.service.ts @@ -131,5 +131,5 @@ export const toggleTentConfirmation = async ( ) ); - return { success: true, message: confirmed ? "Tente validée." : "Tente dévalidée." }; + return { success: true, message: confirmed ? "Tente validée." : "Tente invalidée." }; }; diff --git a/backend/src/utils/emailtemplates.ts b/backend/src/utils/emailtemplates.ts index 309068e..3d53f57 100644 --- a/backend/src/utils/emailtemplates.ts +++ b/backend/src/utils/emailtemplates.ts @@ -341,7 +341,7 @@ export const templateNotifyTentConfirmation = `

La tente entre {{user1}} et {{user2}} a été - {{#if confirmed}}validée{{else}}dévalidée{{/if}} + {{#if confirmed}}validée{{else}}invalidée{{/if}} .

diff --git a/frontend/src/components/Admin/AdminChallenge/adminChallengeValidatedList.tsx b/frontend/src/components/Admin/AdminChallenge/adminChallengeValidatedList.tsx index 7420b64..a136943 100644 --- a/frontend/src/components/Admin/AdminChallenge/adminChallengeValidatedList.tsx +++ b/frontend/src/components/Admin/AdminChallenge/adminChallengeValidatedList.tsx @@ -102,23 +102,23 @@ export const AdminValidatedChallengesList = ({ const handleUnvalidate = async ( ) => { const confirm = await Swal.fire({ - title: "Confirmer la dévalidation ?", + title: "Confirmer la invalidation ?", text: "Cette action retirera la validation du challenge.", icon: "warning", showCancelButton: true, confirmButtonColor: "#e3342f", cancelButtonColor: "#6b7280", - confirmButtonText: "Oui, dévalider", + confirmButtonText: "Oui, invalider", cancelButtonText: "Annuler", }); if (!confirm.isConfirmed) return; for (const targetId of selectedUnvalidationTargetIds) { - console.log("Dévalidation du challenge pour l'ID cible :", targetId); + console.log("Invalidation du challenge pour l'ID cible :", targetId); console.log(validatedChallenges); const challengeToUnvalidate = validatedChallenges.find( (c) => c.challenge_id === showUnvalidationFormForId ); - console.log("Challenge à dévalider :", challengeToUnvalidate); + console.log("Challenge à invalider :", challengeToUnvalidate); if (!challengeToUnvalidate) { Swal.fire({ icon: "error", title: "Erreur", text: "Challenge non trouvé." }); return; @@ -130,7 +130,7 @@ export const AdminValidatedChallengesList = ({ teamId: challengeToUnvalidate.target_team_id ?? 0, userId: challengeToUnvalidate.target_user_id ?? 0, }); - console.log("Réponse de la dévalidation :", res); + console.log("Réponse de la invalidation :", res); validatedChallenges = validatedChallenges.filter( (c) => c.challenge_id === showUnvalidationFormForId && @@ -139,14 +139,14 @@ export const AdminValidatedChallengesList = ({ c.target_faction_id !== targetId ); } catch { - Swal.fire({ icon: "error", title: "Erreur", text: "Impossible de dévalider ce challenge." }); + Swal.fire({ icon: "error", title: "Erreur", text: "Impossible de invalider ce challenge." }); } } Swal.fire({ icon: "success", - title: "Dévalidé", - text: "Les challenges ont été dévalidés.", + title: "Invalidé", + text: "Les challenges ont été invalidés.", timer: 1800, showConfirmButton: false, }); @@ -157,13 +157,13 @@ export const AdminValidatedChallengesList = ({ const handleUnvalidateAll = async () => { const confirm = await Swal.fire({ - title: "Confirmer la dévalidation ?", + title: "Confirmer la invalidation ?", text: "Cette action retirera la validation du challenge.", icon: "warning", showCancelButton: true, confirmButtonColor: "#e3342f", cancelButtonColor: "#6b7280", - confirmButtonText: "Oui, dévalider", + confirmButtonText: "Oui, invalider", cancelButtonText: "Annuler", }); @@ -185,7 +185,7 @@ export const AdminValidatedChallengesList = ({ Swal.fire({ icon: "error", title: "Erreur", - text: "Impossible de dévalider un ou plusieurs challenges.", + text: "Impossible de invalider un ou plusieurs challenges.", }); return; } @@ -193,8 +193,8 @@ export const AdminValidatedChallengesList = ({ Swal.fire({ icon: "success", - title: "Dévalidé", - text: "Les challenges ont été dévalidés.", + title: "Invalidé", + text: "Les challenges ont été invalidés.", timer: 1800, showConfirmButton: false, }); diff --git a/frontend/src/components/Admin/adminTent.tsx b/frontend/src/components/Admin/adminTent.tsx index 644492d..df4ecf6 100644 --- a/frontend/src/components/Admin/adminTent.tsx +++ b/frontend/src/components/Admin/adminTent.tsx @@ -41,7 +41,7 @@ export const TentAdmin = () => { }; const handleToggle = async (pair: TentPair) => { - const action = pair.confirmed ? "dévalider" : "valider"; + const action = pair.confirmed ? "invalider" : "valider"; const confirm = await Swal.fire({ title: '⚠️ Confirmation requise', @@ -73,7 +73,7 @@ export const TentAdmin = () => { Swal.fire( "Succès ✅", - `La tente a bien été ${pair.confirmed ? "dévalidée" : "validée"}.`, + `La tente a bien été ${pair.confirmed ? "invalidée" : "validée"}.`, "success" ); @@ -194,7 +194,7 @@ export const TentAdmin = () => { : "bg-green-600 hover:bg-green-700 text-white" } > - {pair.confirmed ? "❌ Dévalider" : "✅ Valider"} + {pair.confirmed ? "❌ Invalidée" : "✅ Validée"} diff --git a/frontend/src/services/requests/tent.service.ts b/frontend/src/services/requests/tent.service.ts index 945fe85..83709f8 100644 --- a/frontend/src/services/requests/tent.service.ts +++ b/frontend/src/services/requests/tent.service.ts @@ -24,7 +24,7 @@ export const getAllTentPairs = async () => { return response.data; }; -// Valider ou dévalider une tente (admin) +// Valider ou invalider une tente (admin) export const toggleTentConfirmation = async ( userId1: number, userId2: number, From 19b36d4ef8a64599bf859707a75f6e8444685e31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Poncin?= Date: Wed, 1 Jul 2026 09:17:42 +0200 Subject: [PATCH 4/5] fix: error message --- .../AdminChallenge/adminChalengeList.tsx | 2 +- .../services/requests/challenge.service.ts | 56 ++++++++++++++----- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/frontend/src/components/Admin/AdminChallenge/adminChalengeList.tsx b/frontend/src/components/Admin/AdminChallenge/adminChalengeList.tsx index 4395fb1..c3cccf5 100644 --- a/frontend/src/components/Admin/AdminChallenge/adminChalengeList.tsx +++ b/frontend/src/components/Admin/AdminChallenge/adminChalengeList.tsx @@ -95,7 +95,7 @@ const AdminChallengeList = ({ challenges, refreshChallenges, onEdit, teams, fact Swal.fire({ icon: "error", title: "Erreur ❌", - text: "Impossible de valider ce challenge. Réessaie plus tard. (cette erreur peut survenir si le challenge a déjà été validé pour cet utilisateur/équipe/faction)", + text: err as string, }); } } diff --git a/frontend/src/services/requests/challenge.service.ts b/frontend/src/services/requests/challenge.service.ts index 5a90014..9bf8a91 100644 --- a/frontend/src/services/requests/challenge.service.ts +++ b/frontend/src/services/requests/challenge.service.ts @@ -1,5 +1,27 @@ +import { type AxiosError } from "axios"; + import api from "../api"; +interface ApiErrorResponse { + message?: string; + error?: string; +} + +type ApiErrorWithStatus = Error & { status?: number }; + +const buildApiError = (error: unknown): ApiErrorWithStatus => { + const axiosError = error as AxiosError; + const message = + axiosError.response?.data?.message || + axiosError.response?.data?.error || + axiosError.message || + "Une erreur est survenue lors de la requête."; + + const apiError = new Error(message) as ApiErrorWithStatus; + apiError.status = axiosError.response?.status; + return apiError; +}; + // Récupérer tous les challenges (utilisateur ou admin, en fonction du token) export const getAllChallenges = async () => { const response = await api.get("challenge/user/challenges"); @@ -44,12 +66,16 @@ export const validateChallenge = async ({ type: "user" | "team" | "faction"; targetId: number; }) => { - const response = await api.post("challenge/admin/validate", { - challengeId, - type, - targetId, - }); - return response.data; + try { + const response = await api.post("challenge/admin/validate", { + challengeId, + type, + targetId, + }); + return response.data; + } catch (error) { + throw buildApiError(error); + } }; export const unvalidateChallenge = async ({ @@ -63,13 +89,17 @@ export const unvalidateChallenge = async ({ teamId: number; userId: number; }) => { - const response = await api.post("challenge/admin/unvalidate", { - challengeId, - factionId, - teamId, - userId - }); - return response.data; + try { + const response = await api.post("challenge/admin/unvalidate", { + challengeId, + factionId, + teamId, + userId + }); + return response.data; + } catch (error) { + throw buildApiError(error); + } }; // Supprimer un challenge (ADMIN uniquement) From 42ab9d49c0d97c84dbd2807c3bd760747384ca78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Poncin?= Date: Mon, 13 Jul 2026 17:19:54 +0200 Subject: [PATCH 5/5] fix: conflict --- backend/src/utils/emailtemplates.ts | 364 ---------------------------- 1 file changed, 364 deletions(-) delete mode 100644 backend/src/utils/emailtemplates.ts diff --git a/backend/src/utils/emailtemplates.ts b/backend/src/utils/emailtemplates.ts deleted file mode 100644 index 3d53f57..0000000 --- a/backend/src/utils/emailtemplates.ts +++ /dev/null @@ -1,364 +0,0 @@ -import Handlebars from 'handlebars'; - -// Template pour l'e-mail de réinitialisation de mot de passe -export const templateResetPassword = ` - - - - - - Réinitialisation de mot de passe - - -
- Integration UTT Logo -

INTEGRATION UTT

-
- - - - -
- - - - - - - - - - -
-

Réinitialisation de mot de passe

-
-

Bonjour,

-

Vous avez demandé à réinitialiser votre mot de passe. Cliquez sur le bouton ci-dessous pour choisir un nouveau mot de passe :

-

- Réinitialiser mon mot de passe -

-

Attention le lien n'est valide que pendant 1h.

-

Si vous n'avez pas demandé cette réinitialisation, veuillez ignorer cet e-mail.

-

Merci,

-

L'équipe intégration UTT

-
-

Si vous avez des questions, n'hésitez pas à nous contacter.

-
-
- - -`; - -export const templateNotebook = ` - - - - Integration UTT - - -
- - -
- Integration UTT Logo -

INTEGRATION UTT

-
- - -
-

Salut à toi !!!!

- -

Si tu reçois ce mail, c'est que tu es sur le point de rejoindre l'UTT et de vivre tes premières années en école supérieure.

- -

Mais après toutes ces vacances, il est important de ne pas s'endormir et de vite se remettre au travail !

- -

C'est pourquoi l'intégration te propose un cahier de vacances qui te permettra de te remettre à niveau.

- -

Toutes les bases y sont revues, de la terminale… jusqu'au CP. À toi de nous prouver que tu en es capable ! Méthodologie et rigueur seront nécessaires pour en venir à bout (et pas mal d'humour également).

- -

Ce cahier sera examiné par un jury extrêmement talentueux : des ingénieurs hors pair, ayant déjà prouvé leur valeur lors d'un concours de Ricard sur la plage de Banyuls-sur-Mer.

- -

À toi de leur montrer que tu peux égaler leurs compétences ! Ce jury n'hésitera pas à te récompenser pour tes efforts si tu nous renvoies tes réponses à cette adresse mail.

- -

Alors si tu veux y participer, tu peux le télécharger juste ici et le renvoyer à clement.duranson@utt.fr avant le dimanche 31 août.

- - Cahier de vacances ! - -

Nous serons présents sur les réseaux tout au long de l'été pour te tenir informé(e), te partager des astuces, et plein d'autres trucs trop cools ! Rejoins le site de l'intégration pour bien être informé des actus ! Tu as reçu dans le premier mail de notre part, un lien pour réinitialiser ton mot de passe et te connecter.

- - Inscris toi ! - -

Pense aussi à rejoindre notre Discord, c'est uniquement par ce biais que tu pourras contacter tes chefs d'équipe et en savoir plus sur l'intégration !

- - Rejoindre Discord - -

Alors, bon courage à toi, nous sommes impatients de lire tes meilleures réponses.

- -

À très vite !

- -

Toute l'équipe de l'intégration

-
- - -
-

Rejoins nous sur les réseaux !

- -
-
- - -`; - -export const templateAttributionBus = ` - - - - - - Intégration UTT - - - - - - -
- - - - - - - - - - -
- Logo Comic -
- INTEGRATION UTT -
-

Salut !

-

Si tu reçois ce message c'est que tu pars au WEI (youhouu !), tu trouveras dans celui-ci le bus avec lequel tu vas te rendre sur le lieu pour ce week-end.

-

Fais bien attention à ne pas être en retard sous peine de rater ton bus, ça serait embêtant à la fois pour toi et pour nous.

-

Autre point très important : les essentiels pour le WEI. Tu trouveras ci-dessous un rappel des objets obligatoires à ramener pour passer un bon week-end. Il risque de pleuvoir alors prévoyez bien en conséquence !

- - -
    -
  • Duvet et matelas gonflable/tapis de sol 🛏️ (si vous n'avez pas de duvet, vous ne partirez pas)
  • -
  • Gourde, Tupperware, couverts, gobby (=écocup) 🍴
  • -
  • Vêtements : changes pour 2 jours, pull, maillot de bain 👙
  • -
  • Manteau imperméable 🧥
  • -
  • Affaires salissables : change complet & chaussures (à mettre dès le départ en bus) 🚌
  • -
  • Produits d'hygiène : brosse à dent, serviette, nécessaire de toilette 🪥
  • -
  • Tongues/crocs pour les douches 🩴
  • -
  • Papiers importants : Carte d'identité, CB & liquide, autorisation parentale (pour les mineurs) 💳
  • -
  • Ta place au WEI 📩
  • -
  • Crème solaire & anti-moustique ☀️
  • -
  • De quoi grignoter (prenez un pique-nique à manger avant de prendre le bus, pas dans le bus) 😋
  • -
- - -

🚫 Affaires interdites :

-
    -
  • Boissons autres que de l'eau
  • -
  • Substances illicites
  • -
  • Armes blanches
  • -
  • Déodorant en spray
  • -
- -

Pour rappel, voici la vidéo des indispensables du WEI ici

-

Concernant ton bus, tu as été attribué au bus {{bus}}

-

Maintenant il faut que tu sois présent en amphi de verdure à l'UTT à {{time}}

-

Voilà, toute l'équipe de l'intégration te souhaite un excellent WEI ;)

-
-
- - -`; - -export const templateWelcome = ` - - - - - - Intégration UTT - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Logo Comic -
- INTEGRATION UTT -
-

Salut à toi jeune nouveau !

-

Bravo pour ton admission à l'UTT ! Nous sommes l'équipe d'intégration, des étudiants bénévoles qui préparent minutieusement ton arrivée pour que celle-ci reste inoubliable.

-

Un tas d'événements incroyables, dont la participation est basée sur le volontariat, t'attendent dès le Lundi 1er Septembre que tu arrives en 1ère année, en 3ème année, en master ou en Bachelor.

-

Tout est fait pour que tu t'éclates et que tu rencontres les personnes qui feront de ton passage à l'UTT un moment inoubliable. Mais avant toute chose, il faut te préparer.

-

Assure-toi de réaliser les tâches suivantes avant ton arrivée :

-

Pour pouvoir te connecter au site de l'intégration il te suffit de changer ton mot de passe en cliquant sur ce lien suivant :

- -

Changer ton mot de passe

-

Attention, ce lien est valable uniquement une fois !

-

Une fois cela fait, tu pourras te connecter à ton compte et y retrouver toutes les informations relatives aux événements de la semaine via le lien suivant :

https://integration.utt.fr

Pense aussi à lier ton compte discord via la rubrique "Mon Compte" pour échanger avec les membres de ton équipe et avec les autres arrivants. -

-

Lorsque tu arrives à l'UTT, un.e étudiant.e plus ancien.ne devient ton parrain ou ta marraine. Il ou elle sera ton contact privilégié pour découvrir l'école mais aussi la vie étudiante troyenne et répondre à toutes tes questions que ce soit sur l'UTT, les logements, les cours, la vie à Troyes,...

-

Pour t'attribuer quelqu'un qui te correspond au mieux on t'invite à remplir ce questionnaire

-

Pense à nous rejoindre sur les réseaux sociaux !

-

- - Facebook - - - Instagram - - - Discord - -

-
- Logo Comic -
- INTEGRATION UTT -
-

Hello there, newcomer!

-

Congratulations on your admission to UTT! We are the integration team - volunteer students who are carefully preparing your arrival to make it truly unforgettable.

-

A bunch of amazing events, all based on voluntary participation, await you starting on Monday, September 1st, whether you're arriving in your 1st year, 3rd year, Master's or Bachelor's program.

-

Everything is set up for you to have fun and meet the people who will make your time at UTT unforgettable. But first things first - it's time to get ready.

-

Please make sure to complete the following tasks before you arrive:

-

To access the integration website, you just need to change your password by clicking the following link:

- -

Change your password

-

Warning: this link is valid only once!

-

Once that's done, you'll be able to log into your account and find all the information about the integration week events here:

https://integration.utt.fr

Also, don't forget to link your Discord account via the "My Account" section so you can connect with your team and the other newcomers. -

-

When you arrive at UTT, an older student will become your mentor ("parrain" or "marraine"). They will be your main contact to help you discover the school and student life in Troyes, and to answer any questions you may have about UTT, housing, classes, life in Troyes, etc.

-

To match you with someone who fits you best, we invite you to fill out this questionnaire

-

Don't forget to follow us on social media!

-

- - Facebook - - - Instagram - - - Discord - -

-
-
- - -`; - -export const templateNotifyNews = ` -
-
- - -
- Logo Intégration UTT -

Intégration UTT

-
- - -

🗞️ Nouvelle actu !

-

{{title}}

-

👉 Rendez-vous sur le site de l'inté dans l'onglet News pour en savoir plus.

- - -

- Accéder au site -

-
-
-`; - -export const templateNotifyTentConfirmation = ` -
-
- - -
- Logo Intégration UTT -

Intégration UTT

-
- - -

⛺ Mise à jour de ta tente

-

- La tente entre {{user1}} et {{user2}} a été - - {{#if confirmed}}validée{{else}}invalidée{{/if}} - . -

- -

- 👉 Tu peux consulter l'état de ta tente sur le site de l'inté dans l'onglet Tentes. -

- - -

- Accéder au site -

-
-
-`; - -// Fonction pour compiler le template -export const compileTemplate = (data: any, templateName: string) => { - const compiledTemplate = Handlebars.compile(templateName); - return compiledTemplate(data); -};