# Développement React (front) Vous venez de déployer SmartBoot dans votre module et vous vous demandez par où commencer ? Vous êtes au bon endroit ! ## Installation des dépendances ``` cd mobile npm i ``` ## Configuration initiale ### Fichier .env Copiez ou renommez ''mobile/.env.example'' en ''mobile/.env'' : ``` VITE_API_URL=https://votre-dolibarr.com/custom/monmodule/pwa/api.php VITE_APP_VERSION=dev VITE_LOCALES=en,fr ``` ### Configuration de l'application Le fichier ''appConfig.js'' centralise toute la configuration : ``` // src/appConfig.js export const config = { // Mode debug (logs colorés dans la console) debug: import.meta.env.DEV, // Configuration API api: { prefixUrl: import.meta.env.VITE_API_URL, timeout: 30000, paths: { login: "login", logout: "logout", refresh: "refresh", }, }, // Stockage storage: { local: ["session", "settings"], // Persisté en localStorage }, // État global initial globalState: { reducers: { session: null, settings: { lng: "fr" }, items: [], }, }, // Animations de pages pages: { "/": { "/settings": "slideLeft", "*": "fade" }, "*": "fade", }, }; ``` ## Lancement ``` cd mobile npm run dev ``` Ouvrez http://localhost:5173/ (mode mobile recommandé dans les DevTools). Attention [[SmartAuth]] est nécessaire ! ## Structure des pages L'arborescence préinstallée par SmartBoot : ``` src/components/pages/ ├── errors/ │ └── Error404Page/ │ └── index.jsx ├── private/ │ └── HomePage/ │ └── index.jsx └── public/ ├── LoginPage/ │ └── index.jsx └── WelcomePage/ └── index.jsx ``` ^ Dossier ^ Description ^ | ''public/'' | Pages accessibles sans authentification | | ''private/'' | Pages nécessitant une authentification | | ''errors/'' | Pages d'erreur (404, etc.) | ## Créer une page de login Avec SmartCommon, la page de login devient très simple : ``` // src/components/pages/public/LoginPage/index.jsx import { useApi, useGlobalStates, useForm, useNavigation } from '@cap-rel/smartcommon'; import { Form, Input, Button } from '@cap-rel/smartcommon'; export const LoginPage = () => { const api = useApi(); const nav = useNavigation(); const gst = useGlobalStates(); const form = useForm({ defaultValues: { login: '', password: '' } }); const handleSubmit = async (data) => { try { const user = await api.login(data); gst.local.set('session', user); nav.navigate('/'); } catch (error) { console.error('Login failed:', error); } }; return (
); }; ``` ## Créer une page privée ### Page d'accueil avec liste ``` // src/components/pages/private/HomePage/index.jsx import { useApi, useGlobalStates, useNavigation } from '@cap-rel/smartcommon'; import { useEffect } from 'react'; export const HomePage = () => { const api = useApi(); const nav = useNavigation(); const gst = useGlobalStates(); const items = gst.get('items') ?? []; // Charger les items au montage useEffect(() => { const fetchItems = async () => { try { const data = await api.get('items'); gst.set('items', data); } catch (error) { console.error('Fetch failed:', error); } }; fetchItems(); }, []); // Déconnexion const handleLogout = async () => { await api.logout(); nav.navigate('/login'); }; return (

Mes items

{items.map((item) => (
nav.navigate(`/items/${item.id}`)} className="bg-white p-4 rounded-lg shadow" >

{item.label}

{item.description}

))}
); }; ``` ### Page de détail ``` // src/components/pages/private/ItemPage/index.jsx import { useApi, useGlobalStates, useNavigation } from '@cap-rel/smartcommon'; import { useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; export const ItemPage = () => { const { id } = useParams(); const api = useApi(); const nav = useNavigation(); const [item, setItem] = useState(null); useEffect(() => { const fetchItem = async () => { try { const data = await api.get(`items/${id}`); setItem(data); } catch (error) { console.error('Fetch failed:', error); } }; fetchItem(); }, [id]); if (!item) { return
Chargement...
; } return (

{item.label}

{item.description}

); }; ``` ## Configurer le routeur ``` // src/components/app/Router/index.jsx import { BrowserRouter, Routes, Route } from 'react-router-dom'; import { PublicRoutes, PrivateRoutes } from './Guards'; import { LoginPage } from '../../pages/public/LoginPage'; import { WelcomePage } from '../../pages/public/WelcomePage'; import { HomePage } from '../../pages/private/HomePage'; import { ItemPage } from '../../pages/private/ItemPage'; import { Error404Page } from '../../pages/errors/Error404Page'; export const Router = () => { return ( {/* Routes publiques */} }> } /> } /> {/* Routes privées */} }> } /> } /> {/* Erreur 404 */} } /> ); }; ``` ### Guards avec SmartCommon ``` // src/components/app/Router/Guards/index.jsx import { Outlet, Navigate } from 'react-router-dom'; import { useGlobalStates } from '@cap-rel/smartcommon'; export const PublicRoutes = () => { const gst = useGlobalStates(); const session = gst.get('session'); return session ? : ; }; export const PrivateRoutes = () => { const gst = useGlobalStates(); const session = gst.get('session'); return session ? : ; }; ``` ## Utiliser les états globaux ### Stocker des données ``` import { useGlobalStates } from '@cap-rel/smartcommon'; const gst = useGlobalStates(); // Lire une valeur const items = gst.get('items'); const lng = gst.get('settings.lng'); // Écrire en mémoire (non persistant) gst.set('items', newItems); // Écrire dans localStorage (persistant) gst.local.set('session', userData); // Écrire dans sessionStorage (session uniquement) gst.session.set('tempData', data); // Supprimer gst.unset('session'); ``` ### Persistance automatique Les clés listées dans ''config.storage.local'' sont automatiquement persistées en localStorage : ``` // appConfig.js storage: { local: ["session", "settings"], // Persisté automatiquement } ``` ## Utiliser les formulaires ### Formulaire complet ``` import { useForm, Form, Input, Select, Button } from '@cap-rel/smartcommon'; const CreateItemForm = ({ onSuccess }) => { const api = useApi(); const form = useForm({ defaultValues: { label: '', type: '', description: '' } }); const handleSubmit = async (data) => { try { const created = await api.post('items', { json: data }); onSuccess(created); } catch (error) { console.error('Create failed:', error); } }; return (
); }; ``` ## Build et déploiement ``` # Build de production npm run build # Le build génère le dossier dist/ # Copiez-le dans le dossier pwa/ de votre module cp -r dist/* ../pwa/ ``` Ou utilisez le Makefile : ``` make pwa ``` ## Voir aussi * [[../front/hooks|Hooks]] - Documentation complète des hooks * [[../front/smartcommon|SmartCommon]] - Tous les composants disponibles * [[../front/configuration|Configuration]] - Options du Provider * [[../front/requetes_api|Requêtes API]] - Utilisation de useApi * [[devback|Développement PHP]] - API backend