Files
Kent-logistics-Laravel/resources/views/admin/requests.blade.php
Utkarsh Khedkar 9cc6959396 Pdf Changes Done
2026-03-09 10:24:44 +05:30

541 lines
22 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@extends('admin.layouts.app')
@section('page-title', 'User Requests')
@section('content')
<div class="container-fluid px-0">
@php
$perPage = 5; // ✅ FORCED to show pagination even with few records
$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>
@keyframes fadeInUp {0% { transform: translateY(20px); opacity: 0; }100% { transform: translateY(0); opacity: 1; }}
.card, .custom-table-wrapper { animation: fadeInUp 0.8s ease both; }
/* ✅ ROW HOVER EFFECT COMPLETELY DISABLED */
.custom-table tbody tr {
transition: none !important;
}
.custom-table tbody tr:hover {
background-color: transparent !important;
transform: none !important;
box-shadow: none !important;
}
.priority-badge {
display: inline-flex; align-items: center; font-size: 13.5px; padding: 6px 16px; border-radius: 12px; font-weight: 600;
box-shadow: 0 1px 2px 0 rgba(230, 206, 206, 0.15); width: 90px; min-height: 28px; justify-content: center;
color: #fff; margin: 2px 0; transition: transform 0.2s ease-in-out;
}
.priority-badge:hover { transform: scale(1.08); }
.priority-high { background: linear-gradient(135deg, #ff8a8a, #d12929); }
.priority-medium { background: linear-gradient(135deg, #ffe390, #f5b041); }
.priority-low { background: linear-gradient(135deg, #b8f0c2, #1d8660); }
.custom-table thead th {
text-align: center; font-weight: 700; color: #ffffffff; padding: 14px; font-size: 17px; letter-spacing: 0.5px;
border-bottom: 2px solid #bfbfbf; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.custom-table thead tr:first-child th:first-child { border-top-left-radius: 12px; }
.custom-table thead tr:first-child th:last-child { border-top-right-radius: 12px; }
.custom-table tbody tr:last-child td:first-child { border-bottom-left-radius: 12px; }
.custom-table tbody tr:last-child td:last-child { border-bottom-right-radius: 12px; }
.input-group input { border-radius: 10px 0 0 10px; border: 1px solid #ccc; box-shadow: inset 0 1px 3px rgba(0,0,0,0.05); }
.input-group .btn { border-radius: 0 10px 10px 0; transition: all 0.2s ease-in-out; }
.input-group .btn:hover { background: #ffd65a; border-color: #ffd65a; color: #000; }
.card { border-radius: 16px; border: none; box-shadow: 0 4px 10px rgba(0,0,0,0.08); background: #fff; }
.badge {
font-size: 11px !important; font-weight: 600 !important; padding: 7px 13px !important; border-radius: 20px !important;
text-transform: uppercase; letter-spacing: 0.3px; display: inline-flex !important; align-items: center; justify-content: center;
color: #fff !important; text-shadow: 0 1px 2px rgba(0,0,0,0.3); border: 2px solid transparent !important;
line-height: 1.2; gap: 6px; animation: pulse 2s infinite; width: 99px;
}
.status-icon { font-size: 0px; display: flex; align-items: center; justify-content: center; }
.badge.badge-pending { background: linear-gradient(135deg, #fef3c7, #fde68a) !important; color: #d97706 !important; border-color: #f59e0b !important; width: 85px; }
.badge.badge-approved { background: linear-gradient(135deg, #d1fae5, #a7f3d0) !important; color: #065f46 !important; border-color: #10b981 !important; width: 85px; }
.badge.badge-rejected { background: linear-gradient(135deg, #fecaca, #fca5a5) !important; color: #991b1b !important; border-color: #ef4444 !important; width: 85px; }
@keyframes pulse {0% { box-shadow: 0 0 8px rgba(0,0,0,0.1); }50% { box-shadow: 0 0 14px rgba(0,0,0,0.15); }100% { box-shadow: 0 0 8px rgba(0,0,0,0.1); }}
.count-badge { --bs-badge-padding-x: 0.65em; --bs-badge-padding-y: 0.35em; --bs-badge-font-size: 0.75em; --bs-badge-font-weight: 700; --bs-badge-color: #fff; --bs-badge-border-radius: var(--bs-border-radius); }
h4.fw-bold { background: linear-gradient(90deg, #000000ff 0%, #030302ff 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; font-weight: 800; letter-spacing: 1px; }
.custom-table th,
.custom-table td {
text-align: center;
vertical-align: middle;
}
/* ===== PAGINATION STYLES ===== */
.pagination-container {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 15px;
padding: 12px 0;
border-top: 1px solid #eef3fb;
}
.pagination-info {
font-size: 13px;
color: #9ba5bb;
font-weight: 600;
}
.pagination-controls {
display: flex;
align-items: center;
gap: 8px;
}
.pagination-btn {
background: #fff;
border: 1px solid #e3eaf6;
color: #1a2951;
padding: 8px 12px;
border-radius: 6px;
font-size: 13px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
min-width: 40px;
height: 32px;
}
.pagination-btn:hover:not(:disabled) {
background: #1a2951;
color: white;
border-color: #1a2951;
}
.pagination-btn:disabled {
background: #f8fafc;
color: #cbd5e0;
border-color: #e2e8f0;
cursor: not-allowed;
opacity: 0.6;
}
.pagination-page-btn {
background: #fff;
border: 1px solid #e3eaf6;
color: #1a2951;
padding: 6px 12px;
border-radius: 6px;
font-size: 13px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
min-width: 36px;
text-align: center;
text-decoration: none;
}
.pagination-page-btn:hover {
background: #1a2951;
color: white;
border-color: #1a2951;
}
.pagination-page-btn.active {
background: #1a2951;
color: white;
border-color: #1a2951;
}
.pagination-pages {
display: flex;
gap: 4px;
align-items: center;
}
.pagination-ellipsis {
color: #9ba5bb;
font-size: 13px;
padding: 0 4px;
}
.pagination-img-btn {
background: #fff;
border: 1px solid #e3eaf6;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
min-width: 40px;
height: 32px;
padding: 0;
text-decoration: none;
}
.pagination-img-btn:hover:not(:disabled) {
background: #1a2951;
border-color: #1a2951;
}
.pagination-img-btn:disabled {
background: #f8fafc;
border-color: #e2e8f0;
cursor: not-allowed;
opacity: 0.5;
}
.pagination-img-btn svg {
width: 16px;
height: 16px;
transition: filter 0.3s ease;
}
.pagination-img-btn:hover:not(:disabled) svg {
filter: brightness(0) saturate(100%) invert(100%) sepia(100%) saturate(0%) hue-rotate(288deg) brightness(106%) contrast(101%);
}
.pagination-img-btn:disabled svg {
filter: brightness(0) saturate(100%) invert(84%) sepia(8%) saturate(165%) hue-rotate(179deg) brightness(89%) contrast(86%);
}
/* ===== UPDATED SEARCH BAR STYLES ===== */
.search-container {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
gap: 15px;
}
.search-form {
flex: 1;
max-width: 400px;
}
.search-input-group {
display: flex;
box-shadow: 0 2px 6px rgba(0,0,0,0.08);
border-radius: 10px;
overflow: hidden;
}
.search-input {
flex: 1;
border: 1px solid #e2e8f0;
border-right: none;
padding: 10px 16px;
font-size: 14px;
background-color: #fff;
transition: all 0.3s ease;
}
.search-input:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.search-button {
background: #3b82f6;
border: 1px solid #3b82f6;
color: white;
padding: 10px 16px;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
}
.search-button:hover {
background: #2563eb;
border-color: #2563eb;
}
.search-icon {
width: 16px;
height: 16px;
}
.status-badges {
display: flex;
gap: 8px;
align-items: center;
}
.status-badge {
font-size: 12px;
font-weight: 600;
padding: 6px 12px;
border-radius: 20px;
display: inline-flex;
align-items: center;
gap: 4px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.status-badge-pending {
background: linear-gradient(135deg, #fef3c7, #fde68a);
color: #d97706;
border: 1px solid #f59e0b;
}
.status-badge-approved {
background: linear-gradient(135deg, #d1fae5, #a7f3d0);
color: #065f46;
border: 1px solid #10b981;
}
.status-badge-rejected {
background: linear-gradient(135deg, #fecaca, #fca5a5);
color: #991b1b;
border: 1px solid #ef4444;
}
/* ✅ TABLE WRAPPER REMOVE HORIZONTAL SCROLL */
.custom-table-wrapper {
overflow-x: hidden !important;
}
.custom-table {
width: 100%;
table-layout: auto;
}
/* Responsive styles */
@media (max-width: 768px) {
.pagination-container {
flex-direction: column;
gap: 10px;
align-items: stretch;
}
.pagination-controls {
justify-content: center;
}
.search-container {
flex-direction: column;
align-items: stretch;
}
.search-form {
max-width: 100%;
}
.status-badges {
justify-content: center;
}
}
/* PROFILE UPDATE REQUEST BUTTON BADGE FIX */
a.btn.btn-primary.position-relative {
position: relative;
margin-right: 10px;
}
a.btn.btn-primary.position-relative .badge {
width: 30px !important;
height: 30px !important;
min-width: 30px !important;
padding: 0 !important;
font-size: 14px !important;
line-height: 30px !important;
border-radius: 50% !important;
display: inline-flex !important;
align-items: center;
justify-content: center;
animation: none !important;
box-shadow: 0 0 0 2px #ffffff;
}
</style>
<!-- Counts -->
<div class="d-flex justify-content-between align-items-center mb-2 mt-3">
<h4 class="fw-bold mb-0">User Requests (Total: {{ $total }})</h4>
@can('request.update_profile')
<a href="{{ route('admin.profile.requests') }}" class="btn btn-primary position-relative">
<i class="bi bi-person-lines-fill me-1"></i>
Profile Update Requests
@if($pendingProfileUpdates > 0)
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
{{ $pendingProfileUpdates }}
</span>
@endif
</a>
@endcan
</div>
<!-- Search + Table -->
<div class="card mb-4 shadow-sm">
<div class="card-body pb-1">
<div class="search-container">
<form method="GET" action="" class="search-form">
<div class="search-input-group">
<input type="text" name="search" value="{{ request('search') }}" class="search-input" placeholder="Search by name, email, company...">
<button class="search-button" type="submit">
<svg class="search-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21 21L16.514 16.506L21 21ZM19 10.5C19 15.194 15.194 19 10.5 19C5.806 19 2 15.194 2 10.5C2 5.806 5.806 2 10.5 2C15.194 2 19 5.806 19 10.5Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
</div>
</form>
<div class="status-badges">
<span class="status-badge status-badge-pending">{{ $requests->where('status', 'pending')->count() }} Pending</span>
<span class="status-badge status-badge-approved">{{ $requests->where('status', 'approved')->count() }} Approved</span>
<span class="status-badge status-badge-rejected">{{ $requests->where('status', 'rejected')->count() }} Rejected</span>
</div>
</div>
<div class="table-responsive custom-table-wrapper">
<table class="table align-middle mb-0 custom-table">
<thead>
<tr>
<th>#</th>
<th>Request ID</th>
<th>Name</th>
<th>Company</th>
<th>Email</th>
<th>Mobile</th>
<th>Address</th>
<th>Priority</th>
<th>Date</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@forelse($currentItems as $index => $req)
<tr>
<td><strong>{{ ($currentPage - 1) * $perPage + $index + 1 }}</strong></td>
<td>{{ $req->request_id }}</td>
<td>{{ $req->customer_name }}</td>
<td>{{ $req->company_name }}</td>
<td>{{ $req->email }}</td>
<td>{{ $req->mobile_no }}</td>
<td>{{ Str::limit($req->address, 30) }}</td>
<td>
@if(strtolower($req->priority) == 'high')
<span class="priority-badge priority-high">High</span>
@elseif(strtolower($req->priority) == 'medium')
<span class="priority-badge priority-medium">Medium</span>
@elseif(strtolower($req->priority) == 'low')
<span class="priority-badge priority-low">Low</span>
@else
{{ $req->priority ?? 'N/A' }}
@endif
</td>
<td>{{ $req->date }}</td>
<td>
@if($req->status == 'approved')
<span class="badge badge-approved"><i class="bi bi-check-circle-fill status-icon"></i>Approved</span>
@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>
@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>
@endforelse
</tbody>
</table>
</div>
{{-- PAGINATION - WITH ARROW BUTTONS --}}
<div class="pagination-container">
<div class="pagination-info">
Showing {{ ($currentPage - 1) * $perPage + 1 }} to {{ min($currentPage * $perPage, $total) }} of {{ $total }} entries
</div>
<div class="pagination-controls">
{{-- Previous Page --}}
@if($currentPage > 1)
<a href="{{ request()->fullUrlWithQuery(['page' => $currentPage - 1]) }}" class="pagination-img-btn" title="Previous page">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</a>
@else
<button class="pagination-img-btn" disabled title="Previous page">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
@endif
{{-- Page Numbers --}}
<div class="pagination-pages">
@php
$start = max(1, $currentPage - 1);
$end = min($totalPages, $currentPage + 1);
@endphp
@if($start > 1)
<a href="{{ request()->fullUrlWithQuery(['page' => 1]) }}" class="pagination-page-btn">1</a>
@if($start > 2)
<span class="pagination-ellipsis">...</span>
@endif
@endif
@for($i = $start; $i <= $end; $i++)
@if($i == $currentPage)
<span class="pagination-page-btn active">{{ $i }}</span>
@else
<a href="{{ request()->fullUrlWithQuery(['page' => $i]) }}" class="pagination-page-btn">{{ $i }}</a>
@endif
@endfor
@if($end < $totalPages)
@if($end < $totalPages - 1)
<span class="pagination-ellipsis">...</span>
@endif
<a href="{{ request()->fullUrlWithQuery(['page' => $totalPages]) }}" class="pagination-page-btn">{{ $totalPages }}</a>
@endif
</div>
{{-- Next Page --}}
@if($currentPage < $totalPages)
<a href="{{ request()->fullUrlWithQuery(['page' => $currentPage + 1]) }}" class="pagination-img-btn" title="Next page">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 4L10 8L6 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</a>
@else
<button class="pagination-img-btn" disabled title="Next page">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 4L10 8L6 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
@endif
</div>
</div>
</div>
</div>
</div>
@endsection