608 lines
13 KiB
Markdown
608 lines
13 KiB
Markdown
# 🛠️ Guía de Desarrollo - Karibeo
|
|
|
|
## Configuración del Entorno
|
|
|
|
### Requisitos del Sistema
|
|
|
|
- **Node.js**: >= 18.0.0 (recomendado 20.x LTS)
|
|
- **npm**: >= 9.0.0 o **yarn**: >= 1.22.0
|
|
- **Git**: >= 2.30.0
|
|
- **Editor**: VSCode (recomendado) con extensiones
|
|
|
|
### Extensiones VSCode Recomendadas
|
|
|
|
```json
|
|
{
|
|
"recommendations": [
|
|
"dbaeumer.vscode-eslint",
|
|
"esbenp.prettier-vscode",
|
|
"bradlc.vscode-tailwindcss",
|
|
"formulahendry.auto-rename-tag",
|
|
"christian-kohler.path-intellisense",
|
|
"dsznajder.es7-react-js-snippets",
|
|
"mikestead.dotenv"
|
|
]
|
|
}
|
|
```
|
|
|
|
## Setup Inicial
|
|
|
|
### 1. Clonar el Repositorio
|
|
|
|
```bash
|
|
git clone https://github.com/tu-usuario/karibeo.git
|
|
cd karibeo
|
|
```
|
|
|
|
### 2. Instalar Dependencias
|
|
|
|
```bash
|
|
npm install
|
|
# o
|
|
yarn install
|
|
```
|
|
|
|
### 3. Configurar Variables de Entorno
|
|
|
|
Crear archivo `.env` en la raíz:
|
|
|
|
```env
|
|
# API Backend
|
|
VITE_API_BASE_URL=https://karibeo.lesoluciones.net:8443/api/v1
|
|
|
|
# Google Maps
|
|
VITE_GOOGLE_MAPS_API_KEY=your_google_maps_api_key
|
|
|
|
# Stripe (Pagos)
|
|
VITE_STRIPE_PUBLIC_KEY=pk_test_...
|
|
|
|
# Analytics (Opcional)
|
|
VITE_GA_ID=G-XXXXXXXXXX
|
|
|
|
# Sentry (Error Tracking - Opcional)
|
|
VITE_SENTRY_DSN=https://...@sentry.io/...
|
|
|
|
# Feature Flags (Opcional)
|
|
VITE_ENABLE_ANALYTICS=true
|
|
VITE_ENABLE_PWA=false
|
|
```
|
|
|
|
### 4. Iniciar Servidor de Desarrollo
|
|
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
La aplicación estará disponible en: `http://localhost:5173`
|
|
|
|
## Estructura de Carpetas Detallada
|
|
|
|
```
|
|
karibeo/
|
|
├── .vscode/ # Configuración de VSCode
|
|
│ ├── settings.json # Configuraciones del workspace
|
|
│ └── extensions.json # Extensiones recomendadas
|
|
│
|
|
├── docs/ # Documentación
|
|
│ ├── API.md # Documentación de API
|
|
│ ├── ARCHITECTURE.md # Arquitectura del sistema
|
|
│ └── DEVELOPMENT.md # Esta guía
|
|
│
|
|
├── public/ # Assets estáticos
|
|
│ ├── favicon.ico
|
|
│ ├── manifest.json # PWA manifest
|
|
│ └── robots.txt
|
|
│
|
|
├── src/
|
|
│ ├── assets/ # Recursos (imágenes, fonts)
|
|
│ │ ├── images/
|
|
│ │ └── fonts/
|
|
│ │
|
|
│ ├── components/ # Componentes React
|
|
│ │ ├── ui/ # Componentes base (shadcn)
|
|
│ │ │ ├── button.tsx
|
|
│ │ │ ├── input.tsx
|
|
│ │ │ └── ...
|
|
│ │ │
|
|
│ │ ├── admin/ # Componentes de admin
|
|
│ │ │ ├── ConfigTab.tsx
|
|
│ │ │ ├── UsersTab.tsx
|
|
│ │ │ └── ...
|
|
│ │ │
|
|
│ │ ├── hotel/ # Componentes hoteleros
|
|
│ │ ├── restaurant/ # Componentes de restaurante
|
|
│ │ ├── roles/ # Sistema de roles
|
|
│ │ ├── security/ # Componentes de seguridad
|
|
│ │ └── shared/ # Componentes compartidos
|
|
│ │
|
|
│ ├── contexts/ # React Contexts
|
|
│ │ ├── AuthContext.tsx
|
|
│ │ ├── CartContext.tsx
|
|
│ │ ├── CurrencyContext.tsx
|
|
│ │ └── LanguageContext.tsx
|
|
│ │
|
|
│ ├── hooks/ # Custom Hooks
|
|
│ │ ├── useAdminData.ts
|
|
│ │ ├── useBooking.ts
|
|
│ │ ├── useChannelManager.ts
|
|
│ │ └── ...
|
|
│ │
|
|
│ ├── lib/ # Utilidades y helpers
|
|
│ │ ├── utils.ts # Funciones utilitarias
|
|
│ │ └── validation.ts # Schemas de validación
|
|
│ │
|
|
│ ├── pages/ # Páginas/Rutas
|
|
│ │ ├── dashboard/ # Panel de control
|
|
│ │ │ ├── AdminDashboard.tsx
|
|
│ │ │ ├── Dashboard.tsx
|
|
│ │ │ └── ...
|
|
│ │ │
|
|
│ │ ├── Index.tsx # Landing page
|
|
│ │ ├── SignIn.tsx # Login
|
|
│ │ └── SignUp.tsx # Registro
|
|
│ │
|
|
│ ├── services/ # Servicios API
|
|
│ │ ├── adminApi.ts
|
|
│ │ ├── emergencyApi.ts
|
|
│ │ └── ...
|
|
│ │
|
|
│ ├── types/ # TypeScript types
|
|
│ │ ├── index.ts
|
|
│ │ └── roles.ts
|
|
│ │
|
|
│ ├── i18n/ # Internacionalización
|
|
│ │ ├── en.ts
|
|
│ │ └── es.ts
|
|
│ │
|
|
│ ├── App.tsx # Componente principal
|
|
│ ├── main.tsx # Entry point
|
|
│ └── index.css # Estilos globales
|
|
│
|
|
├── .eslintrc.js # Configuración ESLint
|
|
├── .prettierrc # Configuración Prettier
|
|
├── tailwind.config.ts # Configuración Tailwind
|
|
├── tsconfig.json # Configuración TypeScript
|
|
├── vite.config.ts # Configuración Vite
|
|
└── package.json # Dependencias y scripts
|
|
```
|
|
|
|
## Convenciones de Código
|
|
|
|
### Nomenclatura
|
|
|
|
#### Archivos
|
|
```typescript
|
|
// PascalCase para componentes
|
|
UserProfile.tsx
|
|
AdminDashboard.tsx
|
|
|
|
// camelCase para utilidades y hooks
|
|
useAuth.ts
|
|
formatCurrency.ts
|
|
|
|
// kebab-case para estilos
|
|
user-profile.css
|
|
```
|
|
|
|
#### Variables y Funciones
|
|
```typescript
|
|
// camelCase para variables y funciones
|
|
const userName = "John";
|
|
function getUserData() {}
|
|
|
|
// PascalCase para componentes y clases
|
|
const UserCard = () => {};
|
|
class ApiClient {}
|
|
|
|
// UPPER_SNAKE_CASE para constantes
|
|
const MAX_RETRY_ATTEMPTS = 3;
|
|
const API_BASE_URL = "https://...";
|
|
```
|
|
|
|
#### Interfaces y Types
|
|
```typescript
|
|
// PascalCase con prefijo "I" opcional
|
|
interface UserProfile {}
|
|
interface IUserProfile {} // alternativa
|
|
|
|
type UserRole = 'admin' | 'user';
|
|
```
|
|
|
|
### Formato de Código
|
|
|
|
#### Imports
|
|
```typescript
|
|
// 1. Imports de librerías externas
|
|
import React, { useState, useEffect } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
|
// 2. Imports de componentes UI
|
|
import { Button } from '@/components/ui/button';
|
|
import { Input } from '@/components/ui/input';
|
|
|
|
// 3. Imports de componentes propios
|
|
import { UserCard } from '@/components/UserCard';
|
|
|
|
// 4. Imports de hooks y contexts
|
|
import { useAuth } from '@/contexts/AuthContext';
|
|
import { useAdminData } from '@/hooks/useAdminData';
|
|
|
|
// 5. Imports de utilidades y tipos
|
|
import { cn } from '@/lib/utils';
|
|
import type { User } from '@/types';
|
|
|
|
// 6. Imports de assets
|
|
import logo from '@/assets/logo.png';
|
|
|
|
// 7. Imports de estilos
|
|
import './styles.css';
|
|
```
|
|
|
|
#### Componentes Funcionales
|
|
```typescript
|
|
// Buena práctica
|
|
interface UserCardProps {
|
|
user: User;
|
|
onEdit?: (id: string) => void;
|
|
className?: string;
|
|
}
|
|
|
|
export const UserCard: React.FC<UserCardProps> = ({
|
|
user,
|
|
onEdit,
|
|
className
|
|
}) => {
|
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
|
|
useEffect(() => {
|
|
// Effect logic
|
|
}, []);
|
|
|
|
const handleClick = () => {
|
|
setIsExpanded(!isExpanded);
|
|
};
|
|
|
|
return (
|
|
<div className={cn("card", className)}>
|
|
{/* JSX */}
|
|
</div>
|
|
);
|
|
};
|
|
```
|
|
|
|
### TypeScript
|
|
|
|
#### Tipado Estricto
|
|
```typescript
|
|
// ✅ Bueno
|
|
interface User {
|
|
id: string;
|
|
name: string;
|
|
email: string;
|
|
}
|
|
|
|
const getUser = (id: string): Promise<User> => {
|
|
return api.get<User>(`/users/${id}`);
|
|
};
|
|
|
|
// ❌ Evitar
|
|
const getUser = (id: any): any => {
|
|
return api.get(`/users/${id}`);
|
|
};
|
|
```
|
|
|
|
#### Usar Interfaces sobre Types
|
|
```typescript
|
|
// ✅ Preferido para objetos
|
|
interface UserProfile {
|
|
name: string;
|
|
age: number;
|
|
}
|
|
|
|
// ✅ Usar type para unions, intersections
|
|
type UserRole = 'admin' | 'user' | 'guest';
|
|
type ExtendedUser = UserProfile & { role: UserRole };
|
|
```
|
|
|
|
### React Patterns
|
|
|
|
#### Hooks
|
|
```typescript
|
|
// Custom hook
|
|
export const useUser = (userId: string) => {
|
|
const [user, setUser] = useState<User | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<Error | null>(null);
|
|
|
|
useEffect(() => {
|
|
fetchUser(userId)
|
|
.then(setUser)
|
|
.catch(setError)
|
|
.finally(() => setLoading(false));
|
|
}, [userId]);
|
|
|
|
return { user, loading, error };
|
|
};
|
|
```
|
|
|
|
#### Memoization
|
|
```typescript
|
|
// useMemo para cálculos costosos
|
|
const expensiveValue = useMemo(() => {
|
|
return computeExpensiveValue(a, b);
|
|
}, [a, b]);
|
|
|
|
// useCallback para funciones
|
|
const handleSubmit = useCallback((data: FormData) => {
|
|
submitForm(data);
|
|
}, []);
|
|
|
|
// memo para componentes
|
|
export const UserCard = memo(({ user }: Props) => {
|
|
return <div>{user.name}</div>;
|
|
});
|
|
```
|
|
|
|
### Tailwind CSS
|
|
|
|
#### Ordenamiento de Clases
|
|
```tsx
|
|
// Orden recomendado:
|
|
// 1. Layout (display, position)
|
|
// 2. Box model (width, height, margin, padding)
|
|
// 3. Typography
|
|
// 4. Visual (background, border, shadow)
|
|
// 5. Misc (cursor, transform, transition)
|
|
|
|
<div className="
|
|
flex items-center justify-between
|
|
w-full h-20 p-4
|
|
text-lg font-semibold
|
|
bg-white border border-gray-200 rounded-lg shadow-md
|
|
hover:shadow-lg transition-shadow
|
|
">
|
|
Content
|
|
</div>
|
|
```
|
|
|
|
#### Usar cn() para Clases Condicionales
|
|
```tsx
|
|
import { cn } from '@/lib/utils';
|
|
|
|
<Button
|
|
className={cn(
|
|
"base-class",
|
|
isActive && "active-class",
|
|
isDisabled && "disabled-class",
|
|
customClass
|
|
)}
|
|
/>
|
|
```
|
|
|
|
## Testing
|
|
|
|
### Jest + React Testing Library
|
|
|
|
#### Setup
|
|
```bash
|
|
npm install --save-dev @testing-library/react @testing-library/jest-dom jest
|
|
```
|
|
|
|
#### Escribir Tests
|
|
```typescript
|
|
// UserCard.test.tsx
|
|
import { render, screen, fireEvent } from '@testing-library/react';
|
|
import { UserCard } from './UserCard';
|
|
|
|
describe('UserCard', () => {
|
|
const mockUser = {
|
|
id: '1',
|
|
name: 'John Doe',
|
|
email: 'john@example.com'
|
|
};
|
|
|
|
it('renders user information', () => {
|
|
render(<UserCard user={mockUser} />);
|
|
expect(screen.getByText('John Doe')).toBeInTheDocument();
|
|
});
|
|
|
|
it('calls onEdit when edit button is clicked', () => {
|
|
const onEdit = jest.fn();
|
|
render(<UserCard user={mockUser} onEdit={onEdit} />);
|
|
|
|
fireEvent.click(screen.getByRole('button', { name: /edit/i }));
|
|
expect(onEdit).toHaveBeenCalledWith('1');
|
|
});
|
|
});
|
|
```
|
|
|
|
### Ejecutar Tests
|
|
```bash
|
|
npm run test # Ejecutar todos los tests
|
|
npm run test:watch # Watch mode
|
|
npm run test:coverage # Con coverage
|
|
```
|
|
|
|
## Debugging
|
|
|
|
### React Developer Tools
|
|
Instalar extensión de navegador: React Developer Tools
|
|
|
|
### VSCode Debugging
|
|
Crear `.vscode/launch.json`:
|
|
```json
|
|
{
|
|
"version": "0.2.0",
|
|
"configurations": [
|
|
{
|
|
"type": "chrome",
|
|
"request": "launch",
|
|
"name": "Launch Chrome",
|
|
"url": "http://localhost:5173",
|
|
"webRoot": "${workspaceFolder}/src"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Console Logs Útiles
|
|
```typescript
|
|
// Debug con contexto
|
|
console.log('🔍 User data:', user);
|
|
console.error('❌ Error:', error);
|
|
console.warn('⚠️ Warning:', warning);
|
|
|
|
// Grupos
|
|
console.group('API Request');
|
|
console.log('URL:', url);
|
|
console.log('Method:', method);
|
|
console.groupEnd();
|
|
|
|
// Tiempo de ejecución
|
|
console.time('fetchData');
|
|
await fetchData();
|
|
console.timeEnd('fetchData');
|
|
```
|
|
|
|
## Performance
|
|
|
|
### Optimizaciones
|
|
|
|
#### Code Splitting
|
|
```typescript
|
|
// Lazy loading de componentes
|
|
const AdminDashboard = lazy(() => import('./pages/AdminDashboard'));
|
|
|
|
<Suspense fallback={<LoadingSpinner />}>
|
|
<AdminDashboard />
|
|
</Suspense>
|
|
```
|
|
|
|
#### Bundle Analysis
|
|
```bash
|
|
npm run build
|
|
npm run analyze
|
|
```
|
|
|
|
#### Lighthouse CI
|
|
```bash
|
|
npm install -g @lhci/cli
|
|
lhci autorun
|
|
```
|
|
|
|
## Git Workflow
|
|
|
|
### Branches
|
|
```
|
|
main # Producción
|
|
develop # Desarrollo
|
|
feature/xxx # Nuevas características
|
|
bugfix/xxx # Corrección de bugs
|
|
hotfix/xxx # Hotfixes urgentes
|
|
```
|
|
|
|
### Commits
|
|
Usar convención de commits semánticos:
|
|
```bash
|
|
feat: add user authentication
|
|
fix: resolve booking calculation bug
|
|
docs: update API documentation
|
|
style: format code with prettier
|
|
refactor: reorganize admin components
|
|
test: add tests for UserCard component
|
|
chore: update dependencies
|
|
```
|
|
|
|
### Pull Requests
|
|
1. Crear branch desde `develop`
|
|
2. Hacer cambios y commits
|
|
3. Push al repositorio remoto
|
|
4. Crear PR hacia `develop`
|
|
5. Code review
|
|
6. Merge después de aprobación
|
|
|
|
## Build y Deploy
|
|
|
|
### Build Local
|
|
```bash
|
|
npm run build
|
|
```
|
|
|
|
Archivos generados en `/dist`
|
|
|
|
### Preview Build
|
|
```bash
|
|
npm run preview
|
|
```
|
|
|
|
### Deploy a Lovable
|
|
1. Commit y push cambios
|
|
2. Ir a proyecto en Lovable
|
|
3. Cambios se sincronizarán automáticamente
|
|
|
|
### Deploy Manual
|
|
```bash
|
|
# Vercel
|
|
vercel deploy
|
|
|
|
# Netlify
|
|
netlify deploy --prod
|
|
|
|
# AWS S3
|
|
aws s3 sync dist/ s3://your-bucket/
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Problemas Comunes
|
|
|
|
#### Puerto 5173 en uso
|
|
```bash
|
|
# Cambiar puerto en vite.config.ts
|
|
export default defineConfig({
|
|
server: {
|
|
port: 3000
|
|
}
|
|
});
|
|
```
|
|
|
|
#### Problemas con node_modules
|
|
```bash
|
|
rm -rf node_modules package-lock.json
|
|
npm install
|
|
```
|
|
|
|
#### Errores de TypeScript
|
|
```bash
|
|
# Limpiar cache
|
|
rm -rf node_modules/.vite
|
|
npm run dev
|
|
```
|
|
|
|
#### Build falla
|
|
```bash
|
|
# Verificar errores
|
|
npm run build 2>&1 | tee build.log
|
|
|
|
# Limpiar y rebuild
|
|
rm -rf dist
|
|
npm run build
|
|
```
|
|
|
|
## Resources
|
|
|
|
### Documentación Oficial
|
|
- [React](https://react.dev/)
|
|
- [TypeScript](https://www.typescriptlang.org/docs/)
|
|
- [Vite](https://vitejs.dev/)
|
|
- [Tailwind CSS](https://tailwindcss.com/docs)
|
|
- [shadcn/ui](https://ui.shadcn.com/)
|
|
|
|
### Comunidad
|
|
- [Karibeo Discord](#)
|
|
- [GitHub Discussions](#)
|
|
- [Stack Overflow](https://stackoverflow.com/questions/tagged/karibeo)
|
|
|
|
---
|
|
|
|
**Última actualización**: 2025-01-12 |