L'objectif de cette semaine est un rappel de ce qu'on a vu l'année passée dans la ressource R213. De plus nous verrons comment utiliser les types avec TypeScript pour éviter les erreurs en runtime.
-
Initialiser le projet Astro
npm create astro@latest r312-td cd r312-td -
Installer les dépendances
npm install pocketbase
-
Créer la collection
maisonavec les champs suivants :nomMaison(text) - Nom de la propriétéadresse(text) - Adresse complèteprix(number) - Prix en eurossurface(number) - Surface en m²nbChambres(number) - Nombre de chambresnbSdb(number) - Nombre de salles de bainimage(file) - Photo de la propriétéfavori(bool) - Marquer comme favori
-
Générer les types TypeScript
npx pocketbase-typegen --url https://votre-instance.pockethost.io/ --email votre-email --password votre-mot-de-passe --out src/utils/pocketbase-types.ts
Créer le fichier src/utils/db.ts :
import PocketBase from 'pocketbase';
import type { TypedPocketBase } from "./pocketbase-types";
const pb = new PocketBase('URL') as TypedPocketBase;
export default pb;En utilisant TypedPocketBase, nous tirons parti des types générés automatiquement via pocketbase-typegen. Cela nous offre l'autocomplétion et un typage strict pour toutes les collections et tous les champs définis dans la base de donnée. L'avantage principal est une réduction significative des erreurs lors de l'accès aux données, un problème fréquemment rencontré en S2.
Objectif : Afficher la liste des maisons disponibles dans la page
- Récupération des données
- Importer PocketBase depuis
../utils/pb - Utiliser
pb.collection(Collection.Maison).getFullList()pour récupérer toutes les maisons - Trier par date de création décroissante
- Importer PocketBase depuis
---
// le frontmatter de index.astro
import { Collections } from '../../pocketbase-types';
import Card from '../components/Card.astro';
import Layout from '../layouts/Layout.astro';
import pb from '../utils/pb';
let listMaisons = await pb.collection(Collections.Maison).getFullList({
sort: '-created',
});
console.log(listMaisons);
---- Assurez-vous que la liste des offres est affichée dans la console.
- Affichage des données
- Créer un composant
Card.astropour afficher chaque maison - Utiliser la méthode
map()pour parcourir la liste
- Créer un composant
<a href="/add" ><button>Ajouter une Offre</button></a>
{???.map((???) => (
<Card maison={maison} />
))}Objectif : Créer un composant réutilisable pour afficher une maison
- Props et types
- Définir l'interface
Propsavecmaison: MaisonRecord - Importer le type
MaisonRecorddepuis les types générés
- Définir l'interface
---
// frontmatter de CardOffre.astro
// Import du type MaisonRecord généré automatiquement depuis PocketBase
// Ce type contient tous les champs de la collection 'maison' avec leurs types corrects
import type { MaisonRecord } from '../utils/pocketbase-types';
// Définition de l'interface Props pour typer les propriétés passées au composant
// Cela permet l'autocomplétion et la vérification de type au moment de la compilation
interface Props {
maison: MaisonRecord; // La propriété maison doit être de type MaisonRecord
}
// Extraction de la propriété maison depuis les props du composant Astro
const { maison } = Astro.props;
---- Afficher les informations d'une maison:
<div>
<h2>{maison.nomMaison}</h2>
<p>{maison.adresse}</p>
...
</div>Objectif : Afficher les images stockées dans PocketBase dans un composant réutilisable.
-
Créer le composant
PbImage.astro- Ce composant reçoit comme propriétés les paramètres utilisés par la fonction
pb.files.getURL() - Il génère l'URL complète de l'image stockée dans PocketBase
- Utilise ensuite le composant
Imaged'Astro pour l'afficher de manière optimisée
- Ce composant reçoit comme propriétés les paramètres utilisés par la fonction
-
Props du composant
record: L'enregistrement de la base de données contenant l'imageimageField: Le nom du champ qui contient le fichier image
---
// Import de PocketBase pour accéder aux méthodes de gestion des fichiers
import pb from '../utils/pb';
// Import du composant Image d'Astro pour l'optimisation automatique des images
import { Image } from "astro:assets";
interface Props {
record: { [key: string]: any }; // L'enregistrement PocketBase contenant l'image
imageField: string; // Le nom de champ de la collection qui contient l'image
}
// Récupération des propriétés passées au composant
const { record, imageField } = Astro.props;
// Génération de l'URL complète de l'image en utilisant PocketBase
// pb.files.getURL() prend l'enregistrement et le nom du fichier pour créer l'URL
const imageURL = pb.files.getURL(record, record[imageField]);
---
<!-- Affichage de l'image avec le composant Image d'Astro -->
<!-- inferSize={true} permet à Astro de détecter automatiquement les dimensions -->
{imageURL &&
<Image
src={imageURL}
alt={record.nomMaison || 'Image'}
inferSize={true}
/>
}- Utilisation dans Card.astro
<!-- Remplacer <img> par le composant PbImage -->
<PbImage record={maison} imageField="image" />Si le temps le permet, implémentez un formulaire pour ajouter une nouvelle maison à la base de données. Vous pouvez vous inspirer du cours R213 ou consulter la documentation officielle d'Astro sur les formulaires : Astro Forms Recipe.
Instructions importantes :
- Désactivez le prerendering sur la page d'ajout (voir On-Demand Rendering).
- Utilisez l'attribut
enctype="multipart/form-data"dans la balise<form>pour permettre l'upload de fichiers (images). - Effectuez toujours la validation des données côté serveur pour garantir la sécurité et l'intégrité des données.
L'objectif de cette semaine est d'ajouter du style en utilisant DaisyUI. DaisyUI est une librairie de composants basée sur Tailwind CSS qui permet de styliser rapidement des applications web avec des composants préconçus et personnalisables.
-
Installer les libraires de Tailwind CSS et daisyUI:
npx astro add tailwind npm install daisyui@latest
-
Verifier que le fichier astro.config.mjs contient :
// @ts-check import { defineConfig } from "astro/config"; import tailwindcss from "@tailwindcss/vite"; export default defineConfig({ vite: { plugins: [tailwindcss()], }, });
-
Ajouter Tailwind CSS et daisyUI dans votre fichier CSS principal (et supprimer les autres styles) :
@import "tailwindcss"; @plugin "daisyui";
-
Utiliser les classes DaisyUI dans vos composants :
- Par exemple :
<button class="btn btn-primary">Bouton DaisyUI</button>
- Par exemple :
Votre projet Astro est maintenant prêt à utiliser DaisyUI pour styliser vos composants rapidement.
Faites un commit.
DaisyUI propose des couleurs sémantiques (comme primary, secondary, accent, info, success, warning, error) qui facilitent la cohérence du design dans votre application.
-
Modifiez la couleur des textes de vos boutons, cartes et autres éléments en utilisant les classes de couleurs DaisyUI, par exemple :
<button class="btn btn-primary text-primary-content">Ajouter une Offre</button> <div class="card bg-base-100 shadow-xl border border-primary text-primary"> <!-- contenu de la carte --> </div>
-
Essayez différentes variantes :
- Remplacez
text-primarypartext-secondary,text-accent,text-success, etc. - Utilisez aussi les classes
text-base-content,text-info,text-warning, etc. pour tester les couleurs sémantiques sur différents éléments.
- Remplacez
-
Ajoutez des messages d'état avec des couleurs de texte adaptées, par exemple :
<div class="alert alert-success text-success-content">Opération réussie !</div> <div class="alert alert-error text-error-content">Une erreur est survenue.</div>
Testez différentes couleurs et composants pour mieux comprendre l'intérêt des couleurs sémantiques dans la conception d'interfaces accessibles et cohérentes.
DaisyUI propose de nombreux composants prêts à l'emploi (boutons, cartes, alertes, formulaires, modals, etc.) que vous pouvez intégrer facilement dans votre application Astro.
-
Parcourez la documentation DaisyUI - Components pour découvrir les différents composants disponibles.
-
Remplacez vos éléments HTML classiques (boutons, cartes, formulaires, etc.) par les composants DaisyUI correspondants. Par exemple :
<div class="card bg-base-100 w-96 shadow-sm m-5"> <figure> <PbImage record={maison} imageField="image" /> </figure> <div class="card-body"> <h2 class="card-title">{maison.nomMaison}</h2> <p>{maison.adresse}</p> <div class="card-actions justify-end"> <button class="btn btn-primary">Plus d'infos</button> </div> </div>
-
Testez d'autres composants comme les alertes, badges, modals, ou encore les barres de navigation pour enrichir l'interface de votre application.
-
Personnalisez les composants en utilisant les classes utilitaires Tailwind CSS et les options de DaisyUI pour adapter le style à vos besoins.
- Utilisez la documentation officielle pour copier-coller rapidement des exemples de composants.
- Pensez à la cohérence visuelle de votre application en utilisant les couleurs et variantes sémantiques vues précédemment.
- N'hésitez pas à explorer les options de personnalisation de DaisyUI pour adapter les composants à votre charte graphique.
DaisyUI propose plusieurs thèmes prédéfinis qui permettent de changer rapidement l'apparence globale de votre application (couleurs, ambiance claire/sombre, etc.). Vous pouvez aussi créer vos propres thèmes personnalisés.
- Activer le sélecteur de thème DaisyUI
Ajoutez l'attributdata-themesur la balise<html>ou<body>de votre projet Astro pour appliquer un thème (Consultez la liste complète des thèmes DaisyUI pour voir les options disponibles (light,dark,cupcake,bumblebee,emerald, etc.)):<html data-theme="light"> <!-- ou --> <html data-theme="dark"> <!-- ou un autre thème DaisyUI, par exemple --> <html data-theme="cupcake">
Par default,les themes light et dark sont activés. On peut activer d'autre themes dans le fichier css global:
@import "tailwindcss";
@plugin "daisyui" {
themes: light --default, dark --prefersdark, cupcake;
}<div class="p-4">
<button onclick="document.documentElement.setAttribute('data-theme', 'dark')" class="btn btn-neutral">Mode sombre</button>
<button onclick="document.documentElement.setAttribute('data-theme', 'light')" class="btn btn-primary ml-2">Mode clair</button>
</div>Vous pouvez aussi utiliser les composants de type Theme Controller de DaisyUI.
Vous pouvez personnaliser un thème dans le fichier CSS global. Par exemple pour changer la couleur primaire du thème light, il faut ajouter sous la ligne @plugin "daisyui";:
@plugin "daisyui/theme" {
name: "light";
default: true;
--color-primary: blue;
--color-secondary: teal;
}Vous pouvez aussi créer votre propre thème. DaisyUI propose un générateur de thème pour concevoir facilement votre thème, puis copier le code généré dans votre fichier CSS.
Pour aller plus loin, consultez la documentation DaisyUI sur les thèmes.
Pour mettre en application ce que vous avez appris, réalisez les exercices suivants :
-
Créer votre propre thème DaisyUI
- Utilisez le générateur de thème DaisyUI pour concevoir un thème personnalisé (choisissez vos couleurs, polices, etc.).
- Ajoutez ce thème à votre projet en suivant la documentation DaisyUI sur les thèmes.
- Appliquez votre thème à votre site d’agence immobilière.
-
Styliser votre site avec DaisyUI
- Remplacez les éléments HTML classiques par des composants DaisyUI.
- Essayez d’utiliser au moins un composant de chaque catégorie :
- Actions (ex : boutons, dropdowns)
- Navigation (ex : navbar, tabs)
- Data Display (ex : cards, badges, alerts)
- Consultez la documentation des composants DaisyUI pour trouver des exemples.
-
Ajouter un bouton de changement de thème (Theme Controller)
- Ajoutez un bouton qui permet à l’utilisateur de basculer entre deux thèmes : un thème clair et un thème sombre.
- Vous pouvez utiliser le composant Theme Controller de DaisyUI ou créer votre propre bouton avec du JavaScript.
-
Créer une route dynamique pour les détails d’une maison
- Ajoutez une page dynamique qui affiche les détails d’une maison sélectionnée (par exemple :
/maison/[id].astro). - Inspirez-vous de ce que vous avez vu en R213 pour la création de routes dynamiques dans Astro.
- Affichez toutes les informations de la maison, y compris l’image, en utilisant les composants DaisyUI pour la mise en forme.
- Ajoutez une page dynamique qui affiche les détails d’une maison sélectionnée (par exemple :