Skip to content

Commit bffe94f

Browse files
committed
Update selected booking slot styles
1 parent 9a3e1d6 commit bffe94f

File tree

8 files changed

+69
-112
lines changed

8 files changed

+69
-112
lines changed

frontend/src/locales/de.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@
370370
"off": "Aus",
371371
"on": "An",
372372
"online": "Online",
373+
"onlineMeeting": "Online-Meeting",
373374
"open": "Offen",
374375
"openMenu": "Menü öffnen",
375376
"openMyPage": "Meinen Link öffnen",

frontend/src/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@
373373
"off": "Off",
374374
"on": "On",
375375
"online": "Online",
376+
"onlineMeeting": "Online meeting",
376377
"open": "Open",
377378
"openMenu": "Open menu",
378379
"openMyPage": "Open my page",

frontend/src/models.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@ export type Attendee = {
1616
timezone: string;
1717
};
1818

19-
export type GuestUserInfo = {
20-
name?: string;
21-
email: string;
22-
}
23-
2419
export type Slot = {
2520
id: number;
2621
start: Dayjs|string;

frontend/src/stores/booking-view-store.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { defineStore } from 'pinia';
22
import { ref, inject } from 'vue';
33
import { BookingCalendarView } from '@/definitions';
4-
import { Appointment, Attendee, Slot, GuestUserInfo } from '@/models';
4+
import { Appointment, Attendee, Slot } from '@/models';
55
import { dayjsKey } from '@/keys';
66

77
/**
@@ -19,8 +19,6 @@ export const useBookingViewStore = defineStore('bookingView', () => {
1919
const selectedEvent = ref<Appointment & Slot>(null); // The selected slot also needs some data from its parent
2020
const appointment = ref<Appointment>(null);
2121
const attendee = ref<Attendee>(null); // Attendee can either be a guest or an actual user
22-
const guestUserInfo = ref<GuestUserInfo>({ name: '', email: '' }); // Used in the SlotSelectionUserInfo form
23-
const guestUserInfoValid = ref<boolean>(false); // Used in the SlotSelectionUserInfo form
2422

2523
/**
2624
* Restore default state, set date to today and remove other data
@@ -31,7 +29,6 @@ export const useBookingViewStore = defineStore('bookingView', () => {
3129
selectedEvent.value = null;
3230
appointment.value = null;
3331
attendee.value = null;
34-
guestUserInfo.value = { name: '', email: '' };
3532
};
3633

3734
return {
@@ -42,8 +39,6 @@ export const useBookingViewStore = defineStore('bookingView', () => {
4239
selectedEvent,
4340
appointment,
4441
attendee,
45-
guestUserInfo,
46-
guestUserInfoValid,
4742
// Funcs
4843
$reset,
4944
};

frontend/src/views/BookerView/components/BookingViewSlotSelection.vue

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,15 @@ async function onDateChange(dateObj: TimeFormatted) {
7676
:selectable-slots="appointment.slots"
7777
@event-selected="selectEvent"
7878
/>
79-
80-
<div class="calendar-footer">
81-
<ph-globe size="16" />
82-
<span>{{ t('label.timeZone') }}: {{ timezone }}</span>
83-
</div>
8479
</div>
85-
80+
8681
<slot-selection-aside />
8782
</div>
83+
84+
<div class="calendar-footer">
85+
<ph-globe size="16" />
86+
<span>{{ t('label.timeZone') }}: {{ timezone }}</span>
87+
</div>
8888
</template>
8989
</template>
9090

@@ -103,14 +103,14 @@ async function onDateChange(dateObj: TimeFormatted) {
103103
104104
.calendar-container {
105105
flex: 1;
106+
}
106107
107-
.calendar-footer {
108-
display: flex;
109-
align-items: center;
110-
gap: 0.5rem;
111-
margin-block: 1.25rem;
112-
font-size: 0.6875rem;
113-
}
108+
.calendar-footer {
109+
display: flex;
110+
align-items: center;
111+
gap: 0.5rem;
112+
margin-block: 1.25rem;
113+
font-size: 0.6875rem;
114114
}
115115
116116
@media (--md) {

frontend/src/views/BookerView/components/SlotSelectionAside.vue

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
<script setup lang="ts">
2-
import { computed, inject, ref } from 'vue';
2+
import { computed, inject, ref, useTemplateRef } from 'vue';
33
import { storeToRefs } from 'pinia';
44
import { useI18n } from 'vue-i18n';
55
import {
66
PhCalendarBlank,
77
PhClock,
88
PhMapPin
99
} from '@phosphor-icons/vue';
10-
import { PrimaryButton } from '@thunderbirdops/services-ui';
10+
import { TextInput, PrimaryButton } from '@thunderbirdops/services-ui';
1111
import { dayjsKey, callKey } from '@/keys';
1212
import { SlotResponse } from '@/models';
1313
import { usePosthog, posthog } from '@/composables/posthog';
1414
import { useBookingViewStore } from '@/stores/booking-view-store';
1515
import { useUserStore } from '@/stores/user-store';
1616
import { BookingCalendarView, MetricEvents, AlertSchemes } from '@/definitions';
17-
import SlotSelectionUserInfo from './SlotSelectionUserInfo.vue';
1817
import AlertBox from '@/elements/AlertBox.vue';
1918
2019
const { t } = useI18n();
@@ -26,14 +25,16 @@ const userStore = useUserStore();
2625
const {
2726
appointment,
2827
selectedEvent,
29-
guestUserInfo,
30-
guestUserInfoValid,
3128
attendee,
3229
activeView
3330
} = storeToRefs(useBookingViewStore());
3431
32+
const userInfoForm = useTemplateRef<HTMLFormElement>('userInfoForm');
33+
3534
const bookingRequestLoading = ref<boolean>(false);
3635
const bookingRequestError = ref<string>('');
36+
const guestUserName = ref<string>('');
37+
const guestUserEmail = ref<string>('');
3738
3839
const timezone = computed(() => dj.tz.guess());
3940
const selectedSlotDate = computed(() => dj(selectedEvent.value?.start).format('LL'))
@@ -51,6 +52,11 @@ const selectedSlotTimeDuration = computed(() => {
5152
* Book or request to book a selected time.
5253
*/
5354
const bookEvent = async () => {
55+
if (!userInfoForm.value.checkValidity()) {
56+
userInfoForm.value.reportValidity();
57+
return;
58+
}
59+
5460
bookingRequestLoading.value = true;
5561
bookingRequestError.value = '';
5662
@@ -60,8 +66,8 @@ const bookEvent = async () => {
6066
name: userStore.data.name,
6167
timezone: userStore.data.settings.timezone,
6268
} : {
63-
email: guestUserInfo.value.email,
64-
name: guestUserInfo.value.name,
69+
email: guestUserEmail.value,
70+
name: guestUserName.value,
6571
timezone: timezone.value,
6672
}
6773
@@ -142,27 +148,35 @@ const bookEvent = async () => {
142148
</div>
143149
</div>
144150

145-
<slot-selection-user-info />
146-
147-
<alert-box
148-
v-if="bookingRequestError"
149-
:alert="{ title: bookingRequestError }"
150-
:scheme="AlertSchemes.Error"
151-
@close="bookingRequestError = ''"
152-
class="booking-request-error"
153-
/>
154-
155-
<primary-button
156-
v-if="selectedEvent"
157-
:label="t('label.confirmSelection')"
158-
:disabled="bookingRequestLoading || !guestUserInfoValid"
159-
@click="bookEvent"
160-
:title="t('label.confirm')"
161-
class="confirm-selection-button"
162-
data-testid="booking-view-confirm-selection-button"
163-
>
164-
{{ t('label.confirmSelection') }}
165-
</primary-button>
151+
<form ref="userInfoForm" class="user-info-form" @submit.prevent @keyup.enter="bookEvent">
152+
<text-input required name="booker-view-user-name" v-model="guestUserName">
153+
{{ t('label.name') }}
154+
</text-input>
155+
156+
<text-input required type="email" name="booker-view-user-email" v-model="guestUserEmail">
157+
{{ t('label.email') }}
158+
</text-input>
159+
160+
<alert-box
161+
v-if="bookingRequestError"
162+
:alert="{ title: bookingRequestError }"
163+
:scheme="AlertSchemes.Error"
164+
@close="bookingRequestError = ''"
165+
class="booking-request-error"
166+
/>
167+
168+
<primary-button
169+
v-if="selectedEvent && userInfoForm"
170+
:label="t('label.confirmSelection')"
171+
:disabled="bookingRequestLoading"
172+
@click="bookEvent"
173+
:title="t('label.confirm')"
174+
class="confirm-selection-button"
175+
data-testid="booking-view-confirm-selection-button"
176+
>
177+
{{ t('label.confirmSelection') }}
178+
</primary-button>
179+
</form>
166180

167181
<p
168182
v-if="selectedEvent && !appointment.booking_confirmation"
@@ -276,6 +290,12 @@ aside {
276290
}
277291
}
278292
293+
.user-info-form {
294+
display: flex;
295+
flex-direction: column;
296+
gap: 1.5rem;
297+
}
298+
279299
.booking-request-error {
280300
margin-block: 1rem;
281301
border-radius: 0.25rem;
@@ -285,11 +305,7 @@ aside {
285305
}
286306
287307
.booking-request-error {
288-
margin-block: 1rem 0;
289-
}
290-
291-
.confirm-selection-button {
292-
margin-block-start: 1rem;
308+
margin-block: 0;
293309
}
294310
295311
.confirmation-footer-note {

frontend/src/views/BookerView/components/SlotSelectionHeader.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ const { appointment } = storeToRefs(calendarStore);
2020
<div class="booking-header-time-place">
2121
<div class="booking-header-time-place-item">
2222
<ph-clock size="16" />
23-
<span>{{ appointment.slot_duration }} minutes</span>
23+
<span>{{ t('units.minutes', { value: appointment.slot_duration }) }}</span>
2424
</div>
2525
<div class="booking-header-time-place-item">
2626
<ph-map-pin size="16" />
27-
<span>Online meeting</span>
27+
<!-- TODO: We are currently only allowing for events to be online but the backend defaults to in person -->
28+
<!-- <span>{{ selectedEvent.location_type === EventLocationType.Online ? t('label.virtual') : t('label.inPerson') }}</span> -->
29+
<span>{{ t('label.onlineMeeting') }}</span>
2830
</div>
2931
</div>
3032
</div>

frontend/src/views/BookerView/components/SlotSelectionUserInfo.vue

Lines changed: 0 additions & 53 deletions
This file was deleted.

0 commit comments

Comments
 (0)