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

@ -22,11 +22,9 @@
<div class="mt-2 grid grid-cols-1"> <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()"> <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></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="CONFIRMED"{{if eq .filters.status "CONFIRMED"}} selected{{end}}>Confirmé</option>
<option value="CANCELLED"{{if eq .filters.status "CANCELLED"}} selected{{end}}>Annulé</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> </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"> <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" /> <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" />

View File

@ -4,6 +4,52 @@
{{if eq (len .ViewState.bookings_history) 0}} {{if eq (len .ViewState.bookings_history) 0}}
<div class="m-10 text-center text-gray-600">Aucun trajet dans le passé</div> <div class="m-10 text-center text-gray-600">Aucun trajet dans le passé</div>
{{else}} {{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"> <table class="min-w-full divide-y divide-gray-300 border-gray-300 border-t-1">
<thead class="bg-gray-50"> <thead class="bg-gray-50">
<tr> <tr>
@ -42,55 +88,86 @@
</tr> </tr>
</thead> </thead>
<tbody class="divide-y divide-gray-200 bg-white"> <tbody class="divide-y divide-gray-200 bg-white">
{{range .ViewState.bookings_history}} <template x-for="booking in paginatedBookings" :key="booking.id">
<tr> <tr>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> <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}}"> <a class="text-co-blue" :href="'/app/organized-carpool/drivers/' + booking.driverId">
{{ (index $.ViewState.drivers_map .Driver.Id).Data.first_name }} <span x-text="booking.driverFirstName + ' ' + booking.driverLastName"></span>
{{ (index $.ViewState.drivers_map .Driver.Id).Data.last_name }} </a>
</a> </td>
</td> <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<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">
<a class="text-co-blue" href="/app/beneficiaries/{{.Passenger.Id}}"> <span x-text="booking.passengerFirstName + ' ' + booking.passengerLastName"></span>
{{ (index $.ViewState.passengers_map .Passenger.Id).Data.first_name }} </a>
{{ (index $.ViewState.passengers_map .Passenger.Id).Data.last_name }} </td>
</a> <td class="py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.pickupAddress"></td>
</td> <td class="py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.dropAddress"></td>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6"> <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.pickupDate"></td>
{{ .PassengerPickupAddress }} <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
</td> <span :class="getStatusBadge(booking.status).class" x-text="getStatusBadge(booking.status).text"></span>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6"> </td>
{{ .PassengerDropAddress }} <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
</td> <span x-text="booking.price !== 'N/A' ? booking.price + ' ' + booking.currency : 'N/A'"></span>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> </td>
{{ timeFormat .PassengerPickupDate.AsTime "02/01/2006 15:04" }} <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
</td> <a class="text-co-blue" :href="'/app/organized-carpool/bookings/' + booking.id">Voir</a>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> </td>
{{ if eq .Status.String "WAITING_DRIVER_CONFIRMATION"}} </tr>
<span class="p-1 text-xs bg-gray-300 rounded-xl">Attente confirmation</span> </template>
{{ 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 }}
</tbody> </tbody>
</table> </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}}
{{end}} {{end}}

View File

@ -4,6 +4,53 @@
{{if eq (len .ViewState.bookings) 0}} {{if eq (len .ViewState.bookings) 0}}
<div class="m-10 text-center text-gray-600">Aucun trajet déclaré</div> <div class="m-10 text-center text-gray-600">Aucun trajet déclaré</div>
{{else}} {{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"> <table class="min-w-full divide-y divide-gray-300 border-gray-300 border-t-1">
<thead class="bg-gray-50"> <thead class="bg-gray-50">
<tr> <tr>
@ -42,57 +89,86 @@
</tr> </tr>
</thead> </thead>
<tbody class="divide-y divide-gray-200 bg-white"> <tbody class="divide-y divide-gray-200 bg-white">
{{range .ViewState.bookings}} <template x-for="booking in paginatedBookings" :key="booking.id">
<tr> <tr>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> <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}}"> <a class="text-co-blue" :href="'/app/organized-carpool/drivers/' + booking.driverId">
{{ (index $.ViewState.drivers_map .Driver.Id).Data.first_name }} <span x-text="booking.driverFirstName + ' ' + booking.driverLastName"></span>
{{ (index $.ViewState.drivers_map .Driver.Id).Data.last_name }} </a>
</a> </td>
</td> <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<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">
<a class="text-co-blue" href="/app/beneficiaries/{{.Passenger.Id}}"> <span x-text="booking.passengerFirstName + ' ' + booking.passengerLastName"></span>
{{ (index $.ViewState.passengers_map .Passenger.Id).Data.first_name }} </a>
{{ (index $.ViewState.passengers_map .Passenger.Id).Data.last_name }} </td>
</a> <td class="py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.pickupAddress"></td>
</td> <td class="py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.dropAddress"></td>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6"> <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.pickupDate"></td>
{{ .PassengerPickupAddress }} <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
</td> <span :class="getStatusBadge(booking.status).class" x-text="getStatusBadge(booking.status).text"></span>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6"> </td>
{{ .PassengerDropAddress }} <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
</td> <span x-text="booking.price !== 'N/A' ? booking.price + ' ' + booking.currency : 'N/A'"></span>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> </td>
{{ timeFormat .PassengerPickupDate.AsTime "02/01/2006 15:04" }} <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
</td> <a class="text-co-blue" :href="'/app/organized-carpool/bookings/' + booking.id">Voir</a>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> </td>
{{ if eq .Status.String "WAITING_DRIVER_CONFIRMATION"}} </tr>
<span class="p-1 text-xs bg-gray-300 rounded-xl">Attente confirmation</span> </template>
{{ 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 }}
</tbody> </tbody>
</table> </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}}
{{end}} {{end}}

View File

@ -28,6 +28,39 @@
</a> </a>
</div> </div>
</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"> <table class="min-w-full divide-y divide-gray-300 border-gray-300 border-t-1">
<thead class="bg-gray-50"> <thead class="bg-gray-50">
<tr> <tr>
@ -58,27 +91,76 @@
</tr> </tr>
</thead> </thead>
<tbody class="divide-y divide-gray-200 bg-white"> <tbody class="divide-y divide-gray-200 bg-white">
{{ range .ViewState.drivers }} <template x-for="driver in paginatedDrivers" :key="driver.id">
<tr> <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" x-text="driver.firstName + ' ' + driver.lastName"></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" x-text="driver.address"></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" x-text="driver.addressDestination"></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" x-text="driver.phoneNumber"></td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
{{if carpoolDriverValidatedProfile . (carpoolDocuments .ID) }} <span x-show="driver.validated" class="p-1 px-2 text-xs bg-co-green rounded-2xl">Oui</span>
<span 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>
{{else}} </td>
<span class="p-1 px-2 text-xs bg-co-red text-white rounded-2xl">Non</span> <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
{{end}} <a class="text-co-blue hover:text-co-blue" :href="'/app/organized-carpool/drivers/' + driver.id">
</td> Voir
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> </a>
<a class="text-co-blue hover:text-co-blue" </td>
href="/app/organized-carpool/drivers/{{.ID}}"> </tr>
Voir </template>
</a>
</td>
</tr>
{{ end }}
</tbody> </tbody>
</table> </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 }} {{ end }}

View File

@ -4,87 +4,145 @@
{{if eq (len .ViewState.bookings_history) 0}} {{if eq (len .ViewState.bookings_history) 0}}
<div class="m-10 text-center text-gray-600">Aucun trajet dans le passé</div> <div class="m-10 text-center text-gray-600">Aucun trajet dans le passé</div>
{{else}} {{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"> <table class="min-w-full divide-y divide-gray-300 border-gray-300 border-t-1">
<thead class="bg-gray-50"> <thead class="bg-gray-50">
<tr> <tr>
<th scope="col" <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>
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6"> <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>
Conducteur <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> <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" <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>
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6"> <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>
Passager <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> <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">
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> </tr>
</thead> </thead>
<tbody class="divide-y divide-gray-200 bg-white"> <tbody class="divide-y divide-gray-200 bg-white">
{{range .ViewState.bookings_history}} <template x-for="booking in paginatedBookings" :key="booking.id">
<tr> <tr>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> <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}}"> <a class="text-co-blue" :href="'/app/solidarity-transport/drivers/' + booking.driverId">
{{ (index $.ViewState.drivers_map .DriverId).Data.first_name }} <span x-text="booking.driverFirstName + ' ' + booking.driverLastName"></span>
{{ (index $.ViewState.drivers_map .DriverId).Data.last_name }} </a>
</a> </td>
</td> <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<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">
<a class="text-co-blue" href="/app/beneficiaries/{{.PassengerId}}"> <span x-text="booking.passengerFirstName + ' ' + booking.passengerLastName"></span>
{{ (index $.ViewState.passengers_map .PassengerId).Data.first_name }} </a>
{{ (index $.ViewState.passengers_map .PassengerId).Data.last_name }} </td>
</a> <td class="py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.pickupLabel"></td>
</td> <td class="py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.dropLabel"></td>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6"> <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.pickupDate"></td>
{{ .Journey.PassengerPickup.Properties.label }} <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
</td> <span :class="getStatusBadge(booking.status).class" x-text="getStatusBadge(booking.status).text"></span>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6"> </td>
{{ .Journey.PassengerDrop.Properties.label }} <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
</td> <span x-text="booking.price + ' ' + booking.currency"></span>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> </td>
{{ .Journey.PassengerPickupDate.Format "02/01/2006 15:04" }} <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
</td> <a class="text-co-blue" :href="'/app/solidarity-transport/bookings/' + booking.id">Voir</a>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> </td>
{{ if eq .Status "WAITING_CONFIRMATION"}} </tr>
<span class="p-1 text-xs bg-gray-300 rounded-xl">Attente confirmation</span> </template>
{{ 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 }}
</tbody> </tbody>
</table> </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}}
{{end}} {{end}}

View File

@ -5,81 +5,148 @@
{{if eq (len .ViewState.bookings) 0}} {{if eq (len .ViewState.bookings) 0}}
<div class="m-10 text-center text-gray-600">Aucun trajet déclaré</div> <div class="m-10 text-center text-gray-600">Aucun trajet déclaré</div>
{{else}} {{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"> <table class="min-w-full divide-y divide-gray-300 border-gray-300 border-t-1">
<thead class="bg-gray-50"> <thead class="bg-gray-50">
<tr> <tr>
<th scope="col" <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>
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6"> <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>
Conducteur <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> <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" <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>
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6"> <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>
Passager <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>
<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> </tr>
</thead> </thead>
<tbody class="divide-y divide-gray-200 bg-white"> <tbody class="divide-y divide-gray-200 bg-white">
{{range .ViewState.bookings}} <template x-for="booking in paginatedBookings" :key="booking.id">
<tr> <tr>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> <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}}"> <a class="text-co-blue" :href="'/app/solidarity-transport/drivers/' + booking.driverId">
{{ (index $.ViewState.drivers_map .DriverId).Data.first_name }} <span x-text="booking.driverFirstName + ' ' + booking.driverLastName"></span>
{{ (index $.ViewState.drivers_map .DriverId).Data.last_name }} </a>
</a> </td>
</td> <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
<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">
<a class="text-co-blue" href="/app/beneficiaries/{{.PassengerId}}"> <span x-text="booking.passengerFirstName + ' ' + booking.passengerLastName"></span>
{{ (index $.ViewState.passengers_map .PassengerId).Data.first_name }} </a>
{{ (index $.ViewState.passengers_map .PassengerId).Data.last_name }} </td>
</a> <td class="py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.pickupLabel"></td>
</td> <td class="py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.dropLabel"></td>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6"> <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6" x-text="booking.pickupDate"></td>
{{ .Journey.PassengerPickup.Properties.label }} <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
</td> <span :class="getStatusBadge(booking.status).class" x-text="getStatusBadge(booking.status).text"></span>
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6"> <template x-if="booking.motivation && isGuaranteedTrip(booking.motivation)">
{{ .Journey.PassengerDrop.Properties.label }} <div class="mt-4">
</td> <span class="text-xs p-2 bg-co-green text-white rounded-2xl" x-text="'Trajet garanti : ' + booking.motivation"></span>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> </div>
{{ timeFormat .Journey.PassengerPickupDate "02/01/2006 15:04" }} </template>
</td> </td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
{{ if eq .Status "WAITING_CONFIRMATION"}} <a class="text-co-blue" :href="'/app/solidarity-transport/bookings/' + booking.id">Voir</a>
<span class="p-1 text-xs bg-gray-300 rounded-xl">Attente confirmation</span> </td>
{{ else if eq .Status "VALIDATED"}} </tr>
<span class="p-1 text-xs bg-co-green rounded-xl">Validé</span> </template>
{{ 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 }}
</tbody> </tbody>
</table> </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}}
{{end}} {{end}}

View File

@ -27,6 +27,38 @@
</a> </a>
</div> </div>
</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"> <table class="min-w-full divide-y divide-gray-300 border-gray-300 border-t-1">
<thead class="bg-gray-50"> <thead class="bg-gray-50">
<tr> <tr>
@ -53,26 +85,75 @@
</tr> </tr>
</thead> </thead>
<tbody class="divide-y divide-gray-200 bg-white"> <tbody class="divide-y divide-gray-200 bg-white">
{{ range .ViewState.drivers }} <template x-for="driver in paginatedDrivers" :key="driver.id">
<tr> <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" x-text="driver.firstName + ' ' + driver.lastName"></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" x-text="driver.address"></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" x-text="driver.phoneNumber"></td>
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
{{if solidarityDriverValidatedProfile . (solidarityDocuments .ID) }} <span x-show="driver.validated" class="p-1 px-2 text-xs bg-co-green rounded-2xl">Oui</span>
<span 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>
{{else}} </td>
<span class="p-1 px-2 text-xs bg-co-red text-white rounded-2xl">Non</span> <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
{{end}} <a class="text-co-blue hover:text-co-blue" :href="'/app/solidarity-transport/drivers/' + driver.id">
</td> Voir
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6"> </a>
<a class="text-co-blue hover:text-co-blue" </td>
href="/app/solidarity-transport/drivers/{{.ID}}"> </tr>
Voir </template>
</a>
</td>
</tr>
{{ end }}
</tbody> </tbody>
</table> </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 }} {{ end }}

View File

@ -138,6 +138,48 @@
</div> </div>
</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"> <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> <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/"> <a href="/app/vehicles-management/">

View File

@ -170,26 +170,37 @@
</div> </div>
</div> </div>
</div> </div>
<section aria-labelledby="timeline-title" class="lg:col-start-3 lg:col-span-1"> {{if .ViewState.vehicle_optional_fields}}
<div class="bg-white px-4 py-5 shadow sm:rounded-lg sm:px-6"> <section aria-labelledby="vehicle-other-properties-title" class="lg:col-start-3 lg:col-span-1">
<h2 id="timeline-title" class="text-lg font-medium text-gray-900">Réservations à venir</h2> <div class="bg-white shadow sm:rounded-lg">
{{if eq (len .ViewState.vehicle.Bookings) 0}} <div class="px-4 py-5 sm:px-6">
<p class="p-12 text-gray-500 text-center text-md">Aucune réservation à venir</p> <h2 id="vehicle-other-properties-title" class="text-lg leading-6 font-medium text-gray-900">Autres propriétés</h2>
{{end}} <p class="mt-1 max-w-2xl text-sm text-gray-500">Informations complémentaires sur le véhicule</p>
<ul role="list" class="divide-y divide-gray-200"> </div>
{{range .ViewState.vehicle.Bookings}} <div class="border-t border-gray-200 px-4 py-5 sm:px-6">
<li class="py-4 flex"> <dl class="space-y-4">
<div class="ml-3"> {{range .ViewState.vehicle_optional_fields}}
<a href="/app/vehicles-management/bookings/{{.ID}}" class="hover:bg-gray-200"> {{if index $.ViewState.vehicle.Data .name}}
<p class="text-sm font-medium text-gray-900">Du {{(timeFrom .Startdate).Format "02/01/2006"}} au {{(timeFrom .Enddate).Format "02/01/2006"}}</p> <div>
<p class="text-sm text-gray-500"></p> <dt class="text-sm font-medium text-gray-500">{{.label}}</dt>
</a> <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> </div>
</li>
{{end}} {{end}}
</ul> {{end}}
</dl>
</div>
</div> </div>
</section> </section>
{{end}}
</div> </div>
</main> </main>

View File

@ -9,8 +9,9 @@
fields: { fields: {
licence_plate: '{{ .ViewState.vehicle.Data.licence_plate }}', licence_plate: '{{ .ViewState.vehicle.Data.licence_plate }}',
name: '{{ .ViewState.vehicle.Data.name }}', name: '{{ .ViewState.vehicle.Data.name }}',
type: '{{ .ViewState.vehicle.Type }}',
kilometers: '{{ .ViewState.vehicle.Data.kilometers }}', kilometers: '{{ .ViewState.vehicle.Data.kilometers }}',
informations: '{{ .ViewState.vahicle.Data.informations}}', informations: '{{ .ViewState.vehicle.Data.informations}}',
}, },
rules: { rules: {
licence_plate: ['required', 'regexMatch:^[A-Z]{1,2}-[0-9]{1,3}-[A-Z]{1,2}$'], 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> <legend class="sr-only">Automatique</legend>
<div class="relative flex items-start"> <div class="relative flex items-start">
<div class="flex h-5 items-center"> <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>
<div class="ml-3 text-sm"> <div class="ml-3 text-sm">
<label for="automatic" class="font-medium text-gray-700">Automatique</label> <label for="automatic" class="font-medium text-gray-700">Automatique</label>
@ -126,8 +127,8 @@
</div> </div>
<div class="mt-5 md:mt-0 md:col-span-2"> <div class="mt-5 md:mt-0 md:col-span-2">
{{ $fieldName := "address" }} {{ $fieldName := "address" }}
{{if .ViewState.Data.address}} {{if .ViewState.vehicle.Data.address}}
{{$default := .ViewState.Data.address}} {{$default := .ViewState.vehicle.Data.address}}
{{ template "address" dict "FieldName" $fieldName "Default" $default}} {{ template "address" dict "FieldName" $fieldName "Default" $default}}
{{else}} {{else}}
{{ template "address_autocomplete" dict "FieldName" $fieldName}} {{ template "address_autocomplete" dict "FieldName" $fieldName}}
@ -144,6 +145,48 @@
</div> </div>
</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"> <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> <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}}"> <a href="/app/vehicles-management/fleet/{{.ViewState.vehicle.ID}}">

View File

@ -3027,6 +3027,11 @@
} }
} }
} }
.focus\:z-20 {
&:focus {
z-index: 20;
}
}
.focus\:border-blue-500 { .focus\:border-blue-500 {
&:focus { &:focus {
border-color: var(--color-blue-500); border-color: var(--color-blue-500);
@ -3119,6 +3124,11 @@
outline-offset: calc(2px * -1); outline-offset: calc(2px * -1);
} }
} }
.focus\:outline-offset-0 {
&:focus {
outline-offset: 0px;
}
}
.focus\:outline-indigo-600 { .focus\:outline-indigo-600 {
&:focus { &:focus {
outline-color: var(--color-indigo-600); outline-color: var(--color-indigo-600);
@ -3135,6 +3145,12 @@
--tw-ring-inset: inset; --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-2 {
&:focus-visible { &:focus-visible {
outline-style: var(--tw-outline-style); outline-style: var(--tw-outline-style);
@ -3146,6 +3162,16 @@
outline-offset: calc(2px * -1); 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-indigo-600 {
&:focus-visible { &:focus-visible {
outline-color: var(--color-indigo-600); outline-color: var(--color-indigo-600);
@ -3161,6 +3187,11 @@
opacity: 30%; opacity: 30%;
} }
} }
.disabled\:opacity-50 {
&:disabled {
opacity: 50%;
}
}
.sm\:col-span-1 { .sm\:col-span-1 {
@media (width >= 40rem) { @media (width >= 40rem) {
grid-column: span 1 / span 1; grid-column: span 1 / span 1;