Pdf Changes Done

This commit is contained in:
Utkarsh Khedkar
2026-03-09 10:24:44 +05:30
parent c11467068c
commit 9cc6959396
32 changed files with 3416 additions and 2188 deletions

View File

@@ -65,40 +65,77 @@
.stats-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
margin-bottom: 24px;
}
.stat-card {
background: white;
border-radius: 12px;
padding: 20px;
box-shadow: var(--shadow-sm);
border-left: 4px solid;
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
padding: 20px 22px;
border-radius: 14px;
border-left: 4px solid;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
transition: transform 0.3s ease, box-shadow 0.3s ease;
position: relative;
overflow: hidden;
}
.stat-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
transform: translateY(-4px);
box-shadow: 0 8px 20px rgba(0,0,0,0.1);
}
.stat-card.total { border-left-color: #667eea; }
.stat-card.paid { border-left-color: #10b981; }
.stat-card.pending { border-left-color: #f59e0b; }
.stat-card.overdue { border-left-color: #ef4444; }
.stat-card.total {
background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
border-left-color: #3b82f6;
}
.stat-card.paid {
background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
border-left-color: #22c55e;
}
.stat-card.pending {
background: linear-gradient(135deg, #fffbeb 0%, #fef9c3 100%);
border-left-color: #f59e0b;
}
.stat-card.overdue {
background: linear-gradient(135deg, #fff5f5 0%, #fee2e2 100%);
border-left-color: #ef4444;
}
.stat-icon-wrap {
width: 48px;
height: 48px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
font-size: 20px;
}
.stat-card.total .stat-icon-wrap { background: rgba(59,130,246,0.12); color: #3b82f6; }
.stat-card.paid .stat-icon-wrap { background: rgba(34,197,94,0.15); color: #16a34a; }
.stat-card.pending .stat-icon-wrap{ background: rgba(245,158,11,0.15); color: #d97706; }
.stat-card.overdue .stat-icon-wrap{ background: rgba(239,68,68,0.12); color: #dc2626; }
.stat-text {
display: flex;
flex-direction: column;
gap: 4px;
}
.stat-value {
font-size: 28px;
font-size: 26px;
font-weight: 700;
margin-bottom: 8px;
line-height: 1;
color: var(--text-dark);
}
.stat-label {
font-size: 14px;
font-size: 13px;
color: var(--text-muted);
font-weight: 500;
}
@@ -483,9 +520,9 @@
@media(max-width: 768px) {
.orders-title { font-size: 24px; }
.orders-container { padding: 16px; }
.stats-container { grid-template-columns: 1fr; }
.stat-card { padding: 16px; }
.stat-value { font-size: 24px; }
.stats-container { grid-template-columns: 1fr 1fr; }
.stat-card { padding: 14px 16px; }
.stat-value { font-size: 22px; }
.download-section { justify-content: stretch; }
.download-btn { flex: 1; justify-content: center; }
@@ -497,6 +534,10 @@
.pagination-container { flex-direction: column; gap: 16px; }
}
@media(max-width: 480px) {
.stats-container { grid-template-columns: 1fr; }
}
</style>
<div class="orders-container">
@@ -504,7 +545,6 @@
<i class="fas fa-file-invoice-dollar"></i> Invoices Management
</div>
{{-- Stats Cards based on invoices --}}
<div class="stats-container">
@php
$totalInvoices = $invoices->count();
@@ -512,22 +552,45 @@
$pendingInvoices = $invoices->where('invoice_status', 'pending')->count();
$overdueInvoices = $invoices->where('invoice_status', 'overdue')->count();
@endphp
<div class="stat-card total">
<div class="stat-value">{{ $totalInvoices }}</div>
<div class="stat-label">Total Invoices</div>
<div class="stat-icon-wrap">
<i class="fas fa-file-invoice"></i>
</div>
<div class="stat-text">
<div class="stat-value">{{ $totalInvoices }}</div>
<div class="stat-label">Total Invoices</div>
</div>
</div>
<div class="stat-card paid">
<div class="stat-value">{{ $paidInvoices }}</div>
<div class="stat-label">Paid Invoices</div>
<div class="stat-icon-wrap">
<i class="fas fa-check-circle"></i>
</div>
<div class="stat-text">
<div class="stat-value">{{ $paidInvoices }}</div>
<div class="stat-label">Paid Invoices</div>
</div>
</div>
<div class="stat-card pending">
<div class="stat-value">{{ $pendingInvoices }}</div>
<div class="stat-label">Pending Invoices</div>
<div class="stat-icon-wrap">
<i class="fas fa-clock"></i>
</div>
<div class="stat-text">
<div class="stat-value">{{ $pendingInvoices }}</div>
<div class="stat-label">Pending Invoices</div>
</div>
</div>
<div class="stat-card overdue">
<div class="stat-value">{{ $overdueInvoices }}</div>
<div class="stat-label">Overdue Invoices</div>
<div class="stat-icon-wrap">
<i class="fas fa-exclamation-triangle"></i>
</div>
<div class="stat-text">
<div class="stat-value">{{ $overdueInvoices }}</div>
<div class="stat-label">Overdue Invoices</div>
</div>
</div>
</div>
@@ -570,7 +633,7 @@
<tr>
<th>Invoice No</th>
<th>Invoice Date</th>
<th>Mark No</th>
{{-- <th>Mark No</th> --}}
<th>Container No</th>
<th>Container Date</th>
<th>Company</th>
@@ -586,10 +649,30 @@
$status = strtolower($inv->invoice_status ?? 'pending');
@endphp
<tr>
<td>{{ $inv->invoice_number }}</td>
<td>
@if($inv->invoice_number)
<a href="javascript:void(0);"
class="invoice-popup-link"
data-invoice-id="{{ $inv->id }}">
{{ $inv->invoice_number }}
</a>
@else
-
@endif
</td>
<td>{{ $inv->invoice_date ? \Carbon\Carbon::parse($inv->invoice_date)->format('d-m-Y') : '-' }}</td>
<td>{{ $inv->mark_no ?? '-' }}</td>
<td>{{ $inv->container_number ?? '-' }}</td>
{{-- <td>{{ $inv->mark_no ?? '-' }}</td> --}}
<td>
@if(!empty($inv->container_id) && !empty($inv->container_number))
<a href="javascript:void(0);"
class="container-popup-link"
data-container-id="{{ $inv->container_id }}">
{{ $inv->container_number }}
</a>
@else
-
@endif
</td>
<td>{{ $inv->container_date ? \Carbon\Carbon::parse($inv->container_date)->format('d-m-Y') : '-' }}</td>
<td>{{ $inv->company_name ?? '-' }}</td>
<td>{{ $inv->customer_name ?? '-' }}</td>
@@ -633,6 +716,20 @@
@endif
</div>
<div class="modal fade" id="invoiceModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="invoiceModalTitle">Invoice Details</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body" id="invoiceModalBody">
<p class="text-center text-muted">Loading...</p>
</div>
</div>
</div>
</div>
<script>
let currentPage = 1;
const itemsPerPage = 10;
@@ -680,7 +777,7 @@
const term = searchTerm.toLowerCase();
const fields = [
inv.invoice_number?.toString().toLowerCase(),
inv.mark_no?.toString().toLowerCase(),
// inv.mark_no?.toString().toLowerCase(),
inv.container_number?.toString().toLowerCase(),
inv.company_name?.toString().toLowerCase(),
inv.customer_name?.toString().toLowerCase()
@@ -711,6 +808,21 @@
document.getElementById('downloadPdf').addEventListener('click', downloadPdf);
document.getElementById('downloadExcel').addEventListener('click', downloadExcel);
document.addEventListener('click', function(e) {
const invLink = e.target.closest('.invoice-popup-link');
if (invLink) {
e.preventDefault();
openInvoicePopup(invLink.dataset.invoiceId);
return;
}
const contLink = e.target.closest('.container-popup-link');
if (contLink) {
e.preventDefault();
openContainerPopup(contLink.dataset.containerId);
}
});
});
function handleFilter() {
@@ -797,7 +909,7 @@
tbody.innerHTML = '';
if (filteredInvoices.length === 0) {
tbody.innerHTML = '<tr><td colspan="10" class="text-center py-4 text-muted">No invoices found matching your criteria.</td></tr>';
tbody.innerHTML = '<tr><td colspan="9" class="text-center py-4 text-muted">No invoices found matching your criteria.</td></tr>';
return;
}
@@ -809,10 +921,26 @@
const status = (inv.invoice_status || 'pending').toLowerCase();
const row = document.createElement('tr');
row.innerHTML = `
<td>${inv.invoice_number || '-'}</td>
<td>
${
inv.invoice_number
? `<a href="javascript:void(0);" class="invoice-popup-link" data-invoice-id="${inv.id}">
${inv.invoice_number}
</a>`
: '-'
}
</td>
<td>${inv.invoice_date ? new Date(inv.invoice_date).toLocaleDateString('en-GB') : '-'}</td>
<td>${inv.mark_no || '-'}</td>
<td>${inv.container_number || '-'}</td>
<!-- <td>${inv.mark_no || '-'}</td> -->
<td>
${
inv.container_id && inv.container_number
? `<a href="javascript:void(0);" class="container-popup-link" data-container-id="${inv.container_id}">
${inv.container_number}
</a>`
: '-'
}
</td>
<td>${inv.container_date ? new Date(inv.container_date).toLocaleDateString('en-GB') : '-'}</td>
<td>${inv.company_name || '-'}</td>
<td>${inv.customer_name || '-'}</td>
@@ -828,6 +956,66 @@
});
}
function openInvoicePopup(invoiceId) {
const modal = new bootstrap.Modal(document.getElementById('invoiceModal'));
document.getElementById('invoiceModalTitle').textContent = 'Invoice Details';
document.getElementById('invoiceModalBody').innerHTML =
"<div class='text-center py-4'>" +
"<div class='spinner-border text-primary' role='status'></div>" +
"<p class='mt-2 text-muted'>Loading invoice details...</p>" +
"</div>";
modal.show();
fetch(`/admin/invoices/${invoiceId}/popup`)
.then(res => {
if (!res.ok) throw new Error('Network error');
return res.text();
})
.then(html => {
document.getElementById('invoiceModalBody').innerHTML = html;
})
.catch(error => {
console.error(error);
document.getElementById('invoiceModalBody').innerHTML =
"<div class='text-center py-4 text-danger'>" +
"<i class='bi bi-exclamation-triangle fs-1'></i>" +
"<p class='mt-2'>Failed to load invoice details. Please try again.</p>" +
"</div>";
});
}
function openContainerPopup(containerId) {
const modal = new bootstrap.Modal(document.getElementById('invoiceModal'));
document.getElementById('invoiceModalTitle').textContent = 'Container Details';
document.getElementById('invoiceModalBody').innerHTML =
"<div class='text-center py-4'>" +
"<div class='spinner-border text-primary' role='status'></div>" +
"<p class='mt-2 text-muted'>Loading container details...</p>" +
"</div>";
modal.show();
fetch(`/admin/containers/${containerId}/popup`)
.then(res => {
if (!res.ok) throw new Error('Network error');
return res.text();
})
.then(html => {
document.getElementById('invoiceModalBody').innerHTML = html;
})
.catch(error => {
console.error(error);
document.getElementById('invoiceModalBody').innerHTML =
"<div class='text-center py-4 text-danger'>" +
"<i class='bi bi-exclamation-triangle fs-1'></i>" +
"<p class='mt-2'>Failed to load container details.</p>" +
"</div>";
});
}
function downloadPdf() {
if (filteredInvoices.length === 0) {
showNotification('No data available to download', 'warning');