# Frontend Angular

Structure du frontend Angular, modules, composants, services, navigation, état et conventions utilisées dans l'application Web.

# Structure et routing Angular

## Structure principale

Le frontend Angular se trouve dans `uniksimFrontEnd/`. Le dossier principal est `src/app/`.

- `Pages/` : écrans complets de l’application.
- `Components/` : composants réutilisables.
- `Popup/` : interfaces modales/popups.
- `service/` : services Angular, auth, pipes et logique partagée.
- `Models/` : modèles TypeScript.
- `constants/` : constantes frontend.
- `styles/` : styles partagés.

## Module racine

`src/app/app.module.ts` centralise actuellement :

- déclarations de pages et composants ;
- Angular Material et autres dépendances UI ;
- configuration des traductions ;
- configuration des notifications ;
- routing principal ;
- guards ;
- intercepteur HTTP d’authentification.

## Familles de routes

- **Publiques** : login, reset de mot de passe, page unauthorized, Chen login.
- **Utilisateur** : logout, game, demo, alpha, etc.
- **Utilisateur Uniksim** : index.
- **Admin** : liste, support, présence.
- **True Admin** : settings, recherche de démos, simulations actives, commentaires, fiche utilisateur.

## Point à connaître

Le routing n’est pas dans un `app-routing.module.ts` séparé : il est défini directement avec `RouterModule.forRoot(...)` dans `app.module.ts`.

# Services Angular et communication avec l’API

## Vue d’ensemble

Le frontend ne doit pas appeler le backend directement depuis chaque composant. La logique partagée est regroupée dans `uniksimFrontEnd/src/app/service/`, avec plusieurs familles spécialisées.

## Flux standard

```mermaid
sequenceDiagram
    participant P as Page / Component
    participant S as Service Angular
    participant I as AuthInterceptor
    participant C as Controller NestJS
    participant B as Service backend

    P->>S: Action utilisateur
    S->>I: Requête HttpClient
    I->>I: Ajoute / gère auth
    I->>C: HTTP
    C->>B: Logique métier
    B-->>C: Résultat
    C-->>S: Réponse
    S-->>P: État / données UI

```

## Auth

`service/auth/` contient :

- `AuthGuard.service.ts` : guards de navigation selon le type d’utilisateur.
- `authInterceptor.service.ts` : intercepteur HTTP enregistré globalement dans `app.module.ts`.

## Accès aux données et APIs

`service/requestAndData/` contient les services historiques de communication et de données :

- `braincloudRequest.service.ts`
- `dataBaseRequest.service.ts`
- `dataSource.service.ts`

Avant de créer un nouveau service HTTP générique, vérifier si l’appel appartient déjà à l’un de ces services ou à un service fonctionnel plus spécifique.

## Support

`service/support/` sépare le support en trois responsabilités :

- `support.service.ts` : appels et logique du support.
- `support-socket.service.ts` : namespace `/support`, rooms de conversations et événements temps réel.
- `support-state.service.ts` : état frontend partagé du support.

## Notifications

`service/notifications/` contient notamment :

- `user-notification.service.ts` : inbox locale, synchronisation HTTP et fusion par UID des notifications transmises par AppComponent.
- `notification-sound.service.ts` : gestion du son lors de nouvelles notifications.

## Présence et WebPanel

- `service/presence/admin-presence.service.ts` : données de présence utilisées par l’interface admin.
- `service/webPanel/web-panel.service.ts` : logique du WebPanel.

## Choisir où placer une nouvelle logique

```mermaid
flowchart TD
    NEW[Nouvelle logique frontend] --> SHARED{Utilisée par plusieurs pages ?}
    SHARED -- Non --> PAGE[La garder près de la Page / Component]
    SHARED -- Oui --> DOMAIN{Sous-système existant ?}
    DOMAIN -- Auth --> AUTH[service/auth]
    DOMAIN -- Support --> SUP[service/support]
    DOMAIN -- Notifications --> NOTIF[service/notifications]
    DOMAIN -- Présence --> PRES[service/presence]
    DOMAIN -- Données / API générique --> DATA[service/requestAndData]
    DOMAIN -- Autre --> NEWSVC[Nouveau service spécialisé]

```

## Points d’attention

- Éviter de dupliquer les appels HTTP dans plusieurs pages.
- Garder les composants centrés sur l’UI et déléguer la logique partagée aux services.
- Pour le temps réel, toujours prévoir le chargement initial HTTP et la mise à jour Socket.IO.
- Lorsqu’un endpoint change, vérifier le service Angular correspondant et non seulement la page visible.

## Temps réel du compte et transport partagé — septembre 2026

`service/realtime/realtime-socket.ts` centralise connexion JWT, événements observables, reconnexion et acknowledgements. `service/account/account-socket.service.ts` utilise `/account` pour présence, télémétrie consentie, jeu actif et `notification.created`. `service/support/support-socket.service.ts` utilise `/support` pour messages, tickets et typing, et restaure la conversation active à la reconnexion. Les composants de support et de présence admin consomment le service du compte pour les signaux de présence.

`AccountSocketService` joue le son et émet la notification; `AppComponent` la transmet à `UserNotificationService.upsert()`. Les modèles sont séparés dans `Models/Notification.ts`, `Presence.ts` et `Support.ts`; les constantes communes vivent dans `realtime.constants.ts` et `account.constants.ts`. Voir [Support temps réel](https://wiki.uniksim.com/books/web/page/support-temps-reel).

# Pages, composants et structure UI

## Vue d’ensemble

Le frontend sépare globalement les **écrans complets**, les **composants réutilisables** et les **popups**. Cette page sert de guide pour savoir où ajouter ou modifier une interface.

## Structure UI

```mermaid
flowchart TD
    APP[AppModule] --> ROUTES[RouterModule.forRoot]
    ROUTES --> PAGES[Pages]
    PAGES --> COMP[Components]
    PAGES --> POP[Popup]
    PAGES --> SERVICES[Services Angular]
    COMP --> SERVICES

```

## Pages

`src/app/Pages/` contient les écrans routables ou les grosses vues fonctionnelles. Les dossiers actuellement présents incluent notamment :

- `PageLogin`, `PageForgotPassword`, `PageUnauthorized`
- `PageIndex`
- `PageWebgl`
- `PageSupport` et `PageSupportAdmin`
- `PageAdminPresence`
- `PageTableList` et `PageUserInformation`
- `PageSettings`, `PageDemoSearch`, `PageActiveSimulation`, `PageSimulationComments`

## Components

`src/app/Components/` contient les composants destinés à être utilisés par d’autres vues. On y trouve notamment `CommunicationOverlay` et `WebPanel`.

Un élément devrait devenir un composant partagé lorsqu’il possède une responsabilité UI autonome ou qu’il est utilisé par plusieurs pages.

## Popup

`src/app/Popup/` regroupe les interfaces modales. Lorsqu’une interaction est temporaire et ne mérite pas une route complète, vérifier d’abord si elle appartient à cette couche.

## Routing

Le routing est centralisé directement dans `src/app/app.module.ts` avec `RouterModule.forRoot(...)`. Il n’existe pas de `app-routing.module.ts` séparé.

Les routes sont regroupées par niveau d’accès : publiques, utilisateur, utilisateur Uniksim, admin et true admin. Voir **Structure et routing Angular** pour la liste détaillée.

## Créer une nouvelle vue

```mermaid
flowchart LR
    NEED[Nouvelle interface] --> ROUTE{Doit avoir une URL ?}
    ROUTE -- Oui --> PAGE[Nouvelle Page]
    PAGE --> APP[Ajouter déclaration + route dans app.module.ts]
    ROUTE -- Non --> REUSE{Réutilisable ?}
    REUSE -- Oui --> COMPONENT[Component]
    REUSE -- Non --> POPUP{Interaction modale ?}
    POPUP -- Oui --> P[Popup]
    POPUP -- Non --> LOCAL[Composant local à la page]

```

## Conventions pratiques

- Une Page orchestre l’écran; elle ne devrait pas absorber toute la logique métier.
- Les appels backend réutilisables passent par les services Angular.
- Un composant partagé ne devrait pas dépendre inutilement d’une route précise.
- Lorsqu’une page devient très volumineuse, extraire les parties UI cohérentes plutôt que créer une deuxième page sans raison.
- Avant de créer un nouveau composant, vérifier si un équivalent existe déjà dans `Components/` ou `Popup/`.

# Panel Web — interface superposée au jeu et intégration Unity

## Le panel au-dessus du jeu

Le panel Web donne accès au support UnikBot et au centre de notifications pendant que le jeu Unity WebGL reste affiché. Angular dessine la barre d'outils et les fenêtres au-dessus du canvas Unity. L'utilisateur ouvre une vue, l'utilise puis la ferme pour retrouver le jeu.

Le composant `app-web-panel` est monté dans `AppComponent`, à côté du `router-outlet`. Il est partagé avec les autres pages du site. Dans le jeu, il reçoit la classe `game-panel-host`, qui adapte sa disposition à la barre d'outils.

## Barre d'outils en jeu

La barre `game-tools-rail` apparaît lorsque l'utilisateur est authentifié, que la route est `/game`, `/demo`, `/alpha`, `/alpha2` ou `/demoLive`, et que `WebPanelService.isGameReady` vaut `true`.

- La cloche ouvre le centre de notifications et affiche son nombre de notifications non lues.
- Le bouton UnikBot ouvre le support et affiche son compteur de messages non lus.
- La poignée replie ou déplie la barre. Quand elle est repliée, un badge conserve le total des deux compteurs, plafonné visuellement à `99+`.
- Replier la barre ferme la vue ouverte. Ouvrir une vue redéplie la barre.

`AppComponent.openGamePanel()` appelle `WebPanelService.toggle()` : cliquer une seconde fois sur la vue active la ferme; choisir l'autre bouton change de vue.

## État partagé et cycle d'ouverture

`WebPanelService` conserve la vue active dans un `BehaviorSubject`. `activePanel$` informe le composant du changement et `currentPanel` expose sa valeur courante. Une seule vue est active à la fois.

<table id="bkmrk-valeur-interne-vue-a"><thead><tr><th>Valeur interne</th><th>Vue affichée</th></tr></thead><tbody><tr><td>`null`</td><td>Panel fermé.</td></tr><tr><td>`notifications`</td><td>Centre de notifications.</td></tr><tr><td>`chat`</td><td>Support Web UnikBot : `app-page-support` en mode compact.</td></tr></tbody></table>

`open(panel)` sélectionne une vue, `toggle(panel)` alterne ouverture et fermeture, et `close()` remet la sélection à `null`. La touche Échap et le bouton de fermeture appellent `close()`.

## Intégration avec Unity WebGL

`PageWebglComponent` héberge `#unity-canvas` et charge le build Unity. À son initialisation, il appelle `setGameReady(false)`. Son listener `window:uniksim:game-ready` passe ensuite l'état à `true` au prochain `requestAnimationFrame`, ce qui rend la barre disponible.

Le composant du panel écoute aussi `window:uniksim:open-panel`. Le champ `detail` accepte une chaîne ou un objet avec `panel`. Seules les valeurs `notifications` et `chat` sont reconnues. Cette entrée permet à un appelant de demander l'ouverture sans changer la route Angular.

```
window.dispatchEvent(new CustomEvent('uniksim:open-panel', {
  detail: { panel: 'notifications' }
}));
```

Dans la branche Game `refactor_notifications`, `MainControlStudent.Start()` et l’initialisation de `MainControlTeacher` appellent `WebGameReadyBridge.Notify()`. En build WebGL, ce bridge appelle `NotifyWebGameReady()` dans `Assets/Src/Plugins/javaLib.jslib`, qui émet `uniksim:game-ready`. Angular reçoit cet événement et affiche les outils. Dans l’éditeur Unity, le bridge écrit seulement un log.

À la destruction de `PageWebglComponent`, `setGameReady(false)` masque les outils du jeu. Le composant enregistre aussi le jeu actif avec `AccountSocketService.setGamePresence(pid, gameUid)` après validation de l'accès, puis appelle `clearGamePresence()` à la sortie.

## Support UnikBot

La vue support embarque `PageSupportComponent` avec `compact=true`. Ce mode conserve la présentation du jeu : le composant ne réactive pas l'en-tête et le pied de page du site.

Le support charge la conversation IA et les tickets de l'utilisateur. Il gère le fil sélectionné, les nouveaux messages, les mises à jour de tickets, les indicateurs de saisie et le statut des administrateurs. `SupportService` porte les appels métier, `SupportStateService` réconcilie les données et `SupportSocketService` fournit les événements temps réel.

La fenêtre support utilise un fond assombri cliquable pour fermer le panel. Sur ordinateur, elle peut atteindre 880 × 700 px, dans les limites du viewport. En mode jeu, elle est décalée pour laisser la barre accessible. Sur petit écran, elle occupe presque toute la surface et réserve de l'espace aux outils.

Voir [Support temps réel](https://wiki.uniksim.com/books/web/page/support-temps-reel) pour les conversations et les transports.

## Centre de notifications

La vue notifications est un popover positionné près de la cloche. Sa position est recalculée à l'ouverture, au redimensionnement et au scroll. Sur ordinateur dans le jeu, il apparaît à gauche de la barre. Sa largeur est limitée à 380 px; sa liste défile lorsque le contenu dépasse la hauteur disponible.

La couche externe laisse passer les interactions vers le jeu avec `pointer-events: none`; la fenêtre réactive ses propres interactions. Un clic hors de la fenêtre et de la cloche ferme la vue.

`UserNotificationService` partage la liste entre le panel et les compteurs :

<table id="bkmrk-action-api-web-charg"><thead><tr><th>Action</th><th>API Web</th></tr></thead><tbody><tr><td>Charger la liste</td><td>`GET /notifications`</td></tr><tr><td>Marquer comme lu</td><td>`POST /notifications/:uid/read` avec `isRead`</td></tr><tr><td>Supprimer</td><td>`DELETE /notifications/:uid`</td></tr></tbody></table>

La première ouverture charge la liste; le bouton de rafraîchissement permet de la recharger. Le panel affiche les états de chargement, d'erreur avec nouvelle tentative, et de liste vide. Cliquer une notification non lue la marque comme lue; le bouton de suppression retire l'entrée sans déclencher ce clic de lecture.

`AccountSocketService.onNotificationCreated$` alimente `UserNotificationService.upsert()`, qui fusionne les entrées par UID. `AppComponent` recharge les notifications après reconnexion du compte. Les titres et corps utilisent `uniksim.notification_<type>_title` et `_body`, avec un texte par défaut si la traduction manque.

Côté Game, `NotificationManager.SaveNotification()` délègue à `BackEndBase.SaveNotification()`, qui envoie `POST /saveNotification`. L'affichage du panel et sa liste sont gérés côté Web. Voir [Notifications et Push](https://wiki.uniksim.com/books/web/page/notifications-et-push) pour la réception serveur, l'inbox et le push.

## Fichiers à modifier

<table id="bkmrk-fichier-responsabili"><thead><tr><th>Fichier</th><th>Responsabilité</th></tr></thead><tbody><tr><td>`uniksimFrontEnd/src/app/app.component.html`, `.ts` et `.scss`</td><td>Montage global, barre en jeu, boutons, compteurs et accès hors jeu.</td></tr><tr><td>`service/webPanel/web-panel.service.ts`</td><td>Vue active et état de disponibilité du jeu.</td></tr><tr><td>`Components/WebPanel/WebPanel.component.ts`, `.html` et `.scss`</td><td>Ouverture, fermeture, contenu, position et superposition.</td></tr><tr><td>`Pages/PageWebgl/PageWebgl.component.ts`</td><td>Chargement Unity, disponibilité et cycle du jeu actif.</td></tr><tr><td>`Pages/PageSupport/` et `service/support/`</td><td>Support embarqué et ses conversations.</td></tr><tr><td>`service/notifications/user-notification.service.ts`</td><td>Liste, compteur et mutations de notifications.</td></tr><tr><td>`service/account/account-socket.service.ts`</td><td>Événements du compte et jeu actif.</td></tr><tr><td>`Game/Assets/Src/Game/Notifications/NotificationManager.cs` et `Game/Assets/Src/Game/BackEnd/BackEndBase.cs`</td><td>Envoi des notifications depuis Unity.</td></tr></tbody></table>

## Vérifier une modification

- Entrer dans le jeu : les outils attendent le signal de disponibilité.
- Ouvrir chaque vue depuis la barre, changer de vue, recliquer le bouton actif, fermer avec Échap et avec la croix.
- Replier la barre avec une vue ouverte, puis la redéplier; contrôler les compteurs.
- Contrôler le placement sur ordinateur et petit écran, et les clics qui doivent atteindre le jeu autour du popover.
- Tester le support intégré, le chargement des notifications, la lecture, la suppression et une reconnexion.
- Sortir du jeu : vérifier le retrait des outils et du jeu actif côté compte.

Sources de cette page : frontend Web de la branche `messagerie_fixes` et code Game de la branche `refactor_notifications`, inspecté le 30 septembre 2026.