changes + saved search
This commit is contained in:
@@ -24,6 +24,10 @@
|
||||
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||
Distance du covoiturage
|
||||
</th>
|
||||
<th scope="col"
|
||||
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||
Profil validé
|
||||
</th>
|
||||
<th scope="col"
|
||||
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||
|
||||
@@ -38,8 +42,15 @@
|
||||
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6">{{ .DriverDepartureAddress }}</td>
|
||||
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6">{{ .DriverArrivalAddress }}</td>
|
||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">{{ .Distance }} km</td>
|
||||
<td class="py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||
{{if carpoolDriverValidatedProfile $driver (carpoolDocuments $driver.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"
|
||||
<a class="text-co-blue hover:text-co-blue"
|
||||
href="/app/organized-carpool/drivers/{{$driver.ID}}/journeys/{{.Id}}">
|
||||
Organiser
|
||||
</a>
|
||||
|
||||
110
web/layouts/journeys/_partials/saved-searches.html
Normal file
110
web/layouts/journeys/_partials/saved-searches.html
Normal file
@@ -0,0 +1,110 @@
|
||||
{{define "saved_searches"}}
|
||||
<div class="bg-white shadow sm:rounded-2xl sm:overflow-hidden">
|
||||
<h2 class="text-lg font-medium text-gray-900 p-4 sm:px-6">Recherches sauvegardées</h2>
|
||||
<div class="border-t border-gray-200">
|
||||
|
||||
{{if .ViewState.saved_searches}}
|
||||
<div class="overflow-x-auto">
|
||||
<table class="min-w-full divide-y divide-gray-300">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th scope="col" class="w-1/6 py-2 px-3 text-left text-sm font-semibold text-gray-900">
|
||||
Bénéficiaire
|
||||
</th>
|
||||
<th scope="col" class="w-1/4 px-3 py-2 text-left text-sm font-semibold text-gray-900">
|
||||
Départ
|
||||
</th>
|
||||
<th scope="col" class="w-1/4 px-3 py-2 text-left text-sm font-semibold text-gray-900">
|
||||
Destination
|
||||
</th>
|
||||
<th scope="col" class="w-1/6 px-3 py-2 text-left text-sm font-semibold text-gray-900">
|
||||
Date/Heure
|
||||
</th>
|
||||
<th scope="col" class="w-1/6 relative py-2 px-3 text-right text-sm font-semibold text-gray-900">
|
||||
<span class="sr-only">Actions</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 bg-white">
|
||||
{{range .ViewState.saved_searches}}
|
||||
<tr>
|
||||
<td class="py-3 px-3 text-sm text-gray-500">
|
||||
{{if and .Data .Data.passenger_id}}
|
||||
{{$beneficiary := index $.ViewState.beneficiaries .Data.passenger_id}}
|
||||
{{if $beneficiary}}
|
||||
<a href="/app/beneficiaries/{{.Data.passenger_id}}" class="text-co-blue hover:text-co-blue-dark">
|
||||
{{$beneficiary.Data.first_name}} {{$beneficiary.Data.last_name}}
|
||||
</a>
|
||||
{{else}}
|
||||
-
|
||||
{{end}}
|
||||
{{else}}
|
||||
-
|
||||
{{end}}
|
||||
</td>
|
||||
<td class="px-3 py-3 text-sm text-gray-500 break-words">
|
||||
{{if .Departure}}
|
||||
{{if .Departure.Properties}}
|
||||
{{if .Departure.Properties.city}}
|
||||
{{.Departure.Properties.city}}
|
||||
{{else}}
|
||||
{{.Departure.Properties.label}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
-
|
||||
{{end}}
|
||||
{{else}}
|
||||
-
|
||||
{{end}}
|
||||
</td>
|
||||
<td class="px-3 py-3 text-sm text-gray-500 break-words">
|
||||
{{if .Destination}}
|
||||
{{if .Destination.Properties}}
|
||||
{{if .Destination.Properties.city}}
|
||||
{{.Destination.Properties.city}}
|
||||
{{else}}
|
||||
{{.Destination.Properties.label}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
-
|
||||
{{end}}
|
||||
{{else}}
|
||||
-
|
||||
{{end}}
|
||||
</td>
|
||||
<td class="px-3 py-3 text-sm text-gray-500 whitespace-nowrap">
|
||||
{{if .DateTime}}
|
||||
{{timeFormat .DateTime "02/01/2006 15:04"}}
|
||||
{{else}}
|
||||
-
|
||||
{{end}}
|
||||
</td>
|
||||
<td class="relative py-3 px-3 text-right text-sm font-medium whitespace-nowrap">
|
||||
<a href="/app/journeys/?departure={{json .Departure}}&destination={{json .Destination}}&departuredate={{timeFormat .DateTime "2006-01-02"}}&departuretime={{timeFormat .DateTime "15:04"}}{{if and .Data .Data.passenger_id}}&passengerid={{.Data.passenger_id}}{{end}}" class="text-co-blue hover:text-co-blue-dark mr-4">
|
||||
Rechercher
|
||||
</a>
|
||||
<a href="/app/journeys/saved-searches/{{.ID}}/delete"
|
||||
class="text-red-600 hover:text-red-900"
|
||||
onclick="return confirm('Êtes-vous sûr de vouloir supprimer cette recherche sauvegardée ?')">
|
||||
Supprimer
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="text-center py-8">
|
||||
<div class="text-gray-500">
|
||||
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
||||
</svg>
|
||||
<h3 class="mt-2 text-sm font-medium text-gray-900">Aucune recherche sauvegardée</h3>
|
||||
<p class="mt-1 text-sm text-gray-500">Effectuez une recherche et cliquez sur "Enregistrer pour plus tard" pour commencer.</p>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -21,7 +21,30 @@
|
||||
<div class="bg-white shadow sm:rounded-2xl">
|
||||
<h2 id="timeline-title" class="text-lg font-medium text-gray-900 p-4 sm:px-6">Chercher une solution</h2>
|
||||
<div class="border-t border-gray-200 px-4 py-5 sm:px-6">
|
||||
<form method="GET">
|
||||
<form method="GET" x-data="journeySearch()">
|
||||
|
||||
<div class="py-4">
|
||||
<label for="beneficiary" class="block text-sm font-medium text-gray-700">Bénéficiaire (optionnel)</label>
|
||||
<div class="mt-1 relative" x-data="beneficiaryAutocomplete()">
|
||||
<input type="text"
|
||||
x-model="input"
|
||||
@input="onInput()"
|
||||
@focus="showResults = true"
|
||||
@blur="setTimeout(() => showResults = false, 200)"
|
||||
class="p-2 shadow-sm focus:ring-co-blue focus:border-co-blue block w-full sm:text-sm border-gray-300 rounded-2xl">
|
||||
|
||||
<ul x-show="showResults && filteredBeneficiaries.length > 0"
|
||||
class="absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-xl py-1 text-base overflow-auto focus:outline-none sm:text-sm border border-gray-300"
|
||||
tabindex="-1" role="listbox">
|
||||
<template x-for="beneficiary in filteredBeneficiaries" :key="beneficiary.id">
|
||||
<li class="text-gray-900 hover:bg-gray-200 cursor-default select-none relative py-2 pl-3 pr-9"
|
||||
@click="selectBeneficiary(beneficiary)">
|
||||
<span class="font-normal block truncate" x-text="beneficiary.name"></span>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ $departureField := "departure" }}
|
||||
{{ $departureLabel := "Départ" }}
|
||||
@@ -33,9 +56,7 @@
|
||||
{{ $destination := .ViewState.destination }}
|
||||
{{ template "address_autocomplete" dict "FieldName" $destinationField "FieldLabel" $destinationLabel "Address" $destination }}
|
||||
|
||||
{{if ne .ViewState.passengerid "" }}
|
||||
<input type="hidden" value="{{.ViewState.passengerid}}" name="passengerid" />
|
||||
{{end}}
|
||||
<input type="hidden" name="passengerid" value="{{.ViewState.passengerid}}" />
|
||||
|
||||
<div class="py-4 grid grid-cols-2">
|
||||
<div class="lg:col-span-1">
|
||||
@@ -55,11 +76,100 @@
|
||||
|
||||
</div>
|
||||
|
||||
<button type="submit"
|
||||
class="rounded-2xl border border-transparent bg-co-blue px-4 py-2 my-4 mt-8 w-full text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:ring-co-blue focus:ring-offset-2 sm:w-auto">
|
||||
Chercher
|
||||
</button>
|
||||
<div class="flex gap-2 mt-8">
|
||||
<button type="submit"
|
||||
class="rounded-2xl border border-transparent bg-co-blue px-4 py-2 my-4 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:ring-co-blue focus:ring-offset-2 sm:w-auto">
|
||||
Chercher
|
||||
</button>
|
||||
{{if .ViewState.searched}}
|
||||
<a href="/app/journeys/save?departure={{json .ViewState.departure}}&destination={{ json .ViewState.destination }}&departuredate={{.ViewState.departuredate}}&departuretime={{.ViewState.departuretime}}&passengerid={{.ViewState.passengerid}}"
|
||||
class="rounded-2xl border border-gray-300 bg-white px-4 py-2 my-4 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-co-blue focus:ring-offset-2 sm:w-auto inline-flex items-center">
|
||||
Enregistrer pour plus tard
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
function journeySearch() {
|
||||
return {
|
||||
selectedBeneficiaryId: '{{.ViewState.passengerid}}',
|
||||
}
|
||||
}
|
||||
|
||||
function beneficiaryAutocomplete() {
|
||||
const beneficiaries = [
|
||||
{{range .ViewState.beneficiaries_list}}
|
||||
{
|
||||
id: '{{.ID}}',
|
||||
name: '{{.Data.first_name}} {{.Data.last_name}}',
|
||||
address: {{json .Data.address}}
|
||||
},
|
||||
{{end}}
|
||||
];
|
||||
|
||||
return {
|
||||
input: '',
|
||||
showResults: false,
|
||||
filteredBeneficiaries: [],
|
||||
selectedBeneficiary: null,
|
||||
|
||||
init() {
|
||||
// Set initial value if passengerid is set
|
||||
const currentPassengerId = '{{.ViewState.passengerid}}';
|
||||
if (currentPassengerId) {
|
||||
const beneficiary = beneficiaries.find(b => b.id === currentPassengerId);
|
||||
if (beneficiary) {
|
||||
this.input = beneficiary.name;
|
||||
this.selectedBeneficiary = beneficiary;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onInput() {
|
||||
if (this.input.length === 0) {
|
||||
this.filteredBeneficiaries = [];
|
||||
this.selectedBeneficiary = null;
|
||||
this.updatePassengerId('');
|
||||
return;
|
||||
}
|
||||
|
||||
this.filteredBeneficiaries = beneficiaries.filter(beneficiary =>
|
||||
beneficiary.name.toLowerCase().includes(this.input.toLowerCase())
|
||||
).slice(0, 10); // Limit to 10 results
|
||||
},
|
||||
|
||||
selectBeneficiary(beneficiary) {
|
||||
this.input = beneficiary.name;
|
||||
this.selectedBeneficiary = beneficiary;
|
||||
this.showResults = false;
|
||||
this.updatePassengerId(beneficiary.id);
|
||||
this.setDepartureAddress(beneficiary.address);
|
||||
},
|
||||
|
||||
updatePassengerId(id) {
|
||||
const passengerInput = document.querySelector('input[name="passengerid"]');
|
||||
if (passengerInput) {
|
||||
passengerInput.value = id;
|
||||
}
|
||||
},
|
||||
|
||||
setDepartureAddress(address) {
|
||||
if (address) {
|
||||
// Find the departure address autocomplete container
|
||||
const departureContainer = document.querySelector('input[name="departure"]').closest('[x-data]');
|
||||
if (departureContainer && departureContainer._x_dataStack && departureContainer._x_dataStack[0]) {
|
||||
const addressAutocomplete = departureContainer._x_dataStack[0];
|
||||
// Update the address autocomplete component directly
|
||||
addressAutocomplete.address = JSON.stringify(address);
|
||||
addressAutocomplete.addressObject = address;
|
||||
addressAutocomplete.input = address.properties.label;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -113,6 +223,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{{else}}
|
||||
{{template "saved_searches" .}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user