---
name: gametime-ux-online-client
description: memory note gametime-ux-online-client
metadata:
  type: project
---
# GameTime — UX client couche online, compte, sync, partage (ticket #63, UX 2026-07-19)

Conception client pour consommer les fonctionnalités serveur : comptes utilisateur, synchronisation incrémentale LWW, partage ciblé de programmes/séances. Cette conception respecte la mémoire `gametime-online-layer-philosophy` : l'app reste offline-first, la connexion est optionnelle, aucune action locale n'attend le serveur, aucun échec réseau ne doit interrompre le parcours principal.

## Principe directeur UI

La couche online est une **option de profil**, pas une porte d'entrée obligatoire.

- Ne jamais afficher d'écran de connexion au démarrage.
- Ne jamais bloquer `Exercices`, `Programmes`, `Séances`, `Historique` parce que l'utilisateur est déconnecté.
- Ne jamais afficher de popup globale en cas d'échec de sync.
- Les statuts online apparaissent uniquement dans des zones volontaires : `Profil`, formulaires de connexion, partage, boîte de réception.
- Toute donnée locale reste immédiatement consultable/modifiable, connecté ou non.

## Navigation

Contexte actuel : `HomeScreen` est une liste d'entrées (`Exercices`, `Programmes`, `Séances`, `Historique`) avec AppBar logo + menu thème, sans bottom nav.

Décision UX : ne pas introduire de bottom nav ni refondre la navigation.

Ajouter une entrée `Profil` dans la liste d'accueil, après `Historique` :

```text
Profil
Compte, synchronisation et partages
```

Icône : `Icons.account_circle_outlined` si déconnecté, avatar/photo locale si connecté.

L'AppBar peut rester dédiée au logo et au thème. Si une indication rapide est souhaitée plus tard, préférer un petit avatar en AppBar seulement sur l'accueil, mais ce n'est pas nécessaire au MVP.

## 1. Écran Profil

### État déconnecté

Titre : `Profil`

Bloc principal Court Blazer :

```text
Compte optionnel
GameTime fonctionne entièrement sans compte. Connecte-toi seulement si tu veux sauvegarder tes données en ligne ou partager des programmes et séances.

[Créer un compte]
[Se connecter]
```

Style : ton neutre, aucune culpabilisation, aucun warning.

Section informative :

```text
Données locales
Tes exercices, programmes, séances et historiques sont enregistrés sur cet appareil.
```

Section partages, non interactive ou secondaire :

```text
Partages
Connecte-toi pour envoyer et recevoir des programmes ou des séances.
```

Ne pas afficher de bouton `Continuer sans compte` : l'utilisateur est déjà dans l'app, donc ce bouton serait redondant.

### État connecté

En haut : carte profil.

```text
[photo/avatar]
Pseudo
email@example.com
```

Si pseudo absent : afficher l'email comme identifiant principal. Si photo absente : avatar initiales ou icône compte. Pseudo/photo doivent venir du cache local et s'afficher instantanément même hors ligne.

Actions :

```text
[Modifier le profil]  // seulement si API/client le supporte dans ce lot
[Se déconnecter]
```

Si `Modifier le profil` n'est pas supporté par le serveur, ne pas afficher l'action au MVP.

Section synchronisation :

```text
Synchronisation
À jour à 14:32
```

États possibles, toujours neutres :

- Sync en cours : `Synchronisation en cours...`
- Sync réussie : `À jour à 14:32`
- Sync jamais faite : `Synchronisation en attente`
- Sync échouée : `Dernière synchronisation : hier à 18:20. Nouvelle tentative automatique.`
- Hors ligne détecté : `Hors ligne. Les données restent disponibles.`

Ne pas utiliser de rouge pour la sync échouée. Utiliser icônes neutres : `cloud_outlined`, `sync`, `cloud_done_outlined`, `schedule`.

Section partages :

```text
Partages reçus          [badge si éléments en attente]
Programmes et séances reçus d'autres comptes
```

Tap → `Partages reçus`.

Déconnexion : confirmation nécessaire.

```text
Se déconnecter ?
Les données restent sur cet appareil. La synchronisation et les partages seront suspendus jusqu'à une prochaine connexion.

[Annuler]
[Se déconnecter]
```

Après logout : retour à l'état déconnecté, aucune suppression locale.

## 2. Création de compte / Connexion

Écrans accessibles depuis `Profil`, jamais imposés ailleurs.

### Se connecter

AppBar : `Se connecter`

Champs :

```text
Email
Mot de passe
```

Actions :

```text
[Se connecter]
[Créer un compte]
```

Texte secondaire bas d'écran :

```text
Tu peux continuer à utiliser GameTime sans compte.
```

Validation locale :

- email vide/invalide : `Saisis une adresse email valide.`
- mot de passe vide : `Saisis ton mot de passe.`

Erreurs serveur affichées inline dans le formulaire, jamais en popup :

- identifiants invalides : `Email ou mot de passe incorrect.`
- serveur/réseau indisponible : `Connexion impossible pour le moment. Réessaie plus tard.`

Après succès : revenir à `Profil` avec message discret :

```text
Compte connecté. Synchronisation en arrière-plan.
```

Ne pas afficher de loader bloquant de synchronisation initiale.

### Créer un compte

AppBar : `Créer un compte`

Champs :

```text
Email
Mot de passe
Confirmer le mot de passe
```

Actions :

```text
[Créer le compte]
[Déjà un compte ? Se connecter]
```

Texte secondaire :

```text
Le compte sert à synchroniser tes données et partager tes contenus. L'app reste utilisable sans compte.
```

Validation locale :

- email vide/invalide : `Saisis une adresse email valide.`
- mot de passe vide : `Saisis un mot de passe.`
- confirmation différente : `Les mots de passe ne correspondent pas.`

Erreurs serveur inline :

- email déjà utilisé : `Un compte existe déjà avec cet email.`
- réseau/serveur : `Création impossible pour le moment. Réessaie plus tard.`

Après succès : connecter l'utilisateur si le serveur renvoie un token, retour Profil, sync arrière-plan.

## 3. Indication de synchronisation

La synchronisation doit être transparente et non intrusive.

### Où afficher

- Principalement dans `Profil`, section `Synchronisation`.
- Optionnel : sous-titre de l'entrée `Profil` sur l'accueil :
  - déconnecté : `Compte optionnel`
  - connecté à jour : `Synchronisé récemment`
  - connecté sync en attente : `Synchronisation en attente`

Ne pas ajouter de bannière globale ou snackbar automatique sur échec réseau.

### États visuels

- `Synchronisation en cours...` : petite icône `sync`, éventuellement rotation subtile.
- `À jour à 14:32` : icône neutre ou `cloud_done_outlined` en couleur texte secondaire, pas nécessairement vert.
- `Dernière synchronisation : hier à 18:20. Nouvelle tentative automatique.` : icône `schedule`, texte secondaire.
- `Hors ligne. Les données restent disponibles.` : neutre/informatif.

Actions possibles dans Profil :

```text
[Synchroniser maintenant]
```

Si échec : rester sur le même écran avec texte neutre, pas de dialog.

## 4. Partage sortant

Le partage concerne les `Programmes` et les `Séances`.

### Point d'entrée

Ne pas surcharger les listes avec une nouvelle icône visible sur chaque ligne.

Point d'entrée recommandé : dans l'écran de modification/détail d'un programme ou d'une séance déjà enregistrée, ajouter une action AppBar :

```text
Partager
```

Icône : `Icons.ios_share` ou `Icons.share_outlined`.

Dans les listes, si un menu `...` existe plus tard, `Partager` peut y être ajouté, mais ce n'est pas obligatoire au MVP.

### Si utilisateur déconnecté

Quand il tape `Partager` : écran ou bottom sheet explicative, non bloquante pour le reste de l'app.

```text
Compte requis pour partager
Connecte-toi pour envoyer ce programme à un autre compte GameTime.

[Se connecter]
[Créer un compte]
[Annuler]
```

Aucune obligation de connexion pour continuer à modifier localement.

### Formulaire de partage

Titre :

```text
Partager le programme
```

ou :

```text
Partager la séance
```

Contenu :

```text
Programme à partager
Programme tirs extérieur
6 exercices · 18 séries

Email du destinataire
[ joueur@example.com ]

[Envoyer le partage]
```

Validation locale :

- email vide/invalide : `Saisis l'email du destinataire.`

Après action :

- si envoyé immédiatement : `Partage envoyé.`
- si réseau/serveur indisponible : `Partage enregistré. Envoi dès que possible.`

Pas de popup d'erreur réseau. Le partage peut être mis en file d'attente si l'architecture le permet ; sinon rester inline avec `Envoi impossible pour le moment. Réessaie plus tard.` dans le formulaire, mais ne jamais perturber les autres écrans.

## 5. Partages reçus

Accessible depuis `Profil` > `Partages reçus`.

### Liste

AppBar : `Partages reçus`

États :

- chargement local : indicateur discret si nécessaire ;
- vide :

```text
Aucun partage reçu
Les programmes et séances qu'on t'envoie apparaîtront ici.
```

Chaque item :

```text
Programme
Programme tirs extérieur
Envoyé par Alex
6 exercices · 18 séries

[Accepter] [Refuser]
```

ou :

```text
Séance
Prépa match
Envoyée par Alex
2 programmes · 11 exercices

[Accepter] [Refuser]
```

### Acceptation

`Accepter` importe une copie locale immédiatement si les données du partage sont disponibles localement.

Après acceptation :

- Programme : `Programme ajouté.`
- Séance : `Séance ajoutée.`

La copie devient un objet local normal, disponible offline. Elle n'est pas liée dynamiquement à l'expéditeur.

Si l'accusé serveur ne peut pas partir :

```text
Accepté sur cet appareil. Mise à jour du partage dès que possible.
```

### Refus

Confirmation légère non obligatoire. Recommandation : action directe avec undo possible si facile ; sinon confirmation courte.

Message :

```text
Partage refusé.
```

Si réseau indisponible :

```text
Refus enregistré. Mise à jour dès que possible.
```

### Conflits / doublons

Ne pas bloquer l'acceptation si un programme ou une séance porte déjà le même nom. Autoriser les doublons comme le reste de l'app. Optionnellement ajouter suffixe local si nécessaire : `Prépa match (partagé)`.

## 6. Données locales et cache profil

Exigence UX : après connexion, l'écran Profil doit afficher instantanément la dernière identité connue.

À mettre en cache local :

- email ;
- pseudo si disponible ;
- photo/avatar si disponible ;
- dernier état de sync affichable ;
- partages reçus déjà récupérés si possible.

Ne jamais vider les listes locales lors du logout. Le logout suspend seulement token/sync/partage.

## 7. Libellés à éviter

Éviter :

- `Erreur de synchronisation`
- `Non synchronisé` en rouge
- `Connexion requise`
- `Impossible d'utiliser l'app`

Préférer :

- `Synchronisation en attente`
- `Nouvelle tentative automatique`
- `Compte optionnel`
- `Les données restent disponibles`
- `Partage enregistré. Envoi dès que possible.`

## 8. Découpage tickets conseillé

1. `Profil · entrée navigation + états connecté/déconnecté`.
2. `Auth · écrans créer un compte / se connecter / se déconnecter`.
3. `Sync · statut discret + action Synchroniser maintenant`.
4. `Partage sortant · action Partager sur programme/séance + formulaire email`.
5. `Partages reçus · boîte de réception + accepter/refuser + import local`.