solidarity bookings filters + duplicate solidarity trip + notification when refused

This commit is contained in:
Arnaud Delcasse 2025-09-10 16:11:47 +02:00
parent 54c2ce3367
commit f12f7f581f
9 changed files with 222 additions and 26 deletions

View File

@ -255,6 +255,7 @@ views:
overview:
files:
- web/layouts/solidarity_transport/_partials/drivers_list.html
- web/layouts/solidarity_transport/_partials/booking_filters.html
- web/layouts/solidarity_transport/_partials/bookings_list.html
- web/layouts/solidarity_transport/_partials/bookings_history.html
- web/layouts/solidarity_transport/overview.html
@ -454,16 +455,16 @@ emails:
- emails/layout.html
- emails/onboarding/delete-subscriber.html
solidarity_transport:
boking_driver_accept:
booking_driver_accept:
subject: Trajet accepté par un conducteur
files:
- emails/layout.html
- emails/solidarity_transport/booking_driver_accept.html
boking_driver_decline:
booking_driver_decline:
subject: Trajet accepté par un conducteur
files:
- emails/layout.html
- emails/solidarity_transport/booking_driver_accept.html
- emails/solidarity_transport/booking_driver_decline.html
sms:
solidarity_transport:

View File

@ -1,5 +1,5 @@
{{define "content"}}
<p>Bonjour,</p>
<p>Trajet refusé par un conducteur.</p>
<p>Voir le trajet : <a href="{{ .baseUrl }}/solidarity-transport/bookings/{{.bookingid}}">{{ .baseUrl }}/solidarity-transport/bookings/{{.bookingid}}</a></p>
<p>Voir le trajet : <a href="{{ .baseUrl }}/app/solidarity-transport/bookings/{{.bookingid}}">{{ .baseUrl }}/app/solidarity-transport/bookings/{{.bookingid}}</a></p>
{{end}}

View File

@ -0,0 +1,43 @@
{{ define "booking_filters" }}
{{$tab := or .tab "solidarityTransport"}}
<form>
<input type="hidden" name="tab" value="{{$tab}}" />
<div class="flex flex-row justify-end flex-wrap">
<div class="m-4">
<div>
<label for="{{$tab}}_date_start" class="block text-sm/6 font-medium text-gray-900 dark:text-white">Dates (début / fin)</label>
<div class="mt-2 flex">
<input id="{{$tab}}_date_start" type="date" name="date_start" class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6 dark:bg-white/5 dark:text-white dark:outline-white/10 dark:placeholder:text-gray-500 dark:focus:outline-co-blue" value="{{.filters.date_start}}" onchange="this.form.submit()" />
<input id="{{$tab}}_date_end" type="date" name="date_end" class="mx-2 block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6 dark:bg-white/5 dark:text-white dark:outline-white/10 dark:placeholder:text-gray-500 dark:focus:outline-co-blue" value="{{.filters.date_end}}" onchange="this.form.submit()" />
</div>
</div>
</div>
<div class="m-4">
<label for="{{$tab}}_status" class="block text-sm/6 font-medium text-gray-900 dark:text-white">Statut</label>
<div class="mt-2 grid grid-cols-1">
<select id="{{$tab}}_status" name="status" class="col-start-1 row-start-1 w-full appearance-none rounded-md bg-white py-1.5 pr-8 pl-3 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-indigo-600 sm:text-sm/6 dark:bg-white/5 dark:text-white dark:outline-white/10 dark:*:bg-gray-800 dark:focus-visible:outline-co-blue" onchange="this.form.submit()">
<option></option>
<option value="VALIDATED"{{if eq .filters.status "VALIDATED"}} selected{{end}}>Validé</option>
<option value="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>
</select>
<svg viewBox="0 0 16 16" fill="currentColor" data-slot="icon" aria-hidden="true" class="pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-gray-500 sm:size-4 dark:text-gray-400">
<path d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" fill-rule="evenodd" />
</svg>
</div>
</div>
<div class="m-4">
</div>
</div>
</form>
{{ end }}

View File

@ -1,5 +1,6 @@
{{ define "solidarity_bookings_history" }}
{{template "booking_filters" dict "tab" "solidarityHistory" "filters" .ViewState.hist_filters }}
{{if eq (len .ViewState.bookings_history) 0}}
<div class="m-10 text-center text-gray-600">Aucun trajet dans le passé</div>
{{else}}

View File

@ -1,5 +1,7 @@
{{ define "solidarity_bookings_list" }}
{{template "booking_filters" dict "tab" "solidarityService" "filters" .ViewState.filters }}
{{if eq (len .ViewState.bookings) 0}}
<div class="m-10 text-center text-gray-600">Aucun trajet déclaré</div>
{{else}}

View File

@ -56,6 +56,8 @@
<!-- <button type="button"
class="inline-flex items-center justify-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-2xl text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-co-blue">Supprimer</button> -->
<a href="/app/journeys/?departure={{json .ViewState.booking.Journey.PassengerPickup}}&destination={{ json .ViewState.booking.Journey.PassengerDrop }}&passengerid={{.ViewState.booking.PassengerId}}" class="inline-flex"><button type="button"
class="w-full px-4 py-2 border border-transparent text-sm font-medium rounded-2xl shadow-sm bg-white text-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-co-blue">Dupliquer</button></a>
{{if eq .ViewState.booking.Status "CANCELLED" }}
<a href="/app/journeys/?departure={{json .ViewState.booking.Journey.PassengerPickup}}&destination={{ json .ViewState.booking.Journey.PassengerDrop }}&departuredate={{ .ViewState.booking.Journey.PassengerPickupDate.Format "2006-01-02"}}&departuretime={{ (timeFrom .ViewState.booking.Journey.PassengerPickupDate).Format "15:04"}}&passengerid={{.ViewState.booking.PassengerId}}&solidarity_transport_exclude_driver={{.ViewState.booking.DriverId}}" class="inline-flex"><button type="button"
class="w-full px-4 py-2 border border-transparent text-sm font-medium rounded-2xl shadow-sm bg-white text-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-co-blue">Solliciter un autre conducteur</button></a>

View File

@ -14,6 +14,7 @@
<script src="https://cdn.jsdelivr.net/npm/@protomaps/basemaps@5/dist/basemaps.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@turf/turf@7/turf.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/polyline@0.2.0/src/polyline.js"></script>
<meta name=viewport content="width=device-width" />
<!--<script defer type="text/javascript" src="/public/js/main.js" defer></script>-->
</head>
<body class="h-full">

View File

@ -1,10 +1,10 @@
{{ define "content" }}
{{$defaultTab := "solidarityService"}}
<div class="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">
<h1 class="text-2xl font-semibold text-gray-900">Transport solidaire</h1>
<div class="bg-white shadow sm:rounded-lg sm:overflow-hidden my-4" x-data="{
tab: 'drivers',
tab: '{{or .ViewState.tab $defaultTab}}',
to(event) {
this.tab = event.target.value
}
@ -14,6 +14,11 @@
<div class="hidden sm:block">
<div class="border-b border-gray-200 pl-4">
<nav class="-mb-px flex space-x-8" aria-label="Tabs">
<a href="#" @click="tab = 'solidarityService'"
class="whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
:class="tab == 'solidarityService' ? 'border-co-blue text-co-blue' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'">
Trajets </a>
<a href="#" @click="tab = 'drivers'"
class="whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
:class="tab == 'drivers' ? 'border-co-blue text-co-blue' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'">
@ -24,11 +29,6 @@
:class="tab == 'beneficiaries' ? 'border-co-blue text-co-blue' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'">
Bénéficiaires </a>-->
<a href="#" @click="tab = 'solidarityService'"
class="whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
:class="tab == 'solidarityService' ? 'border-co-blue text-co-blue' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'">
Trajets </a>
<a href="#" @click="tab = 'solidarityHistory'"
class="whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
:class="tab == 'solidarityHistory' ? 'border-co-blue text-co-blue' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'">

View File

@ -1,11 +1,11 @@
/*! tailwindcss v4.0.8 | MIT License | https://tailwindcss.com */
/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
@layer theme, base, components, utilities;
@layer theme {
:root, :host {
--font-sans: ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji';
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
monospace;
--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
"Courier New", monospace;
--color-red-500: oklch(0.637 0.237 25.331);
--color-green-100: oklch(0.962 0.044 156.743);
--color-green-800: oklch(0.448 0.119 151.328);
@ -67,10 +67,16 @@
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
--default-font-family: var(--font-sans);
--default-font-feature-settings: var(--font-sans--font-feature-settings);
--default-font-variation-settings: var(--font-sans--font-variation-settings);
--default-font-variation-settings: var(
--font-sans--font-variation-settings
);
--default-mono-font-family: var(--font-mono);
--default-mono-font-feature-settings: var(--font-mono--font-feature-settings);
--default-mono-font-variation-settings: var(--font-mono--font-variation-settings);
--default-mono-font-feature-settings: var(
--font-mono--font-feature-settings
);
--default-mono-font-variation-settings: var(
--font-mono--font-variation-settings
);
--color-co-blue: #243887;
--color-co-red: #ff1300;
--color-co-green: #6cc11f;
@ -89,9 +95,9 @@
line-height: 1.5;
-webkit-text-size-adjust: 100%;
tab-size: 4;
font-family: var( --default-font-family, ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji' );
font-family: var( --default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" );
font-feature-settings: var(--default-font-feature-settings, normal);
font-variation-settings: var(--default-font-variation-settings, normal);
font-variation-settings: var( --default-font-variation-settings, normal );
-webkit-tap-highlight-color: transparent;
}
body {
@ -119,9 +125,9 @@
font-weight: bolder;
}
code, kbd, samp, pre {
font-family: var( --default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace );
font-feature-settings: var(--default-mono-font-feature-settings, normal);
font-variation-settings: var(--default-mono-font-variation-settings, normal);
font-family: var( --default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace );
font-feature-settings: var( --default-mono-font-feature-settings, normal );
font-variation-settings: var( --default-mono-font-variation-settings, normal );
font-size: 1em;
}
small {
@ -209,13 +215,13 @@
:-moz-ui-invalid {
box-shadow: none;
}
button, input:where([type='button'], [type='reset'], [type='submit']), ::file-selector-button {
button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button {
appearance: button;
}
::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
height: auto;
}
[hidden]:where(:not([hidden='until-found'])) {
[hidden]:where(:not([hidden="until-found"])) {
display: none !important;
}
}
@ -349,6 +355,9 @@
.col-span-full {
grid-column: 1 / -1;
}
.col-start-1 {
grid-column-start: 1;
}
.col-start-auto {
grid-column-start: auto;
}
@ -361,6 +370,9 @@
.row-span-full {
grid-row: 1 / -1;
}
.row-start-1 {
grid-row-start: 1;
}
.row-start-auto {
grid-row-start: auto;
}
@ -451,6 +463,9 @@
.-mx-4 {
margin-inline: calc(var(--spacing) * -4);
}
.mx-2 {
margin-inline: calc(var(--spacing) * 2);
}
.mx-auto {
margin-inline: auto;
}
@ -652,6 +667,10 @@
.aspect-square {
aspect-ratio: 1 / 1;
}
.size-5 {
width: calc(var(--spacing) * 5);
height: calc(var(--spacing) * 5);
}
.h-0 {
height: calc(var(--spacing) * 0);
}
@ -1892,6 +1911,9 @@
.p-4 {
padding: calc(var(--spacing) * 4);
}
.p-10 {
padding: calc(var(--spacing) * 10);
}
.p-12 {
padding: calc(var(--spacing) * 12);
}
@ -1913,6 +1935,9 @@
.py-1 {
padding-block: calc(var(--spacing) * 1);
}
.py-1\.5 {
padding-block: calc(var(--spacing) * 1.5);
}
.py-2 {
padding-block: calc(var(--spacing) * 2);
}
@ -1967,6 +1992,9 @@
.pr-4 {
padding-right: calc(var(--spacing) * 4);
}
.pr-8 {
padding-right: calc(var(--spacing) * 8);
}
.pr-9 {
padding-right: calc(var(--spacing) * 9);
}
@ -2073,6 +2101,10 @@
font-size: var(--text-xs);
line-height: var(--tw-leading, var(--text-xs--line-height));
}
.text-sm\/6 {
font-size: var(--text-sm);
line-height: calc(var(--spacing) * 6);
}
.leading-4 {
--tw-leading: calc(var(--spacing) * 4);
line-height: calc(var(--spacing) * 4);
@ -2466,6 +2498,16 @@
outline-style: var(--tw-outline-style);
outline-width: 1px;
}
.outline-1 {
outline-style: var(--tw-outline-style);
outline-width: 1px;
}
.-outline-offset-1 {
outline-offset: calc(1px * -1);
}
.outline-gray-300 {
outline-color: var(--color-gray-300);
}
.blur {
--tw-blur: blur(8px);
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
@ -2756,6 +2798,11 @@
}
}
}
.placeholder\:text-gray-400 {
&::placeholder {
color: var(--color-gray-400);
}
}
.focus-within\:text-gray-600 {
&:focus-within {
color: var(--color-gray-600);
@ -2970,6 +3017,22 @@
--tw-ring-offset-color: var(--color-gray-100);
}
}
.focus\:outline-2 {
&:focus {
outline-style: var(--tw-outline-style);
outline-width: 2px;
}
}
.focus\:-outline-offset-2 {
&:focus {
outline-offset: calc(2px * -1);
}
}
.focus\:outline-indigo-600 {
&:focus {
outline-color: var(--color-indigo-600);
}
}
.focus\:outline-none {
&:focus {
--tw-outline-style: none;
@ -2981,6 +3044,22 @@
--tw-ring-inset: inset;
}
}
.focus-visible\:outline-2 {
&:focus-visible {
outline-style: var(--tw-outline-style);
outline-width: 2px;
}
}
.focus-visible\:-outline-offset-2 {
&:focus-visible {
outline-offset: calc(2px * -1);
}
}
.focus-visible\:outline-indigo-600 {
&:focus-visible {
outline-color: var(--color-indigo-600);
}
}
.disabled\:cursor-not-allowed {
&:disabled {
cursor: not-allowed;
@ -3086,6 +3165,12 @@
display: none;
}
}
.sm\:size-4 {
@media (width >= 40rem) {
width: calc(var(--spacing) * 4);
height: calc(var(--spacing) * 4);
}
}
.sm\:w-auto {
@media (width >= 40rem) {
width: auto;
@ -3295,6 +3380,12 @@
line-height: var(--tw-leading, var(--text-sm--line-height));
}
}
.sm\:text-sm\/6 {
@media (width >= 40rem) {
font-size: var(--text-sm);
line-height: calc(var(--spacing) * 6);
}
}
.md\:fixed {
@media (width >= 48rem) {
position: fixed;
@ -3533,6 +3624,61 @@
background-color: var(--color-gray-800);
}
}
.dark\:bg-white\/5 {
@media (prefers-color-scheme: dark) {
background-color: color-mix(in oklab, var(--color-white) 5%, transparent);
}
}
.dark\:text-gray-400 {
@media (prefers-color-scheme: dark) {
color: var(--color-gray-400);
}
}
.dark\:text-white {
@media (prefers-color-scheme: dark) {
color: var(--color-white);
}
}
.dark\:outline-white\/10 {
@media (prefers-color-scheme: dark) {
outline-color: color-mix(in oklab, var(--color-white) 10%, transparent);
}
}
.dark\:\*\:bg-gray-800 {
@media (prefers-color-scheme: dark) {
:is(& > *) {
background-color: var(--color-gray-800);
}
}
}
.dark\:placeholder\:text-gray-500 {
@media (prefers-color-scheme: dark) {
&::placeholder {
color: var(--color-gray-500);
}
}
}
.dark\:focus\:outline-co-blue {
@media (prefers-color-scheme: dark) {
&:focus {
outline-color: var(--color-co-blue);
}
}
}
.dark\:focus-visible\:outline-co-blue {
@media (prefers-color-scheme: dark) {
&:focus-visible {
outline-color: var(--color-co-blue);
}
}
}
.dark\:focus-visible\:outline-indigo-500 {
@media (prefers-color-scheme: dark) {
&:focus-visible {
outline-color: var(--color-indigo-500);
}
}
}
}
@font-face {
font-family: "Manometer";