--- name: invoice-ui-components description: Componentes de UI para faturas seguindo o padrão de components do Easy Budget. --- # Componentes de UI para Faturas Esta skill define os componentes Blade específicos para a gestão de faturas no Easy Budget, seguindo o padrão de components estabelecido no sistema. ## Estrutura de Components ``` resources/views/components/ ├── invoice/ │ ├── invoice-card.blade.php # Card resumido de fatura │ ├── invoice-details.blade.php # Detalhes completos da fatura │ ├── invoice-form.blade.php # Formulário de criação/edição │ ├── invoice-status.blade.php # Badge de status da fatura │ ├── invoice-items.blade.php # Lista de itens da fatura │ ├── invoice-actions.blade.php # Ações disponíveis para fatura │ ├── invoice-filters.blade.php # Filtros específicos para faturas │ ├── invoice-payments.blade.php # Histórico de pagamentos │ └── invoice-totals.blade.php # Totais e valores da fatura └── ... ``` ## 1. Invoice Card Component Componente para exibição resumida de faturas em listas e dashboards. ### Uso Básico ```blade ``` ### Parâmetros | Parâmetro | Tipo | Descrição | Padrão | |-----------|------|-----------|--------| | `invoice` | `Invoice` | Modelo da fatura | Obrigatório | | `showCustomer` | `bool` | Exibir informações do cliente | `true` | | `showDueDate` | `bool` | Exibir data de vencimento | `true` | | `variant` | `string` | Estilo do card (primary, secondary, etc.) | `primary` | ### Estrutura ```blade @props([ 'invoice', 'showCustomer' => true, 'showDueDate' => true, 'variant' => 'primary' ])
{{ $invoice->code }}
{{ $invoice->created_at->format('d/m/Y') }}
@if($showCustomer && $invoice->customer)
Cliente:
{{ $invoice->customer->display_name }}
@endif @if($showDueDate)
Vencimento:
{{ $invoice->due_date?->format('d/m/Y') ?? 'Indeterminado' }} @if($invoice->isOverdue()) Atrasado @endif
@endif
Valor Total
R$ {{ number_format($invoice->total, 2, ',', '.') }}
Ver @if($invoice->status->isEditable()) Editar @endif
``` ## 2. Invoice Details Component Componente para exibição detalhada de informações da fatura. ### Uso Básico ```blade ``` ### Parâmetros | Parâmetro | Tipo | Descrição | Padrão | |-----------|------|-----------|--------| | `invoice` | `Invoice` | Modelo da fatura | Obrigatório | | `showItems` | `bool` | Exibir itens da fatura | `true` | | `showPayments` | `bool` | Exibir histórico de pagamentos | `true` | | `collapsible` | `bool` | Permitir colapsar seções | `false` | ### Estrutura ```blade @props([ 'invoice', 'showItems' => true, 'showPayments' => true, 'collapsible' => false ])
{{ $invoice->code }}
{{ $invoice->created_at->format('d/m/Y H:i') }}
{{ $invoice->due_date?->format('d/m/Y') ?? 'Indeterminado' }} @if($invoice->isOverdue()) Atrasado @endif
@if($invoice->customer)
Informações do Cliente
{{ $invoice->customer->display_name }}
@if($invoice->customer->contact)
{{ $invoice->customer->contact->email }}
{{ $invoice->customer->contact->phone }}
@endif
@if($invoice->customer->address)
{{ $invoice->customer->address->address }}, {{ $invoice->customer->address->address_number }}
{{ $invoice->customer->address->neighborhood }} - {{ $invoice->customer->address->city }}/{{ $invoice->customer->address->state }}
@endif
@endif @if($showItems && $invoice->invoiceItems->isNotEmpty())
Itens da Fatura
@foreach($invoice->invoiceItems as $item) @endforeach
Descrição Quantidade Valor Unitário Valor Total
{{ $item->description }} {{ $item->quantity }} R$ {{ number_format($item->unit_price, 2, ',', '.') }} R$ {{ number_format($item->total, 2, ',', '.') }}
@endif @if($showPayments && $invoice->payments->isNotEmpty())
Histórico de Pagamentos
@foreach($invoice->payments as $payment) @endforeach
Data Método Valor Status
{{ $payment->transaction_date?->format('d/m/Y H:i') }} {{ $payment->payment_method }} R$ {{ number_format($payment->transaction_amount, 2, ',', '.') }} {{ $payment->status }}
@endif
``` ## 3. Invoice Status Component Componente para exibição do status da fatura com cores e ícones apropriados. ### Uso Básico ```blade ``` ### Parâmetros | Parâmetro | Tipo | Descrição | Padrão | |-----------|------|-----------|--------| | `invoice` | `Invoice` | Modelo da fatura | Obrigatório | | `showIcon` | `bool` | Exibir ícone ao lado do status | `true` | | `size` | `string` | Tamanho do badge (sm, md, lg) | `md` | ### Estrutura ```blade @props([ 'invoice', 'showIcon' => true, 'size' => 'md' ]) @php $status = $invoice->status; $metadata = $status->getMetadata(); $color = $metadata['color'] ?? '#6c757d'; $icon = $metadata['icon'] ?? 'circle'; $description = $metadata['description'] ?? $status->value; $sizeClass = match($size) { 'sm' => 'badge-sm', 'lg' => 'badge-lg', default => 'badge-md' }; // Lógica para status de atraso $isOverdue = $invoice->isOverdue(); if ($isOverdue && $invoice->status->isPending()) { $color = '#dc3545'; // Vermelho para faturas atrasadas $icon = 'exclamation-triangle'; $description = 'Atrasada'; } @endphp @if($showIcon) @endif {{ $description }} @if($isOverdue) +{{ $invoice->daysOverdue() }} dias @endif ``` ## 4. Invoice Items Component Componente para exibição da lista de itens de uma fatura. ### Uso Básico ```blade ``` ### Parâmetros | Parâmetro | Tipo | Descrição | Padrão | |-----------|------|-----------|--------| | `invoice` | `Invoice` | Modelo da fatura | Obrigatório | | `editable` | `bool` | Permitir edição dos itens | `false` | | `showTotal` | `bool` | Exibir total geral | `true` | ### Estrutura ```blade @props([ 'invoice', 'editable' => false, 'showTotal' => true ])
@if($editable) @endif @foreach($invoice->invoiceItems as $item) @if($editable) @endif @endforeach @if($showTotal) @if($editable) @endif @if($invoice->discount > 0) @if($editable) @endif @endif @if($editable) @endif @endif
Descrição Quantidade Valor Unitário Valor TotalAções
@if($editable) @else
{{ $item->description }}
@endif
@if($editable) @else {{ $item->quantity }} @endif @if($editable) @else R$ {{ number_format($item->unit_price, 2, ',', '.') }} @endif R$ {{ number_format($item->total, 2, ',', '.') }}
Subtotal: R$ {{ number_format($invoice->invoiceItems->sum('total'), 2, ',', '.') }}
Desconto: - R$ {{ number_format($invoice->discount, 2, ',', '.') }}
Total da Fatura: R$ {{ number_format($invoice->total, 2, ',', '.') }}
``` ## 5. Invoice Form Component Componente para formulário de criação e edição de faturas. ### Uso Básico ```blade ``` ### Parâmetros | Parâmetro | Tipo | Descrição | Padrão | |-----------|------|-----------|--------| | `invoice` | `Invoice|null` | Modelo da fatura (para edição) | `null` | | `customers` | `Collection` | Clientes disponíveis | Obrigatório | | `services` | `Collection` | Serviços disponíveis | Obrigatório | | `budget` | `Budget|null` | Orçamento vinculado | `null` | ### Estrutura ```blade @props([ 'invoice' => null, 'customers' => [], 'services' => [], 'budget' => null ])
@csrf @if(isset($invoice)) @method('PUT') @endif
@error('customer_id')
{{ $message }}
@enderror
@error('due_date')
{{ $message }}
@enderror
@error('payment_method')
{{ $message }}
@enderror
@error('notes')
{{ $message }}
@enderror
Itens da Fatura
@if(isset($invoice) && $invoice->invoiceItems->isNotEmpty()) @foreach($invoice->invoiceItems as $item)
@endforeach @else
@endif
Subtotal: R$ 0,00
Desconto:
Total: R$ 0,00
Cancelar
@push('scripts') @endpush ``` ## 6. Invoice Actions Component Componente para exibição de ações disponíveis para uma fatura. ### Uso Básico ```blade ``` ### Parâmetros | Parâmetro | Tipo | Descrição | Padrão | |-----------|------|-----------|--------| | `invoice` | `Invoice` | Modelo da fatura | Obrigatório | | `showPayment` | `bool` | Exibir botão de pagamento | `true` | | `showSend` | `bool` | Exibir botão de envio | `true` | | `showPrint` | `bool` | Exibir botão de impressão | `true` | ### Estrutura ```blade @props([ 'invoice', 'showPayment' => true, 'showSend' => true, 'showPrint' => true ])
Visualizar @if($invoice->status->isEditable()) Editar @endif @if($showPayment && $invoice->status->isPending()) @endif @if($showSend) @endif @if($showPrint) Imprimir @endif @if($invoice->status->isDeletable()) @endif
``` ## 7. Invoice Filters Component Componente para filtros específicos de listagem de faturas. ### Uso Básico ```blade ``` ### Parâmetros | Parâmetro | Tipo | Descrição | Padrão | |-----------|------|-----------|--------| | `filters` | `array` | Filtros atuais | `[]` | | `showCustomer` | `bool` | Exibir filtro por cliente | `true` | | `showStatus` | `bool` | Exibir filtro por status | `true` | | `showDateRange` | `bool` | Exibir filtro por período | `true` | ### Estrutura ```blade @props([ 'filters' => [], 'showCustomer' => true, 'showStatus' => true, 'showDateRange' => true ])
@if($showCustomer)
@endif @if($showStatus)
@endif @if($showDateRange)
até
@endif
Limpar
``` ## 8. Invoice Payments Component Componente para exibição do histórico de pagamentos da fatura. ### Uso Básico ```blade ``` ### Parâmetros | Parâmetro | Tipo | Descrição | Padrão | |-----------|------|-----------|--------| | `invoice` | `Invoice` | Modelo da fatura | Obrigatório | | `showAddPayment` | `bool` | Exibir botão para adicionar pagamento | `true` | | `showBalance` | `bool` | Exibir saldo devedor | `true` | ### Estrutura ```blade @props([ 'invoice', 'showAddPayment' => true, 'showBalance' => true ])
@if($showBalance && $invoice->status->isPending())
Saldo Devedor
R$ {{ number_format($invoice->balance, 2, ',', '.') }}
{{ $invoice->status->getDescription() }}
@endif
Histórico de Pagamentos
@if($invoice->payments->isNotEmpty())
@foreach($invoice->payments as $payment) @endforeach
Data Método Valor Status Ações
{{ $payment->transaction_date?->format('d/m/Y H:i') }} {{ $payment->payment_method }} R$ {{ number_format($payment->transaction_amount, 2, ',', '.') }} {{ $payment->status }}
@else

Nenhum pagamento registrado

@endif
@if($showAddPayment && $invoice->status->isPending())
Receber Pagamento
Registre o pagamento da fatura
@endif
``` ## 9. Invoice Totals Component Componente para exibição detalhada dos totais e valores da fatura. ### Uso Básico ```blade ``` ### Parâmetros | Parâmetro | Tipo | Descrição | Padrão | |-----------|------|-----------|--------| | `invoice` | `Invoice` | Modelo da fatura | Obrigatório | | `showBreakdown` | `bool` | Exibir detalhamento dos valores | `true` | | `variant` | `string` | Estilo visual (primary, success, etc.) | `primary` | ### Estrutura ```blade @props([ 'invoice', 'showBreakdown' => true, 'variant' => 'primary' ])
@if($showBreakdown)
Subtotal
R$ {{ number_format($invoice->invoiceItems->sum('total'), 2, ',', '.') }}
Desconto
- R$ {{ number_format($invoice->discount, 2, ',', '.') }}
Valor Total
R$ {{ number_format($invoice->total, 2, ',', '.') }}
@if($invoice->payments->isNotEmpty())
Total Pago
R$ {{ number_format($invoice->payments->sum('transaction_amount'), 2, ',', '.') }}
Saldo Devedor
R$ {{ number_format($invoice->balance, 2, ',', '.') }}
Status
{{ $invoice->status->getDescription() }}
@endif @else
Valor Total da Fatura
R$ {{ number_format($invoice->total, 2, ',', '.') }}
@endif
``` ## 10. Integração com Padrões Existentes ### Uso em Views ```blade {{-- Dashboard --}} {{-- Listagem --}} {{-- Formulários --}} {{-- Ações --}} ``` ### Estilos CSS ```css /* Invoice Components Styles */ .invoice-form .price-input { text-align: right; } .invoice-form .item-total { background-color: #f8f9fa; font-weight: bold; } .invoice-actions .btn { transition: all 0.2s ease; } .invoice-actions .btn:hover { transform: translateY(-1px); box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .invoice-payments .card { border-left: 4px solid #0d6efd; } .invoice-payments .card.bg-warning { border-left-color: #ffc107; } ``` ## 11. JavaScript Interatividade ### Formulário de Fatura ```javascript // invoice-form.js document.addEventListener('DOMContentLoaded', function() { // Formatar valores monetários document.querySelectorAll('.price-input').forEach(input => { input.addEventListener('input', function() { let value = this.value.replace(/\D/g, ''); value = (value / 100).toFixed(2); this.value = value.replace('.', ','); calculateTotals(); }); }); // Calcular totais function calculateTotals() { let subtotal = 0; document.querySelectorAll('.item-row').forEach(row => { const quantity = parseFloat(row.querySelector('.quantity-input').value) || 0; const unitPrice = parseFloat(row.querySelector('.price-input').value.replace(',', '.')) || 0; const total = quantity * unitPrice; row.querySelector('.item-total').value = 'R$ ' + total.toLocaleString('pt-BR', { minimumFractionDigits: 2 }); subtotal += total; }); const discount = parseFloat(document.getElementById('discountInput').value.replace(',', '.')) || 0; const total = subtotal - discount; document.getElementById('subtotalDisplay').textContent = 'R$ ' + subtotal.toLocaleString('pt-BR', { minimumFractionDigits: 2 }); document.getElementById('totalDisplay').textContent = 'R$ ' + total.toLocaleString('pt-BR', { minimumFractionDigits: 2 }); } // Adicionar item document.getElementById('addInvoiceItem').addEventListener('click', function() { const itemsContainer = document.getElementById('invoiceItems'); const itemCount = itemsContainer.children.length; const newRow = document.createElement('div'); newRow.className = 'row g-3 item-row mb-3'; newRow.innerHTML = `
`; itemsContainer.appendChild(newRow); calculateTotals(); }); // Eventos de cálculo document.getElementById('invoiceItems').addEventListener('input', calculateTotals); document.getElementById('discountInput').addEventListener('input', calculateTotals); // Inicializar cálculos calculateTotals(); }); ``` ## 12. Validação e Segurança ### Autorização ```php // InvoicePolicy.php public function view(User $user, Invoice $invoice) { return $user->tenant_id === $invoice->tenant_id; } public function update(User $user, Invoice $invoice) { return $user->tenant_id === $invoice->tenant_id && $invoice->status->isEditable(); } public function delete(User $user, Invoice $invoice) { return $user->tenant_id === $invoice->tenant_id && $invoice->status->isDeletable(); } public function receivePayment(User $user, Invoice $invoice) { return $user->tenant_id === $invoice->tenant_id && $invoice->status->isPending(); } ``` ### Validations ```blade {{-- Invoice Card com validação de permissões --}} @can('view', $invoice) @endcan {{-- Invoice Actions com validação de status --}} @can('update', $invoice) @if($invoice->status->isEditable()) @endif @endcan ``` Este padrão de components para faturas garante consistência visual, reutilização de código e manutenibilidade, seguindo os mesmos princípios estabelecidos nos outros components do sistema.