SmarMaker - Documentation
Docs» howto:devfront

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
howto:devfront [2026/01/11 22:45] – modification externe 127.0.0.1howto:devfront [Date inconnue] (Version actuelle) – supprimée - modification externe (Date inconnue) 127.0.0.1
Ligne 1: Ligne 1:
-# 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). 
- 
-## 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'; 
-import { z } from 'zod'; 
- 
-const schema = z.object({ 
-  login: z.string().min(1, "Login requis"), 
-  password: z.string().min(1, "Mot de passe requis"), 
-}); 
- 
-export const LoginPage = () => { 
-  const api = useApi(); 
-  const navigate = useNavigation(); 
-  const [, setSession] = useGlobalStates('session'); 
- 
-  const form = useForm({ schema }); 
- 
-  const handleSubmit = async (data) => { 
-    const response = await api.public.post('login', { json: data }); 
- 
-    if (response.success) { 
-      setSession(response.data); 
-      navigate('/'); 
-    } 
-  }; 
- 
-  return ( 
-    <div className="fixed inset-0 bg-white flex justify-center items-center p-10"> 
-      <Form form={form} onSubmit={handleSubmit} className="flex flex-col gap-6 w-full max-w-sm"> 
-        <Input 
-          name="login" 
-          label="Identifiant" 
-          placeholder="Votre login..." 
-        /> 
-        <Input 
-          name="password" 
-          type="password" 
-          label="Mot de passe" 
-          placeholder="●●●●●●●●" 
-        /> 
-        <Button type="submit" loading={form.formState.isSubmitting}> 
-          Connexion 
-        </Button> 
-      </Form> 
-    </div> 
-  ); 
-}; 
-``` 
- 
-## 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 navigate = useNavigation(); 
-  const [items, setItems] = useGlobalStates('items'); 
-  const [session, setSession] = useGlobalStates('session'); 
- 
-  // Charger les items au montage 
-  useEffect(() => { 
-    const fetchItems = async () => { 
-      const response = await api.private.get('items'); 
-      if (response.success) { 
-        setItems(response.data); 
-      } 
-    }; 
-    fetchItems(); 
-  }, []); 
- 
-  // Déconnexion 
-  const handleLogout = async () => { 
-    await api.private.post('logout'); 
-    setSession(null); 
-    navigate('/login'); 
-  }; 
- 
-  return ( 
-    <div className="min-h-screen bg-gray-100 p-4"> 
-      <header className="flex justify-between items-center mb-6"> 
-        <h1 className="text-2xl font-bold">Mes items</h1> 
-        <button onClick={handleLogout} className="text-red-500"> 
-          Déconnexion 
-        </button> 
-      </header> 
- 
-      <div className="space-y-4"> 
-        {items.map((item) => ( 
-          <div 
-            key={item.id} 
-            onClick={() => navigate(`/items/${item.id}`)} 
-            className="bg-white p-4 rounded-lg shadow" 
-          > 
-            <h2 className="font-semibold">{item.label}</h2> 
-            <p className="text-gray-600">{item.description}</p> 
-          </div> 
-        ))} 
-      </div> 
-    </div> 
-  ); 
-}; 
-``` 
- 
-### 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 navigate = useNavigation(); 
-  const [item, setItem] = useState(null); 
- 
-  useEffect(() => { 
-    const fetchItem = async () => { 
-      const response = await api.private.get(`items/${id}`); 
-      if (response.success) { 
-        setItem(response.data); 
-      } 
-    }; 
-    fetchItem(); 
-  }, [id]); 
- 
-  if (!item) { 
-    return <div className="p-4">Chargement...</div>; 
-  } 
- 
-  return ( 
-    <div className="min-h-screen bg-gray-100"> 
-      <header className="bg-white p-4 shadow"> 
-        <button onClick={() => navigate(-1)} className="text-blue-500"> 
-          ← Retour 
-        </button> 
-      </header> 
- 
-      <div className="p-4"> 
-        <h1 className="text-2xl font-bold mb-4">{item.label}</h1> 
-        <p className="text-gray-600">{item.description}</p> 
-      </div> 
-    </div> 
-  ); 
-}; 
-``` 
- 
-## 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 ( 
-    <BrowserRouter> 
-      <Routes> 
-        {/* Routes publiques */} 
-        <Route element={<PublicRoutes />}> 
-          <Route path="/welcome" element={<WelcomePage />} /> 
-          <Route path="/login" element={<LoginPage />} /> 
-        </Route> 
- 
-        {/* Routes privées */} 
-        <Route element={<PrivateRoutes />}> 
-          <Route path="/" element={<HomePage />} /> 
-          <Route path="/items/:id" element={<ItemPage />} /> 
-        </Route> 
- 
-        {/* Erreur 404 */} 
-        <Route path="*" element={<Error404Page />} /> 
-      </Routes> 
-    </BrowserRouter> 
-  ); 
-}; 
-``` 
- 
-### 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 [session] = useGlobalStates('session'); 
-  return session ? <Navigate to="/" /> : <Outlet />; 
-}; 
- 
-export const PrivateRoutes = () => { 
-  const [session] = useGlobalStates('session'); 
-  return session ? <Outlet /> : <Navigate to="/login" />; 
-}; 
-``` 
- 
-## Utiliser les états globaux 
- 
-### Stocker des données 
- 
-``` 
-import { useGlobalStates } from '@cap-rel/smartcommon'; 
- 
-// Lecture + écriture 
-const [items, setItems] = useGlobalStates('items'); 
- 
-// Lecture seule 
-const [items] = useGlobalStates('items'); 
- 
-// Accès à une propriété imbriquée 
-const [settings, setSettings] = useGlobalStates('settings'); 
-const [lng, setLng] = useGlobalStates('settings.lng'); 
-``` 
- 
-### 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 avec validation 
- 
-``` 
-import { useForm, Form, Input, Select, Button } from '@cap-rel/smartcommon'; 
-import { z } from 'zod'; 
- 
-const schema = z.object({ 
-  label: z.string().min(3, "Minimum 3 caractères"), 
-  type: z.enum(["A", "B", "C"]), 
-  description: z.string().optional(), 
-}); 
- 
-const CreateItemForm = ({ onSuccess }) => { 
-  const api = useApi(); 
-  const form = useForm({ schema }); 
- 
-  const handleSubmit = async (data) => { 
-    const response = await api.private.post('items', { json: data }); 
-    if (response.success) { 
-      onSuccess(response.data); 
-      form.reset(); 
-    } 
-  }; 
- 
-  return ( 
-    <Form form={form} onSubmit={handleSubmit}> 
-      <Input name="label" label="Libellé" /> 
-      <Select 
-        name="type" 
-        label="Type" 
-        options={[ 
-          { value: "A", label: "Type A" }, 
-          { value: "B", label: "Type B" }, 
-          { value: "C", label: "Type C" }, 
-        ]} 
-      /> 
-      <Input name="description" label="Description" multiline rows={4} /> 
-      <Button type="submit">Créer</Button> 
-    </Form> 
-  ); 
-}; 
-``` 
- 
-## 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 
  
Made with ❤ by CAP-REL · SmartMaker · GNU AGPL v3+
Code source · Faire un don
SmarMaker - Documentation

Table of Contents

  • SmartAuth
  • SmartMaker - Back (PHP)
    • Mapping Dolibarr - React
  • SmartMaker - Front (React)
    • Animations de pages
    • Architecture
    • Astuces
    • Calendar
    • Composants et pages
    • Configuration du Provider
    • Debug et Logs
    • Hooks SmartCommon
    • PWA (Progressive Web App)
    • Requêtes API
    • Routage
    • SmartCommon
    • Stockage de données
    • Synchronisation offline
    • Thèmes
    • Traductions
  • HowTo - Pas à pas - Votre première application
    • Développement PHP (back)
    • Développement React (front)
    • Première étape : Module Builder Dolibarr
    • SmartAuth
    • SmartBoot : Un squelette prêt à l'emploi
  • Formation SmartMaker
    • Module 1 : Fondamentaux JavaScript ES6+
      • Chapitre 1 : Variables et Scope
      • Chapitre 2 : Fonctions
      • Chapitre 3 : Programmation Asynchrone
      • Chapitre 4 : Modules ES6
    • Module 2 : Introduction à React
      • Chapitre 1 : Philosophie React
      • Chapitre 2 : JSX
      • Chapitre 3 : Composants
    • Module 3 : Hooks React Fondamentaux
      • Chapitre 1 : useState
      • Chapitre 2 : useEffect
      • Chapitre 3 : useRef
      • Chapitre 4 : useContext
    • Module 4 : React Avancé
      • Chapitre 1 : useCallback et useMemo
      • Chapitre 2 : Custom Hooks
      • Chapitre 3 : Redux et Redux Toolkit
    • Module 5 : Architecture SmartMaker
      • Chapitre 1 : Structure du projet
      • Chapitre 2 : Configuration
      • Chapitre 3 : Flux de données
    • Module 6 : SmartCommon - Composants
      • Chapitre 1 : Mise en page
      • Chapitre 2 : Navigation
      • Chapitre 3 : Formulaires
      • Chapitre 4 : Affichage
    • Module 7 : SmartCommon - Hooks
      • Chapitre 1 : useApi
      • Chapitre 2 : Gestion d'état
      • Chapitre 3 : Hooks utilitaires
      • Chapitre 4 : Synchronisation Offline
    • Module 8 : Backend API (PHP)
      • Chapitre 1 : Routage
      • Chapitre 2 : Controllers
      • Chapitre 3 : Mappers
      • Extrafields et formulaires dynamiques
    • Module 9 : Intégration complète
      • Chapitre 1 : Backend
      • Chapitre 2 : Frontend
      • Chapitre 3 : Déploiement
    • Module 10 : Fonctionnalités avancées
      • Chapitre 1 : Mode offline
      • Chapitre 2 : Internationalisation (i18n)
      • Chapitre 3 : Autres fonctionnalités
    • Module 11 : Bonnes pratiques
  • Démonstration
  • Start
  • Composants et pages