Wyszukiwanie i sortowanie
This commit is contained in:
parent
f376bde1b5
commit
44c384f33f
@ -14,9 +14,34 @@ class UserController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Wyświetla listę wszystkich użytkowników.
|
* Wyświetla listę wszystkich użytkowników.
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$users = User::with('roles')->paginate(10);
|
$allowedSorts = ['name', 'email'];
|
||||||
|
|
||||||
|
$sort = in_array($request->query('sort'), $allowedSorts) ? $request->query('sort') : 'name';
|
||||||
|
$direction = $request->query('direction') === 'desc' ? 'desc' : 'asc';
|
||||||
|
$search = trim($request->query('search'));
|
||||||
|
|
||||||
|
$query = User::with('roles');
|
||||||
|
|
||||||
|
// Wyszukiwanie w imieniu, nazwisku i adresie email
|
||||||
|
if ($search) {
|
||||||
|
$query->where(function ($q) use ($search) {
|
||||||
|
$q->where('name', 'like', "%{$search}%")
|
||||||
|
->orWhere('surname', 'like', "%{$search}%")
|
||||||
|
->orWhere('email', 'like', "%{$search}%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sortowanie
|
||||||
|
if ($sort === 'name') {
|
||||||
|
$query->orderBy('name', $direction)->orderBy('surname', $direction);
|
||||||
|
} else {
|
||||||
|
$query->orderBy($sort, $direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zachowujemy query string w paginacji bezpośrednio z poziomu controllera
|
||||||
|
$users = $query->paginate(10)->withQueryString();
|
||||||
|
|
||||||
return view('users.index', compact('users'));
|
return view('users.index', compact('users'));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,7 +45,7 @@ class UserSeeder extends Seeder
|
|||||||
$pracownik->assignRole($pracownikRole);
|
$pracownik->assignRole($pracownikRole);
|
||||||
|
|
||||||
// 2. Generowanie dodatkowych 30 losowych użytkowników z rolami (password = 'password')
|
// 2. Generowanie dodatkowych 30 losowych użytkowników z rolami (password = 'password')
|
||||||
User::factory(30)->create()->each(function ($user) use ($pracownikRole, $kierownikRole) {
|
User::factory(300)->create()->each(function ($user) use ($pracownikRole, $kierownikRole) {
|
||||||
$role = rand(1, 100) <= 80 ? $pracownikRole : $kierownikRole;
|
$role = rand(1, 100) <= 80 ? $pracownikRole : $kierownikRole;
|
||||||
$user->assignRole($role);
|
$user->assignRole($role);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,7 +5,6 @@
|
|||||||
{{ __('Lista użytkowników') }}
|
{{ __('Lista użytkowników') }}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
{{-- Dostęp tylko dla Admina i Kierownika --}}
|
|
||||||
@hasanyrole('admin|kierownik')
|
@hasanyrole('admin|kierownik')
|
||||||
<a href="{{ route('users.create') }}"
|
<a href="{{ route('users.create') }}"
|
||||||
class="inline-flex items-center px-4 py-2 bg-indigo-600 hover:bg-indigo-500 text-white text-sm font-medium rounded-md shadow-sm transition ease-in-out duration-150 gap-2">
|
class="inline-flex items-center px-4 py-2 bg-indigo-600 hover:bg-indigo-500 text-white text-sm font-medium rounded-md shadow-sm transition ease-in-out duration-150 gap-2">
|
||||||
@ -16,9 +15,8 @@
|
|||||||
</a>
|
</a>
|
||||||
@endhasanyrole
|
@endhasanyrole
|
||||||
</div>
|
</div>
|
||||||
</x-slot>
|
</x-slot>
|
||||||
|
|
||||||
<!-- Styl do wymuszenia powiększonych badge'y i efektu hover niezależnie od Vite/Tailwind -->
|
|
||||||
<style>
|
<style>
|
||||||
.custom-table-row:hover {
|
.custom-table-row:hover {
|
||||||
background-color: rgba(255, 255, 255, 0.05) !important;
|
background-color: rgba(255, 255, 255, 0.05) !important;
|
||||||
@ -37,12 +35,79 @@
|
|||||||
<div class="bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg border border-gray-700/50">
|
<div class="bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg border border-gray-700/50">
|
||||||
<div class="p-6 text-white">
|
<div class="p-6 text-white">
|
||||||
|
|
||||||
|
{{-- Formularz Wyszukiwania --}}
|
||||||
|
<div class="mb-6 flex items-center justify-between gap-4">
|
||||||
|
<form method="GET" action="{{ route('users.index') }}" class="flex items-center gap-2 w-full max-w-xs">
|
||||||
|
{{-- Zachowanie bieżącego sortowania podczas wyszukiwania --}}
|
||||||
|
@if(request('sort'))
|
||||||
|
<input type="hidden" name="sort" value="{{ request('sort') }}">
|
||||||
|
@endif
|
||||||
|
@if(request('direction'))
|
||||||
|
<input type="hidden" name="direction" value="{{ request('direction') }}">
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="w-full">
|
||||||
|
<x-text-input
|
||||||
|
type="text"
|
||||||
|
name="search"
|
||||||
|
:value="request('search')"
|
||||||
|
placeholder="Szukaj po imieniu, nazwisku lub e-mailu..."
|
||||||
|
class="block w-full px-3 py-2 text-sm"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<x-primary-button type="submit">
|
||||||
|
Szukaj
|
||||||
|
</x-primary-button>
|
||||||
|
|
||||||
|
@if(request('search'))
|
||||||
|
<a href="{{ route('users.index', request()->only(['sort', 'direction'])) }}"
|
||||||
|
class="inline-flex items-center px-4 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-md font-semibold text-xs text-gray-700 dark:text-gray-300 uppercase tracking-widest shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150 whitespace-nowrap">
|
||||||
|
Wyczyść
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="w-full border-collapse" style="table-layout: fixed;">
|
<table class="w-full border-collapse" style="table-layout: fixed;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="border-b border-gray-700 text-xs font-semibold uppercase tracking-wider text-gray-300">
|
<tr class="border-b border-gray-700 text-xs font-semibold uppercase tracking-wider text-gray-300">
|
||||||
<th scope="col" class="py-3.5 px-4" style="text-align: center !important; width: 25%;">Imię i nazwisko</th>
|
|
||||||
<th scope="col" class="py-3.5 px-4" style="text-align: center !important; width: 35%;">Adres e-mail</th>
|
@php
|
||||||
|
$currentSort = request('sort');
|
||||||
|
$currentDir = request('direction', 'asc');
|
||||||
|
|
||||||
|
$nextDirName = ($currentSort === 'name' && $currentDir === 'asc') ? 'desc' : 'asc';
|
||||||
|
$nextDirEmail = ($currentSort === 'email' && $currentDir === 'asc') ? 'desc' : 'asc';
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
{{-- Imię i nazwisko --}}
|
||||||
|
<th scope="col" class="py-3.5 px-4" style="text-align: center !important; width: 25%;">
|
||||||
|
<a href="{{ route('users.index', array_merge(request()->query(), ['sort' => 'name', 'direction' => $nextDirName])) }}"
|
||||||
|
class="inline-flex items-center gap-1 hover:text-white transition">
|
||||||
|
<span>Imię i nazwisko</span>
|
||||||
|
@if($currentSort === 'name')
|
||||||
|
<svg class="w-4 h-4 text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="{{ $currentDir === 'asc' ? 'M19 9l-7 7-7-7' : 'M5 15l7-7 7 7' }}" />
|
||||||
|
</svg>
|
||||||
|
@endif
|
||||||
|
</a>
|
||||||
|
</th>
|
||||||
|
|
||||||
|
{{-- Adres e-mail --}}
|
||||||
|
<th scope="col" class="py-3.5 px-4" style="text-align: center !important; width: 35%;">
|
||||||
|
<a href="{{ route('users.index', array_merge(request()->query(), ['sort' => 'email', 'direction' => $nextDirEmail])) }}"
|
||||||
|
class="inline-flex items-center gap-1 hover:text-white transition">
|
||||||
|
<span>Adres e-mail</span>
|
||||||
|
@if($currentSort === 'email')
|
||||||
|
<svg class="w-4 h-4 text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="{{ $currentDir === 'asc' ? 'M19 9l-7 7-7-7' : 'M5 15l7-7 7 7' }}" />
|
||||||
|
</svg>
|
||||||
|
@endif
|
||||||
|
</a>
|
||||||
|
</th>
|
||||||
|
|
||||||
<th scope="col" class="py-3.5 px-4" style="text-align: center !important; width: 25%;">Rola</th>
|
<th scope="col" class="py-3.5 px-4" style="text-align: center !important; width: 25%;">Rola</th>
|
||||||
<th scope="col" class="py-3.5 px-4" style="text-align: center !important; width: 15%;">Akcje</th>
|
<th scope="col" class="py-3.5 px-4" style="text-align: center !important; width: 15%;">Akcje</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -52,17 +117,14 @@
|
|||||||
@forelse($users as $user)
|
@forelse($users as $user)
|
||||||
<tr class="custom-table-row transition-colors duration-150">
|
<tr class="custom-table-row transition-colors duration-150">
|
||||||
|
|
||||||
<!-- Imię i Nazwisko -->
|
|
||||||
<td class="py-4 px-4 font-medium text-white align-middle" style="text-align: center !important;">
|
<td class="py-4 px-4 font-medium text-white align-middle" style="text-align: center !important;">
|
||||||
{{ $user->name }} {{ $user->surname }}
|
{{ $user->name }} {{ $user->surname }}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<!-- Email (Wymuszone wycentrowanie) -->
|
|
||||||
<td class="py-4 px-4 text-gray-300 align-middle" style="text-align: center !important;">
|
<td class="py-4 px-4 text-gray-300 align-middle" style="text-align: center !important;">
|
||||||
{{ $user->email }}
|
{{ $user->email }}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<!-- Rola (Poszerzony badge z min-width 120px) -->
|
|
||||||
<td class="py-4 px-4 text-gray-300 align-middle" style="text-align: center !important;">
|
<td class="py-4 px-4 text-gray-300 align-middle" style="text-align: center !important;">
|
||||||
<div style="display: flex; justify-content: center; align-items: center; gap: 8px;">
|
<div style="display: flex; justify-content: center; align-items: center; gap: 8px;">
|
||||||
@forelse($user->roles as $role)
|
@forelse($user->roles as $role)
|
||||||
@ -75,7 +137,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<!-- Akcje -->
|
|
||||||
<td class="py-4 px-4 align-middle" style="text-align: center !important;">
|
<td class="py-4 px-4 align-middle" style="text-align: center !important;">
|
||||||
<a href="{{ route('users.edit', $user) }}" class="text-indigo-400 hover:text-indigo-300 font-medium text-sm transition">
|
<a href="{{ route('users.edit', $user) }}" class="text-indigo-400 hover:text-indigo-300 font-medium text-sm transition">
|
||||||
Edytuj
|
Edytuj
|
||||||
@ -86,7 +147,11 @@
|
|||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="4" class="py-8 text-gray-400" style="text-align: center !important;">
|
<td colspan="4" class="py-8 text-gray-400" style="text-align: center !important;">
|
||||||
|
@if(request('search'))
|
||||||
|
Brak wyników spełniających kryteria wyszukiwania: "<strong>{{ request('search') }}</strong>".
|
||||||
|
@else
|
||||||
Brak użytkowników do wyświetlenia.
|
Brak użytkowników do wyświetlenia.
|
||||||
|
@endif
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user