Composants React
Les composants React Wast-o permettent d'intégrer nativement les fonctionnalités Wast-o dans votre application React.
Installation
npm install @wasto/react-components
Prérequis
- React 16.8 ou supérieur
- React DOM 16.8 ou supérieur
Composant Calendar
Le composant Calendar affiche un calendrier mensuel avec les jours de collecte par type de déchet.
Utilisation de base
import { Calendar } from '@wasto/react-components';
function App() {
return (
<Calendar
cityId="city-uuid"
lang="fr"
theme="light"
/>
);
}
Props
| Prop | Type | Requis | Défaut | Description |
|---|---|---|---|---|
cityId | string | Oui | - | Identifiant unique de la ville (UUID) |
placeId | string | Non | - | Identifiant du lieu de collecte spécifique |
apiBaseUrl | string | Non | 'https://api.wast-o.com' | URL de base de l'API |
lang | 'fr' | 'en' | Non | 'fr' | Langue d'affichage |
theme | 'light' | 'dark' | Non | 'light' | Thème d'affichage |
onDayClick | (date: Date, wasteTypes: string[]) => void | Non | - | Callback appelé lors du clic sur un jour |
className | string | Non | '' | Classe CSS supplémentaire |
Exemple avec gestion d'événements
import { Calendar } from '@wasto/react-components';
import { useState } from 'react';
function App() {
const [selectedDate, setSelectedDate] = useState<Date | null>(null);
const [wasteTypes, setWasteTypes] = useState<string[]>([]);
return (
<div>
<Calendar
cityId="city-uuid"
placeId="place-uuid"
lang="fr"
onDayClick={(date, types) => {
setSelectedDate(date);
setWasteTypes(types);
console.log('Jour sélectionné:', date);
console.log('Types de déchets:', types);
}}
/>
{selectedDate && (
<div>
<h3>Collecte le {selectedDate.toLocaleDateString('fr-FR')}</h3>
<p>Types de déchets: {wasteTypes.join(', ')}</p>
</div>
)}
</div>
);
}
Embeds iframe (PublicWebEmbed)
Pour embarquer le site public (info-tri, centres de tri, calendrier) sans recoder l’UI :
import {
PublicWebEmbed,
RecyclingInfoEmbed,
RecyclingCentersEmbed,
} from '@wasto/react-components';
<RecyclingInfoEmbed cityId="city-uuid" />
<RecyclingCentersEmbed cityId="city-uuid" />
<PublicWebEmbed page="calendrier" cityId="city-uuid" placeId="place-uuid" />
| Prop | Type | Requis | Défaut | Description |
|---|---|---|---|---|
page | 'info' | 'centres-de-tri' | 'calendrier' | 'calendrier-pdf' | oui (PublicWebEmbed) | - | Module affiché |
cityId | string | Oui | - | Commune |
placeId | string | Non | - | Secteur (calendrier) |
cityGroupId | string | Non | - | Groupement (calendrier-pdf) |
publicWebBaseUrl | string | Non | 'https://public-web.wast-o.com' | Base du site public |
height | number | string | Non | 520 | Hauteur de l’iframe |
width | number | string | Non | '100%' | Largeur du widget |
maxWidth | number | string | Non | - | Largeur maximale |
align | 'left' | 'center' | 'right' | Non | - | Alignement |
accentColor | string | Non | '#0f766e' | Couleur d’accent |
preview | 'below' | 'side' | 'none' | Non | 'below' (calendrier-pdf) | Aperçu PDF |
title | string | Non | selon page | title de l’iframe |
RecyclingInfoEmbed et RecyclingCentersEmbed sont des raccourcis (page="info" / page="centres-de-tri").
Widget recherche d’adresse → PDF (CalendarPdfEmbed)
Barre de recherche embarquée : le citoyen saisit sa rue, choisit son secteur, puis télécharge le calendrier PDF généré par l’API.
import { CalendarPdfEmbed } from '@wasto/react-components';
function WidgetCollectivite() {
return (
<CalendarPdfEmbed
cityId="city-uuid"
accentColor="#0f766e"
placeholder="Votre rue"
preview="below"
maxWidth={960}
align="center"
/>
);
}
Équivalent via PublicWebEmbed : page="calendrier-pdf".
| Prop | Type | Requis | Défaut | Description |
|---|---|---|---|---|
cityId | string | Oui | - | Commune |
cityGroupId | string | Non | - | Élargit la recherche aux communes du groupement |
accentColor | string | Non | '#0f766e' | Couleur d’accent |
placeholder | string | Non | - | Placeholder du champ adresse |
year | number | Non | année en cours | Année du calendrier PDF |
preview | 'below' | 'side' | 'none' | Non | 'below' | Aperçu sous / à côté / masqué |
previewHeight | number | Non | auto | Hauteur de l’aperçu (px) |
previewWidth | number | Non | 100% | Largeur de l’aperçu (px) |
width | number | string | Non | '100%' | Largeur du widget |
maxWidth | number | string | Non | - | Largeur max (ex. 960) |
align | 'left' | 'center' | 'right' | Non | - | Alignement dans la page |
publicWebBaseUrl | string | Non | 'https://public-web.wast-o.com' | Base du site public |
height | number | string | Non | 420 | Hauteur initiale (auto-ajustée) |
autoResize | boolean | Non | true | Ajuste la hauteur au contenu |
Snippet iframe copiable : voir Intégration par iframe.
Composant Challenges
Le composant Challenges affiche la liste des challenges disponibles pour une ville.
Utilisation de base
import { Challenges } from '@wasto/react-components';
function App() {
return (
<Challenges
cityId="city-uuid"
lang="fr"
theme="light"
/>
);
}
Props
| Prop | Type | Requis | Défaut | Description |
|---|---|---|---|---|
cityId | string | Oui | - | Identifiant unique de la ville (UUID) |
apiBaseUrl | string | Non | 'https://api.wast-o.com' | URL de base de l'API |
lang | 'fr' | 'en' | Non | 'fr' | Langue d'affichage |
theme | 'light' | 'dark' | Non | 'light' | Thème d'affichage |
onChallengeClick | (challengeId: string) => void | Non | - | Callback appelé lors du clic sur un challenge |
onChallengeComplete | (challengeId: string, score: number) => void | Non | - | Callback appelé lors de la complétion d'un challenge |
className | string | Non | '' | Classe CSS supplémentaire |
Exemple avec navigation
import { Challenges } from '@wasto/react-components';
import { useState } from 'react';
function App() {
const [selectedChallenge, setSelectedChallenge] = useState<string | null>(null);
return (
<div>
<Challenges
cityId="city-uuid"
lang="fr"
onChallengeClick={(challengeId) => {
setSelectedChallenge(challengeId);
// Naviguer vers le quiz
}}
onChallengeComplete={(challengeId, score) => {
console.log(`Challenge ${challengeId} complété avec un score de ${score}%`);
}}
/>
</div>
);
}
Composant Quiz
Le composant Quiz affiche un quiz interactif pour un challenge spécifique.
Utilisation de base
import { Quiz } from '@wasto/react-components';
function App() {
const deviceId = 'device-uuid'; // Généré ou récupéré depuis le localStorage
return (
<Quiz
cityId="city-uuid"
challengeId="challenge-uuid"
deviceId={deviceId}
lang="fr"
theme="light"
/>
);
}
Props
| Prop | Type | Requis | Défaut | Description |
|---|---|---|---|---|
cityId | string | Oui | - | Identifiant unique de la ville (UUID) |
challengeId | string | Oui | - | Identifiant du challenge |
serieId | string | Non | - | Identifiant de la série de questions |
apiBaseUrl | string | Non | 'https://api.wast-o.com' | URL de base de l'API |
lang | 'fr' | 'en' | Non | 'fr' | Langue d'affichage |
theme | 'light' | 'dark' | Non | 'light' | Thème d'affichage |
deviceId | string | Non | - | Identifiant de l'appareil pour sauvegarder la progression |
onComplete | (score: number) => void | Non | - | Callback appelé à la fin du quiz |
className | string | Non | '' | Classe CSS supplémentaire |
Exemple complet
import { Quiz } from '@wasto/react-components';
import { useState, useEffect } from 'react';
function App() {
const [deviceId, setDeviceId] = useState<string>('');
const [score, setScore] = useState<number | null>(null);
useEffect(() => {
// Générer ou récupérer le deviceId
const storedId = localStorage.getItem('wasto_device_id');
if (storedId) {
setDeviceId(storedId);
} else {
const newId = 'web_' + crypto.randomUUID();
localStorage.setItem('wasto_device_id', newId);
setDeviceId(newId);
}
}, []);
return (
<div>
{score === null ? (
<Quiz
cityId="city-uuid"
challengeId="challenge-uuid"
deviceId={deviceId}
lang="fr"
onComplete={(finalScore) => {
setScore(finalScore);
console.log(`Quiz terminé avec un score de ${finalScore}%`);
}}
/>
) : (
<div>
<h2>Quiz terminé !</h2>
<p>Votre score: {score}%</p>
</div>
)}
</div>
);
}
Personnalisation du style
Les composants utilisent des classes CSS avec le préfixe wasto-. Vous pouvez personnaliser le style en surchargeant ces classes :
/* Personnaliser le calendrier */
.wasto-calendar {
font-family: 'Your Font', sans-serif;
}
.wasto-calendar-day.today {
background-color: #e3f2fd;
}
/* Personnaliser les challenges */
.wasto-challenge-card {
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
/* Personnaliser le quiz */
.wasto-quiz-question {
font-size: 1.2rem;
}
Gestion des erreurs
Tous les composants gèrent les erreurs de manière interne et affichent un message d'erreur si nécessaire. Vous pouvez également intercepter les erreurs :
import { Calendar } from '@wasto/react-components';
function App() {
return (
<Calendar
cityId="city-uuid"
apiBaseUrl="https://api.wast-o.com"
onError={(error) => {
console.error('Erreur du calendrier:', error);
// Afficher une notification à l'utilisateur
}}
/>
);
}
Types TypeScript
Tous les types sont exportés pour une utilisation TypeScript :
import type { CalendarProps, ChallengesProps, QuizProps } from '@wasto/react-components';
const calendarProps: CalendarProps = {
cityId: 'city-uuid',
lang: 'fr',
};
Exemple d'application complète
import React, { useState } from 'react';
import { Calendar, Challenges, Quiz } from '@wasto/react-components';
function WastoApp() {
const [view, setView] = useState<'calendar' | 'challenges' | 'quiz'>('calendar');
const [selectedChallenge, setSelectedChallenge] = useState<string | null>(null);
const cityId = 'city-uuid';
const deviceId = localStorage.getItem('wasto_device_id') || 'web_' + crypto.randomUUID();
return (
<div>
<nav>
<button onClick={() => setView('calendar')}>Calendrier</button>
<button onClick={() => setView('challenges')}>Challenges</button>
</nav>
{view === 'calendar' && (
<Calendar
cityId={cityId}
lang="fr"
onDayClick={(date, wasteTypes) => {
console.log('Jour sélectionné:', date, wasteTypes);
}}
/>
)}
{view === 'challenges' && (
<Challenges
cityId={cityId}
lang="fr"
onChallengeClick={(challengeId) => {
setSelectedChallenge(challengeId);
setView('quiz');
}}
/>
)}
{view === 'quiz' && selectedChallenge && (
<Quiz
cityId={cityId}
challengeId={selectedChallenge}
deviceId={deviceId}
lang="fr"
onComplete={(score) => {
console.log('Score:', score);
setView('challenges');
setSelectedChallenge(null);
}}
/>
)}
</div>
);
}
export default WastoApp;
Support
Pour toute question ou problème, consultez la documentation API ou contactez le support technique.