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 }})

    + +
    +
    + +
    + + + + + + + + + + + + + + @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 + + + + + + + + + + + + + + + + @endforeach + +
    #UserRequested ChangesStatusRequested AtActions
    {{ ($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 +
    +
    + +
    +
    +
    +@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 - + + +
    -
    -
    - - -
    -
    - + 🔍 +
    +
    - + + +