# Chapitre 1 : Structure du projet
## Vue d'ensemble
Un projet SmartMaker se compose de deux parties :
1. **mobile/** : Code source React (développement)
2. **pwa/** : Application compilée + API PHP (production)
## Arborescence complète
```
monmodule/ # Module Dolibarr
├── mobile/ # CODE SOURCE REACT
│ ├── src/
│ │ ├── App.jsx # Composant racine
│ │ ├── main.jsx # Point d'entrée
│ │ ├── appConfig.js # Configuration
│ │ ├── components/
│ │ │ ├── app/
│ │ │ │ └── Router/ # Configuration routes
│ │ │ │ ├── index.jsx
│ │ │ │ └── Guards/ # Protection routes
│ │ │ └── pages/
│ │ │ ├── public/ # Pages sans auth
│ │ │ │ ├── LoginPage/
│ │ │ │ └── WelcomePage/
│ │ │ ├── private/ # Pages avec auth
│ │ │ │ ├── HomePage/
│ │ │ │ └── ItemPage/
│ │ │ └── errors/
│ │ │ └── Error404Page/
│ │ ├── redux/ # Store Redux (optionnel)
│ │ │ └── reducers/
│ │ ├── i18n/ # Configuration i18next
│ │ ├── utils/ # Helpers, constantes
│ │ └── locales/ # Fichiers de traductions
│ ├── public/
│ │ ├── images/ # Icônes PWA
│ │ └── locales/ # Traductions
│ ├── index.html # Template HTML
│ ├── package.json # Dépendances npm
│ ├── vite.config.js # Configuration Vite
│ └── .env # Variables d'environnement
│
├── pwa/ # APPLICATION COMPILÉE + API
│ ├── api.php # Point d'entrée API
│ └── dist/ # Fichiers React compilés
│
├── smartmaker-api/ # BACKEND PHP
│ ├── Controllers/ # Logique métier
│ └── Mappers/ # Conversion Dolibarr → DTO
│
└── smartmaker-api-prepend.php # Bootstrap PHP
```
## Détail des fichiers clés
### main.jsx - Point d'entrée
```javascript
// src/main.jsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { App } from './App';
import './index.css';
createRoot(document.getElementById('root')).render(
);
```
C'est le fichier appelé par `index.html`. Il monte l'application React dans le DOM.
### App.jsx - Composant racine
```javascript
// src/App.jsx
import { Provider } from '@cap-rel/smartcommon';
import { Router } from './components/app/Router';
import { config } from './appConfig';
export const App = () => (
);
```
Le `Provider` de SmartCommon englobe toute l'application et fournit :
- Configuration globale
- État Redux
- Contexte API
- i18next
### appConfig.js - Configuration
```javascript
// src/appConfig.js
export const config = {
debug: import.meta.env.DEV,
api: {
prefixUrl: import.meta.env.VITE_API_URL,
timeout: 30000,
paths: {
login: "login",
logout: "logout",
refresh: "refresh"
}
},
storage: {
local: ["session", "settings"]
},
globalState: {
reducers: {
session: null,
settings: { lng: "fr" },
items: []
}
},
pages: {
"/": { "/settings": "slideLeft", "*": "fade" },
"*": "fade"
}
};
```
Détaillé dans le chapitre suivant.
### index.html - Template
```html
Mon Application
```
Vite injecte automatiquement les scripts compilés en production.
## Organisation des composants
### Structure recommandée pour une page
```
components/pages/private/ItemPage/
├── index.jsx # Composant principal
├── ItemPage.module.css # Styles (optionnel)
└── components/ # Sous-composants locaux (optionnel)
├── ItemHeader.jsx
└── ItemActions.jsx
```
### Exemple de page
```javascript
// components/pages/private/ItemPage/index.jsx
import { useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { Page, Block, Spinner } from '@cap-rel/smartcommon';
import { useApi, useStates } from '@cap-rel/smartcommon';
export const ItemPage = () => {
const { id } = useParams();
const api = useApi();
const st = useStates({
initialStates: {
item: null,
loading: true,
error: null
}
});
useEffect(() => {
const fetchItem = async () => {
try {
const data = await api.private.get(`items/${id}`).json();
st.set('item', data);
} catch (err) {
st.set('error', err.message);
} finally {
st.set('loading', false);
}
};
fetchItem();
}, [id]);
if (st.get('loading')) {
return ;
}
if (st.get('error')) {
return Erreur : {st.get('error')};
}
const item = st.get('item');
return (
{item.description}
);
};
```
## Le Router
### Configuration des routes
```javascript
// components/app/Router/index.jsx
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { PublicRoutes, PrivateRoutes } from './Guards';
// Pages
import { LoginPage } from '../../pages/public/LoginPage';
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 protégées */}
}>
} />
} />
{/* Fallback */}
} />
);
};
```
### Guards d'authentification
```javascript
// components/app/Router/Guards/index.jsx
import { Outlet, Navigate } from 'react-router-dom';
import { useGlobalStates } from '@cap-rel/smartcommon';
export const PrivateRoutes = () => {
const [session] = useGlobalStates('session');
return session ? : ;
};
export const PublicRoutes = () => {
const [session] = useGlobalStates('session');
return session ? : ;
};
```
## Variables d'environnement
```bash
# .env
VITE_API_URL=https://mondomaine.com/modules/monmodule/pwa/api.php
```
Accès dans le code :
```javascript
const apiUrl = import.meta.env.VITE_API_URL;
const isDev = import.meta.env.DEV;
const isProd = import.meta.env.PROD;
```
**Important** : Les variables doivent commencer par `VITE_` pour être exposées au client.
## Dossier pwa/ - Production
Après compilation (`npm run build`), les fichiers sont générés dans `pwa/dist/` :
```
pwa/
├── api.php # Point d'entrée API (à créer)
└── dist/
├── index.html # HTML avec assets injectés
├── assets/
│ ├── index-abc123.js # Bundle JS
│ └── index-def456.css # Bundle CSS
└── images/
```
## Points clés à retenir
1. **mobile/** = code source pour développement
2. **pwa/** = code compilé pour production
3. **App.jsx** englobe tout avec le Provider SmartCommon
4. **appConfig.js** centralise la configuration
5. **Router** gère les routes avec guards d'authentification
6. Variables d'environnement préfixées par **VITE_**
[[:15_training:module5-architecture-smartmaker:start|← Retour au module]] | [[:15_training:module5-architecture-smartmaker:configuration|Chapitre suivant : Configuration →]]