feat: implement route planning dashboard including KPIs, user workload tracking, and route assignment management features

This commit is contained in:
2026-08-29 11:55:03 -04:00
parent a0ea3fea48
commit cd5c57c5ee
41 changed files with 3811 additions and 151 deletions
@@ -7,9 +7,19 @@
(input)="dt.filterGlobal($any($event.target).value, 'contains')"
/>
<div class="actions-right">
<button type="button" class="btn-secondary" (click)="goToOverviewMap()" pTooltip="Ver mapa filtrado por usuario" tooltipPosition="top">
<i class="pi pi-map"></i> Ver mapa
</button>
<button type="button" class="btn-secondary" (click)="downloadCSV()">
<i class="pi pi-download"></i> Descargar CSV
</button>
<button type="button" class="btn-secondary" (click)="reoptimizeLocally()" [disabled]="!canReoptimize" title="Vuelve a ejecutar el optimizador con los archivos cargados">
<span *ngIf="reoptLoading" class="spinner-inline"></span>
<i *ngIf="!reoptLoading" class="pi pi-sync"></i> {{ reoptLoading ? 'Reoptimizando...' : 'Reoptimizar rutas' }}
</button>
<button type="button" class="btn-secondary" *ngIf="hasLocalChanges" (click)="restoreOriginal()">
<i class="pi pi-undo"></i> Deshacer cambios
</button>
<button
type="button"
class="btn-secondary"
@@ -22,6 +32,7 @@
</button>
</div>
</div>
<div class="table-error" *ngIf="reoptError"><i class="pi pi-exclamation-triangle"></i> {{ reoptError }}</div>
<p-table
#dt
@@ -60,20 +71,41 @@
<ng-template pTemplate="body" let-row>
<tr>
<td>{{ row.json.nombre_usuario }}</td>
<td>
<ng-container *ngIf="editingRoute === row; else userValue">
<select class="inline-edit" [(ngModel)]="editUserId">
<option *ngFor="let user of userOptions" [value]="user.id">{{ user.name }}</option>
</select>
</ng-container>
<ng-template #userValue><a class="link-usuario" (click)="goToUserMap(row.json.usuario_id)" pTooltip="Ver todas las rutas de este usuario" tooltipPosition="top">{{ row.json.nombre_usuario }}</a></ng-template>
</td>
<td>{{ row.json.nombre_pdv }}</td>
<td>{{ row.json.hora_laboral_semanal_usuario }}</td>
<td>{{ row.json.hora_minima_semanal_pdv }}</td>
<td>{{ row.json.horas_trabajo }}</td>
<td>{{ row.json.dia }}</td>
<td>
<ng-container *ngIf="editingRoute === row; else dayValue">
<select class="inline-edit" [(ngModel)]="editDay">
<option *ngFor="let day of dayOptions" [value]="day">{{ day }}</option>
</select>
</ng-container>
<ng-template #dayValue>{{ row.json.dia }}</ng-template>
</td>
<td>{{ row.json.distancia }}</td>
<td>{{ row.json.horas_desplazamiento }}</td>
<td class="text-center">
<td class="text-center edit-actions">
<ng-container *ngIf="editingRoute === row; else editButton">
<button type="button" class="btn-icon" (click)="saveEdit()" title="Guardar"><i class="pi pi-check"></i></button>
<button type="button" class="btn-icon" (click)="cancelEdit()" title="Cancelar"><i class="pi pi-times"></i></button>
</ng-container>
<ng-template #editButton>
<button type="button" class="btn-icon" (click)="startEdit(row)" title="Editar asignación"><i class="pi pi-pencil"></i></button>
</ng-template>
<button
type="button"
class="btn-icon"
(click)="onShowMap(row)"
pTooltip="Ver en mapa"
pTooltip="Ver en mapa (1 ruta)"
tooltipPosition="top"
>
<i class="pi pi-map-marker"></i>
@@ -84,7 +116,7 @@
<ng-template pTemplate="emptymessage">
<tr>
<td colspan="9" class="text-center">No hay rutas asignadas</td>
<td colspan="9" class="text-center">No hay rutas asignadas</td>
</tr>
</ng-template>
</p-table>