Formulaire academie

This commit is contained in:
2026-06-07 10:16:15 +02:00
parent 0711bd6996
commit 9dfce9bc58
21 changed files with 1666 additions and 854 deletions

View File

@@ -0,0 +1,287 @@
import { createError, readBody } from "h3"
import { getMysqlPool } from "~~/server/utils/mysql"
import { sendProjetAcademieEmails } from "~~/server/utils/mailer"
function normalizeValue(value) {
return typeof value === "string" ? value.trim() : ""
}
function normalizeBoolean(value) {
return value === true
}
function normalizePositiveInteger(value) {
const number = Number(value)
return Number.isInteger(number) && number > 0 ? number : null
}
function normalizeDiploma(diploma) {
return {
type: normalizeValue(diploma?.type),
otherType: normalizeValue(diploma?.otherType),
discipline: normalizeValue(diploma?.discipline),
year: normalizeValue(diploma?.year),
establishment: normalizeValue(diploma?.establishment),
}
}
function isValidEmail(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
}
function withTimeout(promise, delay, message) {
return Promise.race([
promise,
new Promise((_, reject) => {
setTimeout(() => reject(new Error(message)), delay)
}),
])
}
function hasDiplomaData(diploma) {
return Boolean(diploma.type || diploma.otherType || diploma.discipline || diploma.year || diploma.establishment)
}
function validateDiploma(diploma) {
if (!hasDiplomaData(diploma)) {
return true
}
if (!diploma.type || !diploma.discipline || !diploma.year || !diploma.establishment) {
return false
}
if (diploma.type === "Autre" && !diploma.otherType) {
return false
}
return true
}
export default defineEventHandler(async (event) => {
const body = await readBody(event)
const payload = {
lastName: normalizeValue(body?.lastName).toUpperCase(),
firstName: normalizeValue(body?.firstName),
gender: normalizeValue(body?.gender),
birthDate: normalizeValue(body?.birthDate),
birthPlace: normalizeValue(body?.birthPlace),
nationality: normalizeValue(body?.nationality),
email: normalizeValue(body?.email),
phone: normalizeValue(body?.phone),
address: normalizeValue(body?.address),
city: normalizeValue(body?.city),
postalCode: normalizeValue(body?.postalCode),
country: normalizeValue(body?.country),
instrument: normalizeValue(body?.instrument),
previousAcademyParticipation: normalizeValue(body?.previousAcademyParticipation),
previousAcademyParticipationCount: normalizePositiveInteger(body?.previousAcademyParticipationCount),
trainingLevel: normalizeValue(body?.trainingLevel),
otherTrainingLevel: normalizeValue(body?.otherTrainingLevel),
conservatory: normalizeValue(body?.conservatory),
otherConservatory: normalizeValue(body?.otherConservatory),
teacherName: normalizeValue(body?.teacherName),
diplomas: Array.isArray(body?.diplomas)
? body.diplomas.slice(0, 3).map(normalizeDiploma)
: [],
emergencyLastName: normalizeValue(body?.emergencyLastName),
emergencyFirstName: normalizeValue(body?.emergencyFirstName),
emergencyRelation: normalizeValue(body?.emergencyRelation),
emergencyPhone: normalizeValue(body?.emergencyPhone),
emergencyEmail: normalizeValue(body?.emergencyEmail),
acceptRules: normalizeBoolean(body?.acceptRules),
}
while (payload.diplomas.length < 3) {
payload.diplomas.push(normalizeDiploma({}))
}
if (
!payload.lastName ||
!payload.firstName ||
!payload.gender ||
!payload.birthDate ||
!payload.birthPlace ||
!payload.nationality ||
!payload.email ||
!payload.phone ||
!payload.address ||
!payload.city ||
!payload.postalCode ||
!payload.country ||
!payload.instrument ||
!payload.previousAcademyParticipation ||
!payload.trainingLevel ||
!payload.conservatory ||
!payload.teacherName ||
!payload.emergencyLastName ||
!payload.emergencyFirstName ||
!payload.emergencyRelation ||
!payload.emergencyPhone ||
!payload.emergencyEmail ||
!payload.acceptRules
) {
throw createError({
statusCode: 400,
statusMessage: "Tous les champs obligatoires doivent être remplis.",
})
}
if (!isValidEmail(payload.email) || !isValidEmail(payload.emergencyEmail)) {
throw createError({
statusCode: 400,
statusMessage: "Une adresse email nest pas valide.",
})
}
if (payload.previousAcademyParticipation === "oui" && !payload.previousAcademyParticipationCount) {
throw createError({
statusCode: 400,
statusMessage: "Le nombre de participations est obligatoire.",
})
}
if (payload.trainingLevel === "Autre" && !payload.otherTrainingLevel) {
throw createError({
statusCode: 400,
statusMessage: "Lautre formation est obligatoire.",
})
}
if (payload.conservatory === "Autre" && !payload.otherConservatory) {
throw createError({
statusCode: 400,
statusMessage: "Lautre conservatoire est obligatoire.",
})
}
if (!payload.diplomas.every(validateDiploma)) {
throw createError({
statusCode: 400,
statusMessage: "Chaque diplôme renseigné doit être complet.",
})
}
const db = getMysqlPool()
const [diploma1, diploma2, diploma3] = payload.diplomas
try {
const [result] = await db.execute(
`
INSERT INTO academie_orchestre_candidatures (
nom,
prenom,
genre,
date_naissance,
lieu_naissance,
nationalite,
email,
telephone,
adresse,
ville,
code_postal,
pays_residence,
instrument,
deja_participe_academie,
nombre_participations_academie,
niveau_cycle_2026_2027,
autre_formation,
conservatoire_2026_2027,
autre_conservatoire,
professeur_instrument,
diplome_1_type,
diplome_1_autre_type,
diplome_1_discipline,
diplome_1_annee,
diplome_1_etablissement,
diplome_2_type,
diplome_2_autre_type,
diplome_2_discipline,
diplome_2_annee,
diplome_2_etablissement,
diplome_3_type,
diplome_3_autre_type,
diplome_3_discipline,
diplome_3_annee,
diplome_3_etablissement,
contact_urgence_nom,
contact_urgence_prenom,
contact_urgence_lien,
contact_urgence_telephone,
contact_urgence_email,
reglement_accepte
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`,
[
payload.lastName,
payload.firstName,
payload.gender,
payload.birthDate,
payload.birthPlace,
payload.nationality,
payload.email,
payload.phone,
payload.address,
payload.city,
payload.postalCode,
payload.country,
payload.instrument,
payload.previousAcademyParticipation,
payload.previousAcademyParticipationCount,
payload.trainingLevel,
payload.otherTrainingLevel,
payload.conservatory,
payload.otherConservatory,
payload.teacherName,
diploma1.type,
diploma1.otherType,
diploma1.discipline,
diploma1.year,
diploma1.establishment,
diploma2.type,
diploma2.otherType,
diploma2.discipline,
diploma2.year,
diploma2.establishment,
diploma3.type,
diploma3.otherType,
diploma3.discipline,
diploma3.year,
diploma3.establishment,
payload.emergencyLastName,
payload.emergencyFirstName,
payload.emergencyRelation,
payload.emergencyPhone,
payload.emergencyEmail,
payload.acceptRules,
]
)
let emailsSent = false
try {
emailsSent = await withTimeout(
sendProjetAcademieEmails(payload),
15000,
"Délai dépassé pour l'envoi email projet-academie."
)
} catch (mailError) {
console.error("Erreur envoi email projet-academie:", mailError)
}
return {
ok: true,
id: result.insertId,
emailsSent,
}
} catch (error) {
console.error("Erreur API projet-academie:", error)
throw createError({
statusCode: 500,
statusMessage: "Impossible denregistrer la candidature pour le moment.",
})
}
})