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

252 lines
9.0 KiB
HTML

<section class="parcelamentos-page">
<div class="container-geral-responsive">
<div class="parcelamentos-shell">
<header class="page-header">
<div class="page-header-main">
<div class="title-group">
<span class="title-badge"><i class="bi bi-wallet2"></i> PARCELAMENTOS</span>
<div class="header-title">
<h2>Gestao de Parcelamentos</h2>
<p>Painel administrativo de parcelas de aparelhos e contratos</p>
</div>
</div>
<div class="header-actions">
<button class="btn-ghost" type="button" (click)="refresh()" [disabled]="loading">
<i class="bi bi-arrow-repeat"></i> Atualizar
</button>
<button class="btn-primary" type="button" (click)="openCreateModal()">
<i class="bi bi-plus-circle"></i> Novo Parcelamento
</button>
</div>
</div>
<div class="header-highlights" aria-label="Resumo da listagem">
<div class="highlight-card">
<span>Total de registros</span>
<strong>{{ total }}</strong>
</div>
<div class="highlight-card">
<span>Pagina atual</span>
<strong>{{ page }} de {{ totalPages }}</strong>
</div>
<div class="highlight-card">
<span>Segmento ativo</span>
<strong>
{{ activeSegment === 'todos' ? 'Lista geral' : (activeSegment === 'ativos' ? 'Ativos' : (activeSegment === 'futuros' ? 'Futuros' : 'Finalizados')) }}
</strong>
</div>
</div>
</header>
<app-parcelamentos-kpis [cards]="kpiCards"></app-parcelamentos-kpis>
<app-parcelamentos-filters
[filters]="filters"
[monthOptions]="monthOptions"
[loading]="loading"
[competenciaInvalid]="competenciaInvalid"
[activeChips]="activeChips"
(apply)="applyFilters()"
(clear)="clearFilters()"
(searchChange)="onSearchChange($event)">
</app-parcelamentos-filters>
<app-parcelamentos-table
[items]="viewItems"
[loading]="loading"
[errorMessage]="errorMessage"
[segment]="activeSegment"
[segmentCounts]="segmentCounts"
[page]="page"
[pageNumbers]="pageNumbers"
[pageStart]="pageStart"
[pageEnd]="pageEnd"
[total]="total"
[pageSize]="pageSize"
[pageSizeOptions]="pageSizeOptions"
[isAdmin]="isAdmin"
(segmentChange)="setSegment($event)"
(detail)="openDetails($event)"
(edit)="openEdit($event)"
(remove)="openDelete($event)"
(pageChange)="goToPage($event)"
(pageSizeChange)="onPageSizeChange($event)">
</app-parcelamentos-table>
</div>
</div>
</section>
<!-- Modal detalhes -->
<div class="lg-backdrop" *ngIf="detailOpen" (click)="closeDetails()"></div>
<div class="lg-modal" *ngIf="detailOpen">
<div class="lg-modal-card parcelamento-modal" (click)="$event.stopPropagation()">
<div class="modal-header">
<div class="modal-title">
<span class="icon-bg"><i class="bi bi-card-list"></i></span>
<span>Detalhes do Parcelamento</span>
</div>
<div class="modal-actions">
<button class="btn-icon" type="button" (click)="closeDetails()" aria-label="Fechar modal">
<i class="bi bi-x-lg"></i>
</button>
</div>
</div>
<div class="modal-body">
<div class="detail-state" *ngIf="detailLoading && !selectedDetail">
<div class="spinner-border text-brand" role="status"></div>
<span>Carregando detalhes...</span>
</div>
<div class="detail-state error" *ngIf="!detailLoading && detailError && !selectedDetail">
<i class="bi bi-exclamation-triangle"></i>
<span>{{ detailError }}</span>
</div>
<ng-container *ngIf="selectedDetail as detail">
<div class="detail-grid">
<div class="detail-card">
<small>Cliente</small>
<span class="detail-strong">{{ detail.cliente || '-' }}</span>
</div>
<div class="detail-card">
<small>Linha</small>
<span class="detail-strong text-blue">{{ detail.linha || '-' }}</span>
</div>
<div class="detail-card">
<small>AnoRef</small>
<span>{{ detail.anoRef ?? '-' }}</span>
</div>
<div class="detail-card">
<small>Item</small>
<span>{{ detail.item ?? '-' }}</span>
</div>
<div class="detail-card">
<small>Qt Parcelas</small>
<span>{{ displayQtParcelas(detail) }}</span>
</div>
<div class="detail-card">
<small>Parcela Atual</small>
<span class="detail-strong">{{ detail.parcelaAtual ?? '-' }}</span>
</div>
<div class="detail-card">
<small>Total Parcelas</small>
<span>{{ detail.totalParcelas ?? '-' }}</span>
</div>
<div class="detail-card">
<small>Status</small>
<span class="status-pill">{{ detailStatus }}</span>
</div>
<div class="detail-card">
<small>Valor Cheio</small>
<span>{{ formatMoney(detail.valorCheio) }}</span>
</div>
<div class="detail-card">
<small>Desconto</small>
<span class="text-danger">{{ formatMoney(detail.desconto) }}</span>
</div>
<div class="detail-card highlight">
<small>Valor com Desconto</small>
<span class="detail-strong money-strong">{{ formatMoney(detail.valorComDesconto) }}</span>
</div>
</div>
<div class="annual-section">
<div class="annual-head">
<div class="section-title">
<i class="bi bi-table"></i>
<span>Detalhamento anual</span>
</div>
</div>
<div class="annual-table-shell" *ngIf="annualRows.length > 0; else annualEmpty">
<table class="table-modern annual-table">
<thead>
<tr>
<th class="sticky-col col-1">Ano</th>
<th class="sticky-col col-2 text-end">Total</th>
<th *ngFor="let m of annualMonthHeaders" class="text-end">{{ m.label }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of annualRows">
<td class="sticky-col col-1">{{ row.year }}</td>
<td class="sticky-col col-2 text-end">{{ row.total | currency:'BRL':'symbol':'1.2-2':'pt-BR' }}</td>
<td *ngFor="let m of row.months" class="text-end">
{{ m.value !== null && m.value !== undefined ? (m.value | currency:'BRL':'symbol':'1.2-2':'pt-BR') : '-' }}
</td>
</tr>
</tbody>
</table>
</div>
<ng-template #annualEmpty>
<div class="annual-empty">
Sem dados anuais.
</div>
</ng-template>
</div>
</ng-container>
</div>
<div class="modal-footer">
<button class="btn-primary" type="button" (click)="closeDetails()">Fechar</button>
</div>
</div>
</div>
<app-parcelamento-create-modal
[open]="createOpen"
[model]="createModel"
[monthOptions]="monthOptions"
[loading]="createSaving"
[errorMessage]="createError"
title="Novo Parcelamento"
submitLabel="Salvar"
(close)="closeCreateModal()"
(save)="saveNewParcelamento($event)">
</app-parcelamento-create-modal>
<app-parcelamento-create-modal
*ngIf="editOpen && editModel"
[open]="editOpen"
[model]="editModel"
[monthOptions]="monthOptions"
[loading]="editSaving"
[errorMessage]="editError"
title="Editar Parcelamento"
submitLabel="Atualizar"
(close)="closeEditModal()"
(save)="saveEditParcelamento($event)">
</app-parcelamento-create-modal>
<!-- Delete modal -->
<div class="lg-backdrop" *ngIf="deleteOpen"></div>
<div class="lg-modal" *ngIf="deleteOpen">
<div class="lg-modal-card modal-compact" (click)="$event.stopPropagation()">
<div class="modal-header">
<div class="modal-title">
<span class="icon-bg danger-soft"><i class="bi bi-trash"></i></span>
Remover Parcelamento
</div>
<button class="btn-icon" type="button" (click)="cancelDelete()" aria-label="Fechar modal de exclusao">
<i class="bi bi-x-lg"></i>
</button>
</div>
<div class="modal-body">
<div class="confirm-delete">
<div class="confirm-icon"><i class="bi bi-trash"></i></div>
<p class="mb-0">Confirma remover o parcelamento <strong>{{ deleteTarget?.linha }}</strong>?</p>
<small class="text-danger" *ngIf="deleteError">{{ deleteError }}</small>
</div>
</div>
<div class="modal-footer">
<button class="btn-ghost" type="button" (click)="cancelDelete()">Cancelar</button>
<button class="btn-danger" type="button" [disabled]="deleteLoading" (click)="confirmDelete()">
{{ deleteLoading ? 'Excluindo...' : 'Excluir' }}
</button>
</div>
</div>
</div>