AvanzaCast/docs/SHARED_MODULES.md

371 lines
8.2 KiB
Markdown

# Módulos Compartidos - AvanzaCast
## 📋 Descripción
Los módulos compartidos (`shared/`) contienen código reutilizable que se usa en todos los módulos de la aplicación (landing-page, broadcast-studio, admin-panel). Esto garantiza consistencia en autenticación, idioma y componentes UI.
## 📦 Estructura de Módulos Compartidos
```
shared/
├── types/ # TypeScript types compartidos
├── utils/ # Utilidades (auth, i18n, api client)
├── hooks/ # React hooks compartidos
└── components/ # Componentes React compartidos
```
## 🔑 Autenticación Compartida
### Hook `useAuth()`
Todos los módulos frontend usan el mismo hook de autenticación:
```typescript
import { useAuth } from '@avanzacast/shared-hooks';
function MyComponent() {
const { user, isAuthenticated, login, logout, register } = useAuth();
const handleLogin = async () => {
const result = await login({
email: 'user@example.com',
password: 'password123'
});
if (result.success) {
console.log('Login exitoso');
} else {
console.error(result.error);
}
};
return (
<div>
{isAuthenticated ? (
<p>Bienvenido, {user?.name}</p>
) : (
<button onClick={handleLogin}>Iniciar sesión</button>
)}
</div>
);
}
```
### Funciones de utilidad
```typescript
import {
saveTokens,
getTokens,
clearAuth,
isAuthenticated
} from '@avanzacast/shared-utils';
// Guardar tokens después del login
saveTokens({ accessToken: '...', refreshToken: '...', expiresIn: 3600 });
// Verificar si está autenticado
if (isAuthenticated()) {
// Usuario logueado
}
// Cerrar sesión
clearAuth();
```
## 🌍 Internacionalización (i18n)
### Hook `useLanguage()`
```typescript
import { useLanguage } from '@avanzacast/shared-hooks';
function MyComponent() {
const { language, setLanguage, t, availableLanguages } = useLanguage();
return (
<div>
<h1>{t('landing.hero_title')}</h1>
<p>Idioma actual: {language}</p>
<select
value={language}
onChange={(e) => setLanguage(e.target.value as any)}
>
{availableLanguages.map(lang => (
<option key={lang.code} value={lang.code}>
{lang.flag} {lang.name}
</option>
))}
</select>
</div>
);
}
```
### Traducciones disponibles
Las traducciones están en `shared/utils/i18n.ts` y soportan:
- **Español (es)** 🇪🇸
- **English (en)** 🇺🇸
- **Português (pt)** 🇧🇷
- **Français (fr)** 🇫🇷
#### Claves de traducción:
```typescript
// Comunes
t('common.login') // "Iniciar sesión"
t('common.register') // "Registrarse"
t('common.email') // "Correo electrónico"
t('common.password') // "Contraseña"
// Navegación
t('nav.home') // "Inicio"
t('nav.features') // "Características"
t('nav.broadcasts') // "Transmisiones"
t('nav.studio') // "Estudio"
// Landing page
t('landing.hero_title') // "La manera más sencilla de transmitir..."
t('landing.get_started') // "Empecemos"
// Autenticación
t('auth.login_title') // "Inicia sesión en tu cuenta"
t('auth.register_title') // "Crea tu cuenta"
```
## 🧩 Componentes Compartidos
### LanguageSelector
Selector de idioma que se sincroniza entre todos los módulos:
```typescript
import { LanguageSelector } from '@avanzacast/shared-components';
function Header() {
return (
<header>
{/* Dropdown con banderas */}
<LanguageSelector variant="dropdown" position="right" />
{/* Solo banderas */}
<LanguageSelector variant="flags" />
</header>
);
}
```
### AuthButton
Botón de login/logout que se adapta al estado de autenticación:
```typescript
import { AuthButton } from '@avanzacast/shared-components';
function Header() {
return (
<header>
<AuthButton
variant="primary"
size="md"
loginUrl="/auth/login"
dashboardUrl="/broadcasts"
/>
</header>
);
}
```
## 🔌 API Client
Cliente HTTP centralizado para hacer peticiones al backend:
```typescript
import { apiClient } from '@avanzacast/shared-utils';
// Login
const response = await apiClient.login({
email: 'user@example.com',
password: 'password123'
});
// Register
const response = await apiClient.register({
email: 'new@example.com',
password: 'password123',
name: 'John Doe'
});
// Get profile
const response = await apiClient.getProfile();
// Custom endpoint
const response = await apiClient.get('/broadcasts');
const response = await apiClient.post('/broadcasts', { title: 'Mi transmisión' });
```
## 📘 TypeScript Types
Todos los tipos están centralizados en `shared/types/`:
```typescript
import type {
User,
AuthTokens,
LoginCredentials,
RegisterData,
SupportedLanguage,
Broadcast,
Guest
} from '@avanzacast/shared-types';
const user: User = {
id: '123',
email: 'user@example.com',
name: 'John Doe',
role: 'user',
createdAt: new Date(),
updatedAt: new Date()
};
```
## 🚀 Uso en los Módulos
### Landing Page
```typescript
// packages/landing-page/src/App.tsx
import { useAuth, useLanguage } from '@avanzacast/shared-hooks';
import { LanguageSelector, AuthButton } from '@avanzacast/shared-components';
export function App() {
const { t } = useLanguage();
const { isAuthenticated } = useAuth();
return (
<div>
<header>
<LanguageSelector />
<AuthButton />
</header>
<h1>{t('landing.hero_title')}</h1>
</div>
);
}
```
### Broadcast Studio
```typescript
// packages/broadcast-studio/src/App.tsx
import { useAuth } from '@avanzacast/shared-hooks';
import { useEffect } from 'react';
export function App() {
const { isAuthenticated, user } = useAuth();
useEffect(() => {
if (!isAuthenticated) {
window.location.href = '/auth/login?redirect=/studio';
}
}, [isAuthenticated]);
return (
<div>
<h1>Estudio de {user?.name}</h1>
</div>
);
}
```
### Admin Panel
```typescript
// packages/admin-panel/src/App.tsx
import { useAuth, useLanguage } from '@avanzacast/shared-hooks';
export function App() {
const { user } = useAuth();
const { language, setLanguage } = useLanguage();
return (
<div>
<h1>Admin Panel - {user?.name}</h1>
<p>Idioma: {language}</p>
</div>
);
}
```
## 🔄 Sincronización entre módulos
Cuando un usuario:
1. **Inicia sesión en landing-page** → Los datos se guardan en localStorage
2. **Navega a broadcast-studio** → El hook `useAuth()` lee el mismo localStorage
3. **Cambia el idioma en studio** → El cambio se refleja en todos los módulos
4. **Cierra sesión en admin-panel** → Todos los módulos detectan el logout
## ⚙️ Configuración de Variables de Entorno
Cada módulo frontend necesita configurar la URL del backend:
```bash
# packages/landing-page/.env
VITE_API_URL=http://localhost:4000/api/v1
# packages/broadcast-studio/.env
VITE_API_URL=http://localhost:4000/api/v1
# packages/admin-panel/.env
VITE_API_URL=http://localhost:4000/api/v1
```
## 📝 Añadir nuevas traducciones
Edita `shared/utils/i18n.ts`:
```typescript
const translations: Record<SupportedLanguage, Translation> = {
es: {
myNewSection: {
title: 'Mi nuevo título',
description: 'Mi nueva descripción'
}
},
en: {
myNewSection: {
title: 'My new title',
description: 'My new description'
}
},
// ... pt, fr
};
```
Luego úsalo:
```typescript
const { t } = useLanguage();
console.log(t('myNewSection.title'));
```
## 🎯 Beneficios de los Módulos Compartidos
**Consistencia**: Mismo comportamiento de auth e i18n en todos los módulos
**Mantenibilidad**: Cambiar una vez, actualiza en todos lados
**Reutilización**: No duplicar código entre módulos
**Type Safety**: TypeScript types compartidos evitan inconsistencias
**Sincronización**: Cambios en un módulo se reflejan en otros automáticamente
## 🔧 Próximos Pasos
1. Implementar backend API endpoints (`/auth/login`, `/auth/register`)
2. Agregar refresh token automático cuando el access token expire
3. Implementar protección de rutas en cada módulo
4. Añadir más traducciones según se necesite
5. Crear más componentes compartidos (Modals, Alerts, Forms, etc.)