From 5af642f877d842b9ee343cf48768050657a8a750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=BCller?= Date: Thu, 12 Sep 2024 21:44:05 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A8=20Migrate=20inputs=20and=20buttons?= =?UTF-8?q?=20to=20tbpro?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/ScheduleCreation.vue | 280 ++++++++++--------- frontend/src/locales/en.json | 2 +- frontend/src/tbpro/elements/TextInput.vue | 1 + 3 files changed, 145 insertions(+), 138 deletions(-) diff --git a/frontend/src/components/ScheduleCreation.vue b/frontend/src/components/ScheduleCreation.vue index 910011f7..5c25bb62 100644 --- a/frontend/src/components/ScheduleCreation.vue +++ b/frontend/src/components/ScheduleCreation.vue @@ -15,16 +15,18 @@ import { useUserStore } from '@/stores/user-store'; import { dayjsKey, callKey, isoWeekdaysKey } from '@/keys'; import AppointmentCreatedModal from '@/components/AppointmentCreatedModal.vue'; -import PrimaryButton from '@/elements/PrimaryButton.vue'; -import SecondaryButton from '@/elements/SecondaryButton.vue'; +import PrimaryButton from '@/tbpro/elements/PrimaryButton.vue'; +import SecondaryButton from '@/tbpro/elements/SecondaryButton.vue'; import AlertBox from '@/elements/AlertBox.vue'; import SwitchToggle from '@/elements/SwitchToggle.vue'; import ToolTip from '@/elements/ToolTip.vue'; import SnackishBar from '@/elements/SnackishBar.vue'; import BubbleSelect from '@/tbpro/elements/BubbleSelect.vue'; import TextInput from '@/tbpro/elements/TextInput.vue'; +import SelectInput from '@/tbpro/elements/SelectInput.vue'; import LinkButton from '@/tbpro/elements/LinkButton.vue'; import RefreshIcon from '@/tbpro/icons/RefreshIcon.vue'; +import CopyIcon from '@/tbpro/icons/CopyIcon.vue'; // icons import { IconChevronDown, IconInfoCircle } from '@tabler/icons-vue'; @@ -194,25 +196,38 @@ const scheduleDayOptions: SelectOption[] = isoWeekdays.map((day) => ({ value: day.iso, })); -// booking options -const earliestOptions = {}; -[0, 0.5, 1, 2, 3, 4, 5].forEach((d) => { +// Connected calendar options +const calendarOptions = computed(() => props.calendars.map((calendar) => ({ + label: calendar.title, + value: calendar.id, +}))); + +// Earliest booking options +const earliestOptions: SelectOption[] = [0, 0.5, 1, 2, 3, 4, 5].map((d) => { // Special case to avoid "in a few seconds" if (d === 0) { - earliestOptions[0] = t('label.immediately'); - return; + return { + label: t('label.immediately'), + value: 0, + }; } - earliestOptions[d * 60 * 24] = dj.duration(d, 'days').humanize(); -}); -const farthestOptions = {}; -[1, 2, 3, 4].forEach((d) => { - farthestOptions[d * 60 * 24 * 7] = dj.duration(d, 'weeks').humanize(); + return { + label: dj.duration(d, 'days').humanize(), + value: d * 60 * 24, + }; }); -const durationOptions = {}; -SLOT_DURATION_OPTIONS.forEach((duration) => { - durationOptions[duration] = t('units.minutes', { value: duration }); -}); +// Farthest booking options +const farthestOptions: SelectOption[] = [1, 2, 3, 4].map((d) => ({ + label: dj.duration(d, 'weeks').humanize(), + value: d * 60 * 24 * 7, +})); + +// Appointment duration options +const durationOptions: SelectOption[] = SLOT_DURATION_OPTIONS.map((duration) => ({ + label: t('units.minutes', { value: duration }), + value: duration, +})); // humanize selected durations const earliest = computed(() => (scheduleInput.value.earliest_booking === 0 @@ -320,6 +335,26 @@ const toggleBookingConfirmation = (newValue: boolean) => { scheduleInput.value.booking_confirmation = newValue; }; +// Link copy +const myLinkTooltip = ref(t('label.copyLink')); +const myLinkShow = ref(false); +const copyLink = async () => { + await navigator.clipboard.writeText(user.myLink); + + myLinkShow.value = true; + myLinkTooltip.value = t('info.copiedToClipboard'); + + // Fade out after a bit + setTimeout(() => { + myLinkShow.value = false; + + // After the animation fades... + setTimeout(() => { + myLinkTooltip.value = t('label.copyLink'); + }, 500); + }, 4000); +}; + // track if steps were already visited watch( () => scheduleInput.value.active, @@ -424,29 +459,25 @@ watch(

-
- - +
+ + {{ t("label.startTime") }} + + + {{ t("label.endTime") }} +
@@ -493,76 +524,44 @@ watch(

- -
- - - + + {{ t("label.selectCalendar") }} + +
+ + {{ t("label.earliestBooking") }} + + + {{ t("label.farthestBooking") }} +
+ + {{ t("label.slotLength") }} +
{{ t('text.recipientsCanScheduleBetween', { @@ -599,27 +598,31 @@ watch(

-
@@ -782,11 +783,16 @@ watch(
+ @click="copyLink" + :tooltip="myLinkTooltip" + :force-tooltip="myLinkShow" + > + + {{ t('label.shareMyLink') }} +
diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 6a317d9c..05054e94 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -287,7 +287,7 @@ "sendInviteToWaitingList": "Select someone to send an invite! | Send an invite to {count} folk | Send an invite to {count} folks", "sentCountInvitesSuccessfully": "All selected users are already invited! | Sent {count} invite! | Sent {count} invites!", "settings": "Settings", - "shareMyLink": "Share my link", + "shareMyLink": "Share my quick link", "showSecondaryTimeZone": "Show secondary time zone", "signInWithGoogle": "Sign in with Google", "signUpForBeta": "Sign up for the beta", diff --git a/frontend/src/tbpro/elements/TextInput.vue b/frontend/src/tbpro/elements/TextInput.vue index b9081096..67615b32 100644 --- a/frontend/src/tbpro/elements/TextInput.vue +++ b/frontend/src/tbpro/elements/TextInput.vue @@ -150,6 +150,7 @@ const onChange = () => { .tbpro-input { display: inline-block; position: relative; + width: 100%; .tbpro-input-prefix { position: absolute;