pagination + optionsl vehicles fields

This commit is contained in:
Arnaud Delcasse
2025-10-08 22:55:07 +02:00
parent 73d99e7ad7
commit ed726b610f
11 changed files with 870 additions and 304 deletions

View File

@@ -4,87 +4,145 @@
{{if eq (len .ViewState.bookings_history) 0}}
<div class="m-10 text-center text-gray-600">Aucun trajet dans le passé</div>
{{else}}
<div x-data="{
bookings: [
{{range $index, $booking := .ViewState.bookings_history}}{{if $index}},{{end}}{
id: '{{$booking.Id}}',
driverId: '{{$booking.DriverId}}',
driverFirstName: '{{ (index $.ViewState.drivers_map $booking.DriverId).Data.first_name }}',
driverLastName: '{{ (index $.ViewState.drivers_map $booking.DriverId).Data.last_name }}',
passengerId: '{{$booking.PassengerId}}',
passengerFirstName: '{{ (index $.ViewState.passengers_map $booking.PassengerId).Data.first_name }}',
passengerLastName: '{{ (index $.ViewState.passengers_map $booking.PassengerId).Data.last_name }}',
pickupLabel: '{{$booking.Journey.PassengerPickup.Properties.label}}',
dropLabel: '{{$booking.Journey.PassengerDrop.Properties.label}}',
pickupDate: '{{ $booking.Journey.PassengerPickupDate.Format "02/01/2006 15:04" }}',
status: '{{$booking.Status}}',
price: '{{ printf "%.2f" (round2 $booking.Journey.Price.Amount) }}',
currency: '{{$booking.Journey.Price.Currency}}'
}{{end}}
],
currentPage: 1,
itemsPerPage: {{ if .ViewState.trips_items_per_page }}{{ .ViewState.trips_items_per_page }}{{ else }}10{{ end }},
get totalPages() {
return Math.ceil(this.bookings.length / this.itemsPerPage);
},
get paginatedBookings() {
const start = (this.currentPage - 1) * this.itemsPerPage;
const end = start + this.itemsPerPage;
return this.bookings.slice(start, end);
},
nextPage() {
if (this.currentPage < this.totalPages) this.currentPage++;
},
prevPage() {
if (this.currentPage > 1) this.currentPage--;
},
goToPage(page) {
this.currentPage = page;
},
getStatusBadge(status) {
if (status === 'WAITING_CONFIRMATION') return { class: 'p-1 text-xs bg-gray-300 rounded-xl', text: 'Attente confirmation' };
if (status === 'VALIDATED') return { class: 'p-1 text-xs bg-co-green rounded-xl', text: 'Validé' };
if (status === 'CANCELLED') return { class: 'p-1 text-xs bg-co-red text-white rounded-xl', text: 'Annulé' };
return { class: '', text: '' };
}
}">
<table class="min-w-full divide-y divide-gray-300 border-gray-300 border-t-1">
<thead class="bg-gray-50">
<tr>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
Conducteur
</th>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
Passager
</th>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
Départ
</th>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
Destination
</th>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
Date
</th>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
Statut
</th>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
Prix
</th>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
&nbsp;
</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Conducteur</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Passager</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Départ</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Destination</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Date</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Statut</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Prix</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">&nbsp;</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
{{range .ViewState.bookings_history}}
<tr>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<a class="text-co-blue" href="/app/solidarity-transport/drivers/{{.DriverId}}">
{{ (index $.ViewState.drivers_map .DriverId).Data.first_name }}
{{ (index $.ViewState.drivers_map .DriverId).Data.last_name }}
</a>
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<a class="text-co-blue" href="/app/beneficiaries/{{.PassengerId}}">
{{ (index $.ViewState.passengers_map .PassengerId).Data.first_name }}
{{ (index $.ViewState.passengers_map .PassengerId).Data.last_name }}
</a>
</td>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6">
{{ .Journey.PassengerPickup.Properties.label }}
</td>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6">
{{ .Journey.PassengerDrop.Properties.label }}
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
{{ .Journey.PassengerPickupDate.Format "02/01/2006 15:04" }}
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
{{ if eq .Status "WAITING_CONFIRMATION"}}
<span class="p-1 text-xs bg-gray-300 rounded-xl">Attente confirmation</span>
{{ else if eq .Status "VALIDATED"}}
<span class="p-1 text-xs bg-co-green rounded-xl">Validé</span>
{{ else if eq .Status "CANCELLED"}}
<span class="p-1 text-xs bg-co-red text-white rounded-xl">Annulé</span>
{{ end }}
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
{{ printf "%.2f" (round2 .Journey.Price.Amount) }} {{ .Journey.Price.Currency }}
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<a class="text-co-blue" href="/app/solidarity-transport/bookings/{{.Id}}">
Voir
</a>
</td>
</tr>
{{ end }}
<template x-for="booking in paginatedBookings" :key="booking.id">
<tr>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<a class="text-co-blue" :href="'/app/solidarity-transport/drivers/' + booking.driverId">
<span x-text="booking.driverFirstName + ' ' + booking.driverLastName"></span>
</a>
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<a class="text-co-blue" :href="'/app/beneficiaries/' + booking.passengerId">
<span x-text="booking.passengerFirstName + ' ' + booking.passengerLastName"></span>
</a>
</td>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.pickupLabel"></td>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.dropLabel"></td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.pickupDate"></td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<span :class="getStatusBadge(booking.status).class" x-text="getStatusBadge(booking.status).text"></span>
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<span x-text="booking.price + ' ' + booking.currency"></span>
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<a class="text-co-blue" :href="'/app/solidarity-transport/bookings/' + booking.id">Voir</a>
</td>
</tr>
</template>
</tbody>
</table>
<!-- Pagination -->
<div class="flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6">
<div class="flex flex-1 justify-between sm:hidden">
<button @click="prevPage()" :disabled="currentPage === 1"
class="relative inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed">
Précédent
</button>
<button @click="nextPage()" :disabled="currentPage === totalPages"
class="relative ml-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed">
Suivant
</button>
</div>
<div class="hidden sm:flex sm:flex-1 sm:items-center sm:justify-between">
<div>
<p class="text-sm text-gray-700">
Affichage de
<span class="font-medium" x-text="(currentPage - 1) * itemsPerPage + 1"></span>
à
<span class="font-medium" x-text="Math.min(currentPage * itemsPerPage, bookings.length)"></span>
sur
<span class="font-medium" x-text="bookings.length"></span>
résultats
</p>
</div>
<div>
<nav class="isolate inline-flex -space-x-px rounded-md shadow-sm" aria-label="Pagination">
<button @click="prevPage()" :disabled="currentPage === 1"
class="relative inline-flex items-center rounded-l-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0 disabled:opacity-50 disabled:cursor-not-allowed">
<span class="sr-only">Précédent</span>
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z" clip-rule="evenodd" />
</svg>
</button>
<template x-for="page in totalPages" :key="page">
<button @click="goToPage(page)"
:class="page === currentPage ? 'z-10 bg-co-blue text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-co-blue' : 'text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:outline-offset-0'"
class="relative inline-flex items-center px-4 py-2 text-sm font-semibold focus:z-20"
x-text="page"></button>
</template>
<button @click="nextPage()" :disabled="currentPage === totalPages"
class="relative inline-flex items-center rounded-r-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0 disabled:opacity-50 disabled:cursor-not-allowed">
<span class="sr-only">Suivant</span>
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clip-rule="evenodd" />
</svg>
</button>
</nav>
</div>
</div>
</div>
</div>
{{end}}
{{end}}

View File

@@ -5,81 +5,148 @@
{{if eq (len .ViewState.bookings) 0}}
<div class="m-10 text-center text-gray-600">Aucun trajet déclaré</div>
{{else}}
<div x-data="{
bookings: [
{{range $index, $booking := .ViewState.bookings}}{{if $index}},{{end}}{
id: '{{$booking.Id}}',
driverId: '{{$booking.DriverId}}',
driverFirstName: '{{ (index $.ViewState.drivers_map $booking.DriverId).Data.first_name }}',
driverLastName: '{{ (index $.ViewState.drivers_map $booking.DriverId).Data.last_name }}',
passengerId: '{{$booking.PassengerId}}',
passengerFirstName: '{{ (index $.ViewState.passengers_map $booking.PassengerId).Data.first_name }}',
passengerLastName: '{{ (index $.ViewState.passengers_map $booking.PassengerId).Data.last_name }}',
pickupLabel: '{{$booking.Journey.PassengerPickup.Properties.label}}',
dropLabel: '{{$booking.Journey.PassengerDrop.Properties.label}}',
pickupDate: '{{ timeFormat $booking.Journey.PassengerPickupDate "02/01/2006 15:04" }}',
status: '{{$booking.Status}}',
motivation: '{{if $booking.Data.motivation}}{{$booking.Data.motivation}}{{end}}'
}{{end}}
],
currentPage: 1,
itemsPerPage: {{ if .ViewState.trips_items_per_page }}{{ .ViewState.trips_items_per_page }}{{ else }}10{{ end }},
get totalPages() {
return Math.ceil(this.bookings.length / this.itemsPerPage);
},
get paginatedBookings() {
const start = (this.currentPage - 1) * this.itemsPerPage;
const end = start + this.itemsPerPage;
return this.bookings.slice(start, end);
},
nextPage() {
if (this.currentPage < this.totalPages) this.currentPage++;
},
prevPage() {
if (this.currentPage > 1) this.currentPage--;
},
goToPage(page) {
this.currentPage = page;
},
getStatusBadge(status) {
if (status === 'WAITING_CONFIRMATION') return { class: 'p-1 text-xs bg-gray-300 rounded-xl', text: 'Attente confirmation' };
if (status === 'VALIDATED') return { class: 'p-1 text-xs bg-co-green rounded-xl', text: 'Validé' };
if (status === 'CANCELLED') return { class: 'p-1 text-xs bg-co-red text-white rounded-xl', text: 'Annulé' };
return { class: '', text: '' };
},
isGuaranteedTrip(motivation) {
return motivation === 'Santé' || motivation === 'Insertion' || motivation === 'Administratif';
}
}">
<table class="min-w-full divide-y divide-gray-300 border-gray-300 border-t-1">
<thead class="bg-gray-50">
<tr>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
Conducteur
</th>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
Passager
</th>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
Départ
</th>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
Destination
</th>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
Date
</th>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
Statut
</th>
<th scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
&nbsp;
</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Conducteur</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Passager</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Départ</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Destination</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Date</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Statut</th>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">&nbsp;</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
{{range .ViewState.bookings}}
<tr>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<a class="text-co-blue" href="/app/solidarity-transport/drivers/{{.DriverId}}">
{{ (index $.ViewState.drivers_map .DriverId).Data.first_name }}
{{ (index $.ViewState.drivers_map .DriverId).Data.last_name }}
</a>
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<a class="text-co-blue" href="/app/beneficiaries/{{.PassengerId}}">
{{ (index $.ViewState.passengers_map .PassengerId).Data.first_name }}
{{ (index $.ViewState.passengers_map .PassengerId).Data.last_name }}
</a>
</td>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6">
{{ .Journey.PassengerPickup.Properties.label }}
</td>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6">
{{ .Journey.PassengerDrop.Properties.label }}
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
{{ timeFormat .Journey.PassengerPickupDate "02/01/2006 15:04" }}
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
{{ if eq .Status "WAITING_CONFIRMATION"}}
<span class="p-1 text-xs bg-gray-300 rounded-xl">Attente confirmation</span>
{{ else if eq .Status "VALIDATED"}}
<span class="p-1 text-xs bg-co-green rounded-xl">Validé</span>
{{ else if eq .Status "CANCELLED"}}
<span class="p-1 text-xs bg-co-red text-white rounded-xl">Annulé</span>
{{ end }}
{{if and .Data.motivation (or (or (eq .Data.motivation "Santé") (eq .Data.motivation "Insertion")) (eq .Data.motivation "Administratif"))}}<div class="mt-4"><span class="text-xs p-2 bg-co-green text-white rounded-2xl">Trajet garanti : {{.Data.motivation}}</span></div>{{end}}
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<a class="text-co-blue" href="/app/solidarity-transport/bookings/{{.Id}}">
Voir
</a>
</td>
</tr>
{{ end }}
<template x-for="booking in paginatedBookings" :key="booking.id">
<tr>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<a class="text-co-blue" :href="'/app/solidarity-transport/drivers/' + booking.driverId">
<span x-text="booking.driverFirstName + ' ' + booking.driverLastName"></span>
</a>
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<a class="text-co-blue" :href="'/app/beneficiaries/' + booking.passengerId">
<span x-text="booking.passengerFirstName + ' ' + booking.passengerLastName"></span>
</a>
</td>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.pickupLabel"></td>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.dropLabel"></td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.pickupDate"></td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<span :class="getStatusBadge(booking.status).class" x-text="getStatusBadge(booking.status).text"></span>
<template x-if="booking.motivation && isGuaranteedTrip(booking.motivation)">
<div class="mt-4">
<span class="text-xs p-2 bg-co-green text-white rounded-2xl" x-text="'Trajet garanti : ' + booking.motivation"></span>
</div>
</template>
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<a class="text-co-blue" :href="'/app/solidarity-transport/bookings/' + booking.id">Voir</a>
</td>
</tr>
</template>
</tbody>
</table>
<!-- Pagination -->
<div class="flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6">
<div class="flex flex-1 justify-between sm:hidden">
<button @click="prevPage()" :disabled="currentPage === 1"
class="relative inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed">
Précédent
</button>
<button @click="nextPage()" :disabled="currentPage === totalPages"
class="relative ml-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed">
Suivant
</button>
</div>
<div class="hidden sm:flex sm:flex-1 sm:items-center sm:justify-between">
<div>
<p class="text-sm text-gray-700">
Affichage de
<span class="font-medium" x-text="(currentPage - 1) * itemsPerPage + 1"></span>
à
<span class="font-medium" x-text="Math.min(currentPage * itemsPerPage, bookings.length)"></span>
sur
<span class="font-medium" x-text="bookings.length"></span>
résultats
</p>
</div>
<div>
<nav class="isolate inline-flex -space-x-px rounded-md shadow-sm" aria-label="Pagination">
<button @click="prevPage()" :disabled="currentPage === 1"
class="relative inline-flex items-center rounded-l-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0 disabled:opacity-50 disabled:cursor-not-allowed">
<span class="sr-only">Précédent</span>
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z" clip-rule="evenodd" />
</svg>
</button>
<template x-for="page in totalPages" :key="page">
<button @click="goToPage(page)"
:class="page === currentPage ? 'z-10 bg-co-blue text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-co-blue' : 'text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:outline-offset-0'"
class="relative inline-flex items-center px-4 py-2 text-sm font-semibold focus:z-20"
x-text="page"></button>
</template>
<button @click="nextPage()" :disabled="currentPage === totalPages"
class="relative inline-flex items-center rounded-r-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0 disabled:opacity-50 disabled:cursor-not-allowed">
<span class="sr-only">Suivant</span>
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clip-rule="evenodd" />
</svg>
</button>
</nav>
</div>
</div>
</div>
</div>
{{end}}
{{end}}

View File

@@ -27,6 +27,38 @@
</a>
</div>
</div>
<div x-data="{
drivers: [
{{range $index, $driver := .ViewState.drivers}}{{if $index}},{{end}}{
id: '{{$driver.ID}}',
firstName: '{{$driver.Data.first_name}}',
lastName: '{{$driver.Data.last_name}}',
address: '{{if $driver.Data.address}}{{$driver.Data.address.properties.label}}{{end}}',
phoneNumber: '{{$driver.Data.phone_number}}',
validated: {{if solidarityDriverValidatedProfile $driver (solidarityDocuments $driver.ID)}}true{{else}}false{{end}}
}{{end}}
],
currentPage: 1,
itemsPerPage: {{ if .ViewState.drivers_items_per_page }}{{ .ViewState.drivers_items_per_page }}{{ else }}10{{ end }},
get totalPages() {
return Math.ceil(this.drivers.length / this.itemsPerPage);
},
get paginatedDrivers() {
const start = (this.currentPage - 1) * this.itemsPerPage;
const end = start + this.itemsPerPage;
return this.drivers.slice(start, end);
},
nextPage() {
if (this.currentPage < this.totalPages) this.currentPage++;
},
prevPage() {
if (this.currentPage > 1) this.currentPage--;
},
goToPage(page) {
this.currentPage = page;
}
}">
<table class="min-w-full divide-y divide-gray-300 border-gray-300 border-t-1">
<thead class="bg-gray-50">
<tr>
@@ -53,26 +85,75 @@
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
{{ range .ViewState.drivers }}
<tr>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">{{ .Data.first_name }} {{ .Data.last_name }}</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">{{if .Data.address}}{{.Data.address.properties.label}}{{end}}</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">{{ .Data.phone_number }}</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
{{if solidarityDriverValidatedProfile . (solidarityDocuments .ID) }}
<span class="p-1 px-2 text-xs bg-co-green rounded-2xl">Oui</span>
{{else}}
<span class="p-1 px-2 text-xs bg-co-red text-white rounded-2xl">Non</span>
{{end}}
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<a class="text-co-blue hover:text-co-blue"
href="/app/solidarity-transport/drivers/{{.ID}}">
Voir
</a>
</td>
</tr>
{{ end }}
<template x-for="driver in paginatedDrivers" :key="driver.id">
<tr>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="driver.firstName + ' ' + driver.lastName"></td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="driver.address"></td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="driver.phoneNumber"></td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<span x-show="driver.validated" class="p-1 px-2 text-xs bg-co-green rounded-2xl">Oui</span>
<span x-show="!driver.validated" class="p-1 px-2 text-xs bg-co-red text-white rounded-2xl">Non</span>
</td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<a class="text-co-blue hover:text-co-blue" :href="'/app/solidarity-transport/drivers/' + driver.id">
Voir
</a>
</td>
</tr>
</template>
</tbody>
</table>
<!-- Pagination -->
<div class="flex items-center justify-between border-t border-gray-200 bg-white px-4 py-3 sm:px-6">
<div class="flex flex-1 justify-between sm:hidden">
<button @click="prevPage()" :disabled="currentPage === 1"
class="relative inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed">
Précédent
</button>
<button @click="nextPage()" :disabled="currentPage === totalPages"
class="relative ml-3 inline-flex items-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed">
Suivant
</button>
</div>
<div class="hidden sm:flex sm:flex-1 sm:items-center sm:justify-between">
<div>
<p class="text-sm text-gray-700">
Affichage de
<span class="font-medium" x-text="(currentPage - 1) * itemsPerPage + 1"></span>
à
<span class="font-medium" x-text="Math.min(currentPage * itemsPerPage, drivers.length)"></span>
sur
<span class="font-medium" x-text="drivers.length"></span>
résultats
</p>
</div>
<div>
<nav class="isolate inline-flex -space-x-px rounded-md shadow-sm" aria-label="Pagination">
<button @click="prevPage()" :disabled="currentPage === 1"
class="relative inline-flex items-center rounded-l-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0 disabled:opacity-50 disabled:cursor-not-allowed">
<span class="sr-only">Précédent</span>
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z" clip-rule="evenodd" />
</svg>
</button>
<template x-for="page in totalPages" :key="page">
<button @click="goToPage(page)"
:class="page === currentPage ? 'z-10 bg-co-blue text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-co-blue' : 'text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:outline-offset-0'"
class="relative inline-flex items-center px-4 py-2 text-sm font-semibold focus:z-20"
x-text="page"></button>
</template>
<button @click="nextPage()" :disabled="currentPage === totalPages"
class="relative inline-flex items-center rounded-r-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-20 focus:outline-offset-0 disabled:opacity-50 disabled:cursor-not-allowed">
<span class="sr-only">Suivant</span>
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clip-rule="evenodd" />
</svg>
</button>
</nav>
</div>
</div>
</div>
</div>
{{ end }}