From a2c70742210b4fcfa74a058b2914867d63357f58 Mon Sep 17 00:00:00 2001 From: Melissa Autumn Date: Thu, 15 Aug 2024 12:23:05 -0700 Subject: [PATCH] Fix up the sign up button and add metrics --- frontend/src/definitions.ts | 5 ++ frontend/src/router.ts | 18 ++---- frontend/src/views/LoginView.vue | 59 ++++++++++++++++++-- frontend/src/views/WaitingListActionView.vue | 12 +++- 4 files changed, 73 insertions(+), 21 deletions(-) diff --git a/frontend/src/definitions.ts b/frontend/src/definitions.ts index adac7dae4..acc996208 100644 --- a/frontend/src/definitions.ts +++ b/frontend/src/definitions.ts @@ -333,6 +333,11 @@ export enum MetricEvents { RequestBooking = 'apmt.booking.request', ScheduleCreated = 'apmt.schedule.created', ScheduleUpdated = 'apmt.schedule.updated', + SignUp = 'apmt.signup', + SignUpAlreadyExists = 'apmt.signup.already-exists', + Login = 'apmt.login', + WaitingListEmailConfirmed = 'apmt.signup.email-confirmed', + WaitingListEmailRemoved = 'apmt.signup.email-removed', } export default { diff --git a/frontend/src/router.ts b/frontend/src/router.ts index ca2b76c12..2fcf918f5 100644 --- a/frontend/src/router.ts +++ b/frontend/src/router.ts @@ -25,7 +25,7 @@ const FirstTimeUserExperienceView = defineAsyncComponent(() => import('@/views/F type ApmtRouteMeta = { isPublic?: boolean; // Can the page be accessed without authentication? maskForMetrics?: boolean; // Mask url parameters before sending information to metrics - disableMetrics?: boolean; // Disable all metric capturing for this page + disableMetrics?: boolean; // Disable all metric capturing for this page. FIXME: Not Impl }; /** @@ -163,7 +163,7 @@ const routes: RouteRecordRaw[] = [ name: 'admin-subscriber-panel', component: SubscriberPanelView, meta: { - disableMetrics: true, + //disableMetrics: true, }, }, { @@ -171,7 +171,7 @@ const routes: RouteRecordRaw[] = [ name: 'admin-invite-codes-panel', component: InviteCodePanelView, meta: { - disableMetrics: true, + //disableMetrics: true, }, }, { @@ -179,7 +179,7 @@ const routes: RouteRecordRaw[] = [ name: 'admin-waiting-list-panel', component: WaitingListPanelView, meta: { - disableMetrics: true, + //disableMetrics: true, }, }, ]; @@ -194,16 +194,6 @@ router.beforeEach((to, from) => { const toMeta: ApmtRouteMeta = to?.meta ?? {}; const fromMeta: ApmtRouteMeta = from?.meta ?? {}; - if (usePosthog) { - // Handle disableMetrics meta property - if (toMeta?.disableMetrics && !fromMeta?.disableMetrics) { - posthog.opt_out_capturing(); - } - if (!toMeta?.disableMetrics && fromMeta?.disableMetrics) { - posthog.opt_in_capturing(); - } - } - if (!toMeta?.isPublic && !['setup', 'contact', 'undefined'].includes(String(to.name))) { const user = useUserStore(); if (user && user.data?.email && !user.data.isSetup) { diff --git a/frontend/src/views/LoginView.vue b/frontend/src/views/LoginView.vue index 8c78e4cb0..bfb1152b5 100644 --- a/frontend/src/views/LoginView.vue +++ b/frontend/src/views/LoginView.vue @@ -7,6 +7,8 @@ import { dayjsKey, callKey, isPasswordAuthKey, isFxaAuthKey } from "@/keys"; import { BooleanResponse, AuthUrlResponse, Exception, AuthUrl, Error } from "@/models"; import PrimaryButton from '@/elements/PrimaryButton.vue'; import AlertBox from '@/elements/AlertBox.vue'; +import {posthog, usePosthog} from "@/composables/posthog"; +import {MetricEvents} from "@/definitions"; // component constants const user = useUserStore(); @@ -19,8 +21,10 @@ const route = useRoute(); const router = useRouter(); const isPasswordAuth = inject(isPasswordAuthKey); const isFxaAuth = inject(isFxaAuthKey); -const onlyShowInvite = ref(false); +// Show the invite flow if they've failed to login const showInviteFlow = ref(false); +// Don't show the invite code field, only the "Join the waiting list" part +const onlyShowJoin = ref(false); const isLoading = ref(false); // form input and error @@ -33,7 +37,7 @@ const showConfirmEmailScreen = ref(false); onMounted(() => { if (route.name === 'join-the-waiting-list') { showInviteFlow.value = true; - onlyShowInvite.value = true; + onlyShowJoin.value = true; } }); @@ -45,7 +49,30 @@ const goHome = () => { router.push('/'); }; +/** + * What to do when hitting the enter key on a particular input + * @param isEmailField - Is this the email field? Only needed for password auth + */ +const onEnter = (isEmailField: boolean) => { + if (isEmailField && !isFxaAuth) { + return; + } + + if (showInviteFlow.value && onlyShowJoin.value) { + signUp(); + } else { + login(); + } +} + +/** + * Sign up for the beta / waiting list + */ const signUp = async () => { + if (!email.value) { + return; + } + isLoading.value = true; loginError.value = ''; const { data }: BooleanResponse = await call('waiting-list/join').post({ @@ -54,8 +81,22 @@ const signUp = async () => { if (!data.value) { loginError.value = t('waitingList.signUpAlreadyExists'); + + if (usePosthog) { + posthog.capture(MetricEvents.SignUpAlreadyExists, { + waitingList: true, + for: 'beta', + }); + } } else { showConfirmEmailScreen.value = true; + + if (usePosthog) { + posthog.capture(MetricEvents.SignUp, { + waitingList: true, + for: 'beta', + }); + } } isLoading.value = false; @@ -108,6 +149,12 @@ const login = async () => { return; } + if (usePosthog) { + posthog.capture(MetricEvents.Login, { + inviteCodeUsed: !!inviteCode.value, + }); + } + const { url } = data.value as AuthUrl; window.location.href = url; @@ -159,10 +206,10 @@ const login = async () => { type="email" class="mr-6 w-full rounded-md" :class="{'mr-4': isFxaAuth}" - @keydown.enter="isFxaAuth ? login() : null" + @keydown.enter="onEnter(true)" /> - diff --git a/frontend/src/views/WaitingListActionView.vue b/frontend/src/views/WaitingListActionView.vue index 03bf07b59..9ca24a004 100644 --- a/frontend/src/views/WaitingListActionView.vue +++ b/frontend/src/views/WaitingListActionView.vue @@ -1,7 +1,7 @@