parcoursmob-default-theme/web/layouts/journeys/search.html

234 lines
14 KiB
HTML

{{define "content"}}
<div class="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">
<h1 class="text-2xl font-semibold text-gray-900">Déplacements</h1>
<div class="sm:flex sm:items-center">
<div class="sm:flex-auto">
<p class="mt-2 text-sm text-gray-700"></p>
</div>
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
<!--<a href="/app/journeys/groups_covoiturage">
<button type="button"
class="inline-flex items-center justify-center rounded-2xl border border-transparent bg-co-blue px-4 py-2 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">
{{$.IconSet.Icon "hero:outline/plus-circle" "h-5 w-5 mr-3"}}
Gestion des groupes
</button>
</a>-->
</div>
</div>
<div class="mt-8 max-w-3xl mx-auto grid grid-cols-1 gap-6 lg:max-w-7xl lg:grid-flow-col-dense lg:grid-cols-3">
<div class="space-y-6 lg:col-start-1 lg:col-span-1">
<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" action="{{if eq .ViewState.search_view "compact"}}/app/journeys/search{{else}}/app/journeys/{{end}}" 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" }}
{{ $departure := .ViewState.departure }}
{{ template "address_autocomplete" dict "FieldName" $departureField "FieldLabel" $departureLabel "Address" $departure }}
{{ $destinationField := "destination" }}
{{ $destinationLabel := "Destination" }}
{{ $destination := .ViewState.destination }}
{{ template "address_autocomplete" dict "FieldName" $destinationField "FieldLabel" $destinationLabel "Address" $destination }}
<input type="hidden" name="passengerid" value="{{.ViewState.passengerid}}" />
<div class="py-4 grid grid-cols-2">
<div class="lg:col-span-1">
<label for="departuredate" class="block text-sm font-medium text-gray-700">Date de départ</label>
<div class="mt-1">
<input type="date" id="departuredate" name="departuredate" value="{{.ViewState.departuredate}}"
class="p-2 shadow-sm focus:ring-co-blue focus:border-co-blue block w-full sm:text-sm border-gray-300 rounded-l-2xl border-r-1">
</div>
</div>
<div class="lg:col-span-1">
<label for="departuretime" class="block text-sm font-medium text-gray-700">Heure de départ</label>
<div class="mt-1">
<input type="time" id="departuretime" name="departuretime" value="{{.ViewState.departuretime}}"
class="p-2 shadow-sm focus:ring-co-blue focus:border-co-blue block w-full sm:text-sm border-gray-300 rounded-r-2xl border-l-0">
</div>
</div>
</div>
<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>
<div class="lg:col-start-2 lg:col-span-2">
{{if .ViewState.searched}}
<section aria-labelledby="results-title" x-data="{
tab: 'all',
to(event) {
this.tab = event.target.value
}
}">
<div class="bg-white shadow sm:rounded-lg sm:overflow-hidden">
<div class="divide-y divide-gray-200">
<div>
<div class="sm:hidden">
<label for="tabs" class="sr-only">Select a tab</label>
<select id="tabs" name="tabs" @change="to"
class="block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md">
{{range .ViewState.journey_tabs}}
{{if or .enabled (and .module (moduleAvailable .module))}}
<option value="{{.name}}">{{.title}}</option>
{{end}}
{{end}}
</select>
</div>
<div class="hidden sm:block">
<div class="border-b border-gray-200 pl-4 overflow-x-auto">
<nav class="-mb-px flex space-x-8 min-w-max" aria-label="Tabs">
<!-- Current: "border-indigo-500 text-indigo-600", Default: "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" -->
{{range .ViewState.journey_tabs}}
{{if or .enabled (and .module (moduleAvailable .module))}}
<a href="#" @click="tab = '{{.name}}'"
class="whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
:class="tab == '{{.name}}' ? 'border-co-blue text-co-blue' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'">
{{.title}} </a>
{{end}}
{{end}}
</nav>
</div>
</div>
</div>
<div x-show="tab == 'all'">{{template "journeys_all" .}}</div>
<div x-show="tab == 'carpool'">{{template "journeys_carpool" .}}</div>
<div x-show="tab == 'public-transit'">{{template "journeys_public_transit" .}}</div>
<div x-show="tab == 'organized-carpool'">{{template "journeys_organized_carpool" .}}</div>
<div x-show="tab == 'solidarity-transport'">{{template "journeys_solidarity_transport" .}}</div>
<div x-show="tab == 'vehicles'">{{template "journeys_vehicles" .}}</div>
<div x-show="tab == 'directory'">{{template "journeys_local_solutions" .}}</div>
<div x-show="tab == 'others'">{{template "journeys_others" .}}</div>
</div>
</div>
</section>
{{else}}
{{template "saved_searches" .}}
{{end}}
</div>
</div>
</div>
{{end}}