Invoice Frontend
This commit is contained in:
@@ -3,108 +3,878 @@
|
||||
@section('page-title', 'Invoice List')
|
||||
|
||||
@section('content')
|
||||
<style>
|
||||
/*Remove horizontal scroll bar*/
|
||||
html, body {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-light">
|
||||
<h4 class="mb-0">All Invoices</h4>
|
||||
</div>
|
||||
/* Invoice Management Styles */
|
||||
.invoice-management-box {
|
||||
background: #fff;
|
||||
border-radius: 17px;
|
||||
box-shadow: 0 7px 38px #dde3fa77, 0 2px 9px #e5e7ff80;
|
||||
margin-bottom: 33px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
<div class="card-body table-responsive">
|
||||
<table class="table table-bordered table-striped align-middle text-center">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Invoice Number</th>
|
||||
<th>Customer</th>
|
||||
<th>Final Amount (₹)</th>
|
||||
<th>GST %</th>
|
||||
<th>Total w/GST (₹)</th>
|
||||
<th>Status</th>
|
||||
<th>Invoice Date</th>
|
||||
<th>Due Date</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
.invoice-management-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-radius: 17px 17px 0 0;
|
||||
background: #fceeb8ff;
|
||||
min-height: 54px;
|
||||
padding: 15px 26px 10px 22px;
|
||||
border-bottom: 1.4px solid #e8e2cf;
|
||||
box-shadow: 0 1px 13px #ffe2a888;
|
||||
}
|
||||
|
||||
<tbody>
|
||||
@foreach($invoices as $i => $invoice)
|
||||
<tr>
|
||||
<td>{{ $i + 1 }}</td>
|
||||
.invoice-management-title {
|
||||
font-size: 1.32rem;
|
||||
font-weight: 800;
|
||||
color: #2451af;
|
||||
letter-spacing: .08em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 11px;
|
||||
}
|
||||
|
||||
.invoice-management-title i {
|
||||
font-size: 1.12em;
|
||||
color: #336ad3;
|
||||
}
|
||||
|
||||
/* Tools Row Styling */
|
||||
.invoice-tools-row {
|
||||
background: linear-gradient(135deg, #f8fafc 0%, #edf2f7 100%);
|
||||
padding: 20px 25px;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
padding: 8px 15px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
|
||||
border: 1px solid #e2e8f0;
|
||||
min-width: 300px;
|
||||
flex: 1;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.search-box i {
|
||||
color: #64748b;
|
||||
margin-right: 10px;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.search-box input {
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
color: #334155;
|
||||
}
|
||||
|
||||
.search-box input::placeholder {
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.filter-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.filter-select {
|
||||
background: white;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
padding: 8px 12px;
|
||||
font-size: 14px;
|
||||
color: #334155;
|
||||
outline: none;
|
||||
min-width: 150px;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.04);
|
||||
}
|
||||
|
||||
.filter-select:focus {
|
||||
border-color: #3b82f6;
|
||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
||||
}
|
||||
|
||||
.create-invoice-btn {
|
||||
background: linear-gradient(90deg, #226ad6, #46b4fd 123%);
|
||||
padding: 10px 24px;
|
||||
font-weight: 600;
|
||||
border: none;
|
||||
border-radius: 9px;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
box-shadow: 0 2px 13px #dde7fa42;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-family: inherit;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.create-invoice-btn:hover {
|
||||
background: linear-gradient(90deg, #3264f8, #3acfff 140%);
|
||||
box-shadow: 0 4px 25px #5ab8f880;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.invoice-management-main {
|
||||
background: #fff;
|
||||
border-radius: 0 0 17px 17px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Table Styling - CENTERED CONTENT */
|
||||
.table-container {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
scroll-behavior: smooth;
|
||||
border-radius: 0 0 17px 17px;
|
||||
}
|
||||
|
||||
.table-container::-webkit-scrollbar {
|
||||
height: 6px;
|
||||
}
|
||||
.table-container::-webkit-scrollbar-thumb {
|
||||
background: linear-gradient(90deg, #a7b8ff, #6c8eff);
|
||||
border-radius: 10px;
|
||||
}
|
||||
.table-container::-webkit-scrollbar-thumb:hover {
|
||||
background: linear-gradient(90deg, #5a78ff, #3f63e0);
|
||||
}
|
||||
.table-container::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.table {
|
||||
width: 100%;
|
||||
min-width: 1100px;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Center all table content */
|
||||
.table thead tr {
|
||||
background: #feebbe !important;
|
||||
}
|
||||
|
||||
.table thead th:first-child {
|
||||
border-top-left-radius: 17px;
|
||||
}
|
||||
.table thead th:last-child {
|
||||
border-top-right-radius: 17px;
|
||||
}
|
||||
|
||||
|
||||
.table thead th {
|
||||
background: transparent !important;
|
||||
border: none;
|
||||
font-weight: 700;
|
||||
color: #343535;
|
||||
letter-spacing: 0.02em;
|
||||
font-size: 13px;
|
||||
padding: 12px 8px;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
border-bottom: 2px solid #e8e2cf;
|
||||
text-align: center !important; /* Center header text */
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.table thead th:first-child {
|
||||
padding-left: 20px;
|
||||
}
|
||||
.table thead th:last-child {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.table-striped tbody tr {
|
||||
background: #fff;
|
||||
transition: all 0.2s ease;
|
||||
border-bottom: 1px solid #f1f3f4;
|
||||
}
|
||||
|
||||
.table-striped tbody tr:hover {
|
||||
background: #f8fafc !important;
|
||||
}
|
||||
|
||||
.table-striped tbody tr:nth-of-type(odd) {
|
||||
background: #f9fafc;
|
||||
}
|
||||
|
||||
.table-striped tbody tr:nth-of-type(even) {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
/* Center all table cells */
|
||||
.table td {
|
||||
padding: 10px 8px;
|
||||
border: none;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
font-size: 13px;
|
||||
color: #4a5568;
|
||||
border-bottom: 1px solid #f1f3f4;
|
||||
text-align: center !important; /* Center all cell content */
|
||||
}
|
||||
|
||||
.table td:first-child {
|
||||
padding-left: 20px;
|
||||
font-weight: 600;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
.table td:last-child {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
/* Invoice Number with Curved Boxes */
|
||||
.invoice-number-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center; /* Center the invoice number */
|
||||
gap: 8px;
|
||||
padding: 6px 0;
|
||||
}
|
||||
|
||||
.invoice-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 8px; /* Curved border radius */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
|
||||
font-weight: bold;
|
||||
border: 2px solid rgba(255,255,255,0.3); /* Subtle border */
|
||||
}
|
||||
|
||||
/* Different curved background colors for each invoice */
|
||||
.invoice-icon-1 {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 8px;
|
||||
}
|
||||
.invoice-icon-2 {
|
||||
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
||||
border-radius: 8px;
|
||||
}
|
||||
.invoice-icon-3 {
|
||||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||||
border-radius: 8px;
|
||||
}
|
||||
.invoice-icon-4 {
|
||||
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
|
||||
border-radius: 8px;
|
||||
}
|
||||
.invoice-icon-5 {
|
||||
background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);
|
||||
border-radius: 8px;
|
||||
}
|
||||
.invoice-icon-6 {
|
||||
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
|
||||
border-radius: 8px;
|
||||
}
|
||||
.invoice-icon-7 {
|
||||
background: linear-gradient(135deg, #d299c2 0%, #fef9d7 100%);
|
||||
border-radius: 8px;
|
||||
}
|
||||
.invoice-icon-8 {
|
||||
background: linear-gradient(135deg, #89f7fe 0%, #66a6ff 100%);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.invoice-number-link {
|
||||
color: #2469d6;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.invoice-number-link:hover {
|
||||
color: #1a4fb3;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Badge Styling - Centered */
|
||||
.badge {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
padding: 4px 10px;
|
||||
border-radius: 8px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.3px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.bg-success {
|
||||
background: linear-gradient(135deg, #18ce77 60%, #08ac52 110%) !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.bg-warning {
|
||||
background: linear-gradient(135deg, #ffb23c 53%, #e17800 110%) !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.bg-danger {
|
||||
background: linear-gradient(135deg, #ff5a4e 65%, #d90010 110%) !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* Action Button - Centered */
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #3492f8 55%, #1256cc 110%);
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
padding: 5px 10px;
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 1px 4px rgba(52, 146, 248, 0.3);
|
||||
color: white;
|
||||
white-space: nowrap;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: linear-gradient(135deg, #46b4fd 55%, #226ad6 110%);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 8px rgba(52, 146, 248, 0.4);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Amount Styling - Centered */
|
||||
.amount-cell {
|
||||
font-weight: 600;
|
||||
color: #194073;
|
||||
font-size: 13px;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.gst-cell {
|
||||
font-weight: 500;
|
||||
color: #63709b;
|
||||
font-size: 13px;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
/* Date Styling - Centered */
|
||||
.date-cell {
|
||||
font-size: 12.5px;
|
||||
color: #718096;
|
||||
font-weight: 500;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
/* Customer Name Styling - Centered */
|
||||
.customer-cell {
|
||||
font-weight: 500;
|
||||
color: #2d3748;
|
||||
font-size: 13px;
|
||||
max-width: 120px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: center !important;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Modal Styling */
|
||||
.modal.fade .modal-dialog {
|
||||
transition: transform 0.3s ease-out;
|
||||
transform: translate(0, -50px);
|
||||
}
|
||||
|
||||
.modal.show .modal-dialog {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-bottom: none;
|
||||
padding: 15px 25px;
|
||||
border-radius: 20px 20px 0 0;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: white;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.modal-header .btn-close {
|
||||
filter: invert(1);
|
||||
opacity: 0.8;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.modal-header .btn-close:hover {
|
||||
opacity: 1;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 30px;
|
||||
background: #f8fafc;
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 1200px) {
|
||||
.invoice-tools-row {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
max-width: 100%;
|
||||
min-width: auto;
|
||||
}
|
||||
|
||||
.filter-group {
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.invoice-management-bar {
|
||||
padding: 12px 20px;
|
||||
}
|
||||
|
||||
.invoice-tools-row {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.table th, .table td {
|
||||
font-size: 12px;
|
||||
padding: 8px 6px;
|
||||
}
|
||||
|
||||
.badge {
|
||||
font-size: 10px;
|
||||
padding: 3px 8px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
padding: 4px 8px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.filter-group {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.filter-select {
|
||||
min-width: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.create-invoice-btn {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.invoice-icon {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Empty State - Centered */
|
||||
.text-muted {
|
||||
color: #8a9bb9 !important;
|
||||
font-style: italic;
|
||||
padding: 30px !important;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Card Styling */
|
||||
.card {
|
||||
border-radius: 0 0 17px 17px;
|
||||
border: none;
|
||||
margin-bottom: 0 !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
background: #f8f9fa !important;
|
||||
border-bottom: 1px solid #e9ecef;
|
||||
border-radius: 0 !important;
|
||||
padding: 15px 25px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.card-header h4 {
|
||||
margin: 0;
|
||||
color: #2451af;
|
||||
font-weight: 700;
|
||||
font-size: 1.3rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Stats Summary - Centered */
|
||||
.stats-summary {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 12px;
|
||||
margin: 20px 25px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: white;
|
||||
padding: 15px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
|
||||
text-align: center;
|
||||
border-left: 3px solid #667eea;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: #2d3748;
|
||||
margin-bottom: 3px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.85rem;
|
||||
color: #718096;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Column Headers - Centered */
|
||||
.column-header {
|
||||
text-align: center !important;
|
||||
font-weight: 600;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
/* Remove extra spacing */
|
||||
.no-extra-space {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.compact-view {
|
||||
padding-top: 0 !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
/* Ensure all content in table is centered */
|
||||
.table tbody tr td {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.table tbody tr td .invoice-number-cell {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.table tbody tr td .btn-primary {
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container-fluid py-3">
|
||||
<!-- INVOICE MANAGEMENT -->
|
||||
<div class="invoice-management-box">
|
||||
<div class="invoice-management-bar">
|
||||
<span class="invoice-management-title">
|
||||
<i class="bi bi-receipt"></i> Invoice Management
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- TOOLS ROW - Search, Filter, Create Button -->
|
||||
<div class="invoice-tools-row">
|
||||
<!-- Search Box -->
|
||||
<div class="search-box">
|
||||
<i class="bi bi-search"></i>
|
||||
<input type="text" id="invoiceSearch" placeholder="Search by invoice number, customer name...">
|
||||
</div>
|
||||
|
||||
<!-- Filter Group -->
|
||||
<div class="filter-group">
|
||||
<select class="filter-select" id="statusFilter">
|
||||
<option value="">All Status</option>
|
||||
<option value="paid">Paid</option>
|
||||
<option value="pending">Pending</option>
|
||||
<option value="overdue">Overdue</option>
|
||||
</select>
|
||||
|
||||
<select class="filter-select" id="dateFilter">
|
||||
<option value="">All Dates</option>
|
||||
<option value="today">Today</option>
|
||||
<option value="week">This Week</option>
|
||||
<option value="month">This Month</option>
|
||||
</select>
|
||||
|
||||
<select class="filter-select" id="amountFilter">
|
||||
<option value="">Any Amount</option>
|
||||
<option value="0-1000">₹0 - ₹1,000</option>
|
||||
<option value="1000-5000">₹1,000 - ₹5,000</option>
|
||||
<option value="5000+">₹5,000+</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Create Invoice Button -->
|
||||
<a href="{{ route('admin.invoices.create') }}" class="create-invoice-btn">
|
||||
<i class="bi bi-plus-circle"></i> Create Invoice
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="invoice-management-main no-extra-space">
|
||||
<!-- Quick Stats Summary -->
|
||||
<div class="stats-summary">
|
||||
<div class="stat-card">
|
||||
<div class="stat-value">{{ $invoices->count() }}</div>
|
||||
<div class="stat-label">Total Invoices</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-value">₹{{ number_format($invoices->sum('final_amount_with_gst'), 2) }}</div>
|
||||
<div class="stat-label">Total Revenue</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-value">{{ $invoices->where('status', 'paid')->count() }}</div>
|
||||
<div class="stat-label">Paid Invoices</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-value">{{ $invoices->where('status', 'pending')->count() }}</div>
|
||||
<div class="stat-label">Pending Invoices</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ALL INVOICES TABLE -->
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-light d-flex justify-content-between align-items-center compact-view">
|
||||
<h4 class="mb-0">All Invoices</h4>
|
||||
<span class="text-muted" style="font-size: 12px;">
|
||||
{{ $invoices->count() }} invoices
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-0">
|
||||
<div class="table-container">
|
||||
<table class="table table-striped align-middle" id="invoicesTable">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th class="column-header">#</th>
|
||||
<th class="column-header">Invoice Number</th>
|
||||
<th class="column-header">Customer</th>
|
||||
<th class="column-header">Final Amount</th>
|
||||
<th class="column-header">GST %</th>
|
||||
<th class="column-header">Total w/GST</th>
|
||||
<th class="column-header">Status</th>
|
||||
<th class="column-header">Invoice Date</th>
|
||||
<th class="column-header">Due Date</th>
|
||||
<th class="column-header">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@php
|
||||
$totalInvoices = $invoices->count();
|
||||
$sortedInvoices = $invoices->sortByDesc('created_at'); // Latest first
|
||||
@endphp
|
||||
|
||||
@forelse($sortedInvoices as $i => $invoice)
|
||||
<tr>
|
||||
<td>{{ $totalInvoices - $i }}</td>
|
||||
|
||||
<td>
|
||||
<a href="#"
|
||||
class="text-primary fw-bold open-invoice-popup"
|
||||
data-id="{{ $invoice->id }}">
|
||||
{{ $invoice->invoice_number }}
|
||||
<div class="invoice-number-cell">
|
||||
<div class="invoice-icon invoice-icon-{{ (($totalInvoices - $i) % 8) + 1 }}">
|
||||
<i class="bi bi-file-earmark-text"></i>
|
||||
</div>
|
||||
<a href="#" class="invoice-number-link open-invoice-popup" data-id="{{ $invoice->id }}">
|
||||
{{ $invoice->invoice_number }}
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>{{ $invoice->customer_name }}</td>
|
||||
<td class="customer-cell">{{ $invoice->customer_name }}</td>
|
||||
|
||||
<td>₹{{ number_format($invoice->final_amount, 2) }}</td>
|
||||
<td>{{ $invoice->gst_percent }}%</td>
|
||||
<td>₹{{ number_format($invoice->final_amount_with_gst, 2) }}</td>
|
||||
<td class="amount-cell">₹{{ number_format($invoice->final_amount, 2) }}</td>
|
||||
<td class="gst-cell">{{ $invoice->gst_percent }}%</td>
|
||||
<td class="amount-cell">₹{{ number_format($invoice->final_amount_with_gst, 2) }}</td>
|
||||
|
||||
<td>
|
||||
<span class="badge
|
||||
@if($invoice->status=='paid') bg-success
|
||||
@elseif($invoice->status=='overdue') bg-danger
|
||||
@else bg-warning text-dark @endif">
|
||||
{{ ucfirst($invoice->status) }}
|
||||
</span>
|
||||
<span class="badge
|
||||
@if($invoice->status=='paid') bg-success
|
||||
@elseif($invoice->status=='overdue') bg-danger
|
||||
@else bg-warning @endif">
|
||||
{{ ucfirst($invoice->status) }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>{{ $invoice->invoice_date }}</td>
|
||||
<td>{{ $invoice->due_date }}</td>
|
||||
<td class="date-cell">{{ $invoice->invoice_date }}</td>
|
||||
<td class="date-cell">{{ $invoice->due_date }}</td>
|
||||
|
||||
<td>
|
||||
<a href="{{ route('admin.invoices.edit', $invoice->id) }}"
|
||||
class="btn btn-sm btn-primary">
|
||||
Edit
|
||||
</a>
|
||||
<a href="{{ route('admin.invoices.edit', $invoice->id) }}"
|
||||
class="btn btn-sm btn-primary">
|
||||
<i class="bi bi-pencil"></i> Edit
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="10" class="text-muted">No invoices found</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- POPUP MODAL --}}
|
||||
<div class="modal fade" id="invoiceModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">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 class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">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>
|
||||
document.addEventListener('click', function(e) {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Invoice popup functionality
|
||||
document.addEventListener('click', function(e) {
|
||||
if (e.target.closest('.open-invoice-popup')) {
|
||||
e.preventDefault();
|
||||
const id = e.target.closest('.open-invoice-popup').dataset.id;
|
||||
const modal = new bootstrap.Modal(document.getElementById('invoiceModal'));
|
||||
e.preventDefault();
|
||||
const id = e.target.closest('.open-invoice-popup').dataset.id;
|
||||
const modal = new bootstrap.Modal(document.getElementById('invoiceModal'));
|
||||
|
||||
document.getElementById('invoiceModalBody').innerHTML =
|
||||
"<p class='text-center text-muted'>Loading...</p>";
|
||||
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();
|
||||
modal.show();
|
||||
|
||||
fetch(`/admin/invoices/${id}/popup`)
|
||||
.then(res => res.text())
|
||||
.then(html => {
|
||||
document.getElementById('invoiceModalBody').innerHTML = html;
|
||||
});
|
||||
fetch(`/admin/invoices/${id}/popup`)
|
||||
.then(res => {
|
||||
if (!res.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
return res.text();
|
||||
})
|
||||
.then(html => {
|
||||
document.getElementById('invoiceModalBody').innerHTML = html;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading invoice details:', 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>";
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Search functionality
|
||||
const searchInput = document.getElementById('invoiceSearch');
|
||||
const statusFilter = document.getElementById('statusFilter');
|
||||
const dateFilter = document.getElementById('dateFilter');
|
||||
const amountFilter = document.getElementById('amountFilter');
|
||||
const table = document.getElementById('invoicesTable');
|
||||
const tableRows = table.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
|
||||
|
||||
function filterInvoices() {
|
||||
const searchTerm = searchInput.value.toLowerCase();
|
||||
const statusValue = statusFilter.value;
|
||||
const dateValue = dateFilter.value;
|
||||
const amountValue = amountFilter.value;
|
||||
|
||||
for (let row of tableRows) {
|
||||
const cells = row.getElementsByTagName('td');
|
||||
if (cells.length < 9) continue;
|
||||
|
||||
const invoiceNumber = cells[1].textContent.toLowerCase();
|
||||
const customerName = cells[2].textContent.toLowerCase();
|
||||
const status = cells[6].textContent.toLowerCase();
|
||||
const amount = parseFloat(cells[3].textContent.replace('₹', '').replace(',', ''));
|
||||
|
||||
const matchesSearch = invoiceNumber.includes(searchTerm) || customerName.includes(searchTerm);
|
||||
const matchesStatus = !statusValue || status.includes(statusValue);
|
||||
const matchesAmount = !amountValue || (
|
||||
amountValue === '0-1000' ? amount <= 1000 :
|
||||
amountValue === '1000-5000' ? amount > 1000 && amount <= 5000 :
|
||||
amountValue === '5000+' ? amount > 5000 : true
|
||||
);
|
||||
|
||||
row.style.display = matchesSearch && matchesStatus && matchesAmount ? '' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Add event listeners for filtering
|
||||
searchInput.addEventListener('input', filterInvoices);
|
||||
statusFilter.addEventListener('change', filterInvoices);
|
||||
dateFilter.addEventListener('change', filterInvoices);
|
||||
amountFilter.addEventListener('change', filterInvoices);
|
||||
|
||||
// Add hover effects to table rows
|
||||
for (let row of tableRows) {
|
||||
row.addEventListener('mouseenter', function() {
|
||||
this.style.cursor = 'pointer';
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@endsection
|
||||
Reference in New Issue
Block a user