line-gestao-frontend/src/app/pages/mureg/mureg.html

470 lines
19 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<div class="toast-container position-fixed top-0 end-0 p-3" style="z-index: 10000;">
<div #successToast class="toast text-bg-success border-0 shadow" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header border-bottom-0">
<strong class="me-auto text-primary">LineGestão</strong>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Fechar"></button>
</div>
<div class="toast-body bg-white rounded-bottom text-dark">
{{ toastMessage }}
</div>
</div>
</div>
<section class="mureg-page">
<span class="page-blob blob-1" aria-hidden="true"></span>
<span class="page-blob blob-2" aria-hidden="true"></span>
<span class="page-blob blob-3" aria-hidden="true"></span>
<span class="page-blob blob-4" aria-hidden="true"></span>
<div class="container-mureg">
<div class="mureg-card" data-animate>
<div class="mureg-header">
<div class="header-row-top">
<div class="title-badge" data-animate>
<i class="bi bi-table"></i> MUREG
</div>
<div class="header-title" data-animate>
<h5 class="title mb-0">MUREG</h5>
<small class="subtitle">Gestão de registros MUREG</small>
</div>
<div class="header-actions d-flex gap-2 justify-content-end" data-animate>
<button type="button" class="btn btn-brand btn-sm" (click)="onCreate()" [disabled]="loading">
<i class="bi bi-plus-circle me-1"></i> Nova Mureg
</button>
</div>
</div>
<div class="mureg-kpis mt-4 animate-fade-in">
<div class="kpi">
<span class="lbl">Clientes</span>
<span class="val">
<span *ngIf="loading" class="spinner-border spinner-border-sm text-muted"></span>
<span *ngIf="!loading">{{ total || 0 }}</span>
</span>
</div>
<div class="kpi">
<span class="lbl">Registros</span>
<span class="val">
<span *ngIf="loading" class="spinner-border spinner-border-sm text-muted"></span>
<span *ngIf="!loading">{{ groupLoadedRecords || 0 }}</span>
</span>
</div>
<div class="kpi">
<span class="lbl text-brand">Trocas</span>
<span class="val text-brand">
<span *ngIf="loading" class="spinner-border spinner-border-sm text-muted"></span>
<span *ngIf="!loading">{{ groupTotalTrocas || 0 }}</span>
</span>
</div>
<div class="kpi">
<span class="lbl text-success">ICCID</span>
<span class="val text-success">
<span *ngIf="loading" class="spinner-border spinner-border-sm text-muted"></span>
<span *ngIf="!loading">{{ groupTotalIccids || 0 }}</span>
</span>
</div>
</div>
<div class="controls mt-3 mb-2" data-animate>
<div class="input-group input-group-sm search-group">
<span class="input-group-text">
<i class="bi" [class.bi-search]="!loading" [class.bi-hourglass-split]="loading" [class.text-brand]="loading"></i>
</span>
<input class="form-control" placeholder="Pesquisar..." [(ngModel)]="searchTerm" (ngModelChange)="onSearch()" />
<button class="btn btn-outline-secondary btn-clear" type="button" (click)="clearSearch()" *ngIf="searchTerm">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="page-size d-flex align-items-center gap-2">
<span class="text-muted small fw-bold text-uppercase" style="letter-spacing: 0.5px; font-size: 0.75rem;">
Itens por pág:
</span>
<div class="select-wrapper">
<select
class="form-select form-select-sm select-glass"
[(ngModel)]="pageSize"
(change)="onPageSizeChange()"
[disabled]="loading"
>
<option [ngValue]="10">10</option>
<option [ngValue]="20">20</option>
<option [ngValue]="50">50</option>
<option [ngValue]="100">100</option>
</select>
<i class="bi bi-chevron-down select-icon"></i>
</div>
</div>
</div>
</div>
<div class="mureg-body">
<div class="groups-container">
<div class="text-center p-5" *ngIf="loading">
<span class="spinner-border text-brand"></span>
</div>
<div class="empty-group" *ngIf="!loading && pagedClientGroups.length === 0">
Nenhum dado encontrado.
</div>
<div class="group-list" *ngIf="!loading">
<div
*ngFor="let g of pagedClientGroups"
class="client-group-card"
[class.expanded]="expandedGroup === g.cliente"
>
<div class="group-header" (click)="toggleGroup(g.cliente)">
<div class="group-info">
<h6 class="mb-0 fw-bold text-dark td-clip" [title]="g.cliente">{{ g.cliente }}</h6>
<div class="group-badges">
<span class="badge-pill total">{{ g.total }} Registros</span>
<span class="badge-pill swap" *ngIf="g.trocas > 0">{{ g.trocas }} Trocas</span>
<span class="badge-pill ok" *ngIf="g.comIccid > 0">{{ g.comIccid }} ICCID</span>
<span class="badge-pill warn" *ngIf="g.semIccid > 0">{{ g.semIccid }} Sem ICCID</span>
</div>
</div>
<div class="group-toggle-icon">
<i class="bi bi-chevron-down"></i>
</div>
</div>
<div class="group-body" *ngIf="expandedGroup === g.cliente">
<div class="d-flex justify-content-between align-items-center px-4 py-2 border-bottom bg-white">
<small class="text-muted fw-bold">Registros do Cliente</small>
<span class="chip-muted">
<i class="bi bi-info-circle me-1"></i> Use o botão à direita para editar
</span>
</div>
<div class="table-wrap inner-table-wrap">
<table class="table table-modern align-middle text-center mb-0">
<thead>
<tr>
<th>ITEM</th>
<th>LINHA ANTIGA</th>
<th>LINHA NOVA</th>
<th>ICCID</th>
<th>DATA MUREG</th>
<th>SITUAÇÃO</th>
<th style="min-width: 80px;">AÇÕES</th>
</tr>
</thead>
<tbody>
<tr *ngIf="groupRows.length === 0">
<td colspan="7" class="text-center py-4 empty-state text-muted fw-bold">
Nenhum registro.
</td>
</tr>
<tr *ngFor="let r of groupRows; trackBy: trackById" class="table-row-item">
<td class="text-muted fw-bold">{{ r.item || '-' }}</td>
<td class="text-dark">{{ r.linhaAntiga || '-' }}</td>
<td class="fw-black text-blue">{{ r.linhaNova || '-' }}</td>
<td class="small font-monospace">{{ r.iccid || '-' }}</td>
<td class="text-muted small fw-bold">{{ displayValue('dataDaMureg', r.dataDaMureg) }}</td>
<td>
<span class="status-pill" [class.is-swap]="isTroca(r)" [class.is-same]="!isTroca(r)">
{{ isTroca(r) ? 'TROCA' : 'SEM TROCA' }}
</span>
</td>
<td>
<div class="action-group justify-content-center">
<button class="btn-icon primary" (click)="onEditar(r)" title="Editar Registro">
<i class="bi bi-pencil-square"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="mureg-footer">
<div class="small text-muted fw-bold">Mostrando {{ pageStart }}{{ pageEnd }} de {{ total }} Clientes</div>
<nav>
<ul class="pagination pagination-sm mb-0 pagination-modern">
<li class="page-item" [class.disabled]="page === 1 || loading">
<button class="page-link" (click)="goToPage(page - 1)">Anterior</button>
</li>
<li class="page-item" *ngFor="let p of pageNumbers" [class.active]="p === page">
<button class="page-link" (click)="goToPage(p)">{{ p }}</button>
</li>
<li class="page-item" [class.disabled]="page === totalPages || loading">
<button class="page-link" (click)="goToPage(page + 1)">Próxima</button>
</li>
</ul>
</nav>
</div>
</div>
</div>
</section>
<div class="modal-backdrop-custom" *ngIf="editOpen || createOpen" (click)="closeEdit(); closeCreate()"></div>
<!-- ============================== -->
<!-- EDIT MODAL -->
<!-- ============================== -->
<div class="modal-custom" *ngIf="editOpen">
<div class="modal-card modal-lg" (click)="$event.stopPropagation()">
<div class="modal-header">
<div class="modal-title">
<span class="icon-bg primary-soft"><i class="bi bi-pencil-square"></i></span>
Editar Registro Mureg
</div>
<div class="d-flex align-items-center gap-2">
<button class="btn btn-glass btn-sm" (click)="closeEdit()" [disabled]="editSaving">
<i class="bi bi-x-lg me-1"></i> Cancelar
</button>
<button class="btn btn-brand btn-sm" (click)="saveEdit()" [disabled]="!editModel || editSaving">
<span *ngIf="!editSaving"><i class="bi bi-check2-circle me-1"></i> Salvar</span>
<span *ngIf="editSaving"><span class="spinner-border spinner-border-sm me-2"></span> Salvando...</span>
</button>
</div>
</div>
<div class="modal-body modern-body bg-light-gray">
<ng-container *ngIf="editModel; else editLoadingTpl">
<div class="details-dashboard">
<div class="detail-box w-100">
<div class="box-header">
<span><i class="bi bi-card-text me-2"></i> Informações</span>
</div>
<div class="box-body">
<div class="form-grid">
<!-- Cliente (select) -->
<div class="form-field span-2">
<label>Cliente (GERAL)</label>
<select
class="form-control form-control-sm"
[(ngModel)]="editModel.selectedClient"
(change)="onEditClientChange()"
>
<option value="">Selecione...</option>
<option *ngFor="let c of clientOptions" [value]="c">{{ c }}</option>
</select>
<small class="text-muted fw-bold" *ngIf="editClientsLoading">
<span class="spinner-border spinner-border-sm me-2"></span>Carregando clientes...
</small>
</div>
<!-- Linha Antiga (select da Geral) -->
<div class="form-field span-2">
<label>Linha Antiga (GERAL)</label>
<select
class="form-control form-control-sm"
[(ngModel)]="editModel.mobileLineId"
(change)="onEditLineChange()"
[disabled]="!editModel.selectedClient || editLinesLoading"
>
<option value="">Selecione a linha do cliente...</option>
<!-- ✅ ITEM • LINHA • USUÁRIO -->
<option *ngFor="let l of lineOptionsEdit" [value]="l.id">
{{ l.item }} • {{ l.linha || '-' }} • {{ l.usuario || 'SEM USUÁRIO' }}
</option>
</select>
<small class="text-muted fw-bold" *ngIf="editLinesLoading">
<span class="spinner-border spinner-border-sm me-2"></span>Carregando linhas...
</small>
</div>
<div class="form-field">
<label>Item</label>
<input class="form-control form-control-sm" [(ngModel)]="editModel.item" />
</div>
<div class="form-field">
<label>Data Mureg</label>
<input class="form-control form-control-sm" type="date" [(ngModel)]="editModel.dataDaMureg" />
</div>
<!-- LinhaAntiga (snapshot) - preenchido automaticamente -->
<div class="form-field">
<label>Linha Antiga (snapshot)</label>
<input class="form-control form-control-sm" [(ngModel)]="editModel.linhaAntiga" readonly />
</div>
<div class="form-field">
<label>Linha Nova</label>
<input class="form-control form-control-sm fw-bold text-blue" [(ngModel)]="editModel.linhaNova" />
</div>
<!-- ICCID auto do GERAL -->
<div class="form-field span-2">
<label>ICCID (auto)</label>
<input class="form-control form-control-sm font-monospace" [(ngModel)]="editModel.iccid" readonly />
</div>
</div>
<div class="mt-3" *ngIf="editModel?.clienteInfo">
<small class="text-muted fw-bold">
<i class="bi bi-info-circle me-1"></i>
{{ editModel.clienteInfo }}
</small>
</div>
</div>
</div>
</div>
</ng-container>
<ng-template #editLoadingTpl>
<div class="p-5 text-center text-muted">
<span class="spinner-border me-2"></span> Preparando edição...
</div>
</ng-template>
</div>
</div>
</div>
<!-- ============================== -->
<!-- CREATE MODAL -->
<!-- ============================== -->
<div class="modal-custom" *ngIf="createOpen">
<div class="modal-card modal-lg" (click)="$event.stopPropagation()">
<div class="modal-header">
<div class="modal-title">
<span class="icon-bg brand-soft"><i class="bi bi-plus-lg"></i></span>
Nova Mureg
</div>
<div class="d-flex align-items-center gap-2">
<button class="btn btn-glass btn-sm" (click)="closeCreate()" [disabled]="createSaving">
<i class="bi bi-x-lg me-1"></i> Cancelar
</button>
<button class="btn btn-brand btn-sm" (click)="saveCreate()" [disabled]="createSaving">
<span *ngIf="!createSaving"><i class="bi bi-check2-circle me-1"></i> Criar</span>
<span *ngIf="createSaving"><span class="spinner-border spinner-border-sm me-2"></span> Salvando...</span>
</button>
</div>
</div>
<div class="modal-body modern-body bg-light-gray">
<div class="details-dashboard">
<div class="detail-box w-100">
<div class="box-header">
<span><i class="bi bi-pencil me-2"></i> Preencha os dados</span>
</div>
<div class="box-body">
<div class="form-grid">
<!-- Cliente (select) -->
<div class="form-field span-2">
<label>Cliente (GERAL) <span class="text-danger">*</span></label>
<select
class="form-control form-control-sm"
[(ngModel)]="createModel.selectedClient"
(change)="onCreateClientChange()"
>
<option value="">Selecione...</option>
<option *ngFor="let c of clientOptions" [value]="c">{{ c }}</option>
</select>
<small class="text-muted fw-bold" *ngIf="createClientsLoading">
<span class="spinner-border spinner-border-sm me-2"></span>Carregando clientes...
</small>
</div>
<!-- Linha Antiga (select Geral) -->
<div class="form-field span-2">
<label>Linha Antiga (GERAL) <span class="text-danger">*</span></label>
<select
class="form-control form-control-sm"
[(ngModel)]="createModel.mobileLineId"
(change)="onCreateLineChange()"
[disabled]="!createModel.selectedClient || createLinesLoading"
>
<option value="">Selecione a linha do cliente...</option>
<!-- ✅ ITEM • LINHA • USUÁRIO -->
<option *ngFor="let l of lineOptionsCreate" [value]="l.id">
{{ l.item }} • {{ l.linha || '-' }} • {{ l.usuario || 'SEM USUÁRIO' }}
</option>
</select>
<small class="text-muted fw-bold" *ngIf="createLinesLoading">
<span class="spinner-border spinner-border-sm me-2"></span>Carregando linhas...
</small>
</div>
<div class="form-field">
<label>Item</label>
<input class="form-control form-control-sm" [(ngModel)]="createModel.item" />
</div>
<div class="form-field">
<label>Data Mureg</label>
<input class="form-control form-control-sm" type="date" [(ngModel)]="createModel.dataDaMureg" />
</div>
<!-- snapshot -->
<div class="form-field">
<label>Linha Antiga (snapshot)</label>
<input class="form-control form-control-sm" [(ngModel)]="createModel.linhaAntiga" readonly />
</div>
<div class="form-field">
<label>Linha Nova <span class="text-danger">*</span></label>
<input class="form-control form-control-sm fw-bold text-blue" [(ngModel)]="createModel.linhaNova" />
</div>
<!-- ICCID auto do GERAL -->
<div class="form-field span-2">
<label>ICCID (auto)</label>
<input class="form-control form-control-sm font-monospace" [(ngModel)]="createModel.iccid" readonly />
</div>
</div>
<div class="mt-3" *ngIf="createModel?.clienteInfo">
<small class="text-muted fw-bold">
<i class="bi bi-info-circle me-1"></i>
{{ createModel.clienteInfo }}
</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>