pagination + optionsl vehicles fields
This commit is contained in:
parent
73d99e7ad7
commit
ed726b610f
|
@ -22,11 +22,9 @@
|
|||
<div class="mt-2 grid grid-cols-1">
|
||||
<select id="{{$tab}}_status" name="status" class="col-start-1 row-start-1 w-full appearance-none rounded-md bg-white py-1.5 pr-8 pl-3 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-indigo-600 sm:text-sm/6 dark:bg-white/5 dark:text-white dark:outline-white/10 dark:*:bg-gray-800 dark:focus-visible:outline-co-blue" onchange="this.form.submit()">
|
||||
<option></option>
|
||||
<option value="VALIDATED"{{if eq .filters.status "VALIDATED"}} selected{{end}}>Validé</option>
|
||||
<option value="WAITING_DRIVER_CONFIRMATION"{{if eq .filters.status "WAITING_DRIVER_CONFIRMATION"}} selected{{end}}>Attente confirmation conducteur</option>
|
||||
<option value="CONFIRMED"{{if eq .filters.status "CONFIRMED"}} selected{{end}}>Confirmé</option>
|
||||
<option value="CANCELLED"{{if eq .filters.status "CANCELLED"}} selected{{end}}>Annulé</option>
|
||||
<option value="WAITING_CONFIRMATION"{{if eq .filters.status "WAITING_CONFIRMATION"}} selected{{end}}>Attente confirmation</option>
|
||||
<option value="WAITING_DRIVER_CONFIRMATION"{{if eq .filters.status "WAITING_DRIVER_CONFIRMATION"}} selected{{end}}>Attente confirmation conducteur</option>
|
||||
</select>
|
||||
<svg viewBox="0 0 16 16" fill="currentColor" data-slot="icon" aria-hidden="true" class="pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-gray-500 sm:size-4 dark:text-gray-400">
|
||||
<path d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" fill-rule="evenodd" />
|
||||
|
|
|
@ -4,6 +4,52 @@
|
|||
{{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.Driver.Id}}',
|
||||
driverFirstName: '{{ (index $.ViewState.drivers_map $booking.Driver.Id).Data.first_name }}',
|
||||
driverLastName: '{{ (index $.ViewState.drivers_map $booking.Driver.Id).Data.last_name }}',
|
||||
passengerId: '{{$booking.Passenger.Id}}',
|
||||
passengerFirstName: '{{ (index $.ViewState.passengers_map $booking.Passenger.Id).Data.first_name }}',
|
||||
passengerLastName: '{{ (index $.ViewState.passengers_map $booking.Passenger.Id).Data.last_name }}',
|
||||
pickupAddress: '{{$booking.PassengerPickupAddress}}',
|
||||
dropAddress: '{{$booking.PassengerDropAddress}}',
|
||||
pickupDate: '{{ timeFormat $booking.PassengerPickupDate.AsTime "02/01/2006 15:04" }}',
|
||||
status: '{{$booking.Status.String}}',
|
||||
price: '{{if $booking.Price}}{{ printf "%.2f" (round2 $booking.Price.Amount) }}{{else}}N/A{{end}}',
|
||||
currency: '{{if $booking.Price}}{{$booking.Price.Currency}}{{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_DRIVER_CONFIRMATION') return { class: 'p-1 text-xs bg-gray-300 rounded-xl', text: 'Attente confirmation' };
|
||||
if (status === 'CONFIRMED') return { class: 'p-1 text-xs bg-co-green rounded-xl', text: 'Confirmé' };
|
||||
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>
|
||||
|
@ -42,55 +88,86 @@
|
|||
</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/organized-carpool/drivers/{{.Driver.Id}}">
|
||||
{{ (index $.ViewState.drivers_map .Driver.Id).Data.first_name }}
|
||||
{{ (index $.ViewState.drivers_map .Driver.Id).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/{{.Passenger.Id}}">
|
||||
{{ (index $.ViewState.passengers_map .Passenger.Id).Data.first_name }}
|
||||
{{ (index $.ViewState.passengers_map .Passenger.Id).Data.last_name }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||
{{ .PassengerPickupAddress }}
|
||||
</td>
|
||||
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||
{{ .PassengerDropAddress }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||
{{ timeFormat .PassengerPickupDate.AsTime "02/01/2006 15:04" }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||
{{ if eq .Status.String "WAITING_DRIVER_CONFIRMATION"}}
|
||||
<span class="p-1 text-xs bg-gray-300 rounded-xl">Attente confirmation</span>
|
||||
{{ else if eq .Status.String "CONFIRMED"}}
|
||||
<span class="p-1 text-xs bg-co-green rounded-xl">Confirmé</span>
|
||||
{{ else if eq .Status.String "VALIDATED"}}
|
||||
<span class="p-1 text-xs bg-co-green rounded-xl">Validé</span>
|
||||
{{ else if eq .Status.String "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">
|
||||
{{ if .Price }}
|
||||
{{ printf "%.2f" (round2 .Price.Amount) }} {{ .Price.Currency }}
|
||||
{{ else }}
|
||||
N/A
|
||||
{{ end }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||
<a class="text-co-blue" href="/app/organized-carpool/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/organized-carpool/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.pickupAddress"></td>
|
||||
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.dropAddress"></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 !== 'N/A' ? booking.price + ' ' + booking.currency : 'N/A'"></span>
|
||||
</td>
|
||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||
<a class="text-co-blue" :href="'/app/organized-carpool/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}}
|
||||
|
|
|
@ -4,6 +4,53 @@
|
|||
{{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.Driver.Id}}',
|
||||
driverFirstName: '{{ (index $.ViewState.drivers_map $booking.Driver.Id).Data.first_name }}',
|
||||
driverLastName: '{{ (index $.ViewState.drivers_map $booking.Driver.Id).Data.last_name }}',
|
||||
passengerId: '{{$booking.Passenger.Id}}',
|
||||
passengerFirstName: '{{ (index $.ViewState.passengers_map $booking.Passenger.Id).Data.first_name }}',
|
||||
passengerLastName: '{{ (index $.ViewState.passengers_map $booking.Passenger.Id).Data.last_name }}',
|
||||
pickupAddress: '{{$booking.PassengerPickupAddress}}',
|
||||
dropAddress: '{{$booking.PassengerDropAddress}}',
|
||||
pickupDate: '{{ timeFormat $booking.PassengerPickupDate.AsTime "02/01/2006 15:04" }}',
|
||||
status: '{{$booking.Status.String}}',
|
||||
price: '{{if $booking.Price}}{{ printf "%.2f" (round2 $booking.Price.Amount) }}{{else}}N/A{{end}}',
|
||||
currency: '{{if $booking.Price}}{{$booking.Price.Currency}}{{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_DRIVER_CONFIRMATION') return { class: 'p-1 text-xs bg-gray-300 rounded-xl', text: 'Attente confirmation' };
|
||||
if (status === 'WAITING_PASSENGER_CONFIRMATION') return { class: 'p-1 text-xs bg-gray-300 rounded-xl', text: 'Attente confirmation passager' };
|
||||
if (status === 'CONFIRMED') return { class: 'p-1 text-xs bg-co-green rounded-xl', text: 'Confirmé' };
|
||||
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>
|
||||
|
@ -42,57 +89,86 @@
|
|||
</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/organized-carpool/drivers/{{.Driver.Id}}">
|
||||
{{ (index $.ViewState.drivers_map .Driver.Id).Data.first_name }}
|
||||
{{ (index $.ViewState.drivers_map .Driver.Id).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/{{.Passenger.Id}}">
|
||||
{{ (index $.ViewState.passengers_map .Passenger.Id).Data.first_name }}
|
||||
{{ (index $.ViewState.passengers_map .Passenger.Id).Data.last_name }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||
{{ .PassengerPickupAddress }}
|
||||
</td>
|
||||
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||
{{ .PassengerDropAddress }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||
{{ timeFormat .PassengerPickupDate.AsTime "02/01/2006 15:04" }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||
{{ if eq .Status.String "WAITING_DRIVER_CONFIRMATION"}}
|
||||
<span class="p-1 text-xs bg-gray-300 rounded-xl">Attente confirmation</span>
|
||||
{{ else if eq .Status.String "WAITING_PASSENGER_CONFIRMATION"}}
|
||||
<span class="p-1 text-xs bg-gray-300 rounded-xl">Attente confirmation passager</span>
|
||||
{{ else if eq .Status.String "CONFIRMED"}}
|
||||
<span class="p-1 text-xs bg-co-green rounded-xl">Confirmé</span>
|
||||
{{ else if eq .Status.String "VALIDATED"}}
|
||||
<span class="p-1 text-xs bg-co-green rounded-xl">Validé</span>
|
||||
{{ else if eq .Status.String "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">
|
||||
{{ if .Price }}
|
||||
{{ printf "%.2f" (round2 .Price.Amount) }} {{ .Price.Currency }}
|
||||
{{ else }}
|
||||
N/A
|
||||
{{ end }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||
<a class="text-co-blue" href="/app/organized-carpool/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/organized-carpool/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.pickupAddress"></td>
|
||||
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.dropAddress"></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 !== 'N/A' ? booking.price + ' ' + booking.currency : 'N/A'"></span>
|
||||
</td>
|
||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||
<a class="text-co-blue" :href="'/app/organized-carpool/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}}
|
||||
|
|
|
@ -28,6 +28,39 @@
|
|||
</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}}',
|
||||
addressDestination: '{{if $driver.Data.address_destination}}{{$driver.Data.address_destination.properties.label}}{{end}}',
|
||||
phoneNumber: '{{$driver.Data.phone_number}}',
|
||||
validated: {{if carpoolDriverValidatedProfile $driver (carpoolDocuments $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>
|
||||
|
@ -58,27 +91,76 @@
|
|||
</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">{{if .Data.address_destination}}{{.Data.address_destination.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 carpoolDriverValidatedProfile . (carpoolDocuments .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/organized-carpool/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.addressDestination"></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/organized-carpool/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 }}
|
||||
|
|
|
@ -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">
|
||||
|
||||
</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"> </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}}
|
||||
|
|
|
@ -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">
|
||||
|
||||
</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"> </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}}
|
||||
|
|
|
@ -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 }}
|
||||
|
|
|
@ -138,6 +138,48 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{if .ViewState.vehicle_optional_fields}}
|
||||
<div class="bg-white shadow px-4 py-5 sm:rounded-lg sm:p-6">
|
||||
<div class="md:grid md:grid-cols-3 md:gap-6">
|
||||
<div class="md:col-span-1">
|
||||
<h3 class="text-lg font-medium leading-6 text-gray-900">Autres propriétés</h3>
|
||||
<p class="mt-1 text-sm text-gray-500">Informations complémentaires sur le véhicule</p>
|
||||
</div>
|
||||
<div class="mt-5 md:mt-0 md:col-span-2">
|
||||
<div class="grid grid-cols-6 gap-6">
|
||||
{{range .ViewState.vehicle_optional_fields}}
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label for="{{.name}}" class="block text-sm font-medium text-gray-700">{{.label}}</label>
|
||||
{{if eq .type "select"}}
|
||||
<div class="sm:mt-0 sm:col-span-2">
|
||||
<select id="{{.name}}" name="{{.name}}"
|
||||
class="p-2 max-w-lg mt-1 block focus:ring-co-blue focus:border-co-blue w-full shadow-sm sm:max-w-xs sm:text-sm border-gray-300 rounded-2xl">
|
||||
{{range .options}}
|
||||
<option value="{{.value}}">{{.label}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</div>
|
||||
{{else if eq .type "textarea"}}
|
||||
<textarea id="{{.name}}" name="{{.name}}" rows="3"
|
||||
class="mt-1 focus:ring-co-blue focus:border-co-blue block w-full shadow-sm sm:text-sm border-gray-300 rounded-2xl"></textarea>
|
||||
{{else if eq .type "date"}}
|
||||
<input type="date" id="{{.name}}" name="{{.name}}"
|
||||
class="mt-1 focus:ring-co-blue focus:border-co-blue block w-full shadow-sm sm:text-sm border-gray-300 rounded-2xl">
|
||||
{{else if eq .type "number"}}
|
||||
<input type="number" id="{{.name}}" name="{{.name}}"
|
||||
class="mt-1 focus:ring-co-blue focus:border-co-blue block w-full shadow-sm sm:text-sm border-gray-300 rounded-2xl">
|
||||
{{else}}
|
||||
<input type="text" id="{{.name}}" name="{{.name}}"
|
||||
class="mt-1 focus:ring-co-blue focus:border-co-blue block w-full shadow-sm sm:text-sm border-gray-300 rounded-2xl">
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="flex justify-end">
|
||||
<p x-show="! isFormValid" class="px-4 py-2 text-sm text-co-red">Certains champs de sont pas valides.</p>
|
||||
<a href="/app/vehicles-management/">
|
||||
|
|
|
@ -170,26 +170,37 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<section aria-labelledby="timeline-title" class="lg:col-start-3 lg:col-span-1">
|
||||
<div class="bg-white px-4 py-5 shadow sm:rounded-lg sm:px-6">
|
||||
<h2 id="timeline-title" class="text-lg font-medium text-gray-900">Réservations à venir</h2>
|
||||
{{if eq (len .ViewState.vehicle.Bookings) 0}}
|
||||
<p class="p-12 text-gray-500 text-center text-md">Aucune réservation à venir</p>
|
||||
{{end}}
|
||||
<ul role="list" class="divide-y divide-gray-200">
|
||||
{{range .ViewState.vehicle.Bookings}}
|
||||
<li class="py-4 flex">
|
||||
<div class="ml-3">
|
||||
<a href="/app/vehicles-management/bookings/{{.ID}}" class="hover:bg-gray-200">
|
||||
<p class="text-sm font-medium text-gray-900">Du {{(timeFrom .Startdate).Format "02/01/2006"}} au {{(timeFrom .Enddate).Format "02/01/2006"}}</p>
|
||||
<p class="text-sm text-gray-500"></p>
|
||||
</a>
|
||||
{{if .ViewState.vehicle_optional_fields}}
|
||||
<section aria-labelledby="vehicle-other-properties-title" class="lg:col-start-3 lg:col-span-1">
|
||||
<div class="bg-white shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:px-6">
|
||||
<h2 id="vehicle-other-properties-title" class="text-lg leading-6 font-medium text-gray-900">Autres propriétés</h2>
|
||||
<p class="mt-1 max-w-2xl text-sm text-gray-500">Informations complémentaires sur le véhicule</p>
|
||||
</div>
|
||||
<div class="border-t border-gray-200 px-4 py-5 sm:px-6">
|
||||
<dl class="space-y-4">
|
||||
{{range .ViewState.vehicle_optional_fields}}
|
||||
{{if index $.ViewState.vehicle.Data .name}}
|
||||
<div>
|
||||
<dt class="text-sm font-medium text-gray-500">{{.label}}</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900">
|
||||
{{if eq .type "select"}}
|
||||
{{$fieldValue := index $.ViewState.vehicle.Data .name}}
|
||||
{{range .options}}
|
||||
{{if eq .value $fieldValue}}{{.label}}{{end}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{index $.ViewState.vehicle.Data .name}}
|
||||
{{end}}
|
||||
</dd>
|
||||
</div>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{end}}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{{end}}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
fields: {
|
||||
licence_plate: '{{ .ViewState.vehicle.Data.licence_plate }}',
|
||||
name: '{{ .ViewState.vehicle.Data.name }}',
|
||||
type: '{{ .ViewState.vehicle.Type }}',
|
||||
kilometers: '{{ .ViewState.vehicle.Data.kilometers }}',
|
||||
informations: '{{ .ViewState.vahicle.Data.informations}}',
|
||||
informations: '{{ .ViewState.vehicle.Data.informations}}',
|
||||
},
|
||||
rules: {
|
||||
licence_plate: ['required', 'regexMatch:^[A-Z]{1,2}-[0-9]{1,3}-[A-Z]{1,2}$'],
|
||||
|
@ -86,7 +87,7 @@
|
|||
<legend class="sr-only">Automatique</legend>
|
||||
<div class="relative flex items-start">
|
||||
<div class="flex h-5 items-center">
|
||||
<input id="automatic" aria-describedby="automatic-description" name="automatic" type="checkbox" class="h-4 w-4 rounded border-gray-300 text-co-blue focus:ring-co-blue">
|
||||
<input id="automatic" aria-describedby="automatic-description" name="automatic" type="checkbox" {{if .ViewState.vehicle.Data.automatic}}checked{{end}} class="h-4 w-4 rounded border-gray-300 text-co-blue focus:ring-co-blue">
|
||||
</div>
|
||||
<div class="ml-3 text-sm">
|
||||
<label for="automatic" class="font-medium text-gray-700">Automatique</label>
|
||||
|
@ -126,8 +127,8 @@
|
|||
</div>
|
||||
<div class="mt-5 md:mt-0 md:col-span-2">
|
||||
{{ $fieldName := "address" }}
|
||||
{{if .ViewState.Data.address}}
|
||||
{{$default := .ViewState.Data.address}}
|
||||
{{if .ViewState.vehicle.Data.address}}
|
||||
{{$default := .ViewState.vehicle.Data.address}}
|
||||
{{ template "address" dict "FieldName" $fieldName "Default" $default}}
|
||||
{{else}}
|
||||
{{ template "address_autocomplete" dict "FieldName" $fieldName}}
|
||||
|
@ -144,6 +145,48 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{if .ViewState.vehicle_optional_fields}}
|
||||
<div class="bg-white shadow px-4 py-5 sm:rounded-lg sm:p-6">
|
||||
<div class="md:grid md:grid-cols-3 md:gap-6">
|
||||
<div class="md:col-span-1">
|
||||
<h3 class="text-lg font-medium leading-6 text-gray-900">Autres propriétés</h3>
|
||||
<p class="mt-1 text-sm text-gray-500">Informations complémentaires sur le véhicule</p>
|
||||
</div>
|
||||
<div class="mt-5 md:mt-0 md:col-span-2">
|
||||
<div class="grid grid-cols-6 gap-6">
|
||||
{{range .ViewState.vehicle_optional_fields}}
|
||||
<div class="col-span-6 sm:col-span-3">
|
||||
<label for="{{.name}}" class="block text-sm font-medium text-gray-700">{{.label}}</label>
|
||||
{{if eq .type "select"}}
|
||||
<div class="sm:mt-0 sm:col-span-2">
|
||||
<select id="{{.name}}" name="{{.name}}"
|
||||
class="p-2 max-w-lg mt-1 block focus:ring-co-blue focus:border-co-blue w-full shadow-sm sm:max-w-xs sm:text-sm border-gray-300 rounded-2xl">
|
||||
{{range .options}}
|
||||
<option value="{{.value}}" {{if eq .value (index $.ViewState.vehicle.Data .name)}}selected{{end}}>{{.label}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</div>
|
||||
{{else if eq .type "textarea"}}
|
||||
<textarea id="{{.name}}" name="{{.name}}" rows="3"
|
||||
class="mt-1 focus:ring-co-blue focus:border-co-blue block w-full shadow-sm sm:text-sm border-gray-300 rounded-2xl">{{index $.ViewState.vehicle.Data .name}}</textarea>
|
||||
{{else if eq .type "date"}}
|
||||
<input type="date" id="{{.name}}" name="{{.name}}" value="{{index $.ViewState.vehicle.Data .name}}"
|
||||
class="mt-1 focus:ring-co-blue focus:border-co-blue block w-full shadow-sm sm:text-sm border-gray-300 rounded-2xl">
|
||||
{{else if eq .type "number"}}
|
||||
<input type="number" id="{{.name}}" name="{{.name}}" value="{{index $.ViewState.vehicle.Data .name}}"
|
||||
class="mt-1 focus:ring-co-blue focus:border-co-blue block w-full shadow-sm sm:text-sm border-gray-300 rounded-2xl">
|
||||
{{else}}
|
||||
<input type="text" id="{{.name}}" name="{{.name}}" value="{{index $.ViewState.vehicle.Data .name}}"
|
||||
class="mt-1 focus:ring-co-blue focus:border-co-blue block w-full shadow-sm sm:text-sm border-gray-300 rounded-2xl">
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="flex justify-end">
|
||||
<p x-show="! isFormValid" class="px-4 py-2 text-sm text-co-red">Certains champs de sont pas valides.</p>
|
||||
<a href="/app/vehicles-management/fleet/{{.ViewState.vehicle.ID}}">
|
||||
|
|
|
@ -3027,6 +3027,11 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.focus\:z-20 {
|
||||
&:focus {
|
||||
z-index: 20;
|
||||
}
|
||||
}
|
||||
.focus\:border-blue-500 {
|
||||
&:focus {
|
||||
border-color: var(--color-blue-500);
|
||||
|
@ -3119,6 +3124,11 @@
|
|||
outline-offset: calc(2px * -1);
|
||||
}
|
||||
}
|
||||
.focus\:outline-offset-0 {
|
||||
&:focus {
|
||||
outline-offset: 0px;
|
||||
}
|
||||
}
|
||||
.focus\:outline-indigo-600 {
|
||||
&:focus {
|
||||
outline-color: var(--color-indigo-600);
|
||||
|
@ -3135,6 +3145,12 @@
|
|||
--tw-ring-inset: inset;
|
||||
}
|
||||
}
|
||||
.focus-visible\:outline {
|
||||
&:focus-visible {
|
||||
outline-style: var(--tw-outline-style);
|
||||
outline-width: 1px;
|
||||
}
|
||||
}
|
||||
.focus-visible\:outline-2 {
|
||||
&:focus-visible {
|
||||
outline-style: var(--tw-outline-style);
|
||||
|
@ -3146,6 +3162,16 @@
|
|||
outline-offset: calc(2px * -1);
|
||||
}
|
||||
}
|
||||
.focus-visible\:outline-offset-2 {
|
||||
&:focus-visible {
|
||||
outline-offset: 2px;
|
||||
}
|
||||
}
|
||||
.focus-visible\:outline-co-blue {
|
||||
&:focus-visible {
|
||||
outline-color: var(--color-co-blue);
|
||||
}
|
||||
}
|
||||
.focus-visible\:outline-indigo-600 {
|
||||
&:focus-visible {
|
||||
outline-color: var(--color-indigo-600);
|
||||
|
@ -3161,6 +3187,11 @@
|
|||
opacity: 30%;
|
||||
}
|
||||
}
|
||||
.disabled\:opacity-50 {
|
||||
&:disabled {
|
||||
opacity: 50%;
|
||||
}
|
||||
}
|
||||
.sm\:col-span-1 {
|
||||
@media (width >= 40rem) {
|
||||
grid-column: span 1 / span 1;
|
||||
|
|
Loading…
Reference in New Issue