486 lines
21 KiB
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>
|
|
|
|
|
|
|