Files
rutero/route-planner/src/app/private/home/home.component.html
T

114 lines
6.0 KiB
HTML

<div class="glm-topbar">
<img src="GLM_completo.png" alt="GomezLee Marketing" class="glm-topbar-logo" />
<span class="glm-topbar-sep">|</span>
<span class="glm-topbar-context">Route Planner</span><div class="user-profile" *ngIf="profile.current"><img *ngIf="profile.avatarUrl" [src]="profile.avatarUrl" alt=""><span *ngIf="!profile.avatarUrl" class="avatar-fallback">{{ profile.current.nombre.charAt(0) }}</span><span>{{ profile.current.nombre }}</span></div><div class="projects-link"><button type="button" (click)="signOut()"><i class="pi pi-sign-out"></i> Salir</button></div>
</div>
<div class="home-container">
<a class="employees-link home-employees-link" routerLink="/empleados"><i class="pi pi-users"></i> Gestionar empleados</a>
<header class="home-header">
<div class="project-heading"><div class="project-title-line"><a class="back-projects" routerLink="/home"><i class="pi pi-arrow-left"></i> Mis proyectos</a><h1 *ngIf="!editingProject">{{ projectName || 'Proyecto' }}</h1><input *ngIf="editingProject" [(ngModel)]="projectName" maxlength="120"><button *ngIf="!editingProject" type="button" class="edit-project" (click)="startProjectEdit()"><i class="pi pi-pencil"></i> Editar proyecto</button><div *ngIf="editingProject" class="project-edit-actions"><button type="button" (click)="saveProject()" [disabled]="projectSaving">Guardar</button><button type="button" (click)="cancelProjectEdit()" [disabled]="projectSaving">Cancelar</button></div></div><textarea *ngIf="editingProject" [(ngModel)]="projectDescription" maxlength="500" placeholder="Descripción del proyecto"></textarea><p *ngIf="!editingProject">Gestión de rutas asignadas y puntos de venta pendientes</p></div>
</header>
<section class="card upload-card">
<h2 class="section-title">PDVs del proyecto</h2>
<p class="employees-summary" [class.empty]="!employeesLoading && !activeEmployees"><i class="pi pi-users"></i> <span *ngIf="employeesLoading">Cargando empleados activos...</span><span *ngIf="!employeesLoading">{{ activeEmployees }} empleados activos de {{ projectCountry }} se usarán para planificar.</span></p>
<div class="upload-grid">
<div class="file-input-wrapper">
<label class="file-label" for="pdvFile" [class.has-error]="pdvPreview && !pdvPreview.valid" [class.has-success]="pdvPreview?.valid">
<i class="pi pi-file-excel"></i>
<span>Archivo PDVs guardado</span>
<span class="file-hint">Los PDVs pertenecen a este proyecto</span>
</label>
<input
id="pdvFile"
type="file"
accept=".xlsx,.xls"
disabled
class="file-input"
[class.has-file]="pdvFile"
/>
<div class="file-name" *ngIf="pdvFile">
<i class="pi" [class.pi-check-circle]="pdvPreview?.valid" [class.pi-exclamation-circle]="pdvPreview && !pdvPreview.valid" [class.pi-spin]="pdvPreviewLoading"></i>
{{ pdvFile.name }}
<span *ngIf="pdvPreviewLoading" class="preview-loading">Validando...</span>
</div>
<div class="preview-card" *ngIf="pdvPreviewLoading">
<div class="preview-loading-row"><span class="spinner-inline"></span> Analizando archivo PDV...</div>
</div>
<div class="preview-card preview-success" *ngIf="pdvPreview?.valid">
<div class="preview-header"><i class="pi pi-check-circle"></i> PDV válido — {{ pdvPreview!.totalRows }} filas</div>
<div class="preview-stats">{{ pdvPreview!.validRows }} filas válidas • Columnas: {{ pdvPreview!.headers.join(', ') }}</div>
</div>
<div class="preview-card preview-error" *ngIf="pdvPreview && !pdvPreview.valid">
<div class="preview-header"><i class="pi pi-exclamation-triangle"></i> Errores en PDV ({{ pdvPreview.errors.length }})</div>
<div class="preview-stats" *ngIf="pdvPreview.missingHeaders.length">Faltan: {{ pdvPreview.missingHeaders.join(', ') }}</div>
<div class="preview-stats">{{ pdvPreview.totalRows }} filas leídas • {{ pdvPreview.validRows }} válidas</div>
<ul class="preview-errors">
<li *ngFor="let e of pdvPreview.errors.slice(0, 8)">
<strong>Fila {{ e.row }} — {{ e.field }}:</strong> {{ e.message }}
<span *ngIf="e.value !== undefined && e.value !== null" class="error-value">({{ e.value }})</span>
</li>
<li *ngIf="pdvPreview.errors.length > 8" class="more-errors">+ {{ pdvPreview.errors.length - 8 }} errores más...</li>
</ul>
</div>
</div>
</div>
<div class="upload-actions">
<div class="upload-error" *ngIf="uploadError">
<i class="pi pi-exclamation-triangle"></i>
{{ uploadError }}
</div>
<div class="actions-row">
<button
type="button"
class="btn-primary"
(click)="cargarRutas()"
[disabled]="!canSubmit"
[title]="submitDisabledReason || ''"
>
<span *ngIf="isLoading" class="spinner-inline"></span>
<i *ngIf="!isLoading" class="pi pi-upload"></i>
{{ isLoading ? 'Procesando...' : 'Cargar rutas' }}
</button>
<button
type="button"
class="btn-secondary"
*ngIf="isLoading"
(click)="cancelarCarga()"
>
<i class="pi pi-times"></i> Cancelar
</button>
<button
type="button"
class="btn-secondary"
(click)="clearFiles()"
[disabled]="!pdvFile"
>
<i class="pi pi-times"></i> Limpiar
</button>
</div>
<small class="hint-text" *ngIf="submitDisabledReason && !isLoading">{{ submitDisabledReason }}</small>
</div>
</section>
<section class="card kpis-card">
<app-planning-kpis></app-planning-kpis>
</section>
<section class="card">
<app-assigned-route></app-assigned-route>
</section>
<section class="card">
<h2 class="section-title">PDVs sin ruta asignada</h2>
<app-no-assigned-route></app-no-assigned-route>
</section>
</div>