Files
Kent-logistics-Laravel/resources/views/admin/invoice_edit.blade.php
2026-02-17 14:44:47 +05:30

1487 lines
51 KiB
PHP

@extends('admin.layouts.app')
@section('page-title', 'Edit Invoice')
@section('content')
<style>
:root {
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--success-gradient: linear-gradient(135deg, #10b981 0%, #059669 100%);
--warning-gradient: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
--danger-gradient: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
--glass-bg: rgba(255, 255, 255, 0.95);
--glass-border: rgba(255, 255, 255, 0.2);
--shadow-soft: 0 8px 32px rgba(0, 0, 0, 0.08);
--shadow-medium: 0 12px 48px rgba(0, 0, 0, 0.12);
--shadow-strong: 0 20px 60px rgba(0, 0, 0, 0.15);
--border-radius: 12px;
}
body {
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
font-family: "Inter", "Segoe UI", system-ui, sans-serif;
}
@keyframes fadeUp {
0% {
opacity: 0;
transform: translateY(20px) scale(0.98);
}
100% {
opacity: 1;
transform: translateY(0) scale(1);
}
}
/* --------------------------------------------------
INVOICE PREVIEW RESPONSIVE FIXES
-------------------------------------------------- */
.invoice-preview-wrapper {
width: 100%;
overflow: auto;
max-width: 100%;
box-sizing: border-box;
}
.invoice-preview-wrapper * {
box-sizing: border-box;
}
/* Override any fixed width styles that might be in popup_invoice */
#invoicePreview,
.invoice-container,
.invoice-wrapper {
max-width: 100% !important;
width: 100% !important;
}
/* Responsive table fixes for invoice */
.invoice-preview-wrapper table {
width: 100% !important;
max-width: 100% !important;
table-layout: auto !important;
}
.invoice-preview-wrapper .table-responsive {
overflow-x: auto !important;
-webkit-overflow-scrolling: touch;
}
/* Ensure all elements scale properly */
.invoice-preview-wrapper .row,
.invoice-preview-wrapper .col,
.invoice-preview-wrapper [class*="col-"] {
flex: 1 1 auto !important;
max-width: 100% !important;
}
/* Force responsive behavior for print-style elements */
@media (max-width: 1200px) {
.invoice-preview-wrapper {
font-size: 95%;
}
}
@media (max-width: 992px) {
.invoice-preview-wrapper {
font-size: 90%;
}
}
@media (max-width: 768px) {
.invoice-preview-wrapper {
font-size: 85%;
}
.invoice-preview-wrapper table th,
.invoice-preview-wrapper table td {
padding: 0.5rem !important;
}
}
@media (max-width: 576px) {
.invoice-preview-wrapper {
font-size: 80%;
}
.invoice-preview-wrapper .d-flex {
flex-direction: column !important;
}
.invoice-preview-wrapper .text-end,
.invoice-preview-wrapper .text-start {
text-align: center !important;
}
}
/* Prevent any fixed pixel widths */
.invoice-preview-wrapper [style*="width:"]:not([style*="width:100%"]):not([style*="width:auto"]) {
width: auto !important;
max-width: 100% !important;
}
.invoice-preview-wrapper [style*="min-width"] {
min-width: 0 !important;
}
/* --------------------------------------------------
COMPACT CARD DESIGN
-------------------------------------------------- */
.glass-card {
background: var(--glass-bg);
backdrop-filter: blur(20px);
border-radius: var(--border-radius);
border: 1px solid var(--glass-border);
box-shadow: var(--shadow-strong);
position: relative;
overflow: hidden;
animation: fadeUp 0.6s ease;
margin-bottom: 1.5rem;
}
.glass-card::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(45deg,
rgba(102, 126, 234, 0.03),
rgba(118, 75, 162, 0.03) 50%,
rgba(16, 185, 129, 0.03));
pointer-events: none;
}
/* --------------------------------------------------
COMPACT CARD HEADER
-------------------------------------------------- */
.card-header-compact {
background: var(--primary-gradient);
color: #fff;
padding: 1rem 1.5rem;
border: none;
position: relative;
overflow: hidden;
}
.card-header-compact h4 {
margin: 0;
font-weight: 700;
font-size: 1.3rem;
display: flex;
align-items: center;
gap: 10px;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
/* --------------------------------------------------
COMPACT CARD BODY
-------------------------------------------------- */
.card-body-compact {
padding: 1.5rem;
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
position: relative;
z-index: 1;
}
/* --------------------------------------------------
COMPACT FORM ELEMENTS
-------------------------------------------------- */
.form-grid-compact {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}
.form-group-compact {
position: relative;
}
.form-label-compact {
font-weight: 600;
color: #374151;
margin-bottom: 8px;
font-size: 0.9rem;
display: flex;
align-items: center;
gap: 8px;
}
.form-control-compact, .form-select-compact {
border: 2px solid #e2e8f0;
border-radius: 8px;
padding: 10px 12px;
font-size: 0.9rem;
transition: all 0.3s ease;
background: white;
width: 100%;
}
.form-control-compact:focus, .form-select-compact:focus {
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
outline: none;
}
/* --------------------------------------------------
COMPACT BUTTONS
-------------------------------------------------- */
.btn-compact {
padding: 10px 20px;
border-radius: 8px;
font-weight: 600;
font-size: 0.9rem;
transition: all 0.3s ease;
border: none;
display: inline-flex;
align-items: center;
gap: 6px;
text-decoration: none;
}
.btn-success-compact {
background: var(--success-gradient);
color: white;
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
}
.btn-success-compact:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(16, 185, 129, 0.4);
color: white;
}
.btn-primary-compact {
background: var(--primary-gradient);
color: white;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}
.btn-primary-compact:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
color: white;
}
.btn-danger-compact {
background: var(--danger-gradient);
color: white;
box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
}
.btn-danger-compact:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(239, 68, 68, 0.4);
color: white;
}
.btn-info-compact {
background: linear-gradient(135deg, #06b6d4 0%, #0ea5e9 100%);
color: white;
box-shadow: 0 4px 12px rgba(6, 182, 212, 0.3);
}
.btn-info-compact:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(6, 182, 212, 0.4);
color: white;
}
.btn-warning-compact {
background: var(--warning-gradient);
color: white;
box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);
}
.btn-warning-compact:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(245, 158, 11, 0.4);
color: white;
}
/* --------------------------------------------------
COMPACT SUMMARY CARDS
-------------------------------------------------- */
.summary-grid-compact {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}
.summary-card-compact {
background: white;
padding: 1rem;
border-radius: 8px;
box-shadow: var(--shadow-soft);
border-left: 4px solid;
text-align: center;
}
.summary-card-compact.total { border-left-color: #10b981; }
.summary-card-compact.paid { border-left-color: #3b82f6; }
.summary-card-compact.remaining { border-left-color: #f59e0b; }
.summary-value-compact {
font-size: 1.5rem;
font-weight: 700;
margin-bottom: 0.25rem;
}
.summary-label-compact {
font-size: 0.8rem;
color: #64748b;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
/* --------------------------------------------------
COMPACT AMOUNT BREAKDOWN
-------------------------------------------------- */
.amount-breakdown-compact {
background: white;
padding: 1.5rem;
border-radius: 8px;
box-shadow: var(--shadow-soft);
margin-bottom: 1.5rem;
}
.breakdown-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5rem 0;
border-bottom: 1px solid #f1f5f9;
}
.breakdown-row:last-child {
border-bottom: none;
}
.breakdown-label {
font-weight: 600;
color: #374151;
font-size: 0.9rem;
}
.breakdown-value {
font-weight: 600;
font-size: 0.9rem;
}
/* --------------------------------------------------
COMPACT TABLE
-------------------------------------------------- */
.table-compact {
width: 100%;
border-collapse: collapse;
margin-bottom: 0;
font-size: 0.85rem;
}
.table-compact thead th {
background: var(--primary-gradient);
color: white;
padding: 0.75rem 1rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
font-size: 0.8rem;
border: none;
}
.table-compact tbody tr {
background: white;
transition: all 0.2s ease;
}
.table-compact tbody tr:hover {
background: #f8fafc;
}
.table-compact tbody td {
padding: 0.75rem 1rem;
border-bottom: 1px solid #e2e8f0;
vertical-align: middle;
}
/* --------------------------------------------------
BADGE STYLES
-------------------------------------------------- */
.badge-compact {
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
}
/* --------------------------------------------------
HEADER ACTION BUTTONS
-------------------------------------------------- */
.header-actions {
display: flex;
gap: 0.75rem;
align-items: center;
}
/* --------------------------------------------------
RESPONSIVE DESIGN
-------------------------------------------------- */
@media (max-width: 768px) {
.glass-card {
background: var(--glass-bg);
backdrop-filter: blur(20px);
border-radius: var(--border-radius);
border: 1px solid var(--glass-border);
box-shadow: var(--shadow-strong);
position: relative;
overflow: hidden;
animation: fadeUp 0.6s ease;
margin-bottom: 1.5rem;
}
.glass-card::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(
45deg,
rgba(102, 126, 234, 0.03),
rgba(118, 75, 162, 0.03) 50%,
rgba(16, 185, 129, 0.03)
);
pointer-events: none;
}
.card-header-compact {
background: var(--primary-gradient);
color: #fff;
padding: 1rem 1.5rem;
border: none;
position: relative;
overflow: hidden;
}
.card-header-compact h4 {
margin: 0;
font-weight: 700;
font-size: 1.3rem;
display: flex;
align-items: center;
gap: 10px;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
.card-body-compact {
padding: 1.5rem;
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
position: relative;
z-index: 1;
}
.form-grid-compact {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}
.form-group-compact {
position: relative;
}
.form-label-compact {
font-weight: 600;
color: #374151;
margin-bottom: 8px;
font-size: 0.9rem;
display: flex;
align-items: center;
gap: 8px;
}
.form-control-compact,
.form-select-compact {
border: 2px solid #e2e8f0;
border-radius: 8px;
padding: 10px 12px;
font-size: 0.9rem;
transition: all 0.3s ease;
background: #ffffff;
width: 100%;
}
.form-control-compact:focus,
.form-select-compact:focus {
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
outline: none;
}
.btn-compact {
padding: 10px 20px;
border-radius: 8px;
font-weight: 600;
font-size: 0.9rem;
transition: all 0.3s ease;
border: none;
display: inline-flex;
align-items: center;
gap: 6px;
text-decoration: none;
}
.btn-success-compact {
background: var(--success-gradient);
color: white;
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
}
.btn-success-compact:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(16, 185, 129, 0.4);
color: white;
}
.btn-primary-compact {
background: var(--primary-gradient);
color: white;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}
.btn-primary-compact:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
color: white;
}
.btn-danger-compact {
background: var(--danger-gradient);
color: white;
box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
}
.btn-danger-compact:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(239, 68, 68, 0.4);
color: white;
}
.summary-grid-compact {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}
.summary-card-compact {
background: #ffffff;
padding: 1rem;
border-radius: 8px;
box-shadow: var(--shadow-soft);
border-left: 4px solid;
text-align: center;
}
.summary-card-compact.total {
border-left-color: #10b981;
}
.summary-card-compact.paid {
border-left-color: #3b82f6;
}
.summary-card-compact.remaining {
border-left-color: #f59e0b;
}
.summary-value-compact {
font-size: 1.5rem;
font-weight: 700;
margin-bottom: 0.25rem;
}
.summary-label-compact {
font-size: 0.8rem;
color: #64748b;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.amount-breakdown-compact {
background: #ffffff;
padding: 1rem;
border-radius: 8px;
box-shadow: var(--shadow-soft);
margin-bottom: 1.5rem;
}
.breakdown-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5rem 0;
border-bottom: 1px solid #f1f5f9;
}
.breakdown-row:last-child {
border-bottom: none;
}
.breakdown-label {
font-weight: 600;
color: #374151;
font-size: 0.9rem;
}
.breakdown-value {
font-weight: 600;
font-size: 0.9rem;
}
.table-compact {
width: 100%;
border-collapse: collapse;
margin-bottom: 0;
font-size: 0.85rem;
}
.table-compact thead th {
background: var(--primary-gradient);
color: #ffffff;
padding: 0.75rem 1rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
font-size: 0.8rem;
border: none;
}
.table-compact tbody tr {
background: #ffffff;
transition: all 0.2s ease;
}
.table-compact tbody tr:hover {
background: #f8fafc;
}
.table-compact tbody td {
padding: 0.75rem 1rem;
border-bottom: 1px solid #e2e8f0;
vertical-align: middle;
}
.badge-compact {
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
}
@media (max-width: 768px) {
.glass-card {
margin: 0.5rem;
border-radius: 10px;
}
.card-body-compact {
padding: 1rem;
}
.form-grid-compact {
grid-template-columns: 1fr;
gap: 0.75rem;
}
.summary-grid-compact {
grid-template-columns: 1fr;
gap: 0.75rem;
}
.btn-compact {
width: 100%;
justify-content: center;
}
.table-compact {
font-size: 0.8rem;
}
}
.header-actions {
flex-direction: column;
width: 100%;
gap: 0.5rem;
margin-top: 0.5rem;
}
}
@media print {
.invoice-preview-wrapper {
max-width: 100% !important;
width: 100% !important;
overflow: visible !important;
}
.invoice-preview-wrapper * {
visibility: visible !important;
}
.glass-card {
box-shadow: none !important;
border: 1px solid #000 !important;
}
.card-header-compact {
background: #000 !important;
color: #fff !important;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
}
</style>
<div class="container-fluid py-3">
{{-- Invoice Preview / Overview --}}
<div class="glass-card">
<div class="card-header-compact d-flex justify-content-between align-items-center">
<h4>
<i class="fas fa-file-invoice me-2"></i>
Invoice Overview
</h4>
<div class="header-actions">
<!-- Share Invoice -->
<button class="btn-info-compact btn-compact" id="shareInvoiceBtn">
<i class="fas fa-share-alt me-2"></i>Share Invoice
</button>
<!-- Download Invoice -->
<a href="{{ route('admin.invoices.download', $invoice->id) }}"
class="btn-warning-compact btn-compact" target="_blank">
<i class="fas fa-download me-2"></i>Download Invoice
</a>
</div>
</div>
<div class="card-body-compact">
{{-- इथे popup_invoice मधूनच items table (editable) येईल --}}
@include('admin.popup_invoice', ['invoice' => $invoice, 'shipment' => $shipment, 'embedded' => true])
</div>
</div>
{{-- Edit Invoice Header Details (POST) --}}
<div class="glass-card">
<div class="card-header-compact">
<h4>
<i class="fas fa-edit me-2"></i>
Edit Invoice Details
</h4>
</div>
<div class="card-body-compact">
<form action="{{ route('admin.invoices.update', $invoice->id) }}" method="POST">
@csrf
<div class="form-grid-compact">
{{-- Invoice Date --}}
<div class="form-group-compact">
<label class="form-label-compact">
<i class="fas fa-calendar-day"></i> Invoice Date
</label>
<input type="date"
name="invoice_date"
class="form-control-compact"
value="{{ old('invoice_date', $invoice->invoice_date) }}"
required>
</div>
{{-- Due Date --}}
<div class="form-group-compact">
<label class="form-label-compact">
<i class="fas fa-clock"></i> Due Date
</label>
<input type="date"
name="due_date"
class="form-control-compact"
value="{{ old('due_date', $invoice->due_date) }}"
required>
</div>
{{-- Final Amount (Base) --}}
<div class="form-group-compact">
<label class="form-label-compact">
<i class="fas fa-money-bill-wave"></i> Final Amount (Before GST)
</label>
<input type="number"
step="0.01"
name="final_amount"
class="form-control-compact"
value="{{ old('final_amount', $invoice->final_amount) }}"
required>
</div>
{{-- Tax Type --}}
<div class="form-group-compact">
<label class="form-label-compact">
<i class="fas fa-receipt"></i> Tax Type
</label>
<div class="d-flex gap-3 mt-1">
<div class="form-check">
<input class="form-check-input"
type="radio"
name="tax_type"
value="gst"
{{ old('tax_type', $invoice->tax_type) === 'gst' ? 'checked' : '' }}>
<label class="form-check-label fw-semibold">GST (CGST + SGST)</label>
</div>
<div class="form-check">
<input class="form-check-input"
type="radio"
name="tax_type"
value="igst"
{{ old('tax_type', $invoice->tax_type) === 'igst' ? 'checked' : '' }}>
<label class="form-check-label fw-semibold">IGST</label>
</div>
</div>
</div>
{{-- Tax Percentage --}}
<div class="form-group-compact">
<label class="form-label-compact">
<i class="fas fa-percentage"></i> Tax Percentage
</label>
<input type="number"
step="0.01"
min="0"
max="28"
name="tax_percent"
class="form-control-compact"
value="{{ old('tax_percent',
$invoice->tax_type === 'gst'
? ($invoice->cgst_percent + $invoice->sgst_percent)
: $invoice->igst_percent
) }}"
required>
</div>
{{-- Status --}}
<div class="form-group-compact">
<label class="form-label-compact">
<i class="fas fa-tasks"></i> Status
</label>
<select name="status" class="form-select-compact" required>
<option value="pending" {{ old('status', $invoice->status) === 'pending' ? 'selected' : '' }}>
Pending
</option>
<option value="paid" {{ old('status', $invoice->status) === 'paid' ? 'selected' : '' }}>
Paid
</option>
<option value="overdue" {{ old('status', $invoice->status) === 'overdue' ? 'selected' : '' }}>
Overdue
</option>
</select>
</div>
{{-- Notes --}}
<div class="form-group-compact" style="grid-column: 1 / -1;">
<label class="form-label-compact">
<i class="fas fa-sticky-note"></i> Notes
</label>
<textarea name="notes"
rows="3"
class="form-control-compact"
placeholder="Add any additional notes...">{{ old('notes', $invoice->notes) }}</textarea>
</div>
</div>
<div class="text-end mt-3">
<button type="submit" class="btn-success-compact btn-compact">
<i class="fas fa-save me-2"></i>Update Invoice
</button>
</div>
</form>
</div>
</div>
<<<<<<< HEAD
@php
$totalPaid = $invoice->installments()->sum('amount');
$remaining = $invoice->final_amount_with_gst - $totalPaid;
@endphp
{{-- Amount Breakdown --}}
<div class="amount-breakdown-compact">
<h6 class="fw-bold mb-3 text-dark">
<i class="fas fa-calculator me-2"></i>Amount Breakdown
</h6>
<div class="breakdown-row">
<span class="breakdown-label">Total Amount Before Tax</span>
<span class="breakdown-value" id="baseAmount">
{{ number_format($invoice->final_amount, 2) }}
</span>
</div>
<div class="breakdown-row">
<span class="breakdown-label">Tax Type</span>
<span class="breakdown-value text-primary">
@if($invoice->tax_type === 'gst')
GST (CGST + SGST)
@else
IGST
@endif
</span>
</div>
<div class="breakdown-row">
<span class="breakdown-label">Tax Percentage</span>
<span class="breakdown-value text-primary">
@if($invoice->tax_type === 'gst')
{{ $invoice->cgst_percent + $invoice->sgst_percent }}%
@else
{{ $invoice->igst_percent }}%
@endif
</span>
</div>
<div class="breakdown-row">
<span class="breakdown-label">GST Amount</span>
<span class="breakdown-value text-warning" id="gstAmount">
{{ number_format($invoice->gst_amount, 2) }}
</span>
</div>
<div class="breakdown-row" style="border-top: 2px solid #e2e8f0; padding-top: 0.75rem;">
<span class="breakdown-label fw-bold">Total Invoice Amount Including GST</span>
<span class="breakdown-value fw-bold text-dark" id="totalInvoiceWithGst">
{{ number_format($invoice->final_amount_with_gst, 2) }}
</span>
</div>
<div class="breakdown-row">
<span class="breakdown-label text-success">Total Paid</span>
<span class="breakdown-value fw-bold text-success" id="paidAmount">
{{ number_format($totalPaid, 2) }}
</span>
</div>
<div class="breakdown-row" style="border-bottom: none;">
<span class="breakdown-label text-danger">Remaining</span>
<span class="breakdown-value fw-bold text-danger" id="remainingAmount">
{{ number_format($remaining, 2) }}
</span>
</div>
</div>
{{-- Installment Summary --}}
<div class="summary-grid-compact">
<div class="summary-card-compact total">
<div class="summary-value-compact text-success" id="totalInvoiceWithGstCard">
{{ number_format($invoice->final_amount_with_gst, 2) }}
</div>
<div class="summary-label-compact">Total Amount</div>
</div>
<div class="summary-card-compact paid">
<div class="summary-value-compact text-primary">
{{ number_format($totalPaid, 2) }}
</div>
<div class="summary-label-compact">Total Paid</div>
</div>
<div class="summary-card-compact remaining">
<div class="summary-value-compact text-warning">
{{ number_format($remaining, 2) }}
</div>
<div class="summary-label-compact">Remaining</div>
</div>
</div>
{{-- Installment Management --}}
=======
<!-- Installment Management -->
>>>>>>> 8b6d3d5fadadda310ef45ec03c879b900bff4cb025f45d1bb5d188761d53e043
<div class="glass-card">
<div class="card-header-compact d-flex justify-content-between align-items-center">
<h4 class="mb-0">
<i class="fas fa-credit-card me-2"></i>Installment Payments
</h4>
@if($remaining > 0)
<button id="toggleInstallmentForm" class="btn-primary-compact btn-compact">
<i class="fas fa-plus-circle me-2"></i>Add Installment
</button>
@endif
</div>
<div class="card-body-compact">
{{-- Installment Form --}}
<div id="installmentForm" class="d-none mb-3">
<div class="glass-card" style="background: rgba(248, 250, 252, 0.8);">
<div class="card-header-compact" style="background: var(--success-gradient);">
<h4 class="mb-0">
<i class="fas fa-plus-circle me-2"></i>Add New Installment
</h4>
</div>
<div class="card-body-compact">
<form id="installmentSubmitForm">
@csrf
<div class="form-grid-compact">
<div class="form-group-compact">
<label class="form-label-compact">
<i class="fas fa-calendar-day"></i> Installment Date
</label>
<input type="date"
name="installment_date"
class="form-control-compact"
required>
</div>
<div class="form-group-compact">
<label class="form-label-compact">
<i class="fas fa-credit-card"></i> Payment Method
</label>
<select name="payment_method"
class="form-select-compact"
required>
<option value="cash">Cash</option>
<option value="bank">Bank Transfer</option>
<option value="upi">UPI</option>
<option value="cheque">Cheque</option>
</select>
</div>
<div class="form-group-compact">
<label class="form-label-compact">
<i class="fas fa-hashtag"></i> Reference No
</label>
<input type="text"
name="reference_no"
class="form-control-compact"
placeholder="Enter reference number">
</div>
<div class="form-group-compact">
<label class="form-label-compact">
<i class="fas fa-money-bill-wave"></i> Amount
</label>
<input type="number"
name="amount"
id="installmentAmount"
class="form-control-compact"
step="0.01"
min="1"
max="{{ $remaining }}"
required
placeholder="Enter installment amount">
</div>
</div>
<div class="text-end mt-2">
<button type="submit"
class="btn-success-compact btn-compact"
id="installmentSubmitBtn">
<i class="fas fa-paper-plane me-2"></i>Submit Installment
</button>
</div>
</form>
</div>
</div>
</div>
{{-- Installment History --}}
<h6 class="fw-bold mb-2 text-dark">
<i class="fas fa-history me-2"></i>Installment History
</h6>
@if($invoice->installments->count() > 0)
<div class="table-responsive">
<table class="table-compact">
<thead>
<tr>
<th>#</th>
<th>Date</th>
<th>Payment Method</th>
<th>Reference No</th>
<th>Amount</th>
<th>Action</th>
</tr>
</thead>
<tbody id="installmentTable">
@foreach($invoice->installments as $i)
<tr data-id="{{ $i->id }}">
<td class="fw-bold text-muted">{{ $loop->iteration }}</td>
<td>{{ $i->installment_date }}</td>
<td>
<span class="badge-compact bg-primary bg-opacity-10 text-primary">
{{ strtoupper($i->payment_method) }}
</span>
</td>
<td>
@if($i->reference_no)
<span class="text-muted">{{ $i->reference_no }}</span>
@else
<span class="text-muted">-</span>
@endif
</td>
<td class="fw-bold text-success">
{{ number_format($i->amount, 2) }}
</td>
<td>
<button class="btn-danger-compact btn-compact btn-sm deleteInstallment">
<i class="fas fa-trash me-1"></i>Delete
</button>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@else
<div id="noInstallmentsMsg" class="text-center text-muted fw-bold py-4">
No installments found. Click "Add Installment" to create one.
</div>
@endif
</div>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", function () {
const toggleBtn = document.getElementById("toggleInstallmentForm");
const formBox = document.getElementById("installmentForm");
if (toggleBtn && formBox) {
toggleBtn.addEventListener("click", function (e) {
e.preventDefault();
formBox.classList.toggle("d-none");
});
}
const submitForm = document.getElementById("installmentSubmitForm");
const submitBtn = document.getElementById("installmentSubmitBtn");
const formatINR = (amt) => {
return Number(amt).toLocaleString("en-IN", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
};
<<<<<<< HEAD
if (submitForm && submitBtn) {
submitForm.addEventListener("submit", function (e) {
e.preventDefault();
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Processing...';
submitBtn.disabled = true;
fetch("{{ route('admin.invoice.installment.store', $invoice->id) }}", {
method: "POST",
headers: {
"X-CSRF-TOKEN": submitForm.querySelector('input[name="_token"]').value,
"Accept": "application/json",
},
body: new FormData(submitForm)
})
.then(res => res.json())
.then(data => {
submitBtn.innerHTML = '<i class="fas fa-paper-plane me-2"></i>Submit Installment';
submitBtn.disabled = false;
if (data.status === "error") {
alert(data.message);
return;
}
const table = document.getElementById("installmentTable");
const index = table.rows.length + 1;
document.getElementById("noInstallmentsMsg")?.classList.add("d-none");
table.insertAdjacentHTML("beforeend", `
<tr data-id="${data.installment.id}">
<td class="fw-bold text-muted">${index}</td>
<td>${data.installment.installment_date}</td>
<td>
<span class="badge-compact bg-primary bg-opacity-10 text-primary">
${data.installment.payment_method.toUpperCase()}
</span>
</td>
<td>
${data.installment.reference_no ? `<span class="text-muted">${data.installment.reference_no}</span>` : '<span class="text-muted">-</span>'}
</td>
<td class="fw-bold text-success">
₹${formatINR(data.installment.amount)}
</td>
<td>
<button class="btn-danger-compact btn-compact btn-sm deleteInstallment">
<i class="fas fa-trash me-1"></i>Delete
</button>
</td>
</tr>
`);
if (document.getElementById("paidAmount")) {
document.getElementById("paidAmount").textContent = "" + formatINR(data.totalPaid);
}
if (document.getElementById("remainingAmount")) {
document.getElementById("remainingAmount").textContent = "" + formatINR(data.remaining);
}
if (document.getElementById("baseAmount")) {
document.getElementById("baseAmount").textContent = "" + formatINR(data.baseAmount);
}
if (document.getElementById("gstAmount")) {
document.getElementById("gstAmount").textContent = "" + formatINR(data.gstAmount);
}
if (document.getElementById("totalInvoiceWithGst")) {
document.getElementById("totalInvoiceWithGst").textContent = "" + formatINR(data.finalAmountWithGst);
}
const paidCard = document.querySelector(".summary-card-compact.paid .summary-value-compact");
if (paidCard) paidCard.textContent = "" + formatINR(data.totalPaid);
const remainingCard = document.querySelector(".summary-card-compact.remaining .summary-value-compact");
if (remainingCard) remainingCard.textContent = "" + formatINR(data.remaining);
submitForm.reset();
if (data.isCompleted && toggleBtn) {
toggleBtn.remove();
formBox.classList.add("d-none");
}
alert(data.message);
})
.catch(() => {
submitBtn.innerHTML = '<i class="fas fa-paper-plane me-2"></i>Submit Installment';
submitBtn.disabled = false;
alert("Something went wrong. Please try again.");
});
});
}
document.addEventListener("click", function (e) {
if (!e.target.classList.contains("deleteInstallment") &&
!e.target.closest(".deleteInstallment")) {
return;
}
e.preventDefault();
if (!confirm("Are you sure you want to delete this installment?")) {
return;
}
const btn = e.target.closest(".deleteInstallment");
const row = btn.closest("tr");
const id = row.getAttribute("data-id");
fetch("{{ url('admin/installment') }}/" + id, {
=======
if (submitForm) {
submitForm.addEventListener("submit", function (e) {
e.preventDefault();
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Processing...';
submitBtn.disabled = true;
fetch("{{ route('admin.invoice.installment.store', $invoice->id) }}", {
method: "POST",
headers: {
"X-CSRF-TOKEN": submitForm.querySelector("input[name=_token]").value,
"Accept": "application/json"
},
body: new FormData(submitForm)
})
.then(res => res.json())
.then(data => {
submitBtn.innerHTML = '<i class="fas fa-paper-plane me-2"></i>Submit Installment';
submitBtn.disabled = false;
if (data.status === "error") {
alert(data.message);
return;
}
const table = document.querySelector("#installmentTable");
const noInstallmentsMsg = document.getElementById("noInstallmentsMsg");
if (noInstallmentsMsg) {
noInstallmentsMsg.classList.add("d-none");
}
if (!table) {
// Create table if it doesn't exist
const tableHTML = `
<div class="table-responsive">
<table class="table-compact">
<thead>
<tr>
<th>#</th>
<th>Date</th>
<th>Payment Method</th>
<th>Reference No</th>
<th>Amount</th>
<th>Action</th>
</tr>
</thead>
<tbody id="installmentTable">
</tbody>
</table>
</div>
`;
const parent = submitForm.closest('.card-body-compact');
parent.insertAdjacentHTML('beforeend', tableHTML);
}
const newTable = document.querySelector("#installmentTable");
const index = newTable.rows.length + 1;
newTable.insertAdjacentHTML("beforeend", `
<tr data-id="${data.installment.id}">
<td class="fw-bold text-muted">${index}</td>
<td>${data.installment.installment_date}</td>
<td>
<span class="badge-compact bg-primary bg-opacity-10 text-primary">
${data.installment.payment_method.toUpperCase()}
</span>
</td>
<td>${data.installment.reference_no || '-'}</td>
<td class="fw-bold text-success">${formatINR(data.installment.amount)}</td>
<td>
<button class="btn-danger-compact btn-compact btn-sm deleteInstallment">
<i class="fas fa-trash me-1"></i>Delete
</button>
</td>
</tr>
`);
// Update all displayed values
if (document.getElementById("paidAmount")) document.getElementById("paidAmount").textContent = formatINR(data.totalPaid);
if (document.getElementById("remainingAmount")) document.getElementById("remainingAmount").textContent = formatINR(data.remaining);
// Update summary cards
const paidCard = document.querySelector(".summary-card-compact.paid .summary-value-compact");
if (paidCard) paidCard.textContent = formatINR(data.totalPaid);
const remainingCard = document.querySelector(".summary-card-compact.remaining .summary-value-compact");
if (remainingCard) remainingCard.textContent = formatINR(data.remaining);
submitForm.reset();
// If fully paid, disable/add display logic
if (data.isCompleted) {
toggleBtn?.remove();
formBox.classList.add("d-none");
}
alert(data.message);
})
.catch(() => {
submitBtn.innerHTML = '<i class="fas fa-paper-plane me-2"></i>Submit Installment';
submitBtn.disabled = false;
alert("Something went wrong. Please try again.");
});
});
}
// Delete Installment
document.addEventListener("click", function (e) {
if (!e.target.classList.contains("deleteInstallment")) return;
if (!confirm("Are you sure you want to delete this installment?")) return;
const row = e.target.closest("tr");
const id = row.getAttribute("data-id");
fetch("{{ url('/admin/installment') }}/" + id, {
>>>>>>> 8b6d3d5fadadda310ef45ec03c879b900bff4cb025f45d1bb5d188761d53e043
method: "DELETE",
headers: {
"X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').getAttribute("content"),
"Accept": "application/json",
},
})
<<<<<<< HEAD
.then(res => res.json())
.then(data => {
if (data.status === "success") {
row.style.opacity = 0;
setTimeout(() => row.remove(), 300);
if (document.getElementById("paidAmount")) {
document.getElementById("paidAmount").textContent = "" + formatINR(data.totalPaid);
}
if (document.getElementById("remainingAmount")) {
document.getElementById("remainingAmount").textContent = "" + formatINR(data.remaining);
}
if (document.getElementById("baseAmount")) {
document.getElementById("baseAmount").textContent = "" + formatINR(data.baseAmount);
}
if (document.getElementById("gstAmount")) {
document.getElementById("gstAmount").textContent = "" + formatINR(data.gstAmount);
}
if (document.getElementById("totalInvoiceWithGst")) {
document.getElementById("totalInvoiceWithGst").textContent = "" + formatINR(data.finalAmountWithGst);
}
const paidCard = document.querySelector(".summary-card-compact.paid .summary-value-compact");
if (paidCard) paidCard.textContent = "" + formatINR(data.totalPaid);
const remainingCard = document.querySelector(".summary-card-compact.remaining .summary-value-compact");
if (remainingCard) remainingCard.textContent = "" + formatINR(data.remaining);
=======
.then(res => res.json())
.then(data => {
if (data.status === "success") {
row.style.opacity = "0";
setTimeout(() => {
row.remove();
// Update row numbers
const rows = document.querySelectorAll("#installmentTable tr");
rows.forEach((row, index) => {
row.querySelector("td:first-child").textContent = index + 1;
});
// Show no installments message if empty
if (rows.length === 0) {
const noInstallmentsMsg = document.getElementById("noInstallmentsMsg");
if (noInstallmentsMsg) {
noInstallmentsMsg.classList.remove("d-none");
}
}
}, 300);
// Update all displayed values
if (document.getElementById("paidAmount")) document.getElementById("paidAmount").textContent = formatINR(data.totalPaid);
if (document.getElementById("remainingAmount")) document.getElementById("remainingAmount").textContent = formatINR(data.remaining);
// Update summary cards
const paidCard = document.querySelector(".summary-card-compact.paid .summary-value-compact");
if (paidCard) paidCard.textContent = formatINR(data.totalPaid);
const remainingCard = document.querySelector(".summary-card-compact.remaining .summary-value-compact");
if (remainingCard) remainingCard.textContent = formatINR(data.remaining);
// Show add installment button if there's remaining amount
if (data.remaining > 0 && !document.getElementById("toggleInstallmentForm")) {
const header = document.querySelector(".glass-card .card-header-compact");
header.innerHTML += `
<button id="toggleInstallmentForm" class="btn-primary-compact btn-compact">
<i class="fas fa-plus-circle me-2"></i>Add Installment
</button>
`;
}
>>>>>>> 8b6d3d5fadadda310ef45ec03c879b900bff4cb025f45d1bb5d188761d53e043
if (data.isZero) {
document.getElementById("noInstallmentsMsg")?.classList.remove("d-none");
}
alert(data.message);
} else {
alert(data.message || "Something went wrong. Please try again.");
}
})
.catch(() => {
alert("Something went wrong. Please try again.");
});
});
});
</script>
<<<<<<< HEAD
@endsection
=======
@endsection
>>>>>>> 8b6d3d5fadadda310ef45ec03c879b900bff4cb025f45d1bb5d188761d53e043