# SocioWire Frontend

Interface utilisateur de SocioWire - plateforme sociale géolocalisée. Application React moderne avec cartes 3D, authentification Keycloak, et fonctionnalités temps réel.

## Description

Le frontend SocioWire est une Single Page Application (SPA) construite avec React 19 et Vite. Elle offre une expérience utilisateur riche avec:
- Authentification OAuth2 via Keycloak
- Feed de posts géolocalisés avec cartes interactives
- Recherche intelligente avec autocomplete
- Visualisation 3D des "Islands" utilisateurs
- Engagement temps réel (likes, comments, shares)
- Interface responsive et moderne

## Technologies

- **Framework**: React 19
- **Build Tool**: Vite (rolldown-vite)
- **Routing**: React Router DOM v7
- **Auth**: Keycloak.js (OAuth2/OIDC)
- **Maps**: MapLibre GL
- **HTTP Client**: Axios
- **Icons**: Font Awesome
- **Styling**: CSS modules + custom themes

## Structure du projet

```
sociowire-frontend/
├── src/
│   ├── main.jsx                 # Entry point
│   ├── App.jsx                  # App router
│   ├── api/
│   │   ├── client.js           # Axios client avec auth
│   │   └── templates.js        # API templates
│   ├── auth/
│   │   ├── AuthContext.jsx     # Auth provider
│   │   ├── authStorage.js      # Token storage
│   │   └── emailVerified.js    # Email verification
│   ├── components/
│   │   ├── Posts/              # Post components
│   │   │   ├── PostCard.jsx
│   │   │   ├── PostList.jsx
│   │   │   └── PostCardTemplate.jsx
│   │   ├── Search/             # Search components
│   │   │   └── SmartSearchBar.jsx
│   │   ├── Filters/            # Filter components
│   │   │   ├── FilterButtons.jsx
│   │   │   └── TimeFilterButtons.jsx
│   │   ├── Profile/            # User profile
│   │   │   └── UserProfile.jsx
│   │   ├── Island/             # Island visualization
│   │   │   ├── IslandViewer.jsx
│   │   │   └── IslandUniverse.jsx
│   │   ├── Map/                # Map components
│   │   │   ├── MapView.jsx
│   │   │   ├── MapControls.jsx
│   │   │   └── TemplateMarkerCard.jsx
│   │   ├── Auth/               # Auth components
│   │   │   ├── AuthToast.jsx
│   │   │   └── AuthPill.jsx
│   │   └── ui/                 # UI primitives
│   │       └── ToastHost.jsx
│   ├── services/
│   │   └── recoSearch.js       # Reco service client
│   ├── theme/
│   │   └── cardTokens.js       # Design tokens
│   └── index.css               # Global styles
├── public/                      # Static assets
├── package.json
├── vite.config.js
└── eslint.config.js
```

## Prérequis

- Node.js 18+ (recommandé: 20+)
- npm ou yarn
- Backend SocioWire en cours d'exécution (port 8081)
- Keycloak configuré

## Installation

```bash
cd /home/swire/sociowire-frontend
npm install
```

## Configuration

Les URLs des services sont configurées dans le code:

**Backend API**: `http://localhost:8081`
**Keycloak**: `https://auth.sociowire.com`

Pour changer ces URLs, modifier:
- `src/api/client.js` - Backend URL
- `src/auth/AuthContext.jsx` - Keycloak URL

### Variables d'environnement (optionnel)

Créer un fichier `.env.local`:

```env
VITE_API_URL=http://localhost:8081
VITE_KEYCLOAK_URL=https://auth.sociowire.com
VITE_KEYCLOAK_REALM=sociowire
VITE_KEYCLOAK_CLIENT_ID=sociowire-frontend
```

## Démarrage

### Mode développement

```bash
npm run dev
```

L'application démarre sur `http://localhost:5173` (ou autre port si occupé).

### Build production

```bash
npm run build
```

Les fichiers sont générés dans `dist/`.

### Preview production

```bash
npm run preview
```

Teste le build production localement.

## Fonctionnalités principales

### 1. Authentification

- **Login**: Email/password via Keycloak
- **Signup**: Création de compte avec vérification email
- **OAuth**: Login social (Google, GitHub, etc.)
- **Refresh tokens**: Gestion automatique de l'expiration
- **Logout**: Déconnexion complète (Keycloak + local)

**Composants**:
- `AuthContext` - Provider global d'auth
- `AuthPill` - Widget utilisateur
- `AuthToast` - Notifications auth

### 2. Feed de posts

- **Posts géolocalisés**: Affichage avec lat/lon
- **Catégories**: NEWS, EVENT, DISCUSSION, QUESTION
- **Filtres**: Par catégorie, temps, géolocalisation
- **Pagination**: Chargement progressif
- **Templates**: Posts avec templates visuels

**Composants**:
- `PostList` - Liste de posts
- `PostCard` - Carte de post individuelle
- `PostCardTemplate` - Post avec template

### 3. Recherche

- **Smart Search**: Recherche full-text via reco-service
- **Autocomplete**: Suggestions en temps réel (posts, profils, lieux)
- **Filtres avancés**: Catégorie, temps, géo
- **Unified Search**: Posts + profils + places

**Composants**:
- `SmartSearchBar` - Barre de recherche avec autocomplete
- `FilterButtons` - Filtres de catégorie
- `TimeFilterButtons` - Filtres temporels

### 4. Cartes interactives

- **MapLibre GL**: Cartes vectorielles performantes
- **Markers**: Posts géolocalisés sur la carte
- **Clustering**: Regroupement de markers
- **3D**: Visualisation 3D optionnelle
- **Controls**: Zoom, rotation, pitch

**Composants**:
- `MapView` - Carte principale
- `MapControls` - Contrôles de carte
- `TemplateMarkerCard` - Popup de marker

### 5. Islands (Univers utilisateurs)

- **Island Universe**: Visualisation 3D des utilisateurs
- **Island Viewer**: Détails d'une island
- **Génération procédurale**: Islands uniques par utilisateur
- **Navigation**: Exploration de l'univers

**Composants**:
- `IslandUniverse` - Univers 3D
- `IslandViewer` - Vue détaillée d'island

### 6. Profils utilisateurs

- **User Profile**: Profil complet avec posts
- **Avatar**: Upload et affichage
- **Stats**: Posts, followers, etc.
- **Bio**: Description personnalisée

**Composants**:
- `UserProfile` - Page de profil

### 7. Engagement

- **Likes**: Like/unlike de posts
- **Comments**: Commentaires hiérarchiques
- **Shares**: Partage de posts
- **Truth Voting**: Vote de vérité (fact-checking)

Intégré dans `PostCard`.

## Appels API

Le frontend communique avec:

### 1. sociowire-backend (`http://localhost:8081`)

**Authentification**:
- `POST /api/signup-email`
- `POST /api/signup`
- `POST /api/login`
- `POST /api/refresh`
- `GET /api/me`

**Posts**:
- `GET /api/posts` - Feed
- `POST /api/post` - Créer
- `GET /api/post?id=...` - Get
- `POST /api/post/like` - Like
- `GET /api/post/comments` - Comments
- `POST /api/post/comment` - Ajouter comment

**Recherche**:
- `GET /api/search?q=...` - Recherche full-text
- `GET /api/suggestions?q=...` - Autocomplete
- `GET /api/smart-feed` - Feed personnalisé
- `GET /api/unified-search` - Search combinée

**Profils**:
- `GET /api/profile` - Mon profil
- `PATCH /api/profile/username` - Update username
- `POST /api/profile/avatar` - Upload avatar

**Assets**:
- `POST /api/assets/upload` - Upload image
- `GET /api/assets/url?id=...` - Get asset URL

**Islands**:
- `GET /api/islands/nearby` - Islands à proximité
- `GET /api/islands/by-username/{username}` - Island par username

**Utilitaires**:
- `GET /api/templates` - Templates de posts
- `GET /api/ip-location` - Géolocalisation IP

---

### 2. Keycloak (`https://auth.sociowire.com`)

Le frontend utilise `keycloak-js` pour communiquer avec Keycloak:

- **Init**: `keycloak.init({ onLoad: 'check-sso' })`
- **Login**: `keycloak.login()`
- **Logout**: `keycloak.logout()`
- **Token**: Rafraîchissement automatique via `keycloak.updateToken()`

**Realm**: `sociowire`
**Client ID**: `sociowire-frontend`

---

## Gestion d'état

### AuthContext

Provider global pour l'authentification:

```jsx
import { useAuth } from './auth/AuthContext';

function Component() {
  const { keycloak, isAuthenticated, username, login, logout } = useAuth();
  // ...
}
```

**État**:
- `keycloak` - Instance Keycloak
- `isAuthenticated` - Boolean
- `username` - String
- `emailVerified` - Boolean
- `login()` - Fonction login
- `logout()` - Fonction logout

---

## Axios Client

Client HTTP configuré avec intercepteurs pour auth:

```javascript
// src/api/client.js
import axios from 'axios';

const client = axios.create({
  baseURL: 'http://localhost:8081',
  headers: { 'Content-Type': 'application/json' }
});

// Request interceptor: ajoute Bearer token
client.interceptors.request.use(config => {
  const token = localStorage.getItem('keycloak_token');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

// Response interceptor: refresh token si 401
client.interceptors.response.use(
  response => response,
  async error => {
    if (error.response?.status === 401) {
      // Refresh token logic
    }
    return Promise.reject(error);
  }
);
```

---

## Routing

Routes principales:

```jsx
<BrowserRouter>
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/feed" element={<Feed />} />
    <Route path="/search" element={<Search />} />
    <Route path="/profile/:username" element={<Profile />} />
    <Route path="/islands" element={<Islands />} />
    <Route path="/post/:id" element={<PostDetail />} />
    <Route path="/login" element={<Login />} />
    <Route path="/signup" element={<Signup />} />
  </Routes>
</BrowserRouter>
```

---

## Thème et Styling

Le projet utilise CSS modules + variables CSS:

**Design Tokens** (`theme/cardTokens.js`):
- Couleurs de catégories
- Spacing
- Border radius
- Shadows

**CSS Variables**:
```css
:root {
  --primary-color: #007bff;
  --secondary-color: #6c757d;
  --success-color: #28a745;
  --danger-color: #dc3545;
  --warning-color: #ffc107;
}
```

---

## Icônes (Font Awesome)

```jsx
import '@fortawesome/fontawesome-free/css/all.min.css';

<i className="fas fa-heart"></i>
<i className="fas fa-comment"></i>
<i className="fas fa-share"></i>
```

---

## MapLibre GL

Configuration de la carte:

```jsx
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';

const map = new maplibregl.Map({
  container: 'map',
  style: 'https://demotiles.maplibre.org/style.json',
  center: [-73.5, 45.5],
  zoom: 10
});
```

---

## Build et Déploiement

### Build optimisé

```bash
npm run build
```

Génère:
- `dist/index.html` - HTML principal
- `dist/assets/*.js` - Bundles JavaScript
- `dist/assets/*.css` - Styles
- `dist/assets/*` - Assets (images, fonts)

### Déploiement

Le build peut être déployé sur:
- **Nginx**: Servir `dist/` avec fallback vers `index.html`
- **Vercel**: Détection automatique de Vite
- **Netlify**: Build command `npm run build`, publish dir `dist`
- **Docker**: Nginx container avec `dist/`

**Nginx config**:
```nginx
server {
  listen 80;
  root /var/www/sociowire-frontend/dist;
  index index.html;

  location / {
    try_files $uri $uri/ /index.html;
  }
}
```

---

## Développement

### Hot Module Replacement (HMR)

Vite supporte HMR out-of-the-box:
- Modifications CSS: Rechargement instantané
- Modifications JSX: Preserve state
- Modifications API: Reload complet

### ESLint

```bash
npm run lint
```

Configuration dans `eslint.config.js`.

---

## Tests

Tests à ajouter avec Vitest + React Testing Library:

```bash
npm install -D vitest @testing-library/react @testing-library/jest-dom
```

---

## Performance

Optimisations:
- **Code splitting**: Routes lazy-loaded
- **Tree shaking**: Vite optimise automatiquement
- **Asset optimization**: Images optimisées
- **Caching**: Service Worker (à ajouter)
- **Bundle size**: Analysé avec rollup-plugin-visualizer

---

## Sécurité

- Tokens stockés en localStorage (préférer httpOnly cookies en prod)
- Validation input côté client + serveur
- CORS configuré sur backend
- CSP headers recommandés
- Sanitisation des URLs externes

---

## Debugging

### React DevTools

Installer l'extension browser React DevTools.

### Vite DevTools

Console affiche:
- HMR updates
- Build errors
- Network requests (via browser)

### Logs

```javascript
console.log('Debug:', data);
```

En production, utiliser un service de logging (Sentry, LogRocket).

---

## Notes de développement

- Le frontend assume que le backend est sur `localhost:8081`
- Keycloak doit être configuré avec le client `sociowire-frontend`
- Les tokens JWT sont stockés en localStorage
- MapLibre nécessite une clé API pour certains styles (optionnel)
- L'upload d'images passe par le backend, qui proxy vers asset-service
