ajout de bouton réserver et ajout du formulaire lycée

This commit is contained in:
2026-05-25 17:15:17 +02:00
parent 107093f7bb
commit c2a11f1b61
12 changed files with 929 additions and 26 deletions

View File

@@ -0,0 +1,163 @@
import { createError, readBody } from "h3"
import { getMysqlPool } from "~~/server/utils/mysql"
import { sendProjetLyceeEmails } from "~~/server/utils/mailer"
function normalizeValue(value) {
return typeof value === "string" ? value.trim() : ""
}
function normalizePositiveInteger(value) {
const number = Number(value)
return Number.isInteger(number) && number > 0 ? number : null
}
function normalizePriority(value) {
const normalized = normalizeValue(value)
if (!normalized) return null
const match = normalized.match(/_(\d)$/)
if (!match) return null
const priority = Number(match[1])
return priority >= 0 && priority <= 4 ? priority : null
}
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)
}),
])
}
export default defineEventHandler(async (event) => {
const body = await readBody(event)
const payload = {
schoolName: normalizeValue(body?.schoolName),
department: normalizeValue(body?.department),
city: normalizeValue(body?.city),
coordinatorName: normalizeValue(body?.coordinatorName),
email: normalizeValue(body?.email),
phone: normalizeValue(body?.phone),
discipline: normalizeValue(body?.discipline),
classLevel: normalizeValue(body?.classLevel),
studentCount: normalizePositiveInteger(body?.studentCount),
concertRencontrePriority: normalizePriority(body?.concertRencontrePriority),
immersionPriority: normalizePriority(body?.immersionPriority),
eacPriority: normalizePriority(body?.eacPriority),
concertCommentePriority: normalizePriority(body?.concertCommentePriority),
projectPeriod: normalizeValue(body?.projectPeriod),
}
if (
!payload.schoolName ||
!payload.department ||
!payload.city ||
!payload.coordinatorName ||
!payload.email ||
!payload.phone ||
!payload.discipline ||
!payload.classLevel ||
!payload.studentCount ||
!payload.projectPeriod
) {
throw createError({
statusCode: 400,
statusMessage: "Tous les champs obligatoires doivent être remplis.",
})
}
if (!isValidEmail(payload.email)) {
throw createError({
statusCode: 400,
statusMessage: "Ladresse email nest pas valide.",
})
}
if (!/^\d{2}$/.test(payload.department)) {
throw createError({
statusCode: 400,
statusMessage: "Le département nest pas valide.",
})
}
if (payload.projectPeriod.length > 5000) {
throw createError({
statusCode: 400,
statusMessage: "La période souhaitée est trop longue.",
})
}
const db = getMysqlPool()
try {
const [result] = await db.execute(
`
INSERT INTO projet_lycee_demandes (
nom_etablissement,
departement,
ville,
coordinateur_nom,
email,
telephone,
discipline,
niveau_classe,
nombre_eleves,
priorite_concert_rencontre,
priorite_immersion,
priorite_eac,
priorite_concert_commente,
periode_souhaitee
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`,
[
payload.schoolName,
payload.department,
payload.city,
payload.coordinatorName,
payload.email,
payload.phone,
payload.discipline,
payload.classLevel,
payload.studentCount,
payload.concertRencontrePriority,
payload.immersionPriority,
payload.eacPriority,
payload.concertCommentePriority,
payload.projectPeriod,
]
)
let emailsSent = false
try {
emailsSent = await withTimeout(
sendProjetLyceeEmails(payload),
15000,
"Délai dépassé pour l'envoi email projet-lycee."
)
} catch (mailError) {
console.error("Erreur envoi email projet-lycee:", mailError)
}
return {
ok: true,
id: result.insertId,
emailsSent,
}
} catch (error) {
console.error("Erreur API projet-lycee:", error)
throw createError({
statusCode: 500,
statusMessage: "Impossible denregistrer la candidature pour le moment.",
})
}
})

View File

@@ -27,6 +27,9 @@ function getTransporter() {
host: config.smtpHost,
port: Number(config.smtpPort),
secure: String(config.smtpSecure).toLowerCase() === "true",
connectionTimeout: 10000,
greetingTimeout: 10000,
socketTimeout: 15000,
auth: {
user: config.smtpUser,
pass: config.smtpPassword,
@@ -96,3 +99,93 @@ export async function sendParcDemandEmails(payload) {
return true
}
function formatProjetLyceePriority(priority) {
if (priority === null || priority === undefined) return "Non renseigné"
if (priority === 0) return "Non souhaité"
return `Priorité ${priority}`
}
function getProjetLyceeSummary(payload) {
const projectWishes = [
["Concert-rencontre", payload.concertRencontrePriority],
["Parcours Entrer dans la peau d'un professionnel du spectacle", payload.immersionPriority],
["Parcours EAC", payload.eacPriority],
["Concert commente", payload.concertCommentePriority],
]
.filter(([, priority]) => priority >= 1 && priority <= 4)
.map(([label, priority]) => `${label} : ${formatProjetLyceePriority(priority)}`)
return [
`Etablissement scolaire : ${payload.schoolName}`,
`Departement : ${payload.department}`,
`Ville : ${payload.city}`,
`Enseignant coordinateur : ${payload.coordinatorName}`,
`Email : ${payload.email}`,
`Telephone : ${payload.phone}`,
`Discipline enseignee : ${payload.discipline}`,
`Niveau de classe : ${payload.classLevel}`,
`Nombre probable d'eleves concernes : ${payload.studentCount}`,
...(projectWishes.length ? ["", "Souhaits de projet :", ...projectWishes] : []),
"",
"Periode souhaitee :",
payload.projectPeriod,
].join("\n")
}
export async function sendProjetLyceeEmails(payload) {
const config = useRuntimeConfig()
const mailer = getTransporter()
if (!mailer) {
console.warn("Email projet lycée non envoyé: configuration SMTP incomplète.")
return false
}
if (!config.scolaireRequestRecipientEmail) {
console.warn("Email projet lycée non envoyé: destinataire scolaire manquant.")
return false
}
const from = config.smtpFromName
? `"${config.smtpFromName}" <${config.smtpFromEmail}>`
: config.smtpFromEmail
const summary = getProjetLyceeSummary(payload)
const adminSubject = `WONDIF - Candidature projet lycee - ${payload.schoolName}`
const adminText = [
"Une nouvelle candidature a été envoyée depuis le formulaire Projet lycée.",
"",
summary,
].join("\n")
const userSubject = "ONDIF - Confirmation de votre candidature - Projet lycée"
const userText = [
`Bonjour ${payload.coordinatorName},`,
"",
"Votre candidature à un projet avec l'Orchestre national d'Île-de-France a bien été transmise.",
"L'équipe d'action culturelle reviendra vers vous d'ici fin juin 2026 afin de vous informer de la suite donnée à votre candidature.",
"",
"Recapitulatif :",
summary,
].join("\n")
await Promise.all([
mailer.sendMail({
from,
to: config.scolaireRequestRecipientEmail,
replyTo: payload.email,
subject: adminSubject,
text: adminText,
}),
mailer.sendMail({
from,
to: payload.email,
subject: userSubject,
text: userText,
}),
])
return true
}