Skip to content

📅 SAISON B Semaine 4 Épisode 5 - Projet en autonomie Jour 3 - Base de Données, Gestion des Erreurs et Style

📚 Introduction

Troisième jour de travail sur le projet oCoffee ! Aujourd’hui, j’ai franchi une étape majeure en créant et connectant la base de données PostgreSQL, en dynamisant entièrement les pages avec les données de la base, et en améliorant l’expérience utilisateur avec une page 404 personnalisée et un design responsive. Voici le détail de cette journée bien remplie.

Note

Le dépôt Github du projet est disponible ici.


Étape 1 : Création de la Base de Données PostgreSQL

Contexte

Hier, j’avais préparé un fichier JSON pour simuler une base de données. Aujourd’hui, j’ai créé la base de données PostgreSQL pour stocker les données de manière permanente.

Actions réalisées

  1. Création du script SQL (data/create_db.sql) : Ce script contient les requêtes pour créer les tables COUNTRIES, COFFEE_ATTRIBUTES, COFFEES, et COFFEES_HAVE_COUNTRIES, basées sur le modèle que j’avais conçu le jour 1 du projet.

    Exemple de création de table :

    CREATE TABLE COUNTRIES (
        country_id SERIAL PRIMARY KEY,
        name VARCHAR(100) NOT NULL
    );
    
    CREATE TABLE COFFEES (
        coffee_ref SERIAL PRIMARY KEY,
        coffee_name VARCHAR(100) NOT NULL,
        image VARCHAR(255),
        price DECIMAL(6, 2) NOT NULL,
        availability BOOLEAN DEFAULT TRUE,
        attribute_id INT REFERENCES COFFEE_ATTRIBUTES(attribute_id),
        country_id INT REFERENCES COUNTRIES(country_id)
    );
    

    Voir le script complet sur mon dépôt Github.

  2. Création de la Base De Données et exécution du script :

    • J’ai créé la base de données ocoffee dans psql :
    CREATE DATABASE ocoffe OWNER ocoffee;
    
    • Puis j’ai exécuté le script SQL pour créer les tables :
    psql -U ocoffee -d ocoffee -f data/create_db.sql
    

Étape 2 : Connexion à la Base de Données et Récupération des Données

Contexte

J’ai remplacé la logique de récupération des données depuis le fichier JSON par des requêtes SQL pour interagir avec la base de données PostgreSQL.

Actions réalisées

  1. Configuration de la connexion à la base de données (src/models/databaseClient.js) : J’ai utilisé le module pg pour établir une connexion sécurisée à la base de données.

    src/models/databaseClient.js
    /**
    * Database client module
    *
    * This module initializes and exports a PostgreSQL client instance using the 'pg' library.
    * The connection string is retrieved from the POSTGRES_CONNECTION_STRING environment variable.
    * The client is connected immediately upon import.
    *
    * @module databaseClient
    */
    
    import { Client } from 'pg';
    
    
    /**
    * The PostgreSQL client instance.
    *
    * @type {Client}
    */
    const client = new Client(process.env.POSTGRES_CONNECTION_STRING);
    
    
    // Connect to the PostgreSQL database
    client.connect();
    
    
    /**
    * Exports the connected PostgreSQL client for use in other modules.
    */
    export default client;
    
  2. Création d’un DataMapper (src/models/coffee.dataMapper.js) : Ce fichier contient les fonctions pour interagir avec la table COFFEES.

    src/models/coffee.dataMapper.js
    // Import the PostgreSQL client instance
    import client from './databaseClient.js';
    
    /**
    * Coffee data mapper module
    *
    * Provides methods to interact with the 'coffees' table in the database.
    * @module models/coffeeDataMapper
    */
    export default {
      /**
      * Retrieve the three latest coffees from the database.
      *
      * @async
      * @function getThreeLatestCoffees
      * @returns {Promise<Array<Object>>} Array of the three latest coffee objects (reference, name, image)
      */
      async getThreeLatestCoffees() {
        // SQL query to select the three most recent coffees by reference
        const selectCoffeesQuery = `
          SELECT c.coffee_ref, c.coffee_name, c.image
          FROM coffees c
          ORDER BY c.coffee_ref DESC
          LIMIT 3
        `;
    
        const result = await client.query(selectCoffeesQuery);
        return result.rows;
      },
      // other functions...
    };
    

    Voir les modifications complètes sur mon dépôt Github.

  3. Modification des contrôleurs : J’ai mis à jour les contrôleurs pour utiliser le CoffeeDataMapper au lieu du fichier JSON.

    Exemple avec catalog.controller.js :

    src/models/coffee.dataMapper.js
    // Import the data mapper for database operations related to coffee
    import coffeeDataMapper from '../models/coffee.dataMapper.js';
    
    /**
    * Controller for handling catalog page logic.
    * @module controllers/catalogController
    */
    /**
    * Catalog controller object containing methods for rendering catalog and coffee details pages.
    */
    export default {
      /**
      * Render the catalog page with all coffees from the database.
      *
      * This method fetches all coffee entries using the data mapper and renders the 'catalog' view,
      * passing the coffees as data to the template.
      *
      * @async
      * @function displayCatalog
      * @param {import('express').Request} req - Express request object
      * @param {import('express').Response} res - Express response object
      */
      async displayCatalog(req, res) {
        try {
          // Fetch all coffees from the database
          const coffees = await coffeeDataMapper.getAllCoffees();
          // Render the catalog page with the list of coffees
          res.render('catalog', { coffees });
        } catch(error) {
          // Log the error and render a 500 error page
          console.log(error.message);
          res.status(500).render('error/500');
        }
      },
      // other functions...
    };
    

    Voir les modifications complètes sur mon dépôt Github.


Étape 3 : Gestion des Erreurs 404 et 500

Contexte

Pour améliorer l’expérience utilisateur, j’ai ajouté une page 404 personnalisée et une gestion des erreurs 500.

Actions réalisées

  1. Création d’une vue pour la page 404 (views/404.ejs) :

Une page avec une illustration de tasse de café renversée et des liens utiles.

page erreur 404

  1. Gestion des erreurs 500 :

    J’ai créé une vue views/500.ejs.

  2. Ajout de try...catch dans les contrôleurs :

    Pour gérer les erreurs j'ai ajouté une instruction try...catch dans les functions des controllers.

    Exemple dans le catalog.controller.js :

    Error 500 handling - src/controllers/catalog.controller.js
    async displayCatalog(req, res) {
      try {
        // Fetch all coffees from the database
        const coffees = await coffeeDataMapper.getAllCoffees();
        // Render the catalog page with the list of coffees
        res.render('catalog', { coffees });
      } catch(error) {
        // Log the error and render a 500 error page
        console.log(error.message);
        res.status(500).render('error/500');
      }
    }
    

Étape 4 : Stylisation des Pages et Responsive Design

Contexte

J’ai travaillé sur le style CSS des nouvelles vues (coffee-details.ejs et shop.ejs) et rendu l’application responsive pour les appareils mobiles.

Actions réalisées

  1. Création de fichiers CSS dédiés :

    • public/css/coffee-details.css pour la page de détail d’un café.
    • public/css/shop.css pour la page de présentation de la boutique.
  2. Rendu :

    Détail d'un café :

    détail café

    Boutique :

    page boutique


Bilan de la Journée

Ce qui a bien fonctionné

✅ Base de données PostgreSQL : Créée et connectée avec succès.
✅ Dynamisation des pages : Les données sont maintenant récupérées depuis la base.
✅ Gestion des erreurs : Pages 404 et 500 personnalisées et fonctionnelles.
✅ Responsive Design : L’application s’affiche correctement sur mobile.

Difficultés rencontrées

Pas de difficultés majeurs.


Prochaines Étapes et Fonctionnalités Futures

Pour aller plus loin, j’aimerais ajouter :

  • Une carte interactive dans la page shop.ejs pour indiquer l’emplacement de la boutique (avec Leaflet et OpenStreetMap).
  • Un formulaire de contact qui envoie un email de confirmation (avec EmailJS).
  • Une page d’administration pour ajouter de nouveaux cafés.
  • Déployer l’application sur un PaaS comme Render.

Conclusion

Cette troisième journée a été très enrichissante et m'a permis de voir en détail la gestion d'une base de données.

Ce projet challenge était vraiment sympa à réaliser. Dommage que je n'avais pas plus de temps pour ajouter d'autres fonctionnalités intéressantes (que j'essaierai d'ajouter plus tard). J'ai perdu un peu de temps sur des erreurs bêtes mais c'est comme ça qu'on apprend. C'est le métier qui rentre 😀.