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: "L’adresse email n’est pas valide.", }) } if (!/^\d{2}$/.test(payload.department)) { throw createError({ statusCode: 400, statusMessage: "Le département n’est 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 d’enregistrer la candidature pour le moment.", }) } })