From 97fba0435a4268f39acd2c0f0a15356863353da5 Mon Sep 17 00:00:00 2001 From: Van Leemput Dayron Date: Mon, 12 Jan 2026 17:23:36 +0100 Subject: [PATCH] Add support for project Travel Mate --- backend/src/index.ts | 2 + backend/src/routes/support.ts | 56 +++ frontend/src/App.tsx | 2 + frontend/src/components/TravelMate.tsx | 138 +++++--- .../src/components/TravelMate/EraseData.tsx | 88 ++++- .../src/components/TravelMate/Support.tsx | 324 ++++++++++++++++++ frontend/src/contexts/LanguageContext.tsx | 66 +++- frontend/src/styles/components/_projects.scss | 4 +- 8 files changed, 622 insertions(+), 58 deletions(-) create mode 100644 backend/src/routes/support.ts create mode 100644 frontend/src/components/TravelMate/Support.tsx diff --git a/backend/src/index.ts b/backend/src/index.ts index c330ced..dfac28c 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -14,6 +14,8 @@ app.use(cors()); app.use(express.json()); app.use('/api/messages', messagesRouter); +import supportRouter from './routes/support'; +app.use('/api/support', supportRouter); // Basic health check app.get('/api/health', (req, res) => { diff --git a/backend/src/routes/support.ts b/backend/src/routes/support.ts new file mode 100644 index 0000000..0e56415 --- /dev/null +++ b/backend/src/routes/support.ts @@ -0,0 +1,56 @@ +import { Router, Request, Response } from 'express'; +import pool from '../config/db'; +import { ResultSetHeader } from 'mysql2'; + +const router = Router(); + +// Validation helper +const isValidEmail = (email: string) => { + return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); +}; + +router.post('/', async (req: Request, res: Response): Promise => { + const { nom, prenom, account_email, contact_email, message } = req.body; + + // 1. Validation + const errors: string[] = []; + + if (!nom || nom.trim() === '') errors.push('Le nom est requis.'); + if (!prenom || prenom.trim() === '') errors.push('Le prénom est requis.'); + + if (!account_email || account_email.trim() === '') { + errors.push("L'email du compte est requis."); + } else if (!isValidEmail(account_email)) { + errors.push("Le format de l'email du compte est invalide."); + } + + if (!contact_email || contact_email.trim() === '') { + errors.push("L'email de contact est requis."); + } else if (!isValidEmail(contact_email)) { + errors.push("Le format de l'email de contact est invalide."); + } + + if (!message || message.trim() === '') errors.push('Le message est requis.'); + + if (errors.length > 0) { + res.status(400).json({ status: 'error', errors }); + return; + } + + // 2. Insert into Database + try { + const query = 'INSERT INTO support_requests (nom, prenom, account_email, contact_email, message) VALUES (?, ?, ?, ?, ?)'; + const [result] = await pool.query(query, [nom, prenom, account_email, contact_email, message]); + + res.status(201).json({ + status: 'success', + message: 'Demande de support envoyée avec succès.', + id: result.insertId + }); + } catch (error: any) { + console.error('Error inserting support request:', error); + res.status(500).json({ status: 'error', message: 'Erreur serveur lors de la sauvegarde.' }); + } +}); + +export default router; diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 24128bb..a63649b 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -7,6 +7,7 @@ import Footer from './components/Footer'; import Policies from './components/Policies'; import TravelMate from './components/TravelMate'; import EraseData from './components/TravelMate/EraseData'; +import Support from './components/TravelMate/Support'; import HomeSync from './components/HomeSync'; import ScrollToTop from './components/ScrollToTop'; import './styles/main.scss'; @@ -66,6 +67,7 @@ function AppContent() { } /> } /> } /> + } />