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

@@ -10,7 +10,7 @@
body {
font-family: 'Inter', sans-serif;
overflow-x: hidden; /* Prevent horizontal scroll on body */
overflow-x: hidden;
}
.glass-card {
@@ -22,7 +22,6 @@
overflow: hidden;
}
/* New Stats Container */
.stats-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
@@ -43,9 +42,7 @@
min-height: 70px;
}
.stat-card:hover {
transform: translateY(-2px);
}
.stat-card:hover { transform: translateY(-2px); }
.stat-card.warning {
border-left-color: #f59e0b;
@@ -57,16 +54,6 @@
background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%);
}
.stat-card.danger {
border-left-color: #ef4444;
background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%);
}
.stat-card.info {
border-left-color: #3b82f6;
background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
}
.stat-card.secondary {
border-left-color: #8b5cf6;
background: linear-gradient(135deg, #faf5ff 0%, #f3e8ff 100%);
@@ -91,46 +78,19 @@
.stat-card.warning .stat-icon {
background: rgba(245, 158, 11, 0.1);
}
.stat-card.warning .stat-icon i {
color: #f59e0b;
}
.stat-card.warning .stat-icon i { color: #f59e0b; }
.stat-card.success .stat-icon {
background: rgba(16, 185, 129, 0.1);
}
.stat-card.success .stat-icon i {
color: #10b981;
}
.stat-card.danger .stat-icon {
background: rgba(239, 68, 68, 0.1);
}
.stat-card.danger .stat-icon i {
color: #ef4444;
}
.stat-card.info .stat-icon {
background: rgba(59, 130, 246, 0.1);
}
.stat-card.info .stat-icon i {
color: #3b82f6;
}
.stat-card.success .stat-icon i { color: #10b981; }
.stat-card.secondary .stat-icon {
background: rgba(139, 92, 246, 0.1);
}
.stat-card.secondary .stat-icon i { color: #8b5cf6; }
.stat-card.secondary .stat-icon i {
color: #8b5cf6;
}
.stat-content {
flex: 1;
}
.stat-content { flex: 1; }
.stat-value {
font-size: 22px;
@@ -147,14 +107,13 @@
line-height: 1.3;
}
/* Updated Search Container - Wider with icon on left */
.search-container {
background: rgba(255, 255, 255, 0.9);
border-radius: 10px;
padding: 6px 12px;
border: 1px solid rgba(0, 0, 0, 0.1);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
width: 350px; /* Increased width */
width: 350px;
display: flex;
align-items: center;
}
@@ -210,7 +169,6 @@
font-family: 'Inter', sans-serif;
}
/* Updated Table Styles - Fixed horizontal scroll */
.table-glass {
background: rgba(255, 255, 255, 0.9);
border-radius: 10px;
@@ -219,7 +177,6 @@
font-family: 'Inter', sans-serif;
}
/* Single gradient for entire header - Blue to Purple */
.table thead {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
}
@@ -232,20 +189,9 @@
border: none;
font-family: 'Inter', sans-serif;
position: relative;
background: linear-gradient(135deg, #667eea 0%);;
background: linear-gradient(135deg, #667eea 0%);
}
/* Remove individual curved borders */
.table-header:first-child {
border-top-left-radius: 0;
}
.table-header:last-child {
border-top-right-radius: 0;
}
/* Apply rounded corners to the entire header container */
.table-container thead tr:first-child th:first-child {
border-top-left-radius: 10px;
}
@@ -254,7 +200,6 @@
border-top-right-radius: 10px;
}
/* Updated Table Column Alignment */
.table > :not(caption) > * > * {
padding: 14px 12px;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
@@ -263,44 +208,35 @@
vertical-align: middle;
}
/* Center align specific columns */
.table > :not(caption) > * > *:nth-child(2), /* Customer ID */
.table > :not(caption) > * > *:nth-child(3), /* Orders */
.table > :not(caption) > * > *:nth-child(4), /* Total */
.table > :not(caption) > * > *:nth-child(5) { /* Create Date */
.table > :not(caption) > * > *:nth-child(2),
.table > :not(caption) > * > *:nth-child(3),
.table > :not(caption) > * > *:nth-child(4),
.table > :not(caption) > * > *:nth-child(5) {
text-align: center;
}
/* Customer Info column should remain left-aligned */
.table > :not(caption) > * > *:first-child {
text-align: left;
}
.table > :not(caption) > * > *:first-child { text-align: left; }
/* Status and Actions columns should remain as is */
.table > :not(caption) > * > *:nth-child(6), /* Status */
.table > :not(caption) > * > *:nth-child(7) { /* Actions */
.table > :not(caption) > * > *:nth-child(6),
.table > :not(caption) > * > *:nth-child(7),
.table > :not(caption) > * > *:nth-child(8),
.table > :not(caption) > * > *:nth-child(9) {
text-align: center;
}
/* Updated header alignment to match */
.table-header:nth-child(2),
.table-header:nth-child(3),
.table-header:nth-child(4),
.table-header:nth-child(5) {
text-align: center;
}
/* Customer Info header stays left */
.table-header:first-child {
text-align: Center;
}
/* Status and Actions headers stay centered */
.table-header:nth-child(5),
.table-header:nth-child(6),
.table-header:nth-child(7) {
.table-header:nth-child(7),
.table-header:nth-child(8),
.table-header:nth-child(9) {
text-align: center;
}
.table-header:first-child { text-align: Center; }
.customer-avatar {
width: 40px;
height: 40px;
@@ -374,7 +310,7 @@
.customer-info-column {
min-width: 220px;
max-width: 220px; /* Added max-width to prevent overflow */
max-width: 220px;
}
.table tbody tr {
@@ -391,31 +327,25 @@
color: #6c757d;
}
/* Remove customer-stats since we're adding columns */
/* Enhanced table styling - Fixed horizontal scroll */
.table-container {
border-radius: 10px;
overflow: hidden;
width: 100%; /* Ensure container takes full width */
width: 100%;
}
/* Fix table responsiveness */
.table-responsive {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
width: 100%;
}
/* Ensure table doesn't exceed container */
.table {
width: 100%;
max-width: 100%;
margin-bottom: 0;
table-layout: auto; /* Changed to auto for better column distribution */
table-layout: auto;
}
/* Fix for search and filter section */
.search-filter-container {
display: flex;
align-items: center;
@@ -439,11 +369,10 @@
flex-shrink: 0;
}
/* New columns styling */
.orders-column, .total-column, .customer-id-column, .create-date-column {
text-align: center;
font-weight: 500;
min-width: 80px; /* Added minimum widths for consistency */
min-width: 80px;
}
.orders-count {
@@ -458,7 +387,6 @@
font-weight: 600;
}
/* ---------- Pagination Styles ---------- */
.pagination-container {
display: flex;
justify-content: space-between;
@@ -485,14 +413,10 @@
justify-content: flex-end;
}
.pagination-btn {
.pagination-img-btn {
background: #fff;
border: 1px solid #e3eaf6;
color: #1a2951;
padding: 8px 12px;
border-radius: 6px;
font-size: 13px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
@@ -500,20 +424,19 @@
justify-content: center;
min-width: 40px;
height: 32px;
padding: 0;
}
.pagination-btn:hover:not(:disabled) {
.pagination-img-btn:hover:not(:disabled) {
background: #1a2951;
color: white;
border-color: #1a2951;
}
.pagination-btn:disabled {
.pagination-img-btn:disabled {
background: #f8fafc;
color: #cbd5e0;
border-color: #e2e8f0;
cursor: not-allowed;
opacity: 0.6;
opacity: 0.5;
}
.pagination-page-btn {
@@ -551,61 +474,11 @@
flex-wrap: wrap;
}
.pagination-ellipsis {
color: #9ba5bb;
font-size: 13px;
padding: 0 4px;
}
/* Image-based pagination buttons */
.pagination-img-btn {
background: #fff;
border: 1px solid #e3eaf6;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
min-width: 40px;
height: 32px;
padding: 0;
}
.pagination-img-btn:hover:not(:disabled) {
background: #1a2951;
border-color: #1a2951;
}
.pagination-img-btn:disabled {
background: #f8fafc;
border-color: #e2e8f0;
cursor: not-allowed;
opacity: 0.5;
}
.pagination-img-btn img {
width: 16px;
height: 16px;
filter: brightness(0) saturate(100%) invert(26%) sepia(89%) saturate(748%) hue-rotate(201deg) brightness(93%) contrast(89%);
transition: filter 0.3s ease;
}
.pagination-img-btn:hover:not(:disabled) img {
filter: brightness(0) saturate(100%) invert(100%) sepia(100%) saturate(0%) hue-rotate(288deg) brightness(106%) contrast(101%);
}
.pagination-img-btn:disabled img {
filter: brightness(0) saturate(100%) invert(84%) sepia(8%) saturate(165%) hue-rotate(179deg) brightness(89%) contrast(86%);
}
/* Mobile responsive fixes */
@media (max-width: 1200px) {
.table > :not(caption) > * > * {
padding: 12px 8px;
font-size: 13px;
}
.customer-info-column {
min-width: 180px;
max-width: 180px;
@@ -613,65 +486,42 @@
}
@media (max-width: 992px) {
.search-container {
width: 280px;
}
.stats-container {
grid-template-columns: repeat(2, 1fr);
}
.search-container { width: 280px; }
.stats-container { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 768px) {
.stats-container {
grid-template-columns: repeat(2, 1fr);
}
.stats-container { grid-template-columns: repeat(2, 1fr); }
.search-filter-container {
flex-direction: column;
align-items: stretch;
gap: 10px;
}
.search-section {
justify-content: center;
}
.search-container {
width: 100%;
}
.search-section { justify-content: center; }
.search-container { width: 100%; }
.filter-section {
justify-content: center;
flex-wrap: wrap;
}
.pagination-container {
flex-direction: column;
gap: 10px;
align-items: stretch;
}
.pagination-controls {
justify-content: center;
}
.pagination-controls { justify-content: center; }
.table > :not(caption) > * > * {
padding: 10px 6px;
font-size: 12px;
}
.customer-info-column {
min-width: 150px;
max-width: 150px;
}
.customer-avatar {
width: 32px;
height: 32px;
font-size: 0.8rem;
}
.action-btn {
width: 26px;
height: 26px;
@@ -680,19 +530,12 @@
}
@media (max-width: 576px) {
.stats-container {
grid-template-columns: 1fr;
}
.table-responsive {
font-size: 12px;
}
.stats-container { grid-template-columns: 1fr; }
.table-responsive { font-size: 12px; }
.customer-info-column {
min-width: 120px;
max-width: 120px;
}
.premium-badge,
.regular-badge,
.status-badge {
@@ -703,14 +546,11 @@
</style>
<div class="container-fluid">
<!-- Header - Removed gradient -->
<div class="d-flex justify-content-between align-items-center mb-3">
<h4 style="color: #2c3e50; font-weight: 700; font-family: 'Inter', sans-serif;">Customer List</h4>
</div>
<!-- Stats Cards with NEW DESIGN -->
<div class="stats-container">
<!-- Total Customers -->
<div class="stat-card">
<div class="stat-icon">
<i class="bi bi-people-fill"></i>
@@ -721,7 +561,6 @@
</div>
</div>
<!-- New This Month -->
<div class="stat-card warning">
<div class="stat-icon">
<i class="bi bi-person-plus"></i>
@@ -739,7 +578,6 @@
</div>
</div>
<!-- Active Customers -->
<div class="stat-card success">
<div class="stat-icon">
<i class="bi bi-activity"></i>
@@ -755,7 +593,6 @@
</div>
</div>
<!-- Premium Customers -->
<div class="stat-card secondary">
<div class="stat-icon">
<i class="bi bi-award-fill"></i>
@@ -772,10 +609,8 @@
</div>
</div>
<!-- Search and Filter Section -->
<div class="glass-card p-3 mb-3">
<div class="search-filter-container">
<!-- Search Section - Wider with icon on left -->
<div class="search-section">
<form method="GET" action="{{ route('admin.customers.index') }}" class="d-flex align-items-center">
<div class="search-container">
@@ -792,7 +627,6 @@
</form>
</div>
<!-- Filter Section -->
<div class="filter-section">
<a href="{{ route('admin.customers.index', ['status'=>'active', 'search'=>$search ?? '']) }}"
class="filter-btn {{ ($status ?? '') == 'active' ? 'active' : '' }}">
@@ -818,7 +652,6 @@
</div>
</div>
<!-- Customer List Table -->
<div class="table-container">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
@@ -828,8 +661,8 @@
<th class="table-header">Customer ID</th>
<th class="table-header">Orders</th>
<th class="table-header">Order Total</th>
<th class="table-header">Total Payable</th> {{-- NEW --}}
<th class="table-header">Remaining</th> {{-- NEW --}}
<th class="table-header">Total Payable</th>
<th class="table-header">Remaining</th>
<th class="table-header">Create Date</th>
<th class="table-header">Status</th>
<th class="table-header" width="100">Actions</th>
@@ -839,113 +672,106 @@
<tbody id="customersTableBody">
@forelse($customers as $c)
@php
// Invoice total (with GST)
$totalPayable = $c->invoices->sum('final_amount_with_gst');
// Orders = invoice count
$ordersCount = $c->invoices->count();
// Order Total = items total from all invoices (final_amount)
$orderTotal = $c->invoices->sum('final_amount');
// Total payable = grand total with GST + groups
$totalPayable = $c->invoices->sum('grand_total_with_charges');
// Total paid via installments
$totalPaid = $c->invoices
->flatMap(fn($inv) => $inv->installments)
->sum('amount');
$totalPaid = $c->invoiceInstallments->sum('amount');
// Remaining amount
$remainingAmount = max($totalPayable - $totalPaid, 0);
@endphp
<tr>
<!-- Customer Info Column -->
<td class="customer-info-column">
<div class="d-flex align-items-start">
<div class="customer-avatar me-3">
{{ strtoupper(substr($c->customer_name,0,1)) }}
</div>
<div>
<div class="fw-bold">{{ $c->customer_name }}</div>
@if($c->customer_type == 'premium')
<span class="premium-badge">Premium Customer</span>
@else
<span class="regular-badge">Regular Customer</span>
@endif
<div class="customer-details mt-1">
{{ $c->email }}<br>
{{ $c->mobile_no }}
<tr>
<td class="customer-info-column">
<div class="d-flex align-items-start">
<div class="customer-avatar me-3">
{{ strtoupper(substr($c->customer_name,0,1)) }}
</div>
<div>
<div class="fw-bold">{{ $c->customer_name }}</div>
@if($c->customer_type == 'premium')
<span class="premium-badge">Premium Customer</span>
@else
<span class="regular-badge">Regular Customer</span>
@endif
<div class="customer-details mt-1">
{{ $c->email }}<br>
{{ $c->mobile_no }}
</div>
</div>
</div>
</div>
</td>
</td>
<!-- Customer ID -->
<td class="customer-id-column">
<span class="fw-bold text-primary">{{ $c->customer_id }}</span>
</td>
<td class="customer-id-column">
<span class="fw-bold text-primary">{{ $c->customer_id }}</span>
</td>
<!-- Orders Column -->
<td class="orders-column">
<span class="orders-count">{{ $c->orders->count() }}</span>
</td>
<td class="orders-column">
<span class="orders-count">{{ $ordersCount }}</span>
</td>
<!-- Total Column -->
<td class="total-column">
<span class="total-amount">
{{ number_format($c->orders->sum('ttl_amount'), 2) }}
</span>
</td>
<td class="total-column">
<span class="total-amount">
{{ number_format($totalPayable, 2) }}
</span>
</td>
<td class="total-column">
@if($remainingAmount > 0)
<span class="text-danger fw-bold">
{{ number_format($remainingAmount, 2) }}
<td class="total-column">
<span class="total-amount">
{{ number_format($orderTotal, 2) }}
</span>
@else
<span class="text-success fw-bold">
₹0.00
</td>
<td class="total-column">
<span class="total-amount">
{{ number_format($totalPayable, 2) }}
</span>
@endif
</td>
</td>
<td class="total-column">
@if($remainingAmount > 0)
<span class="text-danger fw-bold">
{{ number_format($remainingAmount, 2) }}
</span>
@else
<span class="text-success fw-bold">
₹0.00
</span>
@endif
</td>
<td class="create-date-column">
<span class="text-muted">{{ $c->created_at ? $c->created_at->format('d-m-Y') : '-' }}</span>
</td>
<td>
@if($c->status === 'active')
<span class="status-badge active-status">Active</span>
@else
<span class="status-badge inactive-status">Inactive</span>
@endif
</td>
<!-- Create Date -->
<td class="create-date-column">
<span class="text-muted">{{ $c->created_at ? $c->created_at->format('d-m-Y') : '-' }}</span>
</td>
<td>
<div class="d-flex justify-content-center">
<a href="{{ route('admin.customers.view', $c->id) }}"
class="action-btn" title="View">
<i class="bi bi-eye"></i>
</a>
<!-- Status -->
<td>
@if($c->status === 'active')
<span class="status-badge active-status">Active</span>
@else
<span class="status-badge inactive-status">Inactive</span>
@endif
</td>
<!-- Actions -->
<td>
<div class="d-flex justify-content-center">
<a href="{{ route('admin.customers.view', $c->id) }}"
class="action-btn" title="View">
<i class="bi bi-eye"></i>
</a>
<form action="{{ route('admin.customers.status', $c->id) }}"
method="POST" style="display:inline-block;">
@csrf
<button class="action-btn" title="Toggle Status" type="submit">
<i class="bi bi-power"></i>
</button>
</form>
</div>
</td>
</tr>
<form action="{{ route('admin.customers.status', $c->id) }}"
method="POST" style="display:inline-block;">
@csrf
<button class="action-btn" title="Toggle Status" type="submit">
<i class="bi bi-power"></i>
</button>
</form>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="text-center py-4">
<td colspan="9" class="text-center py-4">
<i class="bi bi-people display-4 text-muted d-block mb-2"></i>
<span class="text-muted">No customers found.</span>
</td>
@@ -956,14 +782,12 @@
</div>
</div>
<!-- Pagination Controls -->
<div class="pagination-container">
<div class="pagination-info" id="pageInfo">
Showing {{ $customers->firstItem() ?? 0 }} to {{ $customers->lastItem() ?? 0 }} of {{ $customers->total() }} entries
</div>
<div class="pagination-controls">
<button class="pagination-img-btn" id="prevPageBtn" title="Previous page" {{ $customers->onFirstPage() ? 'disabled' : '' }}>
<!-- Left arrow SVG -->
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
@@ -977,7 +801,6 @@
@endfor
</div>
<button class="pagination-img-btn" id="nextPageBtn" title="Next page" {{ $customers->hasMorePages() ? '' : 'disabled' }}>
<!-- Right arrow SVG -->
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 4L10 8L6 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
@@ -988,7 +811,6 @@
<script>
document.addEventListener('DOMContentLoaded', function() {
// Add hover effects to table rows
const tableRows = document.querySelectorAll('.table tbody tr');
tableRows.forEach(row => {
row.addEventListener('mouseenter', function() {
@@ -1000,7 +822,6 @@
});
});
// Pagination button handlers
document.getElementById('prevPageBtn').addEventListener('click', function() {
@if(!$customers->onFirstPage())
window.location.href = '{{ $customers->previousPageUrl() }}';
@@ -1015,4 +836,4 @@
});
</script>
@endsection
@endsection