-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Application web de suggestion de destinations de voyage avec estimation des prix
- Vue d'ensemble
- Architecture
- Structure du projet
- Backend (index.js)
- Frontend
- API
- Données
- Déploiement
- Améliorations possibles
Application qui suggère des destinations de voyage aléatoires avec prix estimés (hôtel, repas, transport).
- Backend : Node.js + Express.js 5.1.0
- Frontend : HTML5, CSS3, JavaScript Vanilla
- Données : JSON
- Modules : ES Modules (import/export)
✅ Génération aléatoire de destinations
✅ Affichage des prix estimés
✅ Interface responsive
✅ Images haute qualité (Unsplash)
✅ API REST
┌─────────────────────────────────────┐
│ FRONTEND (HTML/CSS/JS) │
│ - Affichage │
│ - Interactions utilisateur │
└─────────────────────────────────────┘
↕ HTTP/JSON
┌─────────────────────────────────────┐
│ BACKEND (Express) │
│ - API REST │
│ - Serveur de fichiers statiques │
└─────────────────────────────────────┘
↕ File I/O
┌─────────────────────────────────────┐
│ DONNÉES (JSON) │
│ - destinations.json │
└─────────────────────────────────────┘
-
Chargement : Le navigateur charge
index.html,styles.css,destination.js -
Fetch :
destination.jsrécupère les données viaGET /api/destinations - Sélection : JavaScript sélectionne une destination aléatoire
- Affichage : Mise à jour du DOM avec les infos
- Refresh : Nouvelle sélection sans requête serveur
WhatNext/
├── index.js # Serveur Express
├── package.json # Dépendances npm
├── README.md # Guide utilisateur
├── wiki.md # Documentation technique
│
├── data/
│ └── destinations.json # Base de données
│
└── public/ # Fichiers statiques
├── pages/
│ └── index.html # Page principale
├── scripts/
│ └── destination.js # Logique client
└── styles/
└── styles.css # Styles
// ES Modules (package.json: "type": "module")
import express from "express";
import path from "path";
import { fileURLToPath } from "url";
// Recréer __dirname (non disponible en ES Modules)
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);| Middleware | Rôle |
|---|---|
express.static("public") |
Sert les fichiers statiques (HTML, CSS, JS, images) |
express.json() |
Parse les requêtes JSON |
| Logger custom | Log toutes les requêtes avec timestamp |
| Méthode | Route | Description | Réponse |
|---|---|---|---|
GET |
/ |
Page d'accueil | index.html |
GET |
/api/destinations |
Liste des destinations | JSON array |
* |
Autre | 404 | Message d'erreur |
// 404 - Route introuvable
app.use((req, res) => {
res.status(404).send("404 Not Found");
});
// 500 - Erreur serveur
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send("500 Internal Error");
});const PORT = process.env.PORT || 8080;Port par défaut : 8080 (modifiable via variable d'environnement)
Structure simple avec :
-
<h1>: Titre "What Next" -
.destination-card: Carte avec image, infos et prix -
#refresh-btn: Bouton "New destination" -
<footer>: Copyright
Les données par défaut sont remplacées par JavaScript au chargement.
1. fetchDestinations()
async function fetchDestinations() {
try {
const response = await fetch("/api/destinations");
if (!response.ok) throw new Error("Failed to fetch");
return await response.json();
} catch (error) {
console.error(error);
return [];
}
}- Récupère les destinations depuis l'API
- Gestion d'erreurs avec try/catch
- Retourne
[]si échec
2. getRandomDestination(destinations)
function getRandomDestination(destinations) {
const randomIndex = Math.floor(Math.random() * destinations.length);
return destinations[randomIndex];
}- Sélection aléatoire via
Math.random() - Pure function (pas d'effets de bord)
3. updateDestinationCard(destination)
function updateDestinationCard(destination) {
// Sélectionne les éléments DOM
// Met à jour : image, titre, description, prix
imageDiv.style.backgroundImage = `url(${destination.image})`;
title.textContent = `${destination.ville}, ${destination.pays}`;
// ...
}- Manipulation du DOM via
querySelector - Utilise
textContentpour la sécurité (évite XSS)
document.addEventListener("DOMContentLoaded", async () => {
const destinations = await fetchDestinations();
if (destinations.length === 0) return;
// Affichage initial
updateDestinationCard(getRandomDestination(destinations));
// Event listener sur le bouton
refreshBtn.addEventListener("click", () => {
updateDestinationCard(getRandomDestination(destinations));
});
});Optimisation : Les données sont récupérées 1 seule fois, puis réutilisées en mémoire.
:root {
--primary-color: #3498db;
--primary-color-dark: #2980b9;
--text-color: #333;
--background-color: #f5f5f5;
--card-color: #fff;
--border-radius: 6px;
--transition-speed: 0.3s;
}.container {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1; /* Footer toujours en bas */
}/* Desktop par défaut */
.container { max-width: 800px; }
/* Tablette */
@media (max-width: 768px) { /* ... */ }
/* Mobile */
@media (max-width: 480px) { /* ... */ }Description : Retourne toutes les destinations en JSON
Réponse :
[
{
"pays": "France",
"ville": "Paris",
"description": "La ville lumière...",
"prix": {
"hotel": "150-300€/nuit",
"repas": "15-30€/repas",
"transport": "1.90€/ticket"
},
"image": "https://images.unsplash.com/..."
}
]Test :
curl http://localhost:8080/api/destinations[
{
"pays": "String",
"ville": "String",
"description": "String",
"prix": {
"hotel": "String",
"repas": "String",
"transport": "String"
},
"image": "URL"
}
]🇫🇷 Paris, France
🇯🇵 Tokyo, Japon
🇮🇹 Rome, Italie
🇹🇭 Bangkok, Thaïlande
🇺🇸 New York, États-Unis
... et plus
Suivez le format JSON et ajoutez votre entrée dans le tableau. Utilisez des images Unsplash :
https://images.unsplash.com/photo-{id}?q=80&w=1000
git clone https://github.com/Joshua31400/WhatNext.git
cd WhatNext
npm install
npm startOuvrir : http://localhost:8080
npm start # Production (node index.js)
npm run dev # Développement avec nodemon# Windows CMD
set PORT=3000 && npm start
# Windows PowerShell
$env:PORT=3000; npm start
# Linux/Mac
PORT=3000 npm startheroku create whatnext-app
git push heroku mainCréer un Procfile :
web: node index.js
- Connecter le repo GitHub
- Build :
npm install - Start :
npm start
git clone <repo>
cd WhatNext
npm install
npm install -g pm2
pm2 start index.js --name whatnext
pm2 startup
pm2 save- 🔹 Base de données : MongoDB ou PostgreSQL au lieu de JSON
- 🔹 API CRUD : POST/PUT/DELETE pour gérer les destinations
- 🔹 Authentification : JWT pour sécuriser les endpoints
- 🔹 Compression : Module
compressionpour optimiser
- 🔹 Framework : Migrer vers React/Vue pour une meilleure gestion d'état
- 🔹 Animations : Transitions CSS ou Framer Motion
- 🔹 Mode sombre :
prefers-color-schemeCSS - 🔹 Favoris : LocalStorage pour sauvegarder les préférences
- 🔹 Filtres : Par budget, continent, saison
- 🔹 Météo : Intégration API OpenWeatherMap
- 🔹 Carte : Leaflet ou Google Maps
- 🔹 Comparaison : Comparer plusieurs destinations
- 🔹 Éviter répétitions : Ne pas afficher 2× la même destination consécutive
- 🔹 CDN : Cloudinary pour les images
- 🔹 Cache : Headers de cache pour les ressources statiques
- 🔹 Lazy loading : Charger les images à la demande
// Jest / Vitest
describe('getRandomDestination', () => {
test('retourne une destination valide', () => {
const destinations = [{ ville: 'Paris' }];
const result = getRandomDestination(destinations);
expect(destinations).toContain(result);
});
});✅ Séparation des responsabilités (HTML/CSS/JS)
✅ ES Modules pour un code moderne
✅ Async/await pour la lisibilité
✅ Gestion d'erreurs complète (try/catch + middleware)
✅ Variables CSS pour la maintenabilité
✅ Responsive design
✅ Fonctions pures (ex: getRandomDestination)
✅ Guard clauses (return early)
✅ Const par défaut (immutabilité)
👨💻 Développeurs : Joshua BUDGEN & Pedro MARTINS
📅 Dernière mise à jour : Octobre 2025
📜 Licence : MIT