Initial commit - erp-construccion-frontend-web
This commit is contained in:
commit
0af6d41e4b
37
mobile/App.tsx
Normal file
37
mobile/App.tsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* App Component - React Native + Expo
|
||||||
|
* MVP Sistema Administración de Obra e INFONAVIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { StatusBar } from 'expo-status-bar';
|
||||||
|
import { StyleSheet, Text, View } from 'react-native';
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Text style={styles.title}>🏗️ Sistema Administración de Obra</Text>
|
||||||
|
<Text style={styles.subtitle}>App Móvil - Supervisor</Text>
|
||||||
|
<StatusBar style="auto" />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
padding: 20,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
marginBottom: 8,
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
subtitle: {
|
||||||
|
fontSize: 16,
|
||||||
|
color: '#666',
|
||||||
|
},
|
||||||
|
});
|
||||||
43
mobile/README.md
Normal file
43
mobile/README.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Frontend Mobile - MVP Sistema Administración de Obra
|
||||||
|
|
||||||
|
**Stack:** React Native + Expo
|
||||||
|
**Versión:** 1.0.0
|
||||||
|
**Fecha:** 2025-11-20
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 DESCRIPCIÓN
|
||||||
|
|
||||||
|
Aplicación móvil para supervisores de obra.
|
||||||
|
|
||||||
|
**Funcionalidades principales:**
|
||||||
|
- Registro de avances
|
||||||
|
- Captura fotográfica
|
||||||
|
- Gestión de materiales en sitio
|
||||||
|
- Reportes rápidos
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 SETUP
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
Luego escanea el QR con Expo Go app.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 SCRIPTS
|
||||||
|
|
||||||
|
| Script | Descripción |
|
||||||
|
|--------|-------------|
|
||||||
|
| `npm start` | Inicia Expo |
|
||||||
|
| `npm run android` | Abre en Android |
|
||||||
|
| `npm run ios` | Abre en iOS |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Mantenido por:** Frontend-Agent
|
||||||
|
**Última actualización:** 2025-11-20
|
||||||
32
mobile/app.json
Normal file
32
mobile/app.json
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"expo": {
|
||||||
|
"name": "Sistema Obra - Mobile",
|
||||||
|
"slug": "construccion-mvp-mobile",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"orientation": "portrait",
|
||||||
|
"icon": "./assets/icon.png",
|
||||||
|
"userInterfaceStyle": "light",
|
||||||
|
"splash": {
|
||||||
|
"image": "./assets/splash.png",
|
||||||
|
"resizeMode": "contain",
|
||||||
|
"backgroundColor": "#ffffff"
|
||||||
|
},
|
||||||
|
"assetBundlePatterns": [
|
||||||
|
"**/*"
|
||||||
|
],
|
||||||
|
"ios": {
|
||||||
|
"supportsTablet": true,
|
||||||
|
"bundleIdentifier": "com.construccion.mvp"
|
||||||
|
},
|
||||||
|
"android": {
|
||||||
|
"adaptiveIcon": {
|
||||||
|
"foregroundImage": "./assets/adaptive-icon.png",
|
||||||
|
"backgroundColor": "#ffffff"
|
||||||
|
},
|
||||||
|
"package": "com.construccion.mvp"
|
||||||
|
},
|
||||||
|
"web": {
|
||||||
|
"favicon": "./assets/favicon.png"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14386
mobile/package-lock.json
generated
Normal file
14386
mobile/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
28
mobile/package.json
Normal file
28
mobile/package.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "@construccion-mvp/frontend-mobile",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Frontend Mobile - MVP Sistema Administración de Obra e INFONAVIT",
|
||||||
|
"main": "node_modules/expo/AppEntry.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "expo start",
|
||||||
|
"android": "expo start --android",
|
||||||
|
"ios": "expo start --ios",
|
||||||
|
"web": "expo start --web"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"expo": "~50.0.0",
|
||||||
|
"expo-status-bar": "~1.11.1",
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-native": "0.73.0",
|
||||||
|
"@react-navigation/native": "^6.1.9",
|
||||||
|
"@react-navigation/native-stack": "^6.9.17",
|
||||||
|
"zustand": "^4.4.7",
|
||||||
|
"axios": "^1.6.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.23.5",
|
||||||
|
"@types/react": "~18.2.45",
|
||||||
|
"typescript": "^5.1.3"
|
||||||
|
},
|
||||||
|
"private": true
|
||||||
|
}
|
||||||
14
mobile/tsconfig.json
Normal file
14
mobile/tsconfig.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"extends": "expo/tsconfig.base",
|
||||||
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"],
|
||||||
|
"@screens/*": ["./src/screens/*"],
|
||||||
|
"@components/*": ["./src/components/*"],
|
||||||
|
"@stores/*": ["./src/stores/*"],
|
||||||
|
"@services/*": ["./src/services/*"],
|
||||||
|
"@utils/*": ["./src/utils/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
65
web/Dockerfile
Normal file
65
web/Dockerfile
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Dockerfile - Frontend Web
|
||||||
|
# ERP Construccion - React + Vite + TypeScript
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Stage 1: Base
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
FROM node:20-alpine AS base
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Stage 2: Development
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
FROM base AS development
|
||||||
|
|
||||||
|
# Install all dependencies
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Expose Vite dev server port
|
||||||
|
EXPOSE 5173
|
||||||
|
|
||||||
|
# Development command with hot reload
|
||||||
|
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Stage 3: Builder
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
FROM base AS builder
|
||||||
|
|
||||||
|
# Install all dependencies
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build for production
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Stage 4: Production (with nginx)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
FROM nginx:alpine AS production
|
||||||
|
|
||||||
|
# Copy nginx config
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# Copy built files
|
||||||
|
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||||
|
|
||||||
|
# Expose port
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
|
CMD curl -f http://localhost/ || exit 1
|
||||||
|
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
107
web/README.md
Normal file
107
web/README.md
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
# Frontend Web - MVP Sistema Administración de Obra
|
||||||
|
|
||||||
|
**Stack:** React 18 + Vite + TypeScript + Zustand
|
||||||
|
**Versión:** 1.0.0
|
||||||
|
**Fecha:** 2025-11-20
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 DESCRIPCIÓN
|
||||||
|
|
||||||
|
Aplicación web del sistema de administración de obra e INFONAVIT.
|
||||||
|
|
||||||
|
**Portales incluidos:**
|
||||||
|
- **Admin:** Portal administrativo completo
|
||||||
|
- **Supervisor:** Portal para supervisores de obra
|
||||||
|
- **Obra:** Portal para personal en sitio
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 SETUP INICIAL
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Instalar dependencias
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Iniciar servidor de desarrollo
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# Build para producción
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
La aplicación estará disponible en `http://localhost:5173`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏗️ ESTRUCTURA
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── shared/ # Código compartido entre portales
|
||||||
|
│ ├── components/
|
||||||
|
│ │ ├── ui/ # Componentes UI base (Button, Input, etc.)
|
||||||
|
│ │ └── layout/ # Componentes de layout (Header, Sidebar, etc.)
|
||||||
|
│ ├── hooks/ # Custom hooks
|
||||||
|
│ ├── stores/ # Zustand stores
|
||||||
|
│ ├── services/ # API services
|
||||||
|
│ ├── types/ # TypeScript types
|
||||||
|
│ ├── utils/ # Utilities
|
||||||
|
│ └── constants/ # Constantes
|
||||||
|
└── apps/ # Portales específicos
|
||||||
|
├── admin/ # Portal administrador
|
||||||
|
│ ├── pages/
|
||||||
|
│ ├── components/
|
||||||
|
│ └── routes.tsx
|
||||||
|
├── supervisor/ # Portal supervisor
|
||||||
|
└── obra/ # Portal obra
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 SCRIPTS
|
||||||
|
|
||||||
|
| Script | Descripción |
|
||||||
|
|--------|-------------|
|
||||||
|
| `npm run dev` | Inicia servidor de desarrollo (port 5173) |
|
||||||
|
| `npm run build` | Build para producción |
|
||||||
|
| `npm run preview` | Preview del build de producción |
|
||||||
|
| `npm run lint` | Ejecuta ESLint |
|
||||||
|
| `npm run lint:fix` | Ejecuta ESLint y corrige |
|
||||||
|
| `npm run type-check` | Verifica tipos TypeScript |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 CONVENCIONES
|
||||||
|
|
||||||
|
### Nomenclatura
|
||||||
|
|
||||||
|
Seguir **ESTANDARES-NOMENCLATURA.md**:
|
||||||
|
- Componentes: `PascalCase.tsx`
|
||||||
|
- Páginas: `PascalCasePage.tsx`
|
||||||
|
- Hooks: `useCamelCase.ts`
|
||||||
|
- Stores: `camelCase.store.ts`
|
||||||
|
- Tipos: `camelCase.types.ts`
|
||||||
|
|
||||||
|
### Path Aliases
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Button } from '@components/ui/Button';
|
||||||
|
import { useAuth } from '@hooks/useAuth';
|
||||||
|
import { projectStore } from '@stores/project.store';
|
||||||
|
import type { Project } from '@types/project.types';
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 REFERENCIAS
|
||||||
|
|
||||||
|
- [Vite Documentation](https://vitejs.dev/)
|
||||||
|
- [React Documentation](https://react.dev/)
|
||||||
|
- [Zustand Documentation](https://zustand-demo.pmnd.rs/)
|
||||||
|
- [ESTANDARES-NOMENCLATURA.md](../../orchestration/directivas/ESTANDARES-NOMENCLATURA.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Mantenido por:** Frontend-Agent
|
||||||
|
**Última actualización:** 2025-11-20
|
||||||
14
web/index.html
Normal file
14
web/index.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="es">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta name="description" content="MVP Sistema Administración de Obra e INFONAVIT" />
|
||||||
|
<title>Sistema Administración de Obra - MVP</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
47
web/nginx.conf
Normal file
47
web/nginx.conf
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name localhost;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
# Gzip compression
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_proxied expired no-cache no-store private auth;
|
||||||
|
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml application/javascript;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||||
|
|
||||||
|
# Cache static assets
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||||
|
expires 1y;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
# SPA routing - send all requests to index.html
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Health check endpoint
|
||||||
|
location /health {
|
||||||
|
access_log off;
|
||||||
|
return 200 "healthy\n";
|
||||||
|
add_header Content-Type text/plain;
|
||||||
|
}
|
||||||
|
|
||||||
|
# API proxy (optional - if needed)
|
||||||
|
# location /api {
|
||||||
|
# proxy_pass http://backend:3000;
|
||||||
|
# proxy_http_version 1.1;
|
||||||
|
# proxy_set_header Upgrade $http_upgrade;
|
||||||
|
# proxy_set_header Connection 'upgrade';
|
||||||
|
# proxy_set_header Host $host;
|
||||||
|
# proxy_cache_bypass $http_upgrade;
|
||||||
|
# }
|
||||||
|
}
|
||||||
4552
web/package-lock.json
generated
Normal file
4552
web/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
46
web/package.json
Normal file
46
web/package.json
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"name": "@construccion-mvp/frontend-web",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Frontend Web - MVP Sistema Administración de Obra e INFONAVIT",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc && vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||||
|
"lint:fix": "eslint . --ext ts,tsx --fix",
|
||||||
|
"type-check": "tsc --noEmit"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router-dom": "^6.20.1",
|
||||||
|
"zustand": "^4.4.7",
|
||||||
|
"axios": "^1.6.2",
|
||||||
|
"react-hook-form": "^7.49.2",
|
||||||
|
"zod": "^3.22.4",
|
||||||
|
"@hookform/resolvers": "^3.3.3",
|
||||||
|
"date-fns": "^3.0.6",
|
||||||
|
"clsx": "^2.0.0",
|
||||||
|
"lucide-react": "^0.303.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/react": "^18.2.43",
|
||||||
|
"@types/react-dom": "^18.2.17",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.14.0",
|
||||||
|
"@typescript-eslint/parser": "^6.14.0",
|
||||||
|
"@vitejs/plugin-react": "^4.2.1",
|
||||||
|
"eslint": "^8.55.0",
|
||||||
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.5",
|
||||||
|
"typescript": "^5.2.2",
|
||||||
|
"vite": "^5.0.8",
|
||||||
|
"autoprefixer": "^10.4.16",
|
||||||
|
"postcss": "^8.4.32",
|
||||||
|
"tailwindcss": "^3.4.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0",
|
||||||
|
"npm": ">=9.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
60
web/src/App.tsx
Normal file
60
web/src/App.tsx
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* App Component
|
||||||
|
* Root component con routing básico
|
||||||
|
*
|
||||||
|
* @author Frontend-Agent
|
||||||
|
* @date 2025-11-20
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Componente principal de la aplicación
|
||||||
|
* TODO: Agregar rutas de los diferentes portales (admin, supervisor, obra)
|
||||||
|
*/
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<BrowserRouter>
|
||||||
|
<div className="app">
|
||||||
|
<Routes>
|
||||||
|
{/* Ruta principal */}
|
||||||
|
<Route path="/" element={<HomePage />} />
|
||||||
|
|
||||||
|
{/* Portal Admin */}
|
||||||
|
<Route path="/admin/*" element={<div>Admin Portal (TODO)</div>} />
|
||||||
|
|
||||||
|
{/* Portal Supervisor */}
|
||||||
|
<Route path="/supervisor/*" element={<div>Supervisor Portal (TODO)</div>} />
|
||||||
|
|
||||||
|
{/* Portal Obra */}
|
||||||
|
<Route path="/obra/*" element={<div>Obra Portal (TODO)</div>} />
|
||||||
|
|
||||||
|
{/* 404 */}
|
||||||
|
<Route path="*" element={<Navigate to="/" replace />} />
|
||||||
|
</Routes>
|
||||||
|
</div>
|
||||||
|
</BrowserRouter>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Página de inicio temporal
|
||||||
|
*/
|
||||||
|
function HomePage() {
|
||||||
|
return (
|
||||||
|
<div style={{ padding: '2rem', fontFamily: 'system-ui' }}>
|
||||||
|
<h1>🏗️ Sistema Administración de Obra</h1>
|
||||||
|
<p>MVP - INFONAVIT</p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/admin">Portal Administrador</a></li>
|
||||||
|
<li><a href="/supervisor">Portal Supervisor</a></li>
|
||||||
|
<li><a href="/obra">Portal Obra</a></li>
|
||||||
|
</ul>
|
||||||
|
<p style={{ marginTop: '2rem', color: '#666' }}>
|
||||||
|
Versión: 1.0.0 | Entorno: {import.meta.env.MODE}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
125
web/src/index.css
Normal file
125
web/src/index.css
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/**
|
||||||
|
* Global Styles
|
||||||
|
* Estilos base y reset CSS
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Reset básico */
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Variables CSS (TODO: mover a theme) */
|
||||||
|
:root {
|
||||||
|
--primary-color: #2563eb;
|
||||||
|
--secondary-color: #64748b;
|
||||||
|
--success-color: #22c55e;
|
||||||
|
--warning-color: #f59e0b;
|
||||||
|
--danger-color: #ef4444;
|
||||||
|
|
||||||
|
--text-primary: #1e293b;
|
||||||
|
--text-secondary: #64748b;
|
||||||
|
--text-light: #94a3b8;
|
||||||
|
|
||||||
|
--bg-primary: #ffffff;
|
||||||
|
--bg-secondary: #f8fafc;
|
||||||
|
--bg-tertiary: #f1f5f9;
|
||||||
|
|
||||||
|
--border-color: #e2e8f0;
|
||||||
|
--border-radius: 0.5rem;
|
||||||
|
|
||||||
|
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||||
|
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
|
||||||
|
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tipografía base */
|
||||||
|
html {
|
||||||
|
font-size: 16px;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
|
||||||
|
Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: var(--text-primary);
|
||||||
|
background-color: var(--bg-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enlaces */
|
||||||
|
a {
|
||||||
|
color: var(--primary-color);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #1d4ed8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buttons (estilos base) */
|
||||||
|
button {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inputs (estilos base) */
|
||||||
|
input,
|
||||||
|
textarea,
|
||||||
|
select {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scrollbar personalizado (opcional) */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: var(--bg-tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: var(--border-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: var(--text-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utilidades */
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1280px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.visually-hidden {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border-width: 0;
|
||||||
|
}
|
||||||
18
web/src/main.tsx
Normal file
18
web/src/main.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Main Entry Point
|
||||||
|
* MVP Sistema Administración de Obra e INFONAVIT
|
||||||
|
*
|
||||||
|
* @author Frontend-Agent
|
||||||
|
* @date 2025-11-20
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom/client';
|
||||||
|
import App from './App';
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>,
|
||||||
|
);
|
||||||
1
web/src/vite-env.d.ts
vendored
Normal file
1
web/src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
40
web/tsconfig.json
Normal file
40
web/tsconfig.json
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
|
||||||
|
/* Path aliases */
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"],
|
||||||
|
"@shared/*": ["./src/shared/*"],
|
||||||
|
"@components/*": ["./src/shared/components/*"],
|
||||||
|
"@stores/*": ["./src/shared/stores/*"],
|
||||||
|
"@services/*": ["./src/shared/services/*"],
|
||||||
|
"@hooks/*": ["./src/shared/hooks/*"],
|
||||||
|
"@types/*": ["./src/shared/types/*"],
|
||||||
|
"@utils/*": ["./src/shared/utils/*"],
|
||||||
|
"@constants/*": ["./src/shared/constants/*"],
|
||||||
|
"@apps/*": ["./src/apps/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
|
}
|
||||||
11
web/tsconfig.node.json
Normal file
11
web/tsconfig.node.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
||||||
45
web/vite.config.ts
Normal file
45
web/vite.config.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': path.resolve(__dirname, './src'),
|
||||||
|
'@shared': path.resolve(__dirname, './src/shared'),
|
||||||
|
'@components': path.resolve(__dirname, './src/shared/components'),
|
||||||
|
'@stores': path.resolve(__dirname, './src/shared/stores'),
|
||||||
|
'@services': path.resolve(__dirname, './src/shared/services'),
|
||||||
|
'@hooks': path.resolve(__dirname, './src/shared/hooks'),
|
||||||
|
'@types': path.resolve(__dirname, './src/shared/types'),
|
||||||
|
'@utils': path.resolve(__dirname, './src/shared/utils'),
|
||||||
|
'@constants': path.resolve(__dirname, './src/shared/constants'),
|
||||||
|
'@apps': path.resolve(__dirname, './src/apps'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
port: 5173,
|
||||||
|
host: true,
|
||||||
|
proxy: {
|
||||||
|
'/api': {
|
||||||
|
target: 'http://localhost:3000',
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
outDir: 'dist',
|
||||||
|
sourcemap: true,
|
||||||
|
rollupOptions: {
|
||||||
|
output: {
|
||||||
|
manualChunks: {
|
||||||
|
'react-vendor': ['react', 'react-dom', 'react-router-dom'],
|
||||||
|
'zustand-vendor': ['zustand'],
|
||||||
|
'axios-vendor': ['axios'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user