Merge branch 'dev' of http://103.248.30.24:3000/kent-logistics/Kent-logistics-Laravel into dev
This commit is contained in:
@@ -5,6 +5,14 @@
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
/* Import Inter font */
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
|
||||
|
||||
body {
|
||||
font-family: 'Inter', sans-serif;
|
||||
overflow-x: hidden; /* Prevent horizontal scroll on body */
|
||||
}
|
||||
|
||||
.glass-card {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(20px);
|
||||
@@ -14,71 +22,171 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.stats-card {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
/* New Stats Container */
|
||||
.stats-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
gap: 12px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: linear-gradient(135deg, #f8f9ff 0%, #f0f4ff 100%);
|
||||
padding: 16px;
|
||||
border-radius: 12px;
|
||||
padding: 15px;
|
||||
color: white;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-left: 4px solid #4f46e5;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
transition: transform 0.3s ease;
|
||||
min-height: 80px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
min-height: 70px;
|
||||
}
|
||||
|
||||
.stats-card:hover {
|
||||
transform: translateY(-3px);
|
||||
|
||||
.stat-card:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.stats-count {
|
||||
font-size: 1.4rem;
|
||||
|
||||
.stat-card.warning {
|
||||
border-left-color: #f59e0b;
|
||||
background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%);
|
||||
}
|
||||
|
||||
.stat-card.success {
|
||||
border-left-color: #10b981;
|
||||
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%);
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(79, 70, 229, 0.1);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.stat-icon i {
|
||||
font-size: 18px;
|
||||
color: #4f46e5;
|
||||
}
|
||||
|
||||
.stat-card.warning .stat-icon {
|
||||
background: rgba(245, 158, 11, 0.1);
|
||||
}
|
||||
|
||||
.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.secondary .stat-icon {
|
||||
background: rgba(139, 92, 246, 0.1);
|
||||
}
|
||||
|
||||
.stat-card.secondary .stat-icon i {
|
||||
color: #8b5cf6;
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
color: #1a202c;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.stats-label {
|
||||
font-size: 0.75rem;
|
||||
opacity: 0.9;
|
||||
|
||||
.stat-label {
|
||||
font-size: 12px;
|
||||
color: #718096;
|
||||
font-weight: 500;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.stats-icon {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
font-size: 1.2rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* Updated Search Container - Wider with icon on left */
|
||||
.search-container {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border-radius: 10px;
|
||||
padding: 8px 15px;
|
||||
padding: 6px 12px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
width: 100%;
|
||||
width: 350px; /* Increased width */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
border: none;
|
||||
background: transparent;
|
||||
padding: 5px 10px;
|
||||
padding: 4px 8px;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
font-size: 13px;
|
||||
outline: none;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.search-input::placeholder {
|
||||
color: #9ca3af;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.filter-btn {
|
||||
background: rgba(102, 126, 234, 0.1);
|
||||
border: 2px solid transparent;
|
||||
color: #667eea;
|
||||
padding: 6px 15px;
|
||||
padding: 5px 12px;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
margin: 0 5px;
|
||||
margin: 0 3px;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 0.8rem;
|
||||
font-size: 0.75rem;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.filter-btn.active {
|
||||
@@ -91,45 +199,106 @@
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
padding: 8px 20px;
|
||||
padding: 6px 16px;
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 0.8rem;
|
||||
font-size: 0.75rem;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
/* Updated Table Styles - Fixed horizontal scroll */
|
||||
.table-glass {
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
/* Single gradient for entire header - Blue to Purple */
|
||||
.table thead {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
|
||||
}
|
||||
|
||||
.table-header {
|
||||
color: white !important;
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
padding: 12px 15px !important;
|
||||
position: relative;
|
||||
font-size: 0.85rem;
|
||||
padding: 14px 12px !important;
|
||||
border: none;
|
||||
font-family: 'Inter', sans-serif;
|
||||
position: relative;
|
||||
background: linear-gradient(135deg, #667eea 0%);;
|
||||
|
||||
}
|
||||
|
||||
/* Curved borders for table headers */
|
||||
/* Remove individual curved borders */
|
||||
.table-header:first-child {
|
||||
border-top-left-radius: 10px;
|
||||
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;
|
||||
}
|
||||
|
||||
.table-container thead tr:first-child th:last-child {
|
||||
border-top-right-radius: 10px;
|
||||
}
|
||||
|
||||
/* Updated Table Column Alignment */
|
||||
.table > :not(caption) > * > * {
|
||||
padding: 12px 15px;
|
||||
padding: 14px 12px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
font-size: 14px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
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 */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Customer Info column should remain left-aligned */
|
||||
.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 */
|
||||
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(6),
|
||||
.table-header:nth-child(7) {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.customer-avatar {
|
||||
@@ -165,7 +334,7 @@
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
padding: 4px 10px;
|
||||
padding: 5px 10px;
|
||||
border-radius: 8px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
@@ -203,15 +372,9 @@
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.stats-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.customer-info-column {
|
||||
min-width: 300px;
|
||||
min-width: 220px;
|
||||
max-width: 220px; /* Added max-width to prevent overflow */
|
||||
}
|
||||
|
||||
.table tbody tr {
|
||||
@@ -228,44 +391,28 @@
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.customer-stats {
|
||||
font-size: 0.75rem;
|
||||
color: #6c757d;
|
||||
}
|
||||
/* Remove customer-stats since we're adding columns */
|
||||
|
||||
/* Enhanced table styling */
|
||||
/* Enhanced table styling - Fixed horizontal scroll */
|
||||
.table-container {
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
width: 100%; /* Ensure container takes full width */
|
||||
}
|
||||
|
||||
.table-header-container {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 10px 10px 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Remove horizontal scroll */
|
||||
/* Fix table responsiveness */
|
||||
.table-responsive {
|
||||
overflow-x: visible !important;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container-fluid {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Adjust table layout to fit without scroll */
|
||||
|
||||
/* Ensure table doesn't exceed container */
|
||||
.table {
|
||||
width: 100%;
|
||||
min-width: auto;
|
||||
}
|
||||
|
||||
/* Ensure proper column sizing */
|
||||
.table th,
|
||||
.table td {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 100%;
|
||||
margin-bottom: 0;
|
||||
table-layout: auto; /* Changed to auto for better column distribution */
|
||||
}
|
||||
|
||||
/* Fix for search and filter section */
|
||||
@@ -275,21 +422,43 @@
|
||||
justify-content: space-between;
|
||||
flex-wrap: nowrap;
|
||||
gap: 15px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search-section {
|
||||
flex: 1;
|
||||
min-width: 300px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* ---------- Pagination Styles (Same as Account Dashboard) ---------- */
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
.orders-count {
|
||||
font-size: 14px;
|
||||
color: #1a202c;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.total-amount {
|
||||
font-size: 14px;
|
||||
color: #10b981;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* ---------- Pagination Styles ---------- */
|
||||
.pagination-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -297,18 +466,23 @@
|
||||
margin-top: 15px;
|
||||
padding: 12px 0;
|
||||
border-top: 1px solid #eef3fb;
|
||||
font-family: 'Inter', sans-serif;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pagination-info {
|
||||
font-size: 13px;
|
||||
color: #9ba5bb;
|
||||
font-weight: 600;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.pagination-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.pagination-btn {
|
||||
@@ -354,6 +528,8 @@
|
||||
transition: all 0.3s ease;
|
||||
min-width: 36px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.pagination-page-btn:hover {
|
||||
@@ -372,6 +548,7 @@
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.pagination-ellipsis {
|
||||
@@ -422,14 +599,46 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.search-container {
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
.stats-container {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.stats-container {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.search-filter-container {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.search-section {
|
||||
min-width: auto;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
@@ -446,63 +655,127 @@
|
||||
.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;
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.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 {
|
||||
font-size: 0.6rem;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container-fluid">
|
||||
<!-- Header -->
|
||||
<!-- Header - Removed gradient -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h4 style="color: #2c3e50; font-weight: 700;">Customer List</h4>
|
||||
<h4 style="color: #2c3e50; font-weight: 700; font-family: 'Inter', sans-serif;">Customer List</h4>
|
||||
</div>
|
||||
|
||||
<!-- Stats Cards with REAL DATA -->
|
||||
<div class="stats-row">
|
||||
<div class="stats-card">
|
||||
<div class="stats-count">{{ $allCustomers->count() }}</div>
|
||||
<div class="stats-label">Total Customers</div>
|
||||
<i class="bi bi-people-fill stats-icon"></i>
|
||||
<!-- 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>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ $allCustomers->count() }}</div>
|
||||
<div class="stat-label">Total Customers</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stats-card" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);">
|
||||
<div class="stats-count">
|
||||
@php
|
||||
$newThisMonth = $allCustomers->filter(function($customer) {
|
||||
return $customer->created_at->format('Y-m') === now()->format('Y-m');
|
||||
})->count();
|
||||
@endphp
|
||||
{{ $newThisMonth }}
|
||||
<!-- New This Month -->
|
||||
<div class="stat-card warning">
|
||||
<div class="stat-icon">
|
||||
<i class="bi bi-person-plus"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">
|
||||
@php
|
||||
$newThisMonth = $allCustomers->filter(function($customer) {
|
||||
return $customer->created_at->format('Y-m') === now()->format('Y-m');
|
||||
})->count();
|
||||
@endphp
|
||||
{{ $newThisMonth }}
|
||||
</div>
|
||||
<div class="stat-label">New This Month</div>
|
||||
</div>
|
||||
<div class="stats-label">New This Month</div>
|
||||
<i class="bi bi-person-plus stats-icon"></i>
|
||||
</div>
|
||||
|
||||
<div class="stats-card" style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);">
|
||||
<div class="stats-count">
|
||||
@php
|
||||
$activeCustomers = $allCustomers->where('status', 'active')->count();
|
||||
@endphp
|
||||
{{ $activeCustomers }}
|
||||
<!-- Active Customers -->
|
||||
<div class="stat-card success">
|
||||
<div class="stat-icon">
|
||||
<i class="bi bi-activity"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">
|
||||
@php
|
||||
$activeCustomers = $allCustomers->where('status', 'active')->count();
|
||||
@endphp
|
||||
{{ $activeCustomers }}
|
||||
</div>
|
||||
<div class="stat-label">Active Customers</div>
|
||||
</div>
|
||||
<div class="stats-label">Active Customers</div>
|
||||
<i class="bi bi-activity stats-icon"></i>
|
||||
</div>
|
||||
|
||||
<div class="stats-card" style="background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);">
|
||||
<div class="stats-count">
|
||||
@php
|
||||
$premiumCount = $allCustomers->where('customer_type', 'premium')->count();
|
||||
@endphp
|
||||
{{ $premiumCount }}
|
||||
<!-- Premium Customers -->
|
||||
<div class="stat-card secondary">
|
||||
<div class="stat-icon">
|
||||
<i class="bi bi-award-fill"></i>
|
||||
</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">
|
||||
@php
|
||||
$premiumCount = $allCustomers->where('customer_type', 'premium')->count();
|
||||
@endphp
|
||||
{{ $premiumCount }}
|
||||
</div>
|
||||
<div class="stat-label">Premium Customers</div>
|
||||
</div>
|
||||
<div class="stats-label">Premium Customers</div>
|
||||
<i class="bi bi-award-fill stats-icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Search and Filter Section - FIXED LAYOUT -->
|
||||
<!-- Search and Filter Section -->
|
||||
<div class="glass-card p-3 mb-3">
|
||||
<div class="search-filter-container">
|
||||
<!-- Search Section -->
|
||||
<!-- 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">
|
||||
@@ -511,7 +784,7 @@
|
||||
name="search"
|
||||
value="{{ $search ?? '' }}"
|
||||
class="search-input"
|
||||
placeholder="Search Customer Name, Email, or Phone...">
|
||||
placeholder="Search customers by name, email, or phone...">
|
||||
@if(!empty($status))
|
||||
<input type="hidden" name="status" value="{{ $status }}">
|
||||
@endif
|
||||
@@ -547,13 +820,15 @@
|
||||
<div class="table-container">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead>
|
||||
<thead class="gradient-table-header">
|
||||
<tr>
|
||||
<th class="table-header">Customer Info</th>
|
||||
<th class="table-header">Customer ID</th>
|
||||
<th class="table-header">Orders</th>
|
||||
<th class="table-header">Total</th>
|
||||
<th class="table-header">Create Date</th>
|
||||
<th class="table-header">Status</th>
|
||||
<th class="table-header" width="120">Actions</th>
|
||||
<th class="table-header" width="100">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="customersTableBody">
|
||||
@@ -576,20 +851,27 @@
|
||||
{{ $c->email }}<br>
|
||||
{{ $c->mobile_no }}
|
||||
</div>
|
||||
<div class="customer-stats mt-1">
|
||||
{{ $c->orders->count() }} orders • ₹{{ number_format($c->orders->sum('ttl_amount'), 2) }} total
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<!-- Customer ID -->
|
||||
<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>
|
||||
|
||||
<!-- Total Column -->
|
||||
<td class="total-column">
|
||||
<span class="total-amount">₹{{ number_format($c->orders->sum('ttl_amount'), 2) }}</span>
|
||||
</td>
|
||||
|
||||
<!-- Create Date -->
|
||||
<td>
|
||||
<td class="create-date-column">
|
||||
<span class="text-muted">{{ $c->created_at ? $c->created_at->format('d-m-Y') : '-' }}</span>
|
||||
</td>
|
||||
|
||||
@@ -604,7 +886,7 @@
|
||||
|
||||
<!-- Actions -->
|
||||
<td>
|
||||
<div class="d-flex">
|
||||
<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>
|
||||
@@ -622,7 +904,7 @@
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5" class="text-center py-4">
|
||||
<td colspan="7" 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>
|
||||
|
||||
@@ -12,6 +12,7 @@ html, body {
|
||||
|
||||
body, .container-fluid {
|
||||
background: #f4f7fc;
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
}
|
||||
|
||||
.container-fluid {
|
||||
@@ -34,6 +35,7 @@ body, .container-fluid {
|
||||
letter-spacing: .018em;
|
||||
color: #18213e;
|
||||
margin-bottom: 2px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.dash-title-desc {
|
||||
@@ -42,6 +44,7 @@ body, .container-fluid {
|
||||
margin-bottom: 5px;
|
||||
font-weight: 500;
|
||||
letter-spacing: .01em;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
/* ===== STATS CARDS - RESPONSIVE GRID ===== */
|
||||
@@ -127,12 +130,14 @@ body, .container-fluid {
|
||||
color:#63709b;
|
||||
font-weight:600;
|
||||
letter-spacing:.28px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.stats-value {
|
||||
font-size:1.25rem;
|
||||
font-weight:700;
|
||||
color:#194073;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.stats-card:hover .stats-icon {
|
||||
@@ -170,6 +175,7 @@ body, .container-fluid {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 11px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.order-mgmt-title i {
|
||||
@@ -191,6 +197,7 @@ body, .container-fluid {
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-family: inherit;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.create-order-btn:hover {
|
||||
@@ -201,7 +208,7 @@ body, .container-fluid {
|
||||
.card-body, .order-mgmt-main {
|
||||
background: #fff;
|
||||
border-radius: 0 0 17px 17px;
|
||||
padding:25px;
|
||||
padding:20px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
@@ -213,7 +220,7 @@ body, .container-fluid {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
/* ===== TABLE STYLES ===== */
|
||||
/* ===== IMPROVED TABLE STYLES ===== */
|
||||
.table thead tr {
|
||||
background: #feebbe !important;
|
||||
border-radius: 12px 12px 0 0;
|
||||
@@ -226,9 +233,10 @@ body, .container-fluid {
|
||||
font-weight: 700;
|
||||
color: #343535;
|
||||
letter-spacing: 0.02em;
|
||||
font-size:15px;
|
||||
padding-top: 12px;
|
||||
padding-bottom: 10px;
|
||||
font-size: 15px;
|
||||
padding: 16px 12px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
border-bottom: 2px solid #e9ecef;
|
||||
}
|
||||
|
||||
.table thead th:first-child { border-radius: 9px 0 0 0;}
|
||||
@@ -239,20 +247,24 @@ body, .container-fluid {
|
||||
border-radius:9px;
|
||||
box-shadow:0 2px 12px #e2ebf941;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 2px;
|
||||
border-spacing: 0 8px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.table-striped tbody tr {
|
||||
background: #fff;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.04);
|
||||
margin-bottom: 2px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.04);
|
||||
margin-bottom: 8px;
|
||||
transition: all 0.3s ease;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.table-striped tbody tr:hover {
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.08);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
|
||||
transform: translateY(-2px);
|
||||
background: #f8fafd;
|
||||
}
|
||||
|
||||
.table-striped tbody tr:nth-of-type(odd) {
|
||||
@@ -264,39 +276,110 @@ body, .container-fluid {
|
||||
}
|
||||
|
||||
.table td {
|
||||
padding: 12px 6px;
|
||||
padding: 14px 12px;
|
||||
border: none;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #495057;
|
||||
line-height: 1.5;
|
||||
border-bottom: 1px solid #f1f3f4;
|
||||
}
|
||||
|
||||
.table td:first-child {
|
||||
border-radius: 6px 0 0 6px;
|
||||
border-radius: 8px 0 0 8px;
|
||||
border-left: 3px solid transparent;
|
||||
}
|
||||
|
||||
.table td:last-child {
|
||||
border-radius: 0 6px 6px 0;
|
||||
border-radius: 0 8px 8px 0;
|
||||
}
|
||||
|
||||
.table-responsive {
|
||||
border-radius:10px;
|
||||
}
|
||||
|
||||
.badge {
|
||||
font-size:13px;
|
||||
font-weight:600;
|
||||
padding:7px 17px;
|
||||
border-radius:12px;
|
||||
/* ===== UPDATED STATUS BADGE STYLES ===== */
|
||||
.badge {
|
||||
padding: 7px 17px !important;
|
||||
border-radius: 20px !important;
|
||||
font-weight: 600 !important;
|
||||
font-size: 13px !important;
|
||||
border: 2px solid transparent !important;
|
||||
min-width: 40px !important;
|
||||
text-align: center !important;
|
||||
display: inline-flex !important;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: 1.2 !important;
|
||||
font-family: 'Inter', sans-serif;
|
||||
gap: 6px;
|
||||
width: 110px;
|
||||
}
|
||||
|
||||
.bg-info {
|
||||
background-color:#22cbfa!important;
|
||||
color:#fff!important;
|
||||
.status-icon {
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Pending Status - SAME SIZE WITH CLOCK ICON */
|
||||
.badge-pending {
|
||||
background: linear-gradient(135deg, #fef3c7, #fde68a) !important;
|
||||
color: #d97706 !important;
|
||||
border-color: #f59e0b !important;
|
||||
}
|
||||
|
||||
/* In Transit Status - SAME SIZE WITH TRUCK ICON */
|
||||
.badge-in_transit {
|
||||
background: linear-gradient(135deg, #dbeafe, #93c5fd) !important;
|
||||
color: #1e40af !important;
|
||||
border-color: #3b82f6 !important;
|
||||
}
|
||||
|
||||
/* Dispatched Status - SAME SIZE WITH BOX ICON */
|
||||
.badge-dispatched {
|
||||
background: linear-gradient(135deg, #e9d5ff, #c4b5fd) !important;
|
||||
color: #6b21a8 !important;
|
||||
border-color: #8b5cf6 !important;
|
||||
}
|
||||
|
||||
/* Delivered Status - SAME SIZE WITH CHECK ICON */
|
||||
.badge-delivered {
|
||||
background: linear-gradient(135deg, #d1fae5, #a7f3d0) !important;
|
||||
color: #065f46 !important;
|
||||
border-color: #10b981 !important;
|
||||
}
|
||||
|
||||
/* Default badge styles - SAME SIZE */
|
||||
.badge.bg-info {
|
||||
background: linear-gradient(135deg, #4cc9f0, #4361ee) !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.badge.bg-success {
|
||||
background: linear-gradient(135deg, #4ade80, #22c55e) !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.badge.bg-warning {
|
||||
background: linear-gradient(135deg, #fbbf24, #f59e0b) !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.badge.bg-danger {
|
||||
background: linear-gradient(135deg, #f87171, #ef4444) !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-weight:600;
|
||||
color:#1d3159;
|
||||
font-size:15px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.form-control, .form-select {
|
||||
@@ -305,6 +388,7 @@ body, .container-fluid {
|
||||
background: #f7f9fe;
|
||||
border:1.2px solid #c7dbfa;
|
||||
font-weight:500;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.form-control:focus, .form-select:focus {
|
||||
@@ -316,6 +400,7 @@ body, .container-fluid {
|
||||
color:#2469d6;
|
||||
font-weight:600;
|
||||
text-decoration:underline;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
/* ===== HORIZONTAL SCROLL CONTAINER ===== */
|
||||
@@ -327,7 +412,7 @@ body, .container-fluid {
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
|
||||
padding: 8px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.table-wrapper::-webkit-scrollbar {
|
||||
@@ -348,7 +433,7 @@ body, .container-fluid {
|
||||
}
|
||||
|
||||
.table {
|
||||
min-width: 1200px;
|
||||
min-width: 2000px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
@@ -394,6 +479,7 @@ body, .container-fluid {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.create-order-modal .close-btn {
|
||||
@@ -425,6 +511,7 @@ body, .container-fluid {
|
||||
color: #1d3159;
|
||||
font-size: 15px;
|
||||
margin-bottom: 5px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.create-order-modal .form-control,
|
||||
@@ -435,6 +522,7 @@ body, .container-fluid {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
padding: 8px 12px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.create-order-modal .form-control:focus,
|
||||
@@ -449,6 +537,7 @@ body, .container-fluid {
|
||||
padding: 10px 20px;
|
||||
font-weight: 600;
|
||||
border-radius: 8px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.create-order-modal .btn-info:hover {
|
||||
@@ -461,6 +550,7 @@ body, .container-fluid {
|
||||
padding: 12px 30px;
|
||||
font-weight: 600;
|
||||
border-radius: 8px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.create-order-modal .btn-success:hover {
|
||||
@@ -472,6 +562,7 @@ body, .container-fluid {
|
||||
border: none;
|
||||
color: #000;
|
||||
font-weight: 600;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.create-order-modal .btn-warning:hover {
|
||||
@@ -481,6 +572,7 @@ body, .container-fluid {
|
||||
.create-order-modal .btn-danger {
|
||||
background: #dc3545;
|
||||
border: none;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.create-order-modal .btn-danger:hover {
|
||||
@@ -505,6 +597,7 @@ body, .container-fluid {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
/* ===== ORDER DETAILS MODAL STYLES ===== */
|
||||
@@ -536,6 +629,7 @@ body, .container-fluid {
|
||||
font-weight: 700;
|
||||
color: white;
|
||||
margin: 0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.modal-header .btn-close {
|
||||
@@ -554,6 +648,7 @@ body, .container-fluid {
|
||||
background: #f8fafc;
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
/* ===== PAGINATION STYLES ===== */
|
||||
@@ -570,6 +665,7 @@ body, .container-fluid {
|
||||
font-size: 13px;
|
||||
color: #9ba5bb;
|
||||
font-weight: 600;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.pagination-controls {
|
||||
@@ -593,6 +689,7 @@ body, .container-fluid {
|
||||
justify-content: center;
|
||||
min-width: 40px;
|
||||
height: 32px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.pagination-btn:hover:not(:disabled) {
|
||||
@@ -621,6 +718,7 @@ body, .container-fluid {
|
||||
transition: all 0.3s ease;
|
||||
min-width: 36px;
|
||||
text-align: center;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.pagination-page-btn:hover {
|
||||
@@ -645,6 +743,7 @@ body, .container-fluid {
|
||||
color: #9ba5bb;
|
||||
font-size: 13px;
|
||||
padding: 0 4px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.pagination-img-btn {
|
||||
@@ -728,7 +827,7 @@ body, .container-fluid {
|
||||
|
||||
.table th,
|
||||
.table td {
|
||||
padding: 10px 5px;
|
||||
padding: 12px 8px;
|
||||
}
|
||||
|
||||
.pagination-container {
|
||||
@@ -811,7 +910,7 @@ body, .container-fluid {
|
||||
|
||||
.table th,
|
||||
.table td {
|
||||
padding: 8px 4px;
|
||||
padding: 10px 6px;
|
||||
}
|
||||
|
||||
.badge {
|
||||
@@ -913,7 +1012,7 @@ body, .container-fluid {
|
||||
|
||||
.table th,
|
||||
.table td {
|
||||
padding: 6px 3px;
|
||||
padding: 8px 4px;
|
||||
}
|
||||
|
||||
.form-control, .form-select {
|
||||
@@ -1047,67 +1146,80 @@ body, .container-fluid {
|
||||
</span>
|
||||
</div>
|
||||
<div class="card-body table-responsive">
|
||||
<table class="table table-striped table-bordered align-middle text-center">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Order ID</th>
|
||||
<th>Mark No</th>
|
||||
<th>Origin</th>
|
||||
<th>Destination</th>
|
||||
<th>Total CTN</th>
|
||||
<th>Total QTY</th>
|
||||
<th>Total TTL/QTY</th>
|
||||
<th>Total Amount (₹)</th>
|
||||
<th>Total CBM</th>
|
||||
<th>Total TTL CBM</th>
|
||||
<th>Total KG</th>
|
||||
<th>Total TTL KG</th>
|
||||
<th>Status</th>
|
||||
<th>Date</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="ordersTableBody">
|
||||
@forelse($orders as $order)
|
||||
<tr>
|
||||
<td>{{ $order->id }}</td>
|
||||
<td>
|
||||
<a href="javascript:void(0)"
|
||||
class="fw-semibold text-primary open-order-modal"
|
||||
data-id="{{ $order->id }}">
|
||||
{{ $order->order_id }}
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td>{{ $order->mark_no }}</td>
|
||||
<td>{{ $order->origin }}</td>
|
||||
<td>{{ $order->destination }}</td>
|
||||
<td>{{ $order->ctn }}</td>
|
||||
<td>{{ $order->qty }}</td>
|
||||
<td>{{ $order->ttl_qty }}</td>
|
||||
<td>₹{{ number_format($order->ttl_amount, 2) }}</td>
|
||||
<td>{{ $order->cbm }}</td>
|
||||
<td>{{ $order->ttl_cbm }}</td>
|
||||
<td>{{ $order->kg }}</td>
|
||||
<td>{{ $order->ttl_kg }}</td>
|
||||
<div class="table-wrapper">
|
||||
<table class="table table-striped table-bordered align-middle text-center">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Order ID</th>
|
||||
<th>Mark No</th>
|
||||
<th>Origin</th>
|
||||
<th>Destination</th>
|
||||
<th>Total CTN</th>
|
||||
<th>Total QTY</th>
|
||||
<th>Total TTL/QTY</th>
|
||||
<th>Total Amount (₹)</th>
|
||||
<th>Total CBM</th>
|
||||
<th>Total TTL CBM</th>
|
||||
<th>Total KG</th>
|
||||
<th>Total TTL KG</th>
|
||||
<th>Status</th>
|
||||
<th>Date</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="ordersTableBody">
|
||||
@forelse($orders as $order)
|
||||
<tr>
|
||||
<td>{{ $order->id }}</td>
|
||||
<td>
|
||||
<span class="badge bg-info text-dark">{{ ucfirst($order->status) }}</span>
|
||||
</td>
|
||||
<td>{{ $order->created_at->format('d-m-Y') }}</td>
|
||||
<td>
|
||||
<a href="{{ route('admin.orders.show', $order->id) }}" class="btn btn-sm btn-outline-primary">
|
||||
<i class="bi bi-eye"></i> View
|
||||
<a href="javascript:void(0)"
|
||||
class="fw-semibold text-primary open-order-modal"
|
||||
data-id="{{ $order->id }}">
|
||||
{{ $order->order_id }}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="16" class="text-muted">No orders found</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<td>{{ $order->mark_no }}</td>
|
||||
<td>{{ $order->origin }}</td>
|
||||
<td>{{ $order->destination }}</td>
|
||||
<td>{{ $order->ctn }}</td>
|
||||
<td>{{ $order->qty }}</td>
|
||||
<td>{{ $order->ttl_qty }}</td>
|
||||
<td>₹{{ number_format($order->ttl_amount, 2) }}</td>
|
||||
<td>{{ $order->cbm }}</td>
|
||||
<td>{{ $order->ttl_cbm }}</td>
|
||||
<td>{{ $order->kg }}</td>
|
||||
<td>{{ $order->ttl_kg }}</td>
|
||||
<td>
|
||||
<span class="badge badge-{{ $order->status }}">
|
||||
@if($order->status == 'pending')
|
||||
<i class="bi bi-clock-fill status-icon"></i>
|
||||
@elseif($order->status == 'in_transit')
|
||||
<i class="bi bi-truck status-icon"></i>
|
||||
@elseif($order->status == 'dispatched')
|
||||
<i class="bi bi-box-seam status-icon"></i>
|
||||
@elseif($order->status == 'delivered')
|
||||
<i class="bi bi-check-circle-fill status-icon"></i>
|
||||
@endif
|
||||
{{ ucfirst(str_replace('_', ' ', $order->status)) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ $order->created_at->format('d-m-Y') }}</td>
|
||||
<td>
|
||||
<a href="{{ route('admin.orders.show', $order->id) }}" class="btn btn-sm btn-outline-primary">
|
||||
<i class="bi bi-eye"></i> View
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="16" class="text-muted">No orders found</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Pagination Controls -->
|
||||
<div class="pagination-container">
|
||||
@@ -1566,7 +1678,13 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
<td>${order.kg || ''}</td>
|
||||
<td>${order.ttl_kg || ''}</td>
|
||||
<td>
|
||||
<span class="badge bg-info text-dark">${order.status ? order.status.charAt(0).toUpperCase() + order.status.slice(1) : ''}</span>
|
||||
<span class="badge badge-${order.status}">
|
||||
${order.status === 'pending' ? '<i class="bi bi-clock-fill status-icon"></i>' : ''}
|
||||
${order.status === 'in_transit' ? '<i class="bi bi-truck status-icon"></i>' : ''}
|
||||
${order.status === 'dispatched' ? '<i class="bi bi-box-seam status-icon"></i>' : ''}
|
||||
${order.status === 'delivered' ? '<i class="bi bi-check-circle-fill status-icon"></i>' : ''}
|
||||
${order.status ? order.status.charAt(0).toUpperCase() + order.status.slice(1).replace('_', ' ') : ''}
|
||||
</span>
|
||||
</td>
|
||||
<td>${new Date(order.created_at).toLocaleDateString('en-GB')}</td>
|
||||
<td>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -212,14 +212,21 @@
|
||||
<i class="bi bi-bag"></i> Orders
|
||||
</a>
|
||||
<a href="{{ route('admin.requests') }}" class="{{ request()->routeIs('admin.requests') ? 'active' : '' }}"><i class="bi bi-envelope"></i> Requests</a>
|
||||
<li>
|
||||
<a href="{{ route('admin.profile.requests') }}">
|
||||
<i class="bi bi-person-lines-fill"></i>
|
||||
Profile Update Requests
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<a href="{{ route('admin.staff') }}" class="{{ request()->routeIs('admin.staff') ? 'active' : '' }}"><i class="bi bi-person-badge"></i> Staff</a>
|
||||
<a href="{{ route('admin.account') }}" class="{{ request()->routeIs('admin.account') ? 'active' : '' }}"><i class="bi bi-gear"></i> Account</a>
|
||||
<a href="{{ route('admin.marklist.index') }}" class="{{ request()->routeIs('admin.marklist.index') ? 'active' : '' }}"><i class="bi bi-list-check"></i> Mark List</a>
|
||||
|
||||
<form method="POST" action="{{ route('admin.logout') }}" class="mt-4 px-3">
|
||||
<!-- <form method="POST" action="{{ route('admin.logout') }}" class="mt-4 px-3">
|
||||
@csrf
|
||||
<!-- <button type="submit" class="btn btn-danger w-100"><i class="bi bi-box-arrow-right"></i> Logout</button>-->
|
||||
</form>
|
||||
<button type="submit" class="btn btn-danger w-100"><i class="bi bi-box-arrow-right"></i> Logout</button>
|
||||
</form> -->
|
||||
</div>
|
||||
|
||||
<div class="main-content">
|
||||
|
||||
@@ -5,28 +5,96 @@
|
||||
@section('content')
|
||||
<div class="container py-4">
|
||||
|
||||
{{-- Header --}}
|
||||
{{-- HEADER --}}
|
||||
<div class="card shadow-sm rounded-3 border-0">
|
||||
<div class="card-body">
|
||||
|
||||
{{-- TOP BAR --}}
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<h4 class="fw-bold mb-0">Order Details</Details></h4>
|
||||
<h4 class="fw-bold mb-0">Order Details</h4>
|
||||
<small class="text-muted">Detailed view of this shipment order</small>
|
||||
</div>
|
||||
<a href="{{ route('admin.dashboard') }}" class="btn-close"></a>
|
||||
</div>
|
||||
|
||||
{{-- ACTION BUTTONS --}}
|
||||
<div class="mt-3 d-flex gap-2">
|
||||
|
||||
{{-- ADD ITEM --}}
|
||||
<button class="btn btn-add-item" data-bs-toggle="modal" data-bs-target="#addItemModal">
|
||||
<i class="fas fa-plus-circle me-2"></i>Add New Item
|
||||
</button>
|
||||
|
||||
{{-- EDIT ORDER --}}
|
||||
@if($order->status === 'pending')
|
||||
<button class="btn btn-edit-order" onclick="document.getElementById('editOrderForm').style.display='block'">
|
||||
<i class="fas fa-edit me-2"></i>Edit Order
|
||||
</button>
|
||||
@else
|
||||
<button class="btn btn-edit-order" disabled><i class="fas fa-edit me-2"></i>Edit Order</button>
|
||||
@endif
|
||||
|
||||
{{-- DELETE ORDER --}}
|
||||
@if($order->status === 'pending')
|
||||
<form action="{{ route('admin.orders.destroy', $order->id) }}"
|
||||
method="POST"
|
||||
onsubmit="return confirm('Delete this entire order?')">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button class="btn btn-delete-order">
|
||||
<i class="fas fa-trash-alt me-2"></i>Delete Order
|
||||
</button>
|
||||
</form>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
{{-- Customer Info --}}
|
||||
{{-- EDIT ORDER FORM --}}
|
||||
<div id="editOrderForm" class="p-3 bg-light rounded mb-4 shadow-sm" style="display:none;">
|
||||
<h5 class="fw-bold mb-3">Edit Order</h5>
|
||||
|
||||
<form action="{{ route('admin.orders.update', $order->id) }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label>Mark No</label>
|
||||
<input type="text" name="mark_no" value="{{ $order->mark_no }}" class="form-control custom-input">
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 mb-3">
|
||||
<label>Origin</label>
|
||||
<input type="text" name="origin" value="{{ $order->origin }}" class="form-control custom-input">
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 mb-3">
|
||||
<label>Destination</label>
|
||||
<input type="text" name="destination" value="{{ $order->destination }}" class="form-control custom-input">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-save-changes">Save Changes</button>
|
||||
<button type="button"
|
||||
class="btn btn-cancel"
|
||||
onclick="document.getElementById('editOrderForm').style.display='none'">
|
||||
Cancel
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{-- CUSTOMER INFO --}}
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8 d-flex">
|
||||
<div class="me-3">
|
||||
<div class="rounded-circle bg-secondary text-white d-flex align-items-center justify-content-center"
|
||||
<div class="rounded-circle bg-secondary text-white d-flex align-items-center justify-content-center"
|
||||
style="width:60px; height:60px; font-size:20px;">
|
||||
{{ strtoupper(substr($user->customer_name ?? 'U', 0, 1)) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h5 class="mb-0">{{ $user->customer_name ?? 'Unknown Customer' }}</h5>
|
||||
<p class="mb-0">{{ $user->company_name ?? 'N/A' }}</p>
|
||||
@@ -34,13 +102,14 @@
|
||||
<p class="mb-0 text-muted">{{ $user->mobile_no ?? '' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 text-end">
|
||||
<p class="mb-0">{{ $user->address ?? '' }}</p>
|
||||
<small class="text-muted">{{ $user->pincode ?? '' }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Order Summary --}}
|
||||
{{-- ORDER SUMMARY --}}
|
||||
<div class="bg-light rounded p-3 mb-3">
|
||||
<div class="row text-center">
|
||||
<div class="col-md-3 border-end">
|
||||
@@ -65,7 +134,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Origin - Destination --}}
|
||||
{{-- ORIGIN / DESTINATION --}}
|
||||
<div class="row text-center mb-4">
|
||||
<div class="col-md-6">
|
||||
<p class="mb-1 fw-semibold text-muted">Origin</p>
|
||||
@@ -77,7 +146,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Order Items Table --}}
|
||||
{{-- ITEMS TABLE --}}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered align-middle text-center">
|
||||
<thead class="table-light">
|
||||
@@ -88,15 +157,17 @@
|
||||
<th>QTY</th>
|
||||
<th>TTL/QTY</th>
|
||||
<th>Unit</th>
|
||||
<th>Price (₹)</th>
|
||||
<th>TTL Amount (₹)</th>
|
||||
<th>Price</th>
|
||||
<th>Total Amount</th>
|
||||
<th>CBM</th>
|
||||
<th>TTL CBM</th>
|
||||
<th>KG</th>
|
||||
<th>TTL KG</th>
|
||||
<th>Shop No</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach($order->items as $index => $item)
|
||||
<tr>
|
||||
@@ -113,38 +184,531 @@
|
||||
<td>{{ $item->kg }}</td>
|
||||
<td>{{ $item->ttl_kg }}</td>
|
||||
<td>{{ $item->shop_no }}</td>
|
||||
|
||||
<td>
|
||||
<form action="{{ route('admin.orders.deleteItem', $item->id) }}"
|
||||
method="POST"
|
||||
onsubmit="return confirm('Delete this item?')">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button class="btn btn-sm btn-delete-item">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{-- Totals --}}
|
||||
{{-- TOTALS --}}
|
||||
<div class="row text-center mt-4">
|
||||
<div class="col-md-3">
|
||||
<h6 class="fw-bold text-primary">{{ $order->ctn }}</h6>
|
||||
<small class="text-muted">Total CTN</small>
|
||||
<small>Total CTN</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<h6 class="fw-bold text-primary">{{ $order->qty }}</h6>
|
||||
<small class="text-muted">Total QTY</small>
|
||||
<small>Total QTY</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<h6 class="fw-bold text-success">{{ $order->ttl_kg }}</h6>
|
||||
<small class="text-muted">Total TTL KG</small>
|
||||
<small>Total KG</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<h6 class="fw-bold text-danger">₹{{ number_format($order->ttl_amount, 2) }}</h6>
|
||||
<small class="text-muted">Total Amount</small>
|
||||
<small>Total Amount</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
{{-- ADD ITEM MODAL --}}
|
||||
<div class="modal fade" id="addItemModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content custom-modal">
|
||||
|
||||
<div class="modal-header modal-gradient-header">
|
||||
<h5 class="modal-title text-white"><i class="fas fa-cube me-2"></i>Add Item To Order</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
|
||||
<form action="{{ route('admin.orders.addItem', $order->id) }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<div class="modal-body">
|
||||
|
||||
{{-- DELETED ITEMS --}}
|
||||
@php
|
||||
$deletedItems = \App\Models\OrderItem::onlyTrashed()
|
||||
->where('order_id', $order->id)
|
||||
->get();
|
||||
@endphp
|
||||
|
||||
<h5 class="section-title">Deleted Items (Use / Restore)</h5>
|
||||
|
||||
<ul class="list-group mb-3">
|
||||
|
||||
@forelse($deletedItems as $deleted)
|
||||
<li class="list-group-item">
|
||||
|
||||
<div class="d-flex justify-content-between">
|
||||
|
||||
<div>
|
||||
<strong>{{ $deleted->description }}</strong><br>
|
||||
<small>
|
||||
CTN: {{ $deleted->ctn }},
|
||||
QTY: {{ $deleted->qty }},
|
||||
TTL/QTY: {{ $deleted->ttl_qty }},
|
||||
Unit: {{ $deleted->unit }},
|
||||
Price: ₹{{ $deleted->price }},
|
||||
TTL Amt: ₹{{ $deleted->ttl_amount }},
|
||||
CBM: {{ $deleted->cbm }},
|
||||
TTL CBM: {{ $deleted->ttl_cbm }},
|
||||
KG: {{ $deleted->kg }},
|
||||
TTL KG: {{ $deleted->ttl_kg }},
|
||||
Shop: {{ $deleted->shop_no }}
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
|
||||
{{-- Auto-fill button --}}
|
||||
<button type="button" class="btn btn-sm btn-use-item"
|
||||
onclick="fillFormFromDeleted({{ json_encode($deleted) }})">
|
||||
Use This
|
||||
</button>
|
||||
|
||||
{{-- Restore --}}
|
||||
<form action="{{ route('admin.orders.restoreItem', $deleted->id) }}" method="POST">
|
||||
@csrf
|
||||
<button class="btn btn-sm btn-restore">Restore</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</li>
|
||||
@empty
|
||||
<li class="list-group-item text-muted">No deleted items.</li>
|
||||
@endforelse
|
||||
|
||||
</ul>
|
||||
|
||||
{{-- ADD FORM --}}
|
||||
<div class="row g-3">
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Description</label>
|
||||
<input type="text" name="description" class="form-control custom-input" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">CTN</label>
|
||||
<input type="number" name="ctn" class="form-control custom-input">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">QTY</label>
|
||||
<input type="number" name="qty" class="form-control custom-input">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">TTL QTY</label>
|
||||
<input type="number" name="ttl_qty" class="form-control custom-input">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Unit</label>
|
||||
<input type="text" name="unit" class="form-control custom-input">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Price</label>
|
||||
<input type="number" name="price" class="form-control custom-input">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Total Amount</label>
|
||||
<input type="number" name="ttl_amount" class="form-control custom-input">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">CBM</label>
|
||||
<input type="number" name="cbm" class="form-control custom-input">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">TTL CBM</label>
|
||||
<input type="number" name="ttl_cbm" class="form-control custom-input">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">KG</label>
|
||||
<input type="number" name="kg" class="form-control custom-input">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">TTL KG</label>
|
||||
<input type="number" name="ttl_kg" class="form-control custom-input">
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Shop No</label>
|
||||
<input type="text" name="shop_no" class="form-control custom-input">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-modal-close" data-bs-dismiss="modal">Close</button>
|
||||
<button class="btn btn-modal-add">Add Item</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- AUTO-FILL SCRIPT --}}
|
||||
<script>
|
||||
function fillFormFromDeleted(item) {
|
||||
document.querySelector('input[name="description"]').value = item.description;
|
||||
document.querySelector('input[name="ctn"]').value = item.ctn;
|
||||
document.querySelector('input[name="qty"]').value = item.qty;
|
||||
document.querySelector('input[name="ttl_qty"]').value = item.ttl_qty;
|
||||
document.querySelector('input[name="unit"]').value = item.unit;
|
||||
document.querySelector('input[name="price"]').value = item.price;
|
||||
document.querySelector('input[name="ttl_amount"]').value = item.ttl_amount;
|
||||
document.querySelector('input[name="cbm"]').value = item.cbm;
|
||||
document.querySelector('input[name="ttl_cbm"]').value = item.ttl_cbm;
|
||||
document.querySelector('input[name="kg"]').value = item.kg;
|
||||
document.querySelector('input[name="ttl_kg"]').value = item.ttl_kg;
|
||||
document.querySelector('input[name="shop_no"]').value = item.shop_no;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* Custom Button Styles */
|
||||
.btn-add-item {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 10px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px 0 rgba(102, 126, 234, 0.3);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.btn-add-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px 0 rgba(102, 126, 234, 0.4);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-add-item::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
|
||||
transition: 0.5s;
|
||||
}
|
||||
|
||||
.btn-add-item:hover::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.btn-edit-order {
|
||||
background: linear-gradient(135deg, #4776E6 0%, #8E54E9 100%);
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 10px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px 0 rgba(71, 118, 230, 0.3);
|
||||
}
|
||||
|
||||
.btn-edit-order:hover:not(:disabled) {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px 0 rgba(71, 118, 230, 0.4);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-edit-order:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-delete-order {
|
||||
background: linear-gradient(135deg, #ff416c 0%, #ff4b2b 100%);
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 10px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px 0 rgba(255, 65, 108, 0.3);
|
||||
}
|
||||
|
||||
.btn-delete-order:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px 0 rgba(255, 65, 108, 0.4);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-delete-item {
|
||||
background: linear-gradient(135deg, #ff416c 0%, #ff4b2b 100%);
|
||||
border: none;
|
||||
color: white;
|
||||
border-radius: 6px;
|
||||
padding: 6px 12px;
|
||||
transition: all 0.3s ease;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-delete-item:hover {
|
||||
transform: scale(1.05);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Form Buttons */
|
||||
.btn-save-changes {
|
||||
background: linear-gradient(135deg, #00b09b 0%, #96c93d 100%);
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 12px rgba(0, 176, 155, 0.2);
|
||||
}
|
||||
|
||||
.btn-save-changes:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 6px 20px rgba(0, 176, 155, 0.4);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
background: linear-gradient(135deg, #8e9eab 0%, #eef2f3 100%);
|
||||
border: none;
|
||||
color: #2c3e50;
|
||||
padding: 10px 20px;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-cancel:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(142, 158, 171, 0.3);
|
||||
}
|
||||
|
||||
/* Modal Styles */
|
||||
.custom-modal {
|
||||
border-radius: 15px;
|
||||
border: none;
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.modal-gradient-header {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-bottom: none;
|
||||
padding: 20px 25px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
color: #2c3e50;
|
||||
font-weight: 600;
|
||||
margin-bottom: 15px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 2px solid #667eea;
|
||||
}
|
||||
|
||||
.custom-input {
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 8px;
|
||||
padding: 10px 15px;
|
||||
transition: all 0.3s ease;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.custom-input:focus {
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn-use-item {
|
||||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||||
border: none;
|
||||
color: white;
|
||||
border-radius: 6px;
|
||||
padding: 5px 15px;
|
||||
font-size: 0.875rem;
|
||||
transition: all 0.3s ease;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.btn-use-item:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(79, 172, 254, 0.4);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-restore {
|
||||
background: linear-gradient(135deg, #00b09b 0%, #96c93d 100%);
|
||||
border: none;
|
||||
color: white;
|
||||
border-radius: 6px;
|
||||
padding: 5px 15px;
|
||||
font-size: 0.875rem;
|
||||
transition: all 0.3s ease;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.btn-restore:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(0, 176, 155, 0.4);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-modal-close {
|
||||
background: linear-gradient(135deg, #8e9eab 0%, #eef2f3 100%);
|
||||
border: none;
|
||||
color: #2c3e50;
|
||||
padding: 10px 25px;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-modal-close:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(142, 158, 171, 0.3);
|
||||
}
|
||||
|
||||
.btn-modal-add {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 10px 25px;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 15px 0 rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.btn-modal-add:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px 0 rgba(102, 126, 234, 0.4);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Animation for the Add Item Button */
|
||||
@keyframes pulse-glow {
|
||||
0% {
|
||||
box-shadow: 0 0 0 0 rgba(102, 126, 234, 0.7);
|
||||
}
|
||||
70% {
|
||||
box-shadow: 0 0 0 10px rgba(102, 126, 234, 0);
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 0 0 0 rgba(102, 126, 234, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.btn-add-item {
|
||||
animation: pulse-glow 2s infinite;
|
||||
}
|
||||
|
||||
/* List group items */
|
||||
.list-group-item {
|
||||
border: 1px solid #e9ecef;
|
||||
margin-bottom: 8px;
|
||||
border-radius: 8px !important;
|
||||
transition: all 0.3s ease;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.list-group-item:hover {
|
||||
border-color: #667eea;
|
||||
transform: translateX(5px);
|
||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
/* Enhanced table styling */
|
||||
.table {
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.table thead th {
|
||||
background: #667eea ;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 15px 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.table tbody tr {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.table tbody tr:hover {
|
||||
background-color: rgba(102, 126, 234, 0.05);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* Badge styling */
|
||||
.badge {
|
||||
font-size: 0.85em;
|
||||
padding: 8px 12px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* Card enhancements */
|
||||
.card {
|
||||
border: none;
|
||||
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.btn-add-item,
|
||||
.btn-edit-order,
|
||||
.btn-delete-order {
|
||||
padding: 10px 15px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.modal-gradient-header {
|
||||
padding: 15px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@endsection
|
||||
111
resources/views/admin/profile_update_requests.blade.php
Normal file
111
resources/views/admin/profile_update_requests.blade.php
Normal file
@@ -0,0 +1,111 @@
|
||||
@extends('admin.layouts.app')
|
||||
|
||||
@section('page-title', 'Profile Update Requests')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid px-0">
|
||||
|
||||
@php
|
||||
$perPage = 5;
|
||||
$currentPage = request()->get('page', 1);
|
||||
$currentPage = max(1, (int)$currentPage);
|
||||
$total = $requests->count();
|
||||
$totalPages = ceil($total / $perPage);
|
||||
$currentItems = $requests->slice(($currentPage - 1) * $perPage, $perPage);
|
||||
@endphp
|
||||
|
||||
<style>
|
||||
.old-value { color: #6b7280; font-weight: 600; }
|
||||
.new-value { color: #111827; font-weight: 700; }
|
||||
.changed { background: #fef3c7; padding: 6px; border-radius: 6px; }
|
||||
.box { padding: 10px 14px; border-radius: 8px; background: #f8fafc; margin-bottom: 10px; }
|
||||
.diff-label { font-size: 13px; font-weight: 700; }
|
||||
.actions { display: flex; gap: 10px; }
|
||||
</style>
|
||||
|
||||
<h4 class="fw-bold my-3">Profile Update Requests ({{ $total }})</h4>
|
||||
|
||||
<div class="card mb-4 shadow-sm">
|
||||
<div class="card-body pb-1">
|
||||
|
||||
<div class="table-responsive custom-table-wrapper">
|
||||
<table class="table align-middle mb-0 custom-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>User</th>
|
||||
<th>Requested Changes</th>
|
||||
<th>Status</th>
|
||||
<th>Requested At</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@foreach($currentItems as $index => $req)
|
||||
@php
|
||||
$user = $req->user;
|
||||
// FIX: Convert string to array
|
||||
$newData = is_array($req->data) ? $req->data : json_decode($req->data, true);
|
||||
@endphp
|
||||
|
||||
<tr>
|
||||
<td><strong>{{ ($currentPage - 1) * $perPage + $index + 1 }}</strong></td>
|
||||
|
||||
<td>
|
||||
<strong>{{ $user->customer_name }}</strong><br>
|
||||
<small>{{ $user->email }}</small><br>
|
||||
<small>ID: {{ $user->customer_id }}</small>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
@foreach($newData as $key => $newValue)
|
||||
@php
|
||||
$oldValue = $user->$key ?? '—';
|
||||
$changed = $oldValue != $newValue;
|
||||
@endphp
|
||||
|
||||
<div class="box {{ $changed ? 'changed' : '' }}">
|
||||
<span class="diff-label">{{ ucfirst(str_replace('_',' ', $key)) }}:</span><br>
|
||||
<span class="old-value">Old: {{ $oldValue }}</span><br>
|
||||
<span class="new-value">New: {{ $newValue ?? '—' }}</span>
|
||||
</div>
|
||||
@endforeach
|
||||
</td>
|
||||
|
||||
<td>
|
||||
@if($req->status == 'pending')
|
||||
<span class="badge badge-pending">Pending</span>
|
||||
@elseif($req->status == 'approved')
|
||||
<span class="badge badge-approved">Approved</span>
|
||||
@else
|
||||
<span class="badge badge-rejected">Rejected</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
<td>{{ $req->created_at->format('d M Y, h:i A') }}</td>
|
||||
|
||||
<td class="actions">
|
||||
@if($req->status == 'pending')
|
||||
<a href="{{ route('admin.profile.approve', $req->id) }}" class="btn btn-success btn-sm">
|
||||
<i class="bi bi-check-circle"></i> Approve
|
||||
</a>
|
||||
|
||||
<a href="{{ route('admin.profile.reject', $req->id) }}" class="btn btn-danger btn-sm">
|
||||
<i class="bi bi-x-circle"></i> Reject
|
||||
</a>
|
||||
@else
|
||||
<span class="text-muted">Completed</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@@ -6,20 +6,28 @@
|
||||
<style>
|
||||
/* ===== GLOBAL RESPONSIVE STYLES ===== */
|
||||
html, body {
|
||||
overflow-x: hidden !important;
|
||||
max-width: 100%;
|
||||
overflow-x: hidden !important;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
|
||||
/* Use Inter globally (keeps your existing @import too) */
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
||||
|
||||
|
||||
/* Apply Inter globally but keep specificity low so your component styles still work */
|
||||
:root { --admin-font: 'Inter', sans-serif; }
|
||||
body, input, select, textarea, button, table, th, td, .report-container {
|
||||
font-family: var(--admin-font);
|
||||
}
|
||||
|
||||
.report-container {
|
||||
|
||||
background: #ffffff;
|
||||
padding: 25px;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
|
||||
margin: 20px auto;
|
||||
max-width: 100%;
|
||||
font-family: 'Inter', sans-serif;
|
||||
/* font-family now coming from :root */
|
||||
border: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
@@ -69,18 +77,21 @@
|
||||
.stats-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
gap: 15px;
|
||||
gap: 12px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: linear-gradient(135deg, #f8f9ff 0%, #f0f4ff 100%);
|
||||
padding: 18px 15px;
|
||||
padding: 16px;
|
||||
border-radius: 12px;
|
||||
border-left: 4px solid #4f46e5;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
transition: transform 0.3s ease;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
min-height: 70px;
|
||||
}
|
||||
|
||||
.stat-card:hover {
|
||||
@@ -112,7 +123,16 @@
|
||||
background: linear-gradient(135deg, #faf5ff 0%, #f3e8ff 100%);
|
||||
}
|
||||
|
||||
|
||||
.stat-icon {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(79, 70, 229, 0.1);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.stat-icon i {
|
||||
font-size: 18px;
|
||||
@@ -143,9 +163,9 @@
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
/* .stat-card.info .stat-icon {
|
||||
.stat-card.info .stat-icon {
|
||||
background: rgba(59, 130, 246, 0.1);
|
||||
} */
|
||||
}
|
||||
|
||||
.stat-card.info .stat-icon i {
|
||||
color: #3b82f6;
|
||||
@@ -159,16 +179,20 @@
|
||||
color: #8b5cf6;
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
color: #1a202c;
|
||||
margin-bottom: 4px;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 13px;
|
||||
font-size: 12px;
|
||||
color: #718096;
|
||||
font-weight: 500;
|
||||
line-height: 1.3;
|
||||
@@ -216,10 +240,10 @@
|
||||
border-radius: 8px;
|
||||
border: 1.5px solid #e5e7eb;
|
||||
background: #ffffff;
|
||||
font-size: 13px;
|
||||
font-size: 14px; /* increased to match global font sizing */
|
||||
color: #1f2937;
|
||||
transition: all 0.3s ease;
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-family: var(--admin-font);
|
||||
}
|
||||
|
||||
.filter-control:focus {
|
||||
@@ -242,12 +266,15 @@
|
||||
/* Ensure table takes full width and doesn't wrap */
|
||||
.report-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
/* keep your collapse behavior but update spacing to match Orders page */
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
min-width: 1200px; /* Minimum width to prevent squeezing */
|
||||
table-layout: auto; /* Allow columns to adjust based on content */
|
||||
font-size: 14px; /* unified table font size */
|
||||
}
|
||||
|
||||
/* Table header styling - CENTER ALIGNED */
|
||||
/* Table header styling - CENTER ALIGNED (keep your gradient & sticky) */
|
||||
.report-table thead {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
position: sticky;
|
||||
@@ -255,10 +282,11 @@
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* Adjusted header padding to match Orders spacing */
|
||||
.report-table th {
|
||||
padding: 15px 12px;
|
||||
padding: 16px 20px; /* changed from 15px 12px to match Orders' spacing */
|
||||
text-align: center; /* Center align header text */
|
||||
font-size: 13px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
border-bottom: none;
|
||||
@@ -280,8 +308,8 @@
|
||||
|
||||
/* Table cell styling with proper text handling - CENTER ALIGNED */
|
||||
.report-table td {
|
||||
padding: 12px;
|
||||
font-size: 13px;
|
||||
padding: 14px 20px; /* changed from 12px to match Orders' td padding */
|
||||
font-size: 14px; /* unified */
|
||||
color: #374151;
|
||||
border-bottom: 1px solid #f3f4f6;
|
||||
vertical-align: middle;
|
||||
@@ -292,12 +320,13 @@
|
||||
min-width: 120px; /* Minimum column width */
|
||||
text-align: center; /* Center align all table data */
|
||||
}
|
||||
|
||||
/* Specific column width adjustments */
|
||||
.report-table th:nth-child(1), /* Order ID */
|
||||
.report-table td:nth-child(1) {
|
||||
min-width: 100px;
|
||||
max-width: 150px;
|
||||
min-width: 200px !important;
|
||||
max-width: 200px !important;
|
||||
padding-left: 20px !important;
|
||||
|
||||
}
|
||||
|
||||
.report-table th:nth-child(2), /* Shipment ID */
|
||||
@@ -411,8 +440,12 @@
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.status-badge i {
|
||||
font-size: 8px;
|
||||
/* Status icons */
|
||||
.status-icon {
|
||||
font-size: 11px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
@@ -469,19 +502,18 @@
|
||||
}
|
||||
|
||||
.data-highlight {
|
||||
font-weight: 600;
|
||||
font-weight: 400;
|
||||
color: #1a202c;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center; /* Center content */
|
||||
gap: 4px;
|
||||
font-size: 13px;
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin: 0 auto; /* Center the highlight container */
|
||||
}
|
||||
|
||||
.data-highlight i {
|
||||
color: #4f46e5;
|
||||
font-size: 11px;
|
||||
@@ -678,7 +710,7 @@
|
||||
.stats-container {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
|
||||
.report-table {
|
||||
min-width: 1100px;
|
||||
}
|
||||
@@ -688,49 +720,59 @@
|
||||
.report-container {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
|
||||
.report-header {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
|
||||
.header-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
|
||||
.report-title {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
|
||||
.stats-container {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 12px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
|
||||
.stat-card {
|
||||
padding: 15px 12px;
|
||||
padding: 14px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
|
||||
.stat-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.stat-icon i {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
|
||||
.filter-row {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
|
||||
.filter-group {
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.report-table {
|
||||
min-width: 1000px;
|
||||
}
|
||||
|
||||
|
||||
/* Adjust column widths for mobile */
|
||||
.report-table th,
|
||||
.report-table td {
|
||||
@@ -743,7 +785,7 @@
|
||||
gap: 10px;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
|
||||
.pagination-controls {
|
||||
justify-content: center;
|
||||
}
|
||||
@@ -753,22 +795,22 @@
|
||||
.stats-container {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
|
||||
.stat-card {
|
||||
padding: 15px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
|
||||
.report-table {
|
||||
min-width: 900px;
|
||||
}
|
||||
|
||||
|
||||
.report-table th,
|
||||
.report-table td {
|
||||
min-width: 90px;
|
||||
padding: 8px 6px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
|
||||
.status-badge {
|
||||
font-size: 10px !important;
|
||||
padding: 4px 8px 4px 6px !important;
|
||||
@@ -794,43 +836,55 @@
|
||||
<div class="stat-icon">
|
||||
<i class="fas fa-box-open"></i>
|
||||
</div>
|
||||
<div class="stat-value" id="totalShipments">{{ count($reports) }}</div>
|
||||
<div class="stat-label">Total Shipments</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value" id="totalShipments">{{ count($reports) }}</div>
|
||||
<div class="stat-label">Total Shipments</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card warning">
|
||||
<div class="stat-icon">
|
||||
<i class="fas fa-clock"></i>
|
||||
</div>
|
||||
<div class="stat-value" id="pendingShipments">0</div>
|
||||
<div class="stat-label">Pending Shipments</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value" id="pendingShipments">0</div>
|
||||
<div class="stat-label">Pending Shipments</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card info">
|
||||
<div class="stat-icon">
|
||||
<i class="fas fa-truck-moving"></i>
|
||||
</div>
|
||||
<div class="stat-value" id="inTransitShipments">0</div>
|
||||
<div class="stat-label">In Transit</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value" id="inTransitShipments">0</div>
|
||||
<div class="stat-label">In Transit</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card secondary">
|
||||
<div class="stat-icon">
|
||||
<i class="fas fa-shipping-fast"></i>
|
||||
</div>
|
||||
<div class="stat-value" id="dispatchedShipments">0</div>
|
||||
<div class="stat-label">Dispatched</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value" id="dispatchedShipments">0</div>
|
||||
<div class="stat-label">Dispatched</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card success">
|
||||
<div class="stat-icon">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
</div>
|
||||
<div class="stat-value" id="deliveredShipments">0</div>
|
||||
<div class="stat-label">Delivered</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value" id="deliveredShipments">0</div>
|
||||
<div class="stat-label">Delivered</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card danger">
|
||||
<div class="stat-icon">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
</div>
|
||||
<div class="stat-value" id="overdueInvoices">0</div>
|
||||
<div class="stat-label">Overdue Invoices</div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value" id="overdueInvoices">0</div>
|
||||
<div class="stat-label">Overdue Invoices</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -879,24 +933,23 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TABLE SECTION -->
|
||||
<div class="table-container">
|
||||
<table class="report-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><i class="fas fa-hashtag"></i> Order ID</th>
|
||||
<th><i class="fas fa-barcode"></i> Shipment ID</th>
|
||||
<th><i class="fas fa-building"></i> Company Name</th>
|
||||
<th><i class="fas fa-user"></i> User Name</th>
|
||||
<th>Order ID</th>
|
||||
<th>Shipment ID</th>
|
||||
<th>Company Name</th>
|
||||
<th>User Name</th>
|
||||
<th><i class="fas fa-map-marker-alt"></i> Origin</th>
|
||||
<th><i class="fas fa-location-arrow"></i> Destination</th>
|
||||
<th><i class="fas fa-calendar"></i> Date</th>
|
||||
<th><i class="fas fa-file-invoice"></i> Invoice ID</th>
|
||||
<th><i class="fas fa-calendar-day"></i> Invoice Date</th>
|
||||
<th><i class="fas fa-money-bill-wave"></i> Invoice Amount</th>
|
||||
<th><i class="fas fa-receipt"></i> Invoice Status</th>
|
||||
<th><i class="fas fa-shipping-fast"></i> Shipment Status</th>
|
||||
<th>Date</th>
|
||||
<th>Invoice ID</th>
|
||||
<th>Invoice Date</th>
|
||||
<th>Invoice Amount</th>
|
||||
<th>Invoice Status</th>
|
||||
<th>Shipment Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="reportTableBody">
|
||||
@@ -904,13 +957,11 @@
|
||||
<tr data-status="{{ $r->shipment_status }}" data-invoice-status="{{ strtolower($r->invoice_status) }}" data-company="{{ $r->company_name ?? '' }}" data-date="{{ $r->shipment_date }}">
|
||||
<td>
|
||||
<span class="data-highlight" title="{{ $r->order_id }}">
|
||||
<i class="fas fa-hashtag"></i>
|
||||
{{ $r->order_id }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="data-highlight" title="{{ $r->shipment_id }}">
|
||||
<i class="fas fa-barcode"></i>
|
||||
{{ $r->shipment_id }}
|
||||
</span>
|
||||
</td>
|
||||
@@ -919,9 +970,10 @@
|
||||
<td>
|
||||
<span class="data-highlight" title="{{ $r->origin }}">
|
||||
<i class="fas fa-map-marker-alt"></i>
|
||||
{{ $r->origin }}
|
||||
{{ $r->origin ?? '-' }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="data-highlight" title="{{ $r->destination }}">
|
||||
<i class="fas fa-location-arrow"></i>
|
||||
@@ -931,31 +983,43 @@
|
||||
<td>{{ \Carbon\Carbon::parse($r->shipment_date)->format('d/m/Y') }}</td>
|
||||
<td>
|
||||
<span class="data-highlight" title="{{ $r->invoice_number }}">
|
||||
<i class="fas fa-file-invoice"></i>
|
||||
{{ $r->invoice_number }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ \Carbon\Carbon::parse($r->invoice_date)->format('d/m/Y') }}</td>
|
||||
<td>
|
||||
<span class="data-highlight" title="₹{{ number_format($r->final_amount) }}">
|
||||
<i class="fas fa-rupee-sign"></i>
|
||||
{{ number_format($r->final_amount) }}
|
||||
₹{{ number_format($r->final_amount) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
@php $ist = strtolower($r->invoice_status); @endphp
|
||||
@php $ist = strtolower($r->invoice_status ?? ''); @endphp
|
||||
<span class="status-badge
|
||||
@if($ist === 'paid') status-paid
|
||||
@elseif($ist === 'pending') status-pending
|
||||
@elseif($ist === 'overdue') status-overdue
|
||||
@endif">
|
||||
<i class="fas fa-circle"></i>
|
||||
@if($ist === 'paid')
|
||||
<i class="bi bi-check-circle-fill status-icon"></i>
|
||||
@elseif($ist === 'pending')
|
||||
<i class="bi bi-clock-fill status-icon"></i>
|
||||
@elseif($ist === 'overdue')
|
||||
<i class="bi bi-exclamation-triangle-fill status-icon"></i>
|
||||
@endif
|
||||
{{ ucfirst($ist) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="status-badge ship-{{ $r->shipment_status }}">
|
||||
<i class="fas fa-circle"></i>
|
||||
@if($r->shipment_status === 'pending')
|
||||
<i class="bi bi-clock-fill status-icon"></i>
|
||||
@elseif($r->shipment_status === 'in_transit')
|
||||
<i class="bi bi-truck status-icon"></i>
|
||||
@elseif($r->shipment_status === 'dispatched')
|
||||
<i class="bi bi-send-fill status-icon"></i>
|
||||
@elseif($r->shipment_status === 'delivered')
|
||||
<i class="bi bi-check-circle-fill status-icon"></i>
|
||||
@endif
|
||||
{{ ucfirst(str_replace('_',' ', $r->shipment_status)) }}
|
||||
</span>
|
||||
</td>
|
||||
@@ -999,7 +1063,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Pagination state
|
||||
let currentPage = 1;
|
||||
@@ -1007,32 +1070,68 @@
|
||||
let allReports = @json($reports);
|
||||
let filteredReports = [...allReports];
|
||||
|
||||
// Status icon helper functions
|
||||
function getInvoiceStatusIcon(status) {
|
||||
switch(status) {
|
||||
case 'paid':
|
||||
return '<i class="bi bi-check-circle-fill status-icon"></i>';
|
||||
case 'pending':
|
||||
return '<i class="bi bi-clock-fill status-icon"></i>';
|
||||
case 'overdue':
|
||||
return '<i class="bi bi-exclamation-triangle-fill status-icon"></i>';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function getShipmentStatusIcon(status) {
|
||||
switch(status) {
|
||||
case 'pending':
|
||||
return '<i class="bi bi-clock-fill status-icon"></i>';
|
||||
case 'in_transit':
|
||||
return '<i class="bi bi-truck status-icon"></i>';
|
||||
case 'dispatched':
|
||||
return '<i class="bi bi-send-fill status-icon"></i>';
|
||||
case 'delivered':
|
||||
return '<i class="bi bi-check-circle-fill status-icon"></i>';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Initialize statistics and pagination
|
||||
updateStatistics();
|
||||
renderTable();
|
||||
updatePaginationControls();
|
||||
|
||||
|
||||
// Set default dates for demo purposes
|
||||
const today = new Date();
|
||||
const lastMonth = new Date(today.getFullYear(), today.getMonth() - 1, today.getDate());
|
||||
|
||||
|
||||
const formatDate = (date) => {
|
||||
return date.toISOString().split('T')[0];
|
||||
};
|
||||
|
||||
document.getElementById('fromDate').value = formatDate(lastMonth);
|
||||
document.getElementById('toDate').value = formatDate(today);
|
||||
|
||||
if (document.getElementById('fromDate')) document.getElementById('fromDate').value = formatDate(lastMonth);
|
||||
if (document.getElementById('toDate')) document.getElementById('toDate').value = formatDate(today);
|
||||
|
||||
// Add event listeners for filters
|
||||
document.getElementById('fromDate').addEventListener('change', filterTable);
|
||||
document.getElementById('toDate').addEventListener('change', filterTable);
|
||||
document.getElementById('companyFilter').addEventListener('change', filterTable);
|
||||
document.getElementById('statusFilter').addEventListener('change', filterTable);
|
||||
const fd = document.getElementById('fromDate');
|
||||
const td = document.getElementById('toDate');
|
||||
const cf = document.getElementById('companyFilter');
|
||||
const sf = document.getElementById('statusFilter');
|
||||
|
||||
if(fd) fd.addEventListener('change', filterTable);
|
||||
if(td) td.addEventListener('change', filterTable);
|
||||
if(cf) cf.addEventListener('change', filterTable);
|
||||
if(sf) sf.addEventListener('change', filterTable);
|
||||
|
||||
// Bind pagination events
|
||||
document.getElementById('prevPageBtn').addEventListener('click', goToPreviousPage);
|
||||
document.getElementById('nextPageBtn').addEventListener('click', goToNextPage);
|
||||
const prevBtn = document.getElementById('prevPageBtn');
|
||||
const nextBtn = document.getElementById('nextPageBtn');
|
||||
if(prevBtn) prevBtn.addEventListener('click', goToPreviousPage);
|
||||
if(nextBtn) nextBtn.addEventListener('click', goToNextPage);
|
||||
|
||||
function updateStatistics() {
|
||||
const rows = document.querySelectorAll('#reportTableBody tr');
|
||||
@@ -1046,7 +1145,7 @@
|
||||
rows.forEach(row => {
|
||||
// Skip if row is hidden or empty state
|
||||
if (row.style.display === 'none' || row.querySelector('.empty-state')) return;
|
||||
|
||||
|
||||
totalShipments++;
|
||||
|
||||
// Count shipment statuses
|
||||
@@ -1055,19 +1154,25 @@
|
||||
if (status === 'in_transit') inTransitShipments++;
|
||||
if (status === 'dispatched') dispatchedShipments++;
|
||||
if (status === 'delivered') deliveredShipments++;
|
||||
|
||||
|
||||
// Count invoice statuses
|
||||
const invoiceStatus = row.getAttribute('data-invoice-status');
|
||||
if (invoiceStatus === 'overdue') overdueInvoices++;
|
||||
});
|
||||
|
||||
// Update statistics cards
|
||||
document.getElementById('totalShipments').textContent = totalShipments;
|
||||
document.getElementById('pendingShipments').textContent = pendingShipments;
|
||||
document.getElementById('inTransitShipments').textContent = inTransitShipments;
|
||||
document.getElementById('dispatchedShipments').textContent = dispatchedShipments;
|
||||
document.getElementById('deliveredShipments').textContent = deliveredShipments;
|
||||
document.getElementById('overdueInvoices').textContent = overdueInvoices;
|
||||
const elTotal = document.getElementById('totalShipments');
|
||||
if(elTotal) elTotal.textContent = totalShipments;
|
||||
const elPending = document.getElementById('pendingShipments');
|
||||
if(elPending) elPending.textContent = pendingShipments;
|
||||
const elInTransit = document.getElementById('inTransitShipments');
|
||||
if(elInTransit) elInTransit.textContent = inTransitShipments;
|
||||
const elDispatched = document.getElementById('dispatchedShipments');
|
||||
if(elDispatched) elDispatched.textContent = dispatchedShipments;
|
||||
const elDelivered = document.getElementById('deliveredShipments');
|
||||
if(elDelivered) elDelivered.textContent = deliveredShipments;
|
||||
const elOverdue = document.getElementById('overdueInvoices');
|
||||
if(elOverdue) elOverdue.textContent = overdueInvoices;
|
||||
}
|
||||
|
||||
// Pagination Functions
|
||||
@@ -1094,18 +1199,18 @@
|
||||
const nextBtn = document.getElementById('nextPageBtn');
|
||||
const pageInfo = document.getElementById('pageInfo');
|
||||
const paginationPages = document.getElementById('paginationPages');
|
||||
|
||||
prevBtn.disabled = currentPage === 1;
|
||||
nextBtn.disabled = currentPage === totalPages || totalPages === 0;
|
||||
|
||||
|
||||
if(prevBtn) prevBtn.disabled = currentPage === 1;
|
||||
if(nextBtn) nextBtn.disabled = currentPage === totalPages || totalPages === 0;
|
||||
|
||||
// Update page info text
|
||||
const startIndex = (currentPage - 1) * itemsPerPage + 1;
|
||||
const endIndex = Math.min(currentPage * itemsPerPage, filteredReports.length);
|
||||
pageInfo.textContent = `Showing ${startIndex} to ${endIndex} of ${filteredReports.length} entries`;
|
||||
|
||||
if(pageInfo) pageInfo.textContent = `Showing ${startIndex} to ${endIndex} of ${filteredReports.length} entries`;
|
||||
|
||||
// Generate page numbers
|
||||
paginationPages.innerHTML = '';
|
||||
|
||||
if(paginationPages) paginationPages.innerHTML = '';
|
||||
|
||||
if (totalPages <= 7) {
|
||||
// Show all pages
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
@@ -1114,27 +1219,28 @@
|
||||
} else {
|
||||
// Show first page, current page range, and last page
|
||||
addPageButton(1, paginationPages);
|
||||
|
||||
|
||||
if (currentPage > 3) {
|
||||
paginationPages.innerHTML += '<span class="pagination-ellipsis">...</span>';
|
||||
if(paginationPages) paginationPages.innerHTML += '<span class="pagination-ellipsis">...</span>';
|
||||
}
|
||||
|
||||
|
||||
const start = Math.max(2, currentPage - 1);
|
||||
const end = Math.min(totalPages - 1, currentPage + 1);
|
||||
|
||||
|
||||
for (let i = start; i <= end; i++) {
|
||||
addPageButton(i, paginationPages);
|
||||
}
|
||||
|
||||
|
||||
if (currentPage < totalPages - 2) {
|
||||
paginationPages.innerHTML += '<span class="pagination-ellipsis">...</span>';
|
||||
if(paginationPages) paginationPages.innerHTML += '<span class="pagination-ellipsis">...</span>';
|
||||
}
|
||||
|
||||
|
||||
addPageButton(totalPages, paginationPages);
|
||||
}
|
||||
}
|
||||
|
||||
function addPageButton(pageNumber, container) {
|
||||
if(!container) return;
|
||||
const button = document.createElement('button');
|
||||
button.className = 'pagination-page-btn';
|
||||
if (pageNumber === currentPage) {
|
||||
@@ -1152,8 +1258,9 @@
|
||||
// Render Table Function
|
||||
function renderTable() {
|
||||
const tbody = document.getElementById('reportTableBody');
|
||||
if(!tbody) return;
|
||||
tbody.innerHTML = '';
|
||||
|
||||
|
||||
if (filteredReports.length === 0) {
|
||||
tbody.innerHTML = `
|
||||
<tr>
|
||||
@@ -1170,12 +1277,12 @@
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Calculate pagination
|
||||
const startIndex = (currentPage - 1) * itemsPerPage;
|
||||
const endIndex = startIndex + itemsPerPage;
|
||||
const paginatedItems = filteredReports.slice(startIndex, endIndex);
|
||||
|
||||
|
||||
paginatedItems.forEach(report => {
|
||||
const ist = (report.invoice_status || '').toLowerCase();
|
||||
const row = document.createElement('tr');
|
||||
@@ -1183,46 +1290,42 @@
|
||||
row.setAttribute('data-invoice-status', ist);
|
||||
row.setAttribute('data-company', report.company_name || '');
|
||||
row.setAttribute('data-date', report.shipment_date);
|
||||
|
||||
|
||||
row.innerHTML = `
|
||||
<td>
|
||||
<span class="data-highlight" title="${report.order_id}">
|
||||
<i class="fas fa-hashtag"></i>
|
||||
${report.order_id}
|
||||
${report.order_id || '-'}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="data-highlight" title="${report.shipment_id}">
|
||||
<i class="fas fa-barcode"></i>
|
||||
${report.shipment_id}
|
||||
${report.shipment_id || '-'}
|
||||
</span>
|
||||
</td>
|
||||
<td title="${report.company_name || '-'}">${report.company_name || '-'}</td>
|
||||
<td title="${report.customer_name || '-'}">${report.customer_name || '-'}</td>
|
||||
<td>
|
||||
<span class="data-highlight" title="${report.origin}">
|
||||
<span class="data-highlight" title="${report.origin || '-'}">
|
||||
<i class="fas fa-map-marker-alt"></i>
|
||||
${report.origin}
|
||||
${report.origin || '-'}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="data-highlight" title="${report.destination}">
|
||||
<span class="data-highlight" title="${report.destination || '-'}">
|
||||
<i class="fas fa-location-arrow"></i>
|
||||
${report.destination}
|
||||
${report.destination || '-'}
|
||||
</span>
|
||||
</td>
|
||||
<td>${new Date(report.shipment_date).toLocaleDateString('en-GB')}</td>
|
||||
<td>${report.shipment_date ? new Date(report.shipment_date).toLocaleDateString('en-GB') : '-'}</td>
|
||||
<td>
|
||||
<span class="data-highlight" title="${report.invoice_number}">
|
||||
<i class="fas fa-file-invoice"></i>
|
||||
${report.invoice_number}
|
||||
<span class="data-highlight" title="${report.invoice_number || '-'}">
|
||||
${report.invoice_number || '-'}
|
||||
</span>
|
||||
</td>
|
||||
<td>${new Date(report.invoice_date).toLocaleDateString('en-GB')}</td>
|
||||
<td>${report.invoice_date ? new Date(report.invoice_date).toLocaleDateString('en-GB') : '-'}</td>
|
||||
<td>
|
||||
<span class="data-highlight" title="₹${Number(report.final_amount).toLocaleString('en-IN')}">
|
||||
<i class="fas fa-rupee-sign"></i>
|
||||
${Number(report.final_amount).toLocaleString('en-IN')}
|
||||
<span class="data-highlight" title="₹${Number(report.final_amount || 0).toLocaleString('en-IN')}">
|
||||
₹${Number(report.final_amount || 0).toLocaleString('en-IN')}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
@@ -1230,14 +1333,14 @@
|
||||
${ist === 'paid' ? 'status-paid' : ''}
|
||||
${ist === 'pending' ? 'status-pending' : ''}
|
||||
${ist === 'overdue' ? 'status-overdue' : ''}">
|
||||
<i class="fas fa-circle"></i>
|
||||
${ist.charAt(0).toUpperCase() + ist.slice(1)}
|
||||
${getInvoiceStatusIcon(ist)}
|
||||
${ist ? ist.charAt(0).toUpperCase() + ist.slice(1) : '-'}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="status-badge ship-${report.shipment_status}">
|
||||
<i class="fas fa-circle"></i>
|
||||
${report.shipment_status.charAt(0).toUpperCase() + report.shipment_status.slice(1).replace('_', ' ')}
|
||||
<span class="status-badge ship-${report.shipment_status || ''}">
|
||||
${getShipmentStatusIcon(report.shipment_status)}
|
||||
${report.shipment_status ? (report.shipment_status.charAt(0).toUpperCase() + report.shipment_status.slice(1)).replace('_',' ') : '-'}
|
||||
</span>
|
||||
</td>
|
||||
`;
|
||||
@@ -1246,10 +1349,10 @@
|
||||
}
|
||||
|
||||
function filterTable() {
|
||||
const fromDate = document.getElementById('fromDate').value;
|
||||
const toDate = document.getElementById('toDate').value;
|
||||
const companyFilter = document.getElementById('companyFilter').value;
|
||||
const statusFilter = document.getElementById('statusFilter').value;
|
||||
const fromDate = document.getElementById('fromDate')?.value;
|
||||
const toDate = document.getElementById('toDate')?.value;
|
||||
const companyFilter = document.getElementById('companyFilter')?.value;
|
||||
const statusFilter = document.getElementById('statusFilter')?.value;
|
||||
|
||||
filteredReports = allReports.filter(report => {
|
||||
let include = true;
|
||||
@@ -1285,13 +1388,13 @@
|
||||
updateStatistics();
|
||||
}
|
||||
|
||||
// Add hover effects to table rows
|
||||
// Add hover effects to table rows (for rows present initially in DOM — dynamic rows handled in renderTable)
|
||||
const tableRows = document.querySelectorAll('.report-table tbody tr');
|
||||
tableRows.forEach(row => {
|
||||
row.addEventListener('mouseenter', function() {
|
||||
this.style.transform = 'translateY(-2px)';
|
||||
});
|
||||
|
||||
|
||||
row.addEventListener('mouseleave', function() {
|
||||
this.style.transform = 'translateY(0)';
|
||||
});
|
||||
|
||||
@@ -365,7 +365,22 @@
|
||||
@elseif($req->status == 'rejected')<span class="badge badge-rejected"><i class="bi bi-x-circle-fill status-icon"></i>Rejected</span>
|
||||
@else<span class="badge badge-pending"><i class="bi bi-clock-fill status-icon"></i>Pending</span>@endif
|
||||
</td>
|
||||
<td>N/A</td>
|
||||
<td>
|
||||
@if($req->status == 'pending')
|
||||
<a href="{{ route('admin.requests.approve', $req->id) }}"
|
||||
class="btn btn-success btn-sm">
|
||||
<i class="bi bi-check-circle"></i> Approve
|
||||
</a>
|
||||
|
||||
<a href="{{ route('admin.requests.reject', $req->id) }}"
|
||||
class="btn btn-danger btn-sm">
|
||||
<i class="bi bi-x-circle"></i> Reject
|
||||
</a>
|
||||
@else
|
||||
<span class="text-muted">No Action</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
@empty
|
||||
<tr><td colspan="11" class="text-center text-muted py-4">No records found.</td></tr>
|
||||
|
||||
Reference in New Issue
Block a user