line-gestao-frontend/src/app/pages/chips-controle-recebidos/chips-controle-recebidos.html

486 lines
21 KiB
HTML

<div class="toast-container position-fixed top-0 end-0 p-3" style="z-index: 12000;">
<div
class="toast border-0 shadow"
[class.show]="toastOpen"
[class.text-bg-success]="toastType === 'success'"
[class.text-bg-danger]="toastType === 'danger'"
>
<div class="toast-header border-bottom-0">
<strong class="me-auto">LineGestao</strong>
<button type="button" class="btn-close" (click)="toastOpen = false"></button>
</div>
<div class="toast-body bg-white rounded-bottom text-dark fw-bold">{{ toastMessage }}</div>
</div>
</div>
<section class="chips-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-chips">
<div class="chips-card">
<!-- HEADER -->
<div class="chips-header">
<div class="header-row-top">
<div class="title-badge">
<i class="bi bi-inboxes"></i> Gestão de Chips
</div>
<div class="header-title">
<h5 class="title mb-0">Chips Virgens e Recebidos</h5>
<small class="subtitle">Importação e acompanhamento</small>
</div>
<div class="header-actions"></div>
</div>
<div class="tab-row">
<button type="button" class="tab-btn" [class.active]="activeTab === 'chips'" (click)="setTab('chips')">
<i class="bi bi-sim"></i> Chips Virgens
</button>
<button type="button" class="tab-btn" [class.active]="activeTab === 'controle'" (click)="setTab('controle')">
<i class="bi bi-clipboard-data"></i> Controle Recebidos
</button>
</div>
<div class="filters-row" *ngIf="activeTab === 'controle'">
<div class="filter-item">
<app-select
class="select-glass"
size="sm"
[options]="anoOptions"
labelKey="label"
valueKey="value"
[(ngModel)]="controleAno"
(ngModelChange)="onControleAnoChange()"
></app-select>
</div>
<div class="filter-tabs">
<button type="button" class="filter-tab" [class.active]="controleResumo === ''" (click)="setControleResumo('')">Todos</button>
<button type="button" class="filter-tab" [class.active]="controleResumo === 'false'" (click)="setControleResumo('false')">Detalhado</button>
<button type="button" class="filter-tab" [class.active]="controleResumo === 'true'" (click)="setControleResumo('true')">Resumo</button>
</div>
</div>
<div class="controls">
<div class="input-group input-group-sm search-group">
<span class="input-group-text">
<i
class="bi"
[class.bi-search]="!chipsLoading && !controleLoading"
[class.bi-hourglass-split]="chipsLoading || controleLoading"
[class.text-brand]="chipsLoading || controleLoading"
></i>
</span>
<input
*ngIf="activeTab === 'chips'"
class="form-control"
placeholder="Pesquisar Chips..."
[(ngModel)]="chipsSearch"
(ngModelChange)="onChipsSearch()"
/>
<input
*ngIf="activeTab === 'controle'"
class="form-control"
placeholder="Pesquisar Controle..."
[(ngModel)]="controleSearch"
(ngModelChange)="onControleSearch()"
/>
<button
class="btn btn-outline-secondary btn-clear"
type="button"
(click)="activeTab === 'chips' ? clearChipsSearch() : clearControleSearch()"
*ngIf="chipsSearch || controleSearch"
>
<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">
<app-select
*ngIf="activeTab === 'chips'"
class="select-glass"
size="sm"
[options]="pageSizeOptions"
[(ngModel)]="chipsPageSize"
(ngModelChange)="onChipsPageSizeChange()"
[disabled]="chipsLoading"
></app-select>
<app-select
*ngIf="activeTab === 'controle'"
class="select-glass"
size="sm"
[options]="pageSizeOptions"
[(ngModel)]="controlePageSize"
(ngModelChange)="onControlePageSizeChange()"
[disabled]="controleLoading"
></app-select>
</div>
</div>
</div>
</div>
<!-- BODY (scroll interno do card) -->
<div class="chips-body">
<!-- CHIPS -->
<ng-container *ngIf="activeTab === 'chips'">
<div class="content-scroll groups-container">
<div class="text-center p-5" *ngIf="chipsLoading">
<span class="spinner-border text-brand"></span>
</div>
<div class="empty-group" *ngIf="!chipsLoading && chipsGroups.length === 0">
Nenhum registro encontrado.
</div>
<div class="group-list" *ngIf="!chipsLoading">
<div
*ngFor="let g of pagedChipsGroups"
class="group-card"
[class.expanded]="expandedGroupObservacao === g.observacao"
>
<div class="group-header" (click)="toggleGroup(g.observacao)">
<div class="group-info">
<h6 class="group-title">{{ g.observacao }}</h6>
<div class="group-badges">
<span class="badge-pill">{{ g.total }} Registros</span>
</div>
</div>
<div class="group-toggle-icon">
<i class="bi bi-chevron-down"></i>
</div>
</div>
<div class="group-body-content" *ngIf="expandedGroupObservacao === g.observacao">
<div class="table-wrap inner-table-wrap">
<table class="table table-modern align-middle text-center mb-0">
<thead>
<tr>
<th>ITEM</th>
<th>NÚMERO DO CHIP</th>
<th>OBSERVAÇÕES</th>
<th>AÇÕES</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let r of g.items">
<td class="text-muted fw-bold">{{ r.item }}</td>
<td class="font-monospace text-brand">{{ display(r.numeroDoChip) }}</td>
<td class="text-start td-clip" [title]="display(r.observacoes)">{{ display(r.observacoes) }}</td>
<td>
<div class="action-group justify-content-center">
<button class="btn-icon info" (click)="openChipDetail(r); $event.stopPropagation()" title="Detalhes">
<i class="bi bi-eye"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="table-pagination" *ngIf="!chipsLoading && chipsGroups.length > 0">
<div class="page-info">
Mostrando {{ activePageStart }} a {{ activePageEnd }} de {{ activeTotal }} grupos
</div>
<nav>
<ul class="pagination pagination-sm mb-0 pagination-modern">
<li class="page-item" [class.disabled]="activePage === 1">
<button class="page-link" (click)="goToPage(activePage - 1)">Anterior</button>
</li>
<li class="page-item" *ngFor="let p of activePageNumbers" [class.active]="p === activePage">
<button class="page-link" (click)="goToPage(p)">{{ p }}</button>
</li>
<li class="page-item" [class.disabled]="activePage === activeTotalPages">
<button class="page-link" (click)="goToPage(activePage + 1)">Próxima</button>
</li>
</ul>
</nav>
</div>
</div>
</ng-container>
<!-- CONTROLE -->
<ng-container *ngIf="activeTab === 'controle'">
<div class="content-scroll">
<div class="text-center p-5" *ngIf="controleLoading">
<span class="spinner-border text-brand"></span>
</div>
<div class="empty-group" *ngIf="!controleLoading && controleGroups.length === 0">
Nenhum registro encontrado.
</div>
<div class="group-list" *ngIf="!controleLoading">
<div
*ngFor="let g of pagedControleGroups"
class="group-card"
[class.expanded]="expandedControleConteudo === g.conteudo"
>
<div class="group-header" (click)="toggleControleGroup(g.conteudo)">
<div class="group-info">
<h6 class="group-title">{{ g.conteudo }}</h6>
<div class="group-badges">
<span class="badge-pill">{{ g.total }} Registros</span>
</div>
</div>
<div class="group-toggle-icon">
<i class="bi bi-chevron-down"></i>
</div>
</div>
<div class="group-body-content" *ngIf="expandedControleConteudo === g.conteudo">
<div class="table-wrap inner-table-wrap">
<ng-container *ngIf="getResumoItems(g.items) as resumoItems">
<div class="table-section" *ngIf="resumoItems.length > 0">
<div class="section-label">Resumo</div>
<table class="table table-modern align-middle text-center mb-0">
<thead>
<tr>
<th>ANO</th>
<th>NOTA FISCAL</th>
<th>DATA DA NF</th>
<th>QTD.</th>
<th>CONTEÚDO DA NF</th>
<th>DATA DO RECEBIMENTO</th>
<th>AÇÕES</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let r of resumoItems">
<td class="text-muted fw-bold">{{ display(r.ano) }}</td>
<td>{{ display(r.notaFiscal) }}</td>
<td>{{ formatDate(r.dataDaNf) }}</td>
<td class="fw-bold">{{ display(r.quantidade) }}</td>
<td class="text-start td-clip" [title]="display(r.conteudoDaNf)">{{ display(r.conteudoDaNf) }}</td>
<td>{{ formatDate(r.dataDoRecebimento) }}</td>
<td>
<div class="action-group justify-content-center">
<button class="btn-icon info" (click)="openControleDetail(r); $event.stopPropagation()" title="Detalhes">
<i class="bi bi-eye"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</ng-container>
<ng-container *ngIf="getDetalheItems(g.items) as detalheItems">
<div class="table-section" *ngIf="detalheItems.length > 0">
<div class="section-label">Detalhe</div>
<table class="table table-modern align-middle text-center mb-0">
<thead>
<tr>
<th>ANO</th>
<th>NOTA FISCAL</th>
<th>CHIP</th>
<th>SERIAL</th>
<th>NÚMERO DA LINHA</th>
<th>VALOR UNIT.</th>
<th>VALOR DA NF</th>
<th>AÇÕES</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let r of detalheItems">
<td class="text-muted fw-bold">{{ display(r.ano) }}</td>
<td>{{ display(r.notaFiscal) }}</td>
<td class="font-monospace">{{ display(r.chip) }}</td>
<td class="font-monospace">{{ display(r.serial) }}</td>
<td class="font-monospace">{{ display(r.numeroDaLinha) }}</td>
<td class="text-end fw-bold">{{ formatMoney(r.valorUnit) }}</td>
<td class="text-end fw-bold">{{ formatMoney(r.valorDaNf) }}</td>
<td>
<div class="action-group justify-content-center">
<button class="btn-icon info" (click)="openControleDetail(r); $event.stopPropagation()" title="Detalhes">
<i class="bi bi-eye"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</ng-container>
</div>
</div>
</div>
</div>
<div class="table-pagination" *ngIf="!controleLoading && controleGroups.length > 0">
<div class="page-info">
Mostrando {{ activePageStart }} a {{ activePageEnd }} de {{ activeTotal }} grupos
</div>
<nav>
<ul class="pagination pagination-sm mb-0 pagination-modern">
<li class="page-item" [class.disabled]="activePage === 1">
<button class="page-link" (click)="goToPage(activePage - 1)">Anterior</button>
</li>
<li class="page-item" *ngFor="let p of activePageNumbers" [class.active]="p === activePage">
<button class="page-link" (click)="goToPage(p)">{{ p }}</button>
</li>
<li class="page-item" [class.disabled]="activePage === activeTotalPages">
<button class="page-link" (click)="goToPage(activePage + 1)">Próxima</button>
</li>
</ul>
</nav>
</div>
</div>
</ng-container>
</div>
</div>
</div>
</section>
<div class="modal-backdrop-custom" *ngIf="chipDetailOpen || controleDetailOpen" (click)="closeChipDetail(); closeControleDetail()"></div>
<!-- MODAL CHIP -->
<div class="modal-custom" *ngIf="chipDetailOpen">
<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-sim"></i></span>
Detalhes do Chip
</div>
<button class="btn btn-sm btn-icon" (click)="closeChipDetail()"><i class="bi bi-x-lg"></i></button>
</div>
<div class="modal-body modern-body bg-light-gray">
<div class="p-5 text-center text-muted" *ngIf="chipDetailLoading">
<span class="spinner-border me-2"></span> Carregando detalhes...
</div>
<div class="details-dashboard" *ngIf="!chipDetailLoading && chipDetailData">
<div class="detail-box w-100">
<div class="box-header justify-content-center">
<span><i class="bi bi-card-text me-2"></i> Informações do Chip</span>
</div>
<div class="box-body">
<div class="info-grid">
<div class="info-item">
<span class="lbl">Item</span>
<span class="val">{{ display(chipDetailData.item) }}</span>
</div>
<div class="info-item span-2">
<span class="lbl">Número do Chip</span>
<span class="val text-brand font-monospace">{{ display(chipDetailData.numeroDoChip) }}</span>
</div>
<div class="info-item span-2">
<span class="lbl">Observações</span>
<span class="val">{{ display(chipDetailData.observacoes) }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- MODAL CONTROLE -->
<div class="modal-custom" *ngIf="controleDetailOpen">
<div class="modal-card modal-xl-custom" (click)="$event.stopPropagation()">
<div class="modal-header">
<div class="modal-title">
<span class="icon-bg primary-soft"><i class="bi bi-clipboard-data"></i></span>
Detalhes do Recebimento
</div>
<button class="btn btn-sm btn-icon" (click)="closeControleDetail()"><i class="bi bi-x-lg"></i></button>
</div>
<div class="modal-body modern-body bg-light-gray">
<div class="p-5 text-center text-muted" *ngIf="controleDetailLoading">
<span class="spinner-border me-2"></span> Carregando detalhes...
</div>
<div class="details-dashboard" *ngIf="!controleDetailLoading && controleDetailData">
<div class="detail-box w-100">
<div class="box-header justify-content-center">
<span><i class="bi bi-card-text me-2"></i> Informações da NF</span>
</div>
<div class="box-body">
<div class="info-grid">
<div class="info-item">
<span class="lbl">Ano</span>
<span class="val">{{ display(controleDetailData.ano) }}</span>
</div>
<div class="info-item">
<span class="lbl">Item</span>
<span class="val">{{ display(controleDetailData.item) }}</span>
</div>
<div class="info-item span-2">
<span class="lbl">Nota Fiscal</span>
<span class="val">{{ display(controleDetailData.notaFiscal) }}</span>
</div>
<div class="info-item span-2">
<span class="lbl">Chip</span>
<span class="val font-monospace">{{ display(controleDetailData.chip) }}</span>
</div>
<div class="info-item span-2">
<span class="lbl">Serial</span>
<span class="val font-monospace">{{ display(controleDetailData.serial) }}</span>
</div>
<div class="info-item span-2">
<span class="lbl">Conteúdo da NF</span>
<span class="val">{{ display(controleDetailData.conteudoDaNf) }}</span>
</div>
<div class="info-item">
<span class="lbl">Número da Linha</span>
<span class="val font-monospace">{{ display(controleDetailData.numeroDaLinha) }}</span>
</div>
<div class="info-item">
<span class="lbl">Quantidade</span>
<span class="val">{{ display(controleDetailData.quantidade) }}</span>
</div>
<div class="info-item">
<span class="lbl">Valor Unit</span>
<span class="val">{{ formatMoney(controleDetailData.valorUnit) }}</span>
</div>
<div class="info-item">
<span class="lbl">Valor da NF</span>
<span class="val text-brand">{{ formatMoney(controleDetailData.valorDaNf) }}</span>
</div>
<div class="info-item">
<span class="lbl">Data da NF</span>
<span class="val">{{ formatDate(controleDetailData.dataDaNf) }}</span>
</div>
<div class="info-item">
<span class="lbl">Recebimento</span>
<span class="val">{{ formatDate(controleDetailData.dataDoRecebimento) }}</span>
</div>
<div class="info-item">
<span class="lbl">Tipo</span>
<span class="val">{{ isResumo(controleDetailData) ? "RESUMO" : "DETALHE" }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>