diff --git a/app/Http/Controllers/Admin/UserRequestController.php b/app/Http/Controllers/Admin/UserRequestController.php
index 0b6306f..e09c56f 100644
--- a/app/Http/Controllers/Admin/UserRequestController.php
+++ b/app/Http/Controllers/Admin/UserRequestController.php
@@ -65,4 +65,52 @@ class UserRequestController extends Controller
return redirect()->back()->with('info', 'Request rejected successfully.');
}
+
+ public function profileUpdateRequests()
+{
+ $requests = \App\Models\UpdateRequest::where('status', 'pending')
+ ->orderBy('id', 'desc')
+ ->get();
+
+ return view('admin.profile_update_requests', compact('requests'));
+}
+
+public function approveProfileUpdate($id)
+{
+ $req = \App\Models\UpdateRequest::findOrFail($id);
+ $user = \App\Models\User::findOrFail($req->user_id);
+
+ // FIX: Ensure data is array
+ $newData = is_array($req->data) ? $req->data : json_decode($req->data, true);
+
+ foreach ($newData as $key => $value) {
+ if ($value !== null && $value !== "") {
+ if (in_array($key, ['customer_name','company_name','designation','email','mobile_no','address','pincode'])) {
+ $user->$key = $value;
+ }
+ }
+ }
+
+ $user->save();
+
+ $req->status = 'approved';
+ $req->admin_note = 'Approved by admin on ' . now();
+ $req->save();
+
+ return back()->with('success', 'Profile updated successfully.');
+}
+
+
+
+public function rejectProfileUpdate($id)
+{
+ $req = \App\Models\UpdateRequest::findOrFail($id);
+ $req->status = 'rejected';
+ $req->admin_note = 'Rejected by admin on ' . now();
+ $req->save();
+
+ return back()->with('info', 'Profile update request rejected.');
+}
+
+
}
diff --git a/app/Http/Controllers/UserAuthController.php b/app/Http/Controllers/UserAuthController.php
index a2be041..256f98a 100644
--- a/app/Http/Controllers/UserAuthController.php
+++ b/app/Http/Controllers/UserAuthController.php
@@ -12,19 +12,68 @@ class UserAuthController extends Controller
public function refreshToken()
{
+ \Log::info('🔄 refreshToken() called');
+
try {
- $newToken = JWTAuth::refresh(JWTAuth::getToken());
+ // Get current token
+ $currentToken = JWTAuth::getToken();
+
+ if (!$currentToken) {
+ \Log::warning('⚠ No token provided in refreshToken()');
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Token not provided',
+ ], 401);
+ }
+
+ \Log::info('📥 Current Token:', ['token' => (string) $currentToken]);
+
+ // Try refreshing token
+ $newToken = JWTAuth::refresh($currentToken);
+
+ \Log::info('✅ Token refreshed successfully', ['new_token' => $newToken]);
return response()->json([
'success' => true,
'token' => $newToken,
]);
- } catch (\Exception $e) {
+ } catch (\Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
+ \Log::error('❌ TokenExpiredException in refreshToken()', [
+ 'message' => $e->getMessage(),
+ ]);
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Token expired, cannot refresh.',
+ ], 401);
+
+ } catch (\Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
+ \Log::error('❌ TokenInvalidException in refreshToken()', [
+ 'message' => $e->getMessage(),
+ ]);
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Invalid token.',
+ ], 401);
+
+ } catch (\Tymon\JWTAuth\Exceptions\JWTException $e) {
+ \Log::error('❌ JWTException in refreshToken()', [
+ 'message' => $e->getMessage(),
+ ]);
return response()->json([
'success' => false,
'message' => 'Could not refresh token.',
], 401);
+
+ } catch (\Exception $e) {
+ \Log::error('❌ General Exception in refreshToken()', [
+ 'message' => $e->getMessage(),
+ 'trace' => $e->getTraceAsString(),
+ ]);
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Unexpected error while refreshing token.',
+ ], 500);
}
}
diff --git a/app/Http/Controllers/user/UserProfileController.php b/app/Http/Controllers/user/UserProfileController.php
index a5d644c..ca42ab2 100644
--- a/app/Http/Controllers/user/UserProfileController.php
+++ b/app/Http/Controllers/user/UserProfileController.php
@@ -4,14 +4,17 @@ namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
+use App\Models\UpdateRequest;
use PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth;
class UserProfileController extends Controller
{
+ /**
+ * Get user profile
+ */
public function profile()
{
- // Get logged-in user using JWT
- try {
+ try {
$user = JWTAuth::parseToken()->authenticate();
} catch (\Exception $e) {
return response()->json([
@@ -20,7 +23,6 @@ class UserProfileController extends Controller
], 401);
}
-
if (! $user) {
return response()->json([
'success' => false,
@@ -28,7 +30,6 @@ class UserProfileController extends Controller
], 401);
}
- // Format response
return response()->json([
'success' => true,
'data' => [
@@ -49,7 +50,53 @@ class UserProfileController extends Controller
]);
}
- public function updateProfile(Request $request)
+
+
+ /**
+ * Update profile IMAGE only (no admin approval)
+ */
+ public function updateProfileImage(Request $request)
+ {
+ $user = JWTAuth::parseToken()->authenticate();
+
+ if (! $user) {
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Unauthorized'
+ ], 401);
+ }
+
+ $request->validate([
+ 'profile_image' => 'required|image|mimes:jpg,jpeg,png|max:2048'
+ ]);
+
+ // DELETE OLD IMAGE
+ if ($user->profile_image && file_exists(public_path($user->profile_image))) {
+ @unlink(public_path($user->profile_image));
+ }
+
+ // SAVE NEW IMAGE
+ $file = $request->file('profile_image');
+ $filename = 'profile_' . time() . '.' . $file->getClientOriginalExtension();
+ $folder = 'profile_upload/';
+ $file->move(public_path($folder), $filename);
+
+ $user->profile_image = $folder . $filename;
+ $user->save();
+
+ return response()->json([
+ 'success' => true,
+ 'message' => 'Profile image updated successfully',
+ 'profile_image' => url($user->profile_image),
+ ]);
+ }
+
+
+
+ /**
+ * Submit profile update request (requires admin approval)
+ */
+ public function updateProfileRequest(Request $request)
{
$user = JWTAuth::parseToken()->authenticate();
@@ -60,53 +107,28 @@ class UserProfileController extends Controller
], 401);
}
- // Validate ONLY profile image
+ // Validate input
$request->validate([
- 'profile_image' => 'required|image|mimes:jpg,jpeg,png|max:2048'
+ 'customer_name' => 'nullable|string|max:255',
+ 'company_name' => 'nullable|string|max:255',
+ 'designation' => 'nullable|string|max:255',
+ 'email' => 'nullable|email',
+ 'mobile_no' => 'nullable|string|max:15',
+ 'address' => 'nullable|string',
+ 'pincode' => 'nullable|string|max:10'
]);
- // If new image uploaded
- if ($request->hasFile('profile_image')) {
-
- // DELETE OLD IMAGE
- if ($user->profile_image && file_exists(public_path($user->profile_image))) {
- @unlink(public_path($user->profile_image));
- }
-
- // NEW FILE
- $file = $request->file('profile_image');
- $filename = 'profile_' . time() . '.' . $file->getClientOriginalExtension();
-
- // Correct folder name (from your message)
- $folder = 'profile_upload/';
- $fullPath = $folder . $filename;
-
- // Move file
- $file->move(public_path($folder), $filename);
-
- // Save in DB (same pattern you said)
- $user->profile_image = $fullPath;
- }
-
- $user->save();
+ // SAVE AS ARRAY (NOT JSON STRING!)
+ $updateReq = \App\Models\UpdateRequest::create([
+ 'user_id' => $user->id,
+ 'data' => $request->all(), // <---- FIXED
+ 'status' => 'pending',
+ ]);
return response()->json([
'success' => true,
- 'message' => 'Profile image updated successfully',
- 'data' => [
- 'customer_id' => $user->customer_id,
- 'customer_name' => $user->customer_name,
- 'company_name' => $user->company_name,
- 'designation' => $user->designation,
- 'email' => $user->email,
- 'mobile' => $user->mobile_no,
- 'address' => $user->address,
- 'pincode' => $user->pincode,
- 'status' => $user->status,
- 'customer_type' => $user->customer_type,
- 'profile_image' => $user->profile_image ? url($user->profile_image) : null,
- 'date' => $user->date,
- ]
+ 'message' => 'Profile update request submitted. Waiting for admin approval.',
+ 'request_id' => $updateReq->id
]);
}
diff --git a/app/Models/UpdateRequest.php b/app/Models/UpdateRequest.php
new file mode 100644
index 0000000..27e84a4
--- /dev/null
+++ b/app/Models/UpdateRequest.php
@@ -0,0 +1,30 @@
+ 'array', // converts JSON to array automatically
+ ];
+
+ // Relationship: request belongs to a user
+ public function user()
+ {
+ return $this->belongsTo(User::class);
+ }
+}
diff --git a/database/migrations/2025_12_02_055345_create_update_requests_table.php b/database/migrations/2025_12_02_055345_create_update_requests_table.php
new file mode 100644
index 0000000..cb4c527
--- /dev/null
+++ b/database/migrations/2025_12_02_055345_create_update_requests_table.php
@@ -0,0 +1,37 @@
+id();
+
+ // The user who is requesting profile update
+ $table->unsignedBigInteger('user_id');
+
+ // JSON data of the requested profile changes
+ $table->json('data')->nullable();
+
+ // pending / approved / rejected
+ $table->enum('status', ['pending', 'approved', 'rejected'])->default('pending');
+
+ // Optional message (admin notes)
+ $table->text('admin_note')->nullable();
+
+ $table->timestamps();
+
+ // Foreign key constraint
+ $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
+ });
+ }
+
+ public function down()
+ {
+ Schema::dropIfExists('update_requests');
+ }
+}
diff --git a/public/profile_upload/profile_1764394681.jpeg b/public/profile_upload/profile_1764394681.jpeg
deleted file mode 100644
index 06220af..0000000
Binary files a/public/profile_upload/profile_1764394681.jpeg and /dev/null differ
diff --git a/public/profile_upload/profile_1764645094.jpg b/public/profile_upload/profile_1764645094.jpg
new file mode 100644
index 0000000..3c6a162
Binary files /dev/null and b/public/profile_upload/profile_1764645094.jpg differ
diff --git a/resources/views/admin/layouts/app.blade.php b/resources/views/admin/layouts/app.blade.php
index 248ca8f..5481de3 100644
--- a/resources/views/admin/layouts/app.blade.php
+++ b/resources/views/admin/layouts/app.blade.php
@@ -212,6 +212,13 @@
Orders
Requests
+
+
+
+ Profile Update Requests
+
+
+
Staff
Account
Mark List
diff --git a/resources/views/admin/profile_update_requests.blade.php b/resources/views/admin/profile_update_requests.blade.php
new file mode 100644
index 0000000..4797665
--- /dev/null
+++ b/resources/views/admin/profile_update_requests.blade.php
@@ -0,0 +1,111 @@
+@extends('admin.layouts.app')
+
+@section('page-title', 'Profile Update Requests')
+
+@section('content')
+
+
+ @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
+
+
+
+
Profile Update Requests ({{ $total }})
+
+
+
+
+
+
+
+
+ | # |
+ User |
+ Requested Changes |
+ Status |
+ Requested At |
+ Actions |
+
+
+
+
+ @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
+
+
+ | {{ ($currentPage - 1) * $perPage + $index + 1 }} |
+
+
+ {{ $user->customer_name }}
+ {{ $user->email }}
+ ID: {{ $user->customer_id }}
+ |
+
+
+ @foreach($newData as $key => $newValue)
+ @php
+ $oldValue = $user->$key ?? '—';
+ $changed = $oldValue != $newValue;
+ @endphp
+
+
+ {{ ucfirst(str_replace('_',' ', $key)) }}:
+ Old: {{ $oldValue }}
+ New: {{ $newValue ?? '—' }}
+
+ @endforeach
+ |
+
+
+ @if($req->status == 'pending')
+ Pending
+ @elseif($req->status == 'approved')
+ Approved
+ @else
+ Rejected
+ @endif
+ |
+
+ {{ $req->created_at->format('d M Y, h:i A') }} |
+
+
+ @if($req->status == 'pending')
+
+ Approve
+
+
+
+ Reject
+
+ @else
+ Completed
+ @endif
+ |
+
+
+ @endforeach
+
+
+
+
+
+
+
+@endsection
diff --git a/resources/views/admin/shipments.blade.php b/resources/views/admin/shipments.blade.php
index 4092ae7..5d3f16d 100644
--- a/resources/views/admin/shipments.blade.php
+++ b/resources/views/admin/shipments.blade.php
@@ -7,18 +7,15 @@
/*Remove horizontal scroll bar*/
html, body {
overflow-x: hidden !important;
- font-family: 'Inter', sans-serif;
}
.table thead th,
.table tbody td {
white-space: nowrap !important;
- padding: 14px 8px !important;
- font-size: 14px;
- font-family: 'Inter', sans-serif;
+ padding: 8px 4px !important;
}
- .table th:nth-child(10),
+ .table th:nth-child(10), /* if Date is column 10 */
.table td:nth-child(10) {
max-width: 110px !important;
width: 110px !important;
@@ -28,7 +25,6 @@
.table {
table-layout: fixed !important;
- font-family: 'Inter', sans-serif;
}
@@ -36,7 +32,6 @@
min-width: unset !important;
width: 100% !important;
table-layout: auto !important;
- font-family: 'Inter', sans-serif;
}
.table thead th,
@@ -47,8 +42,6 @@
.shipment-details-table td {
white-space: normal !important;
word-break: break-word;
- font-family: 'Inter', sans-serif;
- font-size: 14px;
}
.table-responsive, .modal .table-responsive {
@@ -70,125 +63,62 @@
--hover-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
- /* Search Bar Styles */
.search-shipment-bar {
display: flex;
align-items: center;
gap: 15px;
padding: 20px;
- background: white;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 16px;
box-shadow: var(--card-shadow);
flex-wrap: wrap;
margin-bottom: 30px;
- color: #333;
+ color: white;
position: relative;
overflow: hidden;
- font-family: 'Inter', sans-serif;
- border: 1px solid #e2e8f0;
}
- .search-input-container {
- display: flex;
- flex: 1;
- min-width: 300px;
- background: white;
- border-radius: 10px;
- overflow: hidden;
- border: 1px solid #d1d5db;
- transition: all 0.3s ease;
+ .search-shipment-bar::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(255,255,255,0.1);
+ z-index: 0;
}
- .search-input-container:focus-within {
- border-color: #4361ee;
- box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.1);
- }
-
- .search-shipment-bar input {
- padding: 12px 16px;
- border: none;
- flex: 1;
- background: transparent;
- font-weight: 500;
- transition: all 0.3s ease;
- font-family: 'Inter', sans-serif;
- font-size: 14px;
- outline: none;
- color: #333;
- }
-
- .search-shipment-bar input::placeholder {
- color: #6b7280;
- }
-
- .search-button {
- background: white;
- color: #4361ee;
- border: none;
- padding: 12px 20px;
- cursor: pointer;
- transition: all 0.3s ease;
- font-weight: 600;
- font-family: 'Inter', sans-serif;
- font-size: 14px;
- display: flex;
- align-items: center;
- gap: 8px;
- border-radius: 0 10px 10px 0;
- min-width: 100px;
- justify-content: center;
- border-left: 1px solid #d1d5db;
- }
-
- .search-input-group {
- border: 1px solid #d1d5db !important;
- border-radius: 8px !important;
- padding: 4px !important;
- background: #ffffff !important;
- }
-
- .search-button:hover {
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- color: white;
- transform: translateY(-1px);
- box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
- }
-
- .search-icon {
- font-size: 16px;
- color: #4361ee;
- transition: all 0.3s ease;
- }
-
- .search-button:hover .search-icon {
- color: white;
+ .search-shipment-bar > * {
+ position: relative;
+ z-index: 1;
}
+ .search-shipment-bar input,
.search-shipment-bar select {
- padding: 20px 16px;
- border: 1px solid #d1d5db;
+ padding: 12px 16px;
+ border: 1px solid rgba(255,255,255,0.2);
border-radius: 10px;
+ flex: 1;
min-width: 150px;
- background: white;
+ background: rgba(255,255,255,0.9);
font-weight: 500;
transition: all 0.3s ease;
- font-family: 'Inter', sans-serif;
- font-size: 14px;
- color: #333;
}
+ .search-shipment-bar input:focus,
.search-shipment-bar select:focus {
background: white;
- box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.1);
+ box-shadow: 0 0 0 3px rgba(255,255,255,0.3);
outline: none;
- border-color: #4361ee;
}
.btn-add-shipment {
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ background: rgba(255,255,255,0.2);
+ backdrop-filter: blur(10px);
color: white;
- border: none;
- padding: 17px 24px;
+ border: 1px solid rgba(255,255,255,0.3);
+ padding: 12px 24px;
border-radius: 10px;
cursor: pointer;
display: flex;
@@ -197,13 +127,17 @@
transition: all 0.3s ease;
white-space: nowrap;
font-weight: 600;
- font-family: 'Inter', sans-serif;
- font-size: 14px;
}
.btn-add-shipment:hover {
+ background: rgba(255,255,255,0.3);
transform: translateY(-2px);
- box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
+ box-shadow: 0 10px 20px rgba(0,0,0,0.1);
+ }
+
+ .search-icon {
+ font-size: 20px;
+ filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1));
}
.truck-icon {
@@ -215,7 +149,7 @@
flex-direction: column;
align-items: stretch;
}
- .search-input-container,
+ .search-shipment-bar input,
.search-shipment-bar select {
width: 100%;
}
@@ -228,7 +162,6 @@
box-shadow: var(--card-shadow);
transition: all 0.3s ease;
overflow: hidden;
- font-family: 'Inter', sans-serif;
}
.card:hover {
@@ -242,7 +175,6 @@
border: none;
padding: 20px 25px;
border-radius: 16px 16px 0 0 !important;
- font-family: 'Inter', sans-serif;
}
.card-header h5 {
@@ -251,8 +183,6 @@
display: flex;
align-items: center;
gap: 10px;
- font-family: 'Inter', sans-serif;
- font-size: 18px;
}
/* Table Styles */
@@ -268,7 +198,6 @@
width: 100%;
min-width: 1200px;
padding: 0;
- font-family: 'Inter', sans-serif;
}
.table thead th {
@@ -282,8 +211,6 @@
border-bottom: 2px solid var(--border);
position: relative;
white-space: nowrap;
- font-family: 'Inter', sans-serif;
- font-size: 14px;
}
.table thead th:first-child {
@@ -312,15 +239,13 @@
border-bottom: 1px solid var(--border);
font-weight: 500;
white-space: nowrap;
- font-family: 'Inter', sans-serif;
- font-size: 14px;
}
.table tbody tr:last-child td {
border-bottom: none;
}
- /* Status Badge Styles */
+ /* UPDATED: Status Badge Styles - ALL SAME SIZE */
.badge {
padding: 7px 17px !important;
border-radius: 20px !important;
@@ -329,51 +254,63 @@
border: 2px solid transparent !important;
min-width: 40px !important;
text-align: center !important;
- display: inline-flex !important;
- align-items: center;
- justify-content: center;
+ display: inline-block !important;
line-height: 1.2 !important;
- font-family: 'Inter', sans-serif;
- gap: 6px;
- width: 110px;
}
- /* Status icons */
- .status-icon {
- font-size: 13px;
- display: flex;
- align-items: center;
- justify-content: center;
- }
-
- /* Pending Status */
+ /* Pending Status - SAME SIZE */
.badge-pending {
background: linear-gradient(135deg, #fef3c7, #fde68a) !important;
color: #d97706 !important;
border-color: #f59e0b !important;
+ width: 110px;
}
- /* In Transit Status */
+ /* In Transit Status - SAME SIZE */
.badge-in_transit {
background: linear-gradient(135deg, #dbeafe, #93c5fd) !important;
color: #1e40af !important;
border-color: #3b82f6 !important;
+ width: 110px;
}
- /* Dispatched Status */
+ /* Dispatched Status - SAME SIZE */
.badge-dispatched {
background: linear-gradient(135deg, #e9d5ff, #c4b5fd) !important;
color: #6b21a8 !important;
border-color: #8b5cf6 !important;
+ width: 110px;
}
- /* Delivered Status */
+ /* Delivered Status - SAME SIZE */
.badge-delivered {
background: linear-gradient(135deg, #d1fae5, #a7f3d0) !important;
color: #065f46 !important;
border-color: #10b981 !important;
+ width: 110px;
}
+ /* 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;
+ }
+
/* Light badges for quantity, kg, cbm */
.badge.bg-light {
background: #f8f9fa !important;
@@ -381,12 +318,9 @@
border: 1px solid #dee2e6 !important;
min-width: 80px !important;
padding: 6px 12px !important;
- font-family: 'Inter', sans-serif;
- font-size: 13px;
- width: auto;
}
- /* Action Button Styles */
+ /* NEW: Action Button Styles */
.action-container {
position: relative;
display: inline-block;
@@ -405,7 +339,6 @@
justify-content: center;
width: 36px;
height: 36px;
- font-family: 'Inter', sans-serif;
}
.btn-edit-status:hover {
@@ -429,7 +362,6 @@
margin-top: -50px;
border: 1px solid var(--border);
z-index: 1050;
- font-family: 'Inter', sans-serif;
}
.status-dropdown.show {
@@ -450,7 +382,6 @@
gap: 8px;
background: transparent;
width: 100%;
- font-family: 'Inter', sans-serif;
}
.status-option:hover {
@@ -516,73 +447,12 @@
background: #10b981;
}
- /* View Button Styles */
- .btn-view {
- background: #4361ee;
- color: white;
- border: none;
- border-radius: 8px;
- padding: 8px;
- cursor: pointer;
- transition: all 0.3s ease;
- display: flex;
- align-items: center;
- justify-content: center;
- width: 36px;
- height: 36px;
- font-weight: 600;
- font-size: 16px;
- font-family: 'Inter', sans-serif;
- position: relative;
- overflow: hidden;
- }
-
- .btn-view::before {
- content: '';
- position: absolute;
- top: 0;
- left: -100%;
- width: 100%;
- height: 100%;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- transition: all 0.3s ease;
- z-index: 1;
- }
-
- .btn-view:hover::before {
- left: 0;
- }
-
- .btn-view i {
- position: relative;
- z-index: 2;
- transition: all 0.3s ease;
- }
-
- .btn-view:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
- }
-
- .btn-view:hover i {
- transform: scale(1.1);
- }
-
- /* Action buttons container */
- .action-buttons {
- display: flex;
- gap: 8px;
- align-items: center;
- justify-content: center;
- }
-
/* Modal Styles */
.modal-content {
border-radius: 20px;
border: none;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
overflow: hidden;
- font-family: 'Inter', sans-serif;
}
.modal-header {
@@ -592,7 +462,6 @@
padding: 25px 30px 15px;
border-radius: 20px 20px 0 0;
position: relative;
- font-family: 'Inter', sans-serif;
}
.modal-header::after {
@@ -608,7 +477,6 @@
.modal-title {
font-weight: 700;
font-size: 1.5rem;
- font-family: 'Inter', sans-serif;
}
.btn-close {
@@ -622,7 +490,6 @@
.modal-body {
padding: 25px 30px;
- font-family: 'Inter', sans-serif;
}
/* Form Styles */
@@ -631,18 +498,16 @@
color: #5a6c7d;
margin-bottom: 8px;
font-size: 0.9rem;
- font-family: 'Inter', sans-serif;
}
.form-control {
border-radius: 10px;
border: 1px solid #e2e8f0;
padding: 12px 16px;
- font-size: 14px;
+ font-size: 15px;
transition: all 0.3s ease;
background: #fafbfc;
color: #4a5568;
- font-family: 'Inter', sans-serif;
}
.form-control:focus {
@@ -655,6 +520,39 @@
color: #a0aec0;
}
+ /* Date Input Styling */
+ input[type="date"] {
+ position: relative;
+ }
+
+ input[type="date"]::-webkit-calendar-picker-indicator {
+ background: transparent;
+ bottom: 0;
+ color: transparent;
+ cursor: pointer;
+ height: auto;
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: auto;
+ }
+
+ input[type="date"] {
+ position: relative;
+ padding-right: 40px;
+ }
+
+ input[type="date"]:after {
+ content: "📅";
+ position: absolute;
+ right: 12px;
+ top: 50%;
+ transform: translateY(-50%);
+ pointer-events: none;
+ font-size: 16px;
+ }
+
/* Button Styles */
.btn-cancel {
background: #f7fafc;
@@ -664,8 +562,6 @@
font-weight: 600;
padding: 12px 30px;
transition: all 0.3s ease;
- font-family: 'Inter', sans-serif;
- font-size: 14px;
}
.btn-cancel:hover {
@@ -679,12 +575,11 @@
background: linear-gradient(135deg, #48bb78, #38a169);
color: white;
font-weight: 600;
- font-size: 14px;
+ font-size: 16px;
border-radius: 10px;
padding: 12px 35px;
border: none;
transition: all 0.3s ease;
- font-family: 'Inter', sans-serif;
}
.btn-create:hover {
@@ -700,7 +595,6 @@
border-spacing: 0 8px;
margin: 0;
min-width: 1300px;
- font-family: 'Inter', sans-serif;
}
.custom-table-modal thead th {
@@ -711,10 +605,9 @@
border: 1px solid #e2e8f0;
text-align: center;
position: relative;
- font-size: 14px;
+ font-size: 0.9rem;
letter-spacing: 0.3px;
white-space: nowrap;
- font-family: 'Inter', sans-serif;
}
.custom-table-modal thead th:first-child {
@@ -751,8 +644,6 @@
position: relative;
color: #4a5568;
white-space: nowrap;
- font-family: 'Inter', sans-serif;
- font-size: 14px;
}
.custom-table-modal tbody tr td:first-child {
@@ -765,6 +656,38 @@
border-bottom-right-radius: 10px;
}
+ /* Checkbox Styling */
+ input[type="checkbox"] {
+ width: 20px;
+ height: 20px;
+ border-radius: 6px;
+ border: 2px solid #cbd5e0;
+ cursor: pointer;
+ position: relative;
+ transition: all 0.2s ease;
+ background: #f7fafc;
+ }
+
+ input[type="checkbox"]:checked {
+ background: var(--primary);
+ border-color: var(--primary);
+ }
+
+ /* Link Styling */
+ a.text-primary {
+ color: var(--primary) !important;
+ text-decoration: none;
+ font-weight: 600;
+ transition: all 0.3s ease;
+ position: relative;
+ color: #4361ee !important;
+ }
+
+ a.text-primary:hover {
+ color: var(--primary-dark) !important;
+ text-decoration: underline;
+ }
+
/* Shipment Details Modal */
.shipment-details-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
@@ -772,12 +695,10 @@
border: none;
padding: 25px 30px 15px;
border-radius: 20px 20px 0 0;
- font-family: 'Inter', sans-serif;
}
.shipment-details-body {
padding: 40px 45px;
- font-family: 'Inter', sans-serif;
}
.shipment-info-row {
@@ -788,7 +709,6 @@
background: #f8fafc;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
- font-family: 'Inter', sans-serif;
}
.shipment-info-item {
@@ -802,14 +722,12 @@
color: #64748b;
font-size: 14px;
margin-bottom: 5px;
- font-family: 'Inter', sans-serif;
}
.shipment-info-value {
font-weight: 700;
font-size: 18px;
color: var(--dark);
- font-family: 'Inter', sans-serif;
}
.shipment-details-table {
@@ -818,7 +736,6 @@
border-spacing: 0 8px;
margin-top: 20px;
min-width: 1400px;
- font-family: 'Inter', sans-serif;
}
.shipment-details-table th {
@@ -830,8 +747,6 @@
border: none;
position: relative;
white-space: nowrap;
- font-family: 'Inter', sans-serif;
- font-size: 14px;
}
.shipment-details-table th:first-child {
@@ -851,8 +766,6 @@
background: white;
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
white-space: nowrap;
- font-family: 'Inter', sans-serif;
- font-size: 14px;
}
.shipment-details-table tr td:first-child {
@@ -865,31 +778,6 @@
border-bottom-right-radius: 10px;
}
- /* Delete Button for Orders */
- .btn-delete-order {
- background: linear-gradient(135deg, #f87171, #ef4444);
- color: white;
- border: none;
- border-radius: 6px;
- padding: 6px 12px;
- cursor: pointer;
- transition: all 0.3s ease;
- font-size: 12px;
- font-weight: 600;
- font-family: 'Inter', sans-serif;
- display: flex;
- align-items: center;
- gap: 4px;
- min-width: 80px;
- justify-content: center;
- }
-
- .btn-delete-order:hover {
- background: linear-gradient(135deg, #ef4444, #dc2626);
- transform: translateY(-2px);
- box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
- }
-
/* Shipment Totals Section */
.shipment-totals {
margin-top: 25px;
@@ -898,7 +786,6 @@
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0,0,0,0.05);
border-left: 4px solid #4361ee;
- font-family: 'Inter', sans-serif;
}
.shipment-totals-row {
@@ -925,7 +812,6 @@
margin-bottom: 8px;
text-transform: uppercase;
letter-spacing: 0.5px;
- font-family: 'Inter', sans-serif;
}
.shipment-total-value {
@@ -933,7 +819,6 @@
font-size: 20px;
color: #1e293b;
line-height: 1.2;
- font-family: 'Inter', sans-serif;
}
.total-amount {
@@ -1006,7 +891,6 @@
/* Status Filter Styles */
.status-filter-container {
position: relative;
- margin-left:350px;
}
.status-filter-select {
@@ -1021,7 +905,20 @@
padding-right: 40px !important;
}
- /* Pagination Styles */
+ /* Shipment row styling for filtering */
+ .shipment-row {
+ transition: all 0.3s ease;
+ }
+
+ .shipment-row.hidden {
+ display: none !important;
+ }
+
+ .shipment-row.visible {
+ display: table-row;
+ }
+
+ /* ---------- Pagination Styles (Same as Account Dashboard) ---------- */
.pagination-container {
display: flex;
justify-content: space-between;
@@ -1029,14 +926,12 @@
margin-top: 15px;
padding: 12px 25px;
border-top: 1px solid #eef3fb;
- font-family: 'Inter', sans-serif;
}
.pagination-info {
font-size: 13px;
color: #9ba5bb;
font-weight: 600;
- font-family: 'Inter', sans-serif;
}
.pagination-controls {
@@ -1060,7 +955,6 @@
justify-content: center;
min-width: 40px;
height: 32px;
- font-family: 'Inter', sans-serif;
}
.pagination-btn:hover:not(:disabled) {
@@ -1089,7 +983,6 @@
transition: all 0.3s ease;
min-width: 36px;
text-align: center;
- font-family: 'Inter', sans-serif;
}
.pagination-page-btn:hover {
@@ -1114,9 +1007,9 @@
color: #9ba5bb;
font-size: 13px;
padding: 0 4px;
- font-family: 'Inter', sans-serif;
}
+ /* Image-based pagination buttons */
.pagination-img-btn {
background: #fff;
border: 1px solid #e3eaf6;
@@ -1169,42 +1062,6 @@
justify-content: center;
}
}
-
- /* Delete Confirmation Modal */
- .delete-confirmation-modal .modal-header {
- background: linear-gradient(135deg, #ef4444, #dc2626);
- }
-
- .delete-confirmation-modal .btn-confirm-delete {
- background: linear-gradient(135deg, #ef4444, #dc2626);
- color: white;
- border: none;
- border-radius: 8px;
- padding: 10px 20px;
- font-weight: 600;
- transition: all 0.3s ease;
- }
-
- .delete-confirmation-modal .btn-confirm-delete:hover {
- background: linear-gradient(135deg, #dc2626, #b91c1c);
- transform: translateY(-2px);
- box-shadow: 0 4px 12px rgba(220, 38, 38, 0.3);
- }
-
- .delete-confirmation-modal .btn-cancel-delete {
- background: #f7fafc;
- color: #718096;
- border: 1px solid #cbd5e0;
- border-radius: 8px;
- padding: 10px 20px;
- font-weight: 600;
- transition: all 0.3s ease;
- }
-
- .delete-confirmation-modal .btn-cancel-delete:hover {
- background: #edf2f7;
- color: #4a5568;
- }
@@ -1226,27 +1083,12 @@
@endif
-
+
+
+
-
-
+
🔍
+
+
-
+
+
+