234 lines
14 KiB
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" 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}}
|