# CLAUDE.md — jamespot-react-core

Application React principale : système d'extensions, registre de composants, dual router (AngularJS + React), store Redux. Déployé comme app, consommé par les extensions.

## Structure

```
src/
├── App.tsx                   # Entry point, expose les libraries sur `window`. Hygen marker ligne 52
├── ReactCore.ts              # Classe core : extensionAdd, require, routeAdd, event system
├── Router.ts                 # Enregistrement états AngularJS pour le router React
├── components/               # Composants spécifiques à l'app
├── displayer/                # Mapping widget → composant (display/input/search)
├── hooks/
├── redux/
│   ├── store.tsx             # Création store : reducers static + async + extension
│   ├── initStore.ts          # State initial depuis l'objet J global
│   └── middleware.ts         # Logger custom
├── registry/
│   ├── core-component-list.ts    # Composants core (lazy imports)
│   ├── ext-component-list.ts     # Composants JRC depuis react-components
│   ├── ReactCoreRegistry.tsx     # registerComponent, registerLib, getLazyComponent
│   ├── ReactCommonRegistry.tsx   # Registre commun (JRC)
│   └── GlobalRegistry.tsx        # Aggrégat common + core, fallback `empty`
├── translation/
└── utils/
    ├── router.tsx            # React Router (addRoute, mount/unmount)
    ├── translation.tsx       # ReactTranslation (addResources, merge)
    └── types.ts              # WindowJ, WindowJNG
```

## Spécificités

- TS : `baseUrl: "./src"` pour la résolution de modules
- TS flags TODO : `exactOptionalPropertyTypes`, `noImplicitOverride`
- Build : Webpack 5 + ts-loader, SharedWorker loader, copy d'assets depuis react-components

### Système d'extensions (API `jCore`)

- `extensionAdd(name, loader)` — enregistre un loader async
- `require(name, options?)` — charge l'extension à la demande, cache dans `loadedExtensions`, ajoute à `displayExtensions`
- `unmountExtension(name)` — retire de `displayExtensions`
- `routeAdd(route, name, anchor, gabarit?, options?)` — enregistre une route AngularJS
- `extensionAddComponent(name, anchorId, component)` — composant pré-chargé sur ancre
- Event system : `on(name, cb)` / `off(name, cb)` / `call(name)`

### Registre de composants à 2 niveaux

1. Common (JRC library de react-components)
2. Core (composants spécifiques à l'app)
3. Fallback `'empty'` si non trouvé (`console.error` en dev)

`registry.getLazyComponent('Calendar.CreateMeetingModal')` — noms imbriqués supportés.

### Dual Router

- `/r/{extension}` — routes AngularJS via `jCore.routeAdd()`
- `/rr/*path` — routes React via `jCore.router.addRoute(route, ng, isPublic)`
- Route gardée par présence d'app : `jCore.router.addAppRoute({ appId, path, children, ng?, isPublic? })` — pose `AppGuard` en element (rend `<Outlet/>` si l'app existe, sinon redirige en 404). `AppGuard` (`components/AppGuard.tsx`) est interne au router, pas exposé au registry.
- Auth check : `isPublic ? true : J.jUserCurrent`

### Objet `J` global

`window.J` (typé `WindowJ` dans `utils/types.ts`) :

- `J.react: ReactCore`
- `J.ng: WindowJNG` — interop AngularJS (`addState`, `transitionTo`, `scrollTop`, `setTitle`, `messengerOpenDiscussion`, `$rootScope.$on`)
- `J.locale`, `J.jUserCurrent`, `J.applications`, `J.hooks`, `J.models`
- `J.config.showKey` (debug), `J.socketLongPolling` (force polling)

### Socket.IO

- Path `/socket.io4`
- Mode dual : SharedWorker (défaut) ou direct
- Transport : websocket (fallback polling si `J.socketLongPolling`)
- Events typés : `onMessage<T>(namespace, functionName, callback)`

### Reducers Redux

- **Static** : `entities/` (applications, models, users, articles), comment, hooks, network, platform, toasts, tinymce, userCurrent
- **Async** : chargés à la demande depuis `jamespot-front-business` (liste à jour dans `redux/store.tsx`)
- API store : `store.add(name, reducer, app?)` (slice connue) et `store.addExtensionStore(name, reducer, app?)` (extension externe)

### Hooks typés exposés

`useAppDispatch`, `useAppSelector` — exportés et consommables par les extensions.

### Build & paths

- Dev : `http://localhost:3030/` (port 3030, hot reload, CORS)
- Prod : `/react-core/`
- Theme : `/themes/EXT-reactjs/js/jamespot-react-core/`
- `pnpm generate-component-list` — régénère le registre

## Voir aussi

- `.claude/rules/frontend/_shared/` — règles universelles
- `.claude/rules/frontend/ui/` — composants, navigation, displayer, styled-components, accessibilité
- `.claude/rules/frontend/domain/extensions.md` — patterns d'enregistrement, guards, cleanup
- `.claude/rules/frontend/domain/redux.md` — Domain Export, ThunkApiConfig
