Pdf Changes Done
This commit is contained in:
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user