Agregar documentacion completa del proyecto

- README.md actualizado con descripcion detallada del sistema
- DOCUMENTATION.md con documentacion tecnica exhaustiva

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Exteban08
2026-01-18 04:58:02 +00:00
parent 143cd77cee
commit 2b5735d78d
2 changed files with 976 additions and 20 deletions

611
DOCUMENTATION.md Normal file
View File

@@ -0,0 +1,611 @@
# Documentacion Tecnica - Water Project GRH
Documentacion tecnica detallada del Sistema de Gestion de Recursos Hidricos.
---
## Tabla de Contenidos
1. [Arquitectura del Sistema](#arquitectura-del-sistema)
2. [Componentes Principales](#componentes-principales)
3. [Capa de API](#capa-de-api)
4. [Hooks Personalizados](#hooks-personalizados)
5. [Sistema de Autenticacion](#sistema-de-autenticacion)
6. [Gestion de Estado](#gestion-de-estado)
7. [Sistema de Temas](#sistema-de-temas)
8. [Guia de Desarrollo](#guia-de-desarrollo)
---
## Arquitectura del Sistema
### Vision General
El proyecto sigue una arquitectura **frontend SPA (Single Page Application)** con las siguientes capas:
```
┌─────────────────────────────────────────────────────────┐
│ Capa de Presentacion │
│ (React Components, Pages, Layout) │
├─────────────────────────────────────────────────────────┤
│ Capa de Logica │
│ (Custom Hooks, State Management) │
├─────────────────────────────────────────────────────────┤
│ Capa de Datos │
│ (API Services, localStorage) │
├─────────────────────────────────────────────────────────┤
│ API Externa │
│ (REST API Backend) │
└─────────────────────────────────────────────────────────┘
```
### Patron de Diseno
El proyecto utiliza varios patrones de diseno:
1. **Container/Presentational Pattern**: Separacion entre componentes con logica (pages) y componentes de UI puros (components)
2. **Custom Hooks Pattern**: Encapsulacion de logica reutilizable en hooks (`useMeters`, `useConcentrators`)
3. **Module Pattern**: Organizacion de codigo relacionado en modulos (meters/, concentrators/)
---
## Componentes Principales
### App.tsx - Componente Raiz
El componente raiz maneja:
- Autenticacion global
- Routing interno (sin react-router)
- Estado de pagina actual
- Modales globales (perfil, configuracion, logout)
```typescript
// Estados principales
const [isAuth, setIsAuth] = useState<boolean>(() => {
return Boolean(localStorage.getItem(AUTH_KEY));
});
const [currentPage, setCurrentPage] = useState("home");
const [currentSubpage, setCurrentSubpage] = useState<string | null>(null);
```
### Sidebar.tsx - Menu Lateral
Caracteristicas:
- Estados: colapsado/expandido
- Hover expansion con delay
- Pin/unpin para mantener expandido
- Menu jerarquico con submenus
```typescript
interface SidebarProps {
currentPage: string;
setCurrentPage: (page: string) => void;
currentSubpage: string | null;
setCurrentSubpage: (subpage: string | null) => void;
}
```
### TopMenu.tsx - Barra Superior
Funcionalidades:
- Breadcrumb de navegacion
- Notificaciones (placeholder)
- Menu de usuario con dropdown
- Acciones: perfil, configuracion, logout
---
## Capa de API
### Estructura de Archivos
```
src/api/
├── me.ts # Perfil de usuario
├── meters.ts # Operaciones CRUD de medidores
├── concentrators.ts # Operaciones CRUD de concentradores
└── projects.ts # Operaciones CRUD de proyectos
```
### Configuracion
```typescript
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
const API_TOKEN = import.meta.env.VITE_API_TOKEN;
```
### Funciones de API - Medidores
```typescript
// meters.ts
// Obtener todos los medidores
export async function fetchMeters(): Promise<Meter[]>
// Crear medidor
export async function createMeter(meterData: Partial<Meter>): Promise<Meter>
// Actualizar medidor
export async function updateMeter(
id: string,
meterData: Partial<Meter>
): Promise<Meter>
// Eliminar medidor
export async function deleteMeter(id: string): Promise<void>
```
### Funciones de API - Concentradores
```typescript
// concentrators.ts
export async function fetchConcentrators(): Promise<Concentrator[]>
export async function createConcentrator(data: Partial<Concentrator>): Promise<Concentrator>
export async function updateConcentrator(id: string, data: Partial<Concentrator>): Promise<Concentrator>
export async function deleteConcentrator(id: string): Promise<void>
```
### Funciones de API - Proyectos
```typescript
// projects.ts
export async function fetchProjects(): Promise<Project[]>
export async function fetchProjectNames(): Promise<string[]>
export async function createProject(data: Partial<Project>): Promise<Project>
export async function updateProject(id: string, data: Partial<Project>): Promise<Project>
export async function deleteProject(id: string): Promise<void>
```
### Manejo de Errores
Todas las funciones de API siguen el patron:
```typescript
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`Error: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error("API Error:", error);
throw error;
}
```
---
## Hooks Personalizados
### useMeters.ts
Hook para gestion completa del modulo de medidores.
```typescript
interface UseMetersReturn {
// Data
meters: Meter[];
filteredMeters: Meter[];
projectNames: string[];
// State
loading: boolean;
selectedMeter: Meter | null;
selectedProject: string | null;
searchTerm: string;
// Actions
setSelectedMeter: (meter: Meter | null) => void;
setSelectedProject: (project: string | null) => void;
setSearchTerm: (term: string) => void;
refreshData: () => Promise<void>;
// CRUD
handleCreate: (data: Partial<Meter>) => Promise<void>;
handleUpdate: (id: string, data: Partial<Meter>) => Promise<void>;
handleDelete: (id: string) => Promise<void>;
}
export function useMeters(): UseMetersReturn
```
### useConcentrators.ts
Hook similar para concentradores con estructura equivalente.
```typescript
interface UseConcentratorsReturn {
concentrators: Concentrator[];
filteredConcentrators: Concentrator[];
projectNames: string[];
loading: boolean;
selectedConcentrator: Concentrator | null;
// ... similar a useMeters
}
export function useConcentrators(): UseConcentratorsReturn
```
---
## Sistema de Autenticacion
### Flujo de Autenticacion
```
┌──────────────┐ ┌─────────────┐ ┌──────────────┐
│ LoginPage │────>│ Validacion │────>│ localStorage│
└──────────────┘ └─────────────┘ └──────────────┘
┌─────────────┐
│ App.tsx │
│ (isAuth) │
└─────────────┘
```
### Almacenamiento de Token
```typescript
const AUTH_KEY = "grh_auth";
interface AuthData {
token: string;
ts: number; // timestamp de login
}
// Guardar
localStorage.setItem(AUTH_KEY, JSON.stringify({ token: "demo", ts: Date.now() }));
// Verificar
const isAuth = Boolean(localStorage.getItem(AUTH_KEY));
// Eliminar (logout)
localStorage.removeItem(AUTH_KEY);
```
### Proteccion de Rutas
```typescript
// App.tsx
if (!isAuth) {
return <LoginPage onSuccess={handleLogin} />;
}
// Si esta autenticado, renderiza la aplicacion
return (
<div className="flex h-screen">
<Sidebar {...props} />
<main>{renderPage()}</main>
</div>
);
```
---
## Gestion de Estado
### Estado Local (useState)
La aplicacion utiliza principalmente `useState` de React para gestion de estado local:
```typescript
// Ejemplo en MeterPage.tsx
const [meters, setMeters] = useState<Meter[]>([]);
const [selectedMeter, setSelectedMeter] = useState<Meter | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false);
const [modalMode, setModalMode] = useState<"add" | "edit">("add");
```
### Estado Persistente (localStorage)
Para datos que deben persistir entre sesiones:
```typescript
// Configuraciones de usuario
const SETTINGS_KEY = "water_project_settings_v1";
interface Settings {
theme: "system" | "light" | "dark";
compactMode: boolean;
}
// Guardar
localStorage.setItem(SETTINGS_KEY, JSON.stringify(settings));
// Cargar
const settings = JSON.parse(localStorage.getItem(SETTINGS_KEY) || "{}");
```
### Flujo de Datos en Modulos
```
┌─────────────┐
│ API Layer │
└──────┬──────┘
┌─────────────┐
│ Custom Hook │ (useMeters, useConcentrators)
└──────┬──────┘
┌─────────────┐
│ Page │ (MeterPage, ConcentratorsPage)
└──────┬──────┘
├────────────────┬────────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ Sidebar │ │ Table │ │ Modal │
└───────────┘ └───────────┘ └───────────┘
```
---
## Sistema de Temas
### Configuracion de Tema
```typescript
type Theme = "system" | "light" | "dark";
const applyTheme = (theme: Theme) => {
if (theme === "system") {
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
document.documentElement.classList.toggle("dark", prefersDark);
} else {
document.documentElement.classList.toggle("dark", theme === "dark");
}
};
```
### Clases CSS con Tailwind
```css
/* Ejemplo de clases con soporte dark mode */
.card {
@apply bg-white dark:bg-gray-800;
@apply text-gray-900 dark:text-white;
@apply border-gray-200 dark:border-gray-700;
}
```
### Modal de Configuracion
```typescript
// SettingsModals.tsx
interface SettingsModalsProps {
open: boolean;
onClose: () => void;
}
// Opciones de tema
const themeOptions = [
{ value: "system", label: "Sistema" },
{ value: "light", label: "Claro" },
{ value: "dark", label: "Oscuro" },
];
```
---
## Guia de Desarrollo
### Agregar una Nueva Pagina
1. **Crear el archivo de pagina**
```typescript
// src/pages/nueva/NuevaPage.tsx
export default function NuevaPage() {
return (
<div className="p-6">
<h1>Nueva Pagina</h1>
</div>
);
}
```
2. **Agregar al Sidebar**
```typescript
// Sidebar.tsx - agregar al menuItems
{
label: "Nueva Pagina",
page: "nueva",
icon: <IconComponent className="w-5 h-5" />,
}
```
3. **Agregar al renderizado en App.tsx**
```typescript
// App.tsx - agregar case en renderPage()
case "nueva":
return <NuevaPage />;
```
### Agregar un Nuevo Endpoint de API
1. **Crear archivo de API**
```typescript
// src/api/nuevo.ts
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
const API_TOKEN = import.meta.env.VITE_API_TOKEN;
export interface NuevoItem {
id: string;
// ... campos
}
export async function fetchNuevos(): Promise<NuevoItem[]> {
const response = await fetch(`${API_BASE_URL}/endpoint`, {
headers: {
Authorization: `Bearer ${API_TOKEN}`,
"Content-Type": "application/json",
},
});
if (!response.ok) throw new Error("Error fetching data");
const data = await response.json();
return data.records.map((r: any) => ({ id: r.id, ...r.fields }));
}
```
2. **Crear hook personalizado (opcional)**
```typescript
// src/pages/nuevo/useNuevo.ts
export function useNuevo() {
const [items, setItems] = useState<NuevoItem[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchNuevos()
.then(setItems)
.finally(() => setLoading(false));
}, []);
return { items, loading };
}
```
### Agregar un Nuevo Componente Reutilizable
```typescript
// src/components/layout/common/NuevoComponente.tsx
interface NuevoComponenteProps {
title: string;
onAction: () => void;
children?: React.ReactNode;
}
export default function NuevoComponente({
title,
onAction,
children,
}: NuevoComponenteProps) {
return (
<div className="bg-white dark:bg-gray-800 rounded-lg shadow p-4">
<h3 className="text-lg font-semibold">{title}</h3>
{children}
<button onClick={onAction}>Accion</button>
</div>
);
}
```
### Convenios de Codigo
1. **Nombres de archivos**: PascalCase para componentes, camelCase para utilidades
2. **Interfaces**: Prefijo descriptivo (ej: `MeterFormData`, `UserSettings`)
3. **Hooks**: Prefijo `use` (ej: `useMeters`, `useAuth`)
4. **Constantes**: UPPER_SNAKE_CASE (ej: `API_BASE_URL`)
5. **CSS**: Utilizar Tailwind CSS, evitar CSS custom
### Testing (Pendiente de Implementacion)
El proyecto actualmente no tiene tests configurados. Para agregar:
```bash
npm install -D vitest @testing-library/react @testing-library/jest-dom
```
```typescript
// vitest.config.ts
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
environment: "jsdom",
globals: true,
},
});
```
---
## Variables de Entorno
| Variable | Descripcion | Requerida |
|----------|-------------|-----------|
| `VITE_API_BASE_URL` | URL base de la API | Si |
| `VITE_API_TOKEN` | Token de autenticacion API | Si |
### Ejemplo .env
```env
VITE_API_BASE_URL=https://api.example.com
VITE_API_TOKEN=your-api-token-here
```
---
## Dependencias Principales
| Paquete | Version | Uso |
|---------|---------|-----|
| react | 18.2.0 | Framework UI |
| react-dom | 18.2.0 | Renderizado DOM |
| typescript | 5.2.2 | Type safety |
| vite | 5.2.0 | Build tool |
| tailwindcss | 4.1.18 | Estilos |
| @mui/material | 7.3.6 | Componentes UI |
| @material-table/core | 6.5.2 | Tablas avanzadas |
| recharts | 3.6.0 | Graficas |
| lucide-react | 0.559.0 | Iconos |
---
## Comandos Utiles
```bash
# Desarrollo
npm run dev
# Build produccion
npm run build
# Preview del build
npm run preview
# Linting
npm run lint
# Type check
npx tsc --noEmit
```
---
## Troubleshooting
### Error: CORS al conectar con API
Verificar que el backend tenga configurados los headers CORS correctos o usar un proxy en desarrollo.
### Error: Module not found
```bash
rm -rf node_modules
npm install
```
### Error: TypeScript type errors
```bash
npx tsc --noEmit
```
Revisar los errores y corregir los tipos.
### La aplicacion no carga
1. Verificar que las variables de entorno estan configuradas
2. Verificar la consola del navegador por errores
3. Verificar que la API esta accesible

385
README.md
View File

@@ -1,30 +1,375 @@
# React + TypeScript + Vite
# Water Project - Sistema de Gestion de Recursos Hidricos (GRH)
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Sistema de gestion y monitoreo de infraestructura hidrica desarrollado con React, TypeScript y Vite.
Currently, two official plugins are available:
## Descripcion General
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
El **Sistema de Gestion de Recursos Hidricos (GRH)** es una aplicacion web frontend disenada para el monitoreo, administracion y control de infraestructura de toma de agua. Permite gestionar medidores, concentradores, proyectos, usuarios y roles a traves de una interfaz moderna y responsiva.
## Expanding the ESLint configuration
### Caracteristicas Principales
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
- **Dashboard interactivo** con KPIs, alertas e historial de actividades
- **Gestion de Medidores (Tomas de Agua)** - CRUD completo con filtros por proyecto
- **Gestion de Concentradores** - Configuracion de gateways LoRa/LoRaWAN
- **Gestion de Proyectos** - Administracion de proyectos de infraestructura
- **Gestion de Usuarios y Roles** - Control de acceso al sistema
- **Tema claro/oscuro** - Personalizacion de la interfaz
- **Diseno responsive** - Compatible con desktop, tablet y movil
- Configure the top-level `parserOptions` property like this:
---
```js
export default {
// other rules...
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: ['./tsconfig.json', './tsconfig.node.json'],
tsconfigRootDir: __dirname,
},
## Stack Tecnologico
### Frontend
| Tecnologia | Version | Proposito |
|------------|---------|-----------|
| React | 18.2.0 | Framework UI |
| TypeScript | 5.2.2 | Type safety |
| Vite | 5.2.0 | Build tool y dev server |
| Tailwind CSS | 4.1.18 | Estilos utility-first |
| Material-UI | 7.3.6 | Componentes UI |
| Recharts | 3.6.0 | Visualizacion de datos |
| Lucide React | 0.559.0 | Iconos SVG |
### Herramientas de Desarrollo
- **ESLint** - Linting de codigo
- **TypeScript ESLint** - Analisis estatico
---
## Instalacion
### Prerrequisitos
- Node.js >= 18.x
- npm >= 9.x o yarn >= 1.22
### Pasos de Instalacion
1. **Clonar el repositorio**
```bash
git clone <url-del-repositorio>
cd water-project
```
2. **Instalar dependencias**
```bash
npm install
```
3. **Configurar variables de entorno**
```bash
cp .env.example .env
```
Editar el archivo `.env`:
```env
VITE_API_BASE_URL=https://tu-api-url.com
VITE_API_TOKEN=tu-token-de-api
```
4. **Iniciar servidor de desarrollo**
```bash
npm run dev
```
La aplicacion estara disponible en `http://localhost:5173`
---
## Scripts Disponibles
| Comando | Descripcion |
|---------|-------------|
| `npm run dev` | Inicia el servidor de desarrollo |
| `npm run build` | Compila TypeScript y genera build de produccion |
| `npm run preview` | Previsualiza el build de produccion |
| `npm run lint` | Ejecuta ESLint en el codigo |
---
## Estructura del Proyecto
```
water-project/
├── public/ # Assets estaticos
│ └── grhWatermark.jpg
├── src/
│ ├── api/ # Capa de comunicacion con API
│ │ ├── me.ts # Endpoints de perfil
│ │ ├── meters.ts # CRUD de medidores
│ │ ├── concentrators.ts # CRUD de concentradores
│ │ └── projects.ts # CRUD de proyectos
│ │
│ ├── components/
│ │ ├── layout/ # Componentes de layout
│ │ │ ├── Sidebar.tsx # Menu lateral
│ │ │ ├── TopMenu.tsx # Barra superior
│ │ │ └── common/ # Componentes reutilizables
│ │ │ ├── ProfileModal.tsx
│ │ │ ├── ConfirmModal.tsx
│ │ │ └── Watermark.tsx
│ │ └── SettingsModals.tsx
│ │
│ ├── pages/ # Paginas principales
│ │ ├── Home.tsx # Dashboard
│ │ ├── LoginPage.tsx # Login
│ │ ├── UsersPage.tsx # Gestion de usuarios
│ │ ├── RolesPage.tsx # Gestion de roles
│ │ ├── projects/
│ │ │ └── ProjectsPage.tsx
│ │ ├── meters/ # Modulo de medidores
│ │ │ ├── MeterPage.tsx
│ │ │ ├── useMeters.ts # Hook personalizado
│ │ │ ├── MetersTable.tsx
│ │ │ ├── MetersModal.tsx
│ │ │ └── MetersSidebar.tsx
│ │ └── concentrators/ # Modulo de concentradores
│ │ ├── ConcentratorsPage.tsx
│ │ ├── useConcentrators.ts
│ │ ├── ConcentratorsTable.tsx
│ │ ├── ConcentratorsModal.tsx
│ │ └── ConcentratorsSidebar.tsx
│ │
│ ├── assets/
│ │ └── images/
│ │
│ ├── App.tsx # Componente raiz
│ ├── main.tsx # Punto de entrada
│ └── index.css # Estilos globales
├── index.html
├── package.json
├── tsconfig.json
├── vite.config.ts
└── .env.example
```
---
## Modulos Funcionales
### 1. Dashboard (Home)
El dashboard principal ofrece:
- Selector de organismos operadores (CESPT TIJUANA, TECATE, MEXICALI)
- Grafico de barras: "Numero de Medidores por Proyecto"
- Tarjetas de acceso rapido: Tomas, Alertas, Mantenimiento, Reportes
- Historial reciente de actividades
- Panel de ultimas alertas
### 2. Gestion de Medidores
Modulo completo para administrar medidores/tomas de agua:
**Funcionalidades:**
- Listado con busqueda y filtros
- Filtrado por proyecto
- Tipos de toma: GENERAL, LORA, LORAWAN, GRANDES
- CRUD completo (Crear, Leer, Actualizar, Eliminar)
**Campos principales:**
- Area, Numero de cuenta, Usuario, Direccion
- Serial del medidor, Nombre, Estado
- Tipo de protocolo, Particion DMA
- Configuracion de dispositivo (Device EUI, AppKey, etc.)
### 3. Gestion de Concentradores
Administracion de concentradores y gateways:
**Funcionalidades:**
- Listado con filtros por proyecto
- Configuracion de Gateway (ID, EUI, Nombre)
- Seleccion de ubicacion de antena (Indoor/Outdoor)
- CRUD completo
### 4. Gestion de Proyectos
Administracion de proyectos de infraestructura:
- Tabla con busqueda integrada
- Estados: ACTIVE/INACTIVE
- Informacion de operador y tiempos
### 5. Gestion de Usuarios
Control de usuarios del sistema:
- Listado de usuarios
- Asignacion de roles
- Estados: ACTIVE/INACTIVE
### 6. Gestion de Roles
Administracion de roles de acceso:
- Roles predefinidos: SUPER_ADMIN, USER
- Descripcion de permisos
---
## API y Comunicacion
### Configuracion
La aplicacion se conecta a una API REST externa. Configurar en `.env`:
```env
VITE_API_BASE_URL=https://tu-api.com
VITE_API_TOKEN=tu-token
```
### Endpoints Principales
| Recurso | Endpoint Base |
|---------|---------------|
| Medidores | `/api/v3/data/.../m4hzpnopjkppaav/records` |
| Concentradores | `/api/v3/data/.../mheif1vdgnyt8x2/records` |
| Proyectos | `/api/v3/data/.../m9882vn3xb31e29/records` |
### Estructura de Respuesta
```typescript
interface ApiResponse<T> {
records: Array<{
id: string;
fields: T;
}>;
next?: string;
prev?: string;
}
```
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
---
## Modelos de Datos
### Meter (Medidor)
```typescript
interface Meter {
id: string;
createdAt: string;
updatedAt: string;
areaName: string;
accountNumber: string | null;
userName: string | null;
userAddress: string | null;
meterSerialNumber: string;
meterName: string;
meterStatus: string;
protocolType: string;
priceNo: string | null;
priceName: string | null;
dmaPartition: string | null;
supplyTypes: string;
deviceId: string;
deviceName: string;
deviceType: string;
usageAnalysisType: string;
installedTime: string;
}
```
### Concentrator
```typescript
interface Concentrator {
id: string;
"Area Name": string;
"Device S/N": string;
"Device Name": string;
"Device Time": string;
"Device Status": string;
"Operator": string;
"Installed Time": string;
"Communication Time": string;
"Instruction Manual": string;
}
```
### Project
```typescript
interface Project {
id: string;
areaName: string;
deviceSN: string;
deviceName: string;
deviceType: string;
deviceStatus: "ACTIVE" | "INACTIVE";
operator: string;
installedTime: string;
communicationTime: string;
}
```
---
## Autenticacion
### Flujo de Login
1. Usuario ingresa credenciales
2. Validacion del checkbox "No soy un robot"
3. Token almacenado en `localStorage` (`grh_auth`)
4. Redireccion al Dashboard
### Almacenamiento
```javascript
// localStorage keys
grh_auth: { token: string, ts: number }
water_project_settings_v1: { theme: string, compactMode: boolean }
```
---
## Configuracion de Temas
El sistema soporta tres modos de tema:
- **Sistema** - Detecta preferencia del OS
- **Claro** - Tema light
- **Oscuro** - Tema dark
Configuracion persistida en `localStorage` bajo `water_project_settings_v1`.
---
## Despliegue
### Build de Produccion
```bash
npm run build
```
Los archivos compilados se generan en la carpeta `dist/`.
### Configuracion de Vite
El servidor de desarrollo esta configurado para:
- Puerto: 5173
- Host: habilitado para acceso remoto
- Hosts permitidos: localhost, 127.0.0.1, dominios personalizados
---
## Contribucion
1. Fork del repositorio
2. Crear rama feature (`git checkout -b feature/nueva-funcionalidad`)
3. Commit de cambios (`git commit -m 'Agregar nueva funcionalidad'`)
4. Push a la rama (`git push origin feature/nueva-funcionalidad`)
5. Crear Pull Request
---
## Licencia
Este proyecto es privado y pertenece a GRH - Gestion de Recursos Hidricos.
---
## Contacto
Para soporte o consultas sobre el sistema, contactar al equipo de desarrollo.