Fixes broken flow

This commit is contained in:
Nithin David Thomas
2024-02-15 00:23:16 +05:30
parent 54bd3c38d5
commit f598b6886f
8 changed files with 174 additions and 50 deletions
@@ -61,3 +61,7 @@ export default {
},
};
export const DEFAULT_REDIRECT_URL = '/app/';
export const ONBOARDING_STEP_NAMES = {
INVITE: 'invite_team',
};
@@ -0,0 +1,13 @@
export const getBrowserLocale = enabledLanguages => {
const localeWithVariant = window.navigator.language.replace('-', '_');
const localeWithoutVariant = localeWithVariant.split('_')[0];
return enabledLanguages.find(
lang =>
lang.iso_639_1_code === localeWithVariant ||
lang.iso_639_1_code === localeWithoutVariant
)?.iso_639_1_code;
};
export const getBrowserTimezone = () => {
return Intl.DateTimeFormat().resolvedOptions().timeZone;
};
@@ -0,0 +1,15 @@
export const findMatchingOption = (value, options, defaultValue) => {
const match = options.find(
option => option.value === value || option === value
);
return match ? match.value || match : defaultValue;
};
export const findCompanySizeMatch = (options, size) => {
return (
options.find(option => {
const upperLimit = option.value.split('-')[1]?.split('+')[0];
return size < (upperLimit ? Number(upperLimit) : Infinity);
})?.value || this.companySizeOptions[0].value
);
};
@@ -0,0 +1,43 @@
import { getBrowserLocale, getBrowserTimezone } from '../BrowserHelper';
describe('getBrowserLocale', () => {
it('should return the correct locale code when an exact match is found', () => {
// Mock window.navigator.language
Object.defineProperty(window.navigator, 'language', {
value: 'en-US',
configurable: true,
});
const languages = [{ iso_639_1_code: 'en' }, { iso_639_1_code: 'en-US' }];
expect(getBrowserLocale(languages)).toBe('en-US');
});
it('should return the correct locale code when only a partial match is found', () => {
Object.defineProperty(window.navigator, 'language', {
value: 'en-GB',
configurable: true,
});
const languages = [{ iso_639_1_code: 'en' }, { iso_639_1_code: 'fr' }];
expect(getBrowserLocale(languages)).toBe('en');
});
it('should return undefined when no match is found', () => {
Object.defineProperty(window.navigator, 'language', {
value: 'es-ES',
configurable: true,
});
const languages = [{ iso_639_1_code: 'en' }, { iso_639_1_code: 'fr' }];
expect(getBrowserLocale(languages)).toBeUndefined();
});
});
describe('getBrowserTimezone', () => {
it('should return the current browser timezone', () => {
// This test assumes the environment's timezone is set.
// It's a basic test as getBrowserTimezone relies on Intl API.
const timezone = getBrowserTimezone();
expect(timezone).toBe(Intl.DateTimeFormat().resolvedOptions().timeZone);
});
});
@@ -0,0 +1,35 @@
import { findMatchingOption, findCompanySizeMatch } from '../OnboardingHelper';
describe('findMatchingOption', () => {
const options = [{ value: 'option1' }, { value: 'option2' }];
it('should return the matching option', () => {
expect(findMatchingOption('option1', options, 'default')).toBe('option1');
});
it('should return the default value when no match is found', () => {
expect(findMatchingOption('nonExistingOption', options, 'default')).toBe(
'default'
);
});
});
describe('findCompanySizeMatch', () => {
const mockCompanySizeOptions = [
{ value: '1-10' },
{ value: '11-50' },
{ value: '51-500' },
{ value: '501-1000' },
{ value: '1001+' },
];
it('should return the correct company size range', () => {
const size = 25;
expect(findCompanySizeMatch(size, mockCompanySizeOptions)).toBe('11-50');
});
it('should return the first company size range when no match is found', () => {
const size = 1500;
expect(findCompanySizeMatch(size, mockCompanySizeOptions)).toBe('1-10');
});
});
+19 -4
View File
@@ -1,5 +1,5 @@
<template>
<div class="h-full w-full dark:bg-slate-900 relative">
<div class="flex h-full w-full dark:bg-slate-900 relative overflow-hidden">
<div
class="absolute inset-0 h-full w-full bg-white dark:bg-slate-900 bg-[radial-gradient(var(--w-100)_1px,transparent_1px)] dark:bg-[radial-gradient(var(--w-800)_1px,transparent_1px)] [background-size:16px_16px] z-0"
/>
@@ -13,6 +13,7 @@
viewBox="0 0 528 96"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="absolute -left-full -bottom-full"
>
<defs>
<mask id="cutoutMask">
@@ -24,9 +25,11 @@
</defs>
</svg>
<div class="flex h-full relative z-50">
<div
class="flex w-full h-full relative z-50 items-center justify-center overflow-auto"
>
<div
class="flex-1 min-h-[640px] inline-flex items-center h-full justify-center overflow-auto py-6"
class="flex-1 min-h-[640px] inline-flex items-center h-full justify-center py-6"
>
<div
class="relative bg-white dark:bg-slate-800 before:bg-white dark:before:bg-slate-800 px-16 pt-8 pb-16 max-w-[528px] w-full rounded-3xl signup-box"
@@ -85,7 +88,19 @@ export default {
},
};
</script>
<style>
<style scoped>
.overlay-gradient {
background: linear-gradient(90deg, rgba(252, 252, 253, 0) 81.8%, #fcfcfd 95%),
linear-gradient(270deg, rgba(252, 252, 253, 0) 76.93%, #fcfcfd 95%),
linear-gradient(0deg, rgba(252, 252, 253, 0) 68.63%, #fcfcfd 95%),
linear-gradient(180deg, rgba(252, 252, 253, 0) 73.2%, #fcfcfd 95%);
}
.dark .overlay-gradient {
background: linear-gradient(270deg, rgba(24, 24, 26, 0) 76.93%, #151718 95%),
linear-gradient(90deg, rgba(24, 24, 26, 0) 81.8%, #151718 95%),
linear-gradient(0deg, rgba(24, 24, 26, 0) 68.63%, #151718 95%),
linear-gradient(180deg, rgba(24, 24, 26, 0) 73.2%, #151718 95%);
}
.signup-box::before {
width: 100%;
height: 200px;
@@ -90,8 +90,14 @@ import FormRadioTags from 'v3/components/Form/RadioTags.vue';
import { required, minLength } from 'vuelidate/lib/validators';
import { mapGetters } from 'vuex';
import { ONBOARDING_STEP_NAMES } from 'dashboard/constants/globals';
import SubmitButton from 'dashboard/components/buttons/FormSubmitButton.vue';
import { timeZoneOptions } from 'dashboard/routes/dashboard/settings/inbox/helpers/businessHour.js';
import { getBrowserTimezone, getBrowserLocale } from 'v3/helpers/BrowserHelper';
import {
findMatchingOption,
findCompanySizeMatch,
} from 'v3/helpers/OnboardingHelper';
import alertMixin from 'shared/mixins/alertMixin';
import configMixin from 'shared/mixins/configMixin';
export default {
@@ -148,9 +154,12 @@ export default {
timeZones() {
return [...timeZoneOptions()];
},
intelligentData() {
const { clearbit_data: data } = this.getAccount;
return data;
hasIntelligentData() {
const {
custom_attributes: { onboarding_step: onboardingStep },
} = this.accountDetails;
return !onboardingStep !== ONBOARDING_STEP_NAMES.INVITE;
},
},
@@ -163,9 +172,6 @@ export default {
},
},
mounted() {
this.setLocaleFromBrowser();
this.setTimezone();
this.initFormData();
},
@@ -194,58 +200,47 @@ export default {
this.$root.$i18n.locale = locale;
},
setLocaleFromBrowser() {
const localeWithVariant = window.navigator.language.replace('-', '_');
const localeWithoutVariant = localeWithVariant.split('_')[0];
const { iso_639_1_code: locale } =
this.enabledLanguages.find(
lang =>
lang.iso_639_1_code === localeWithVariant ||
lang.iso_639_1_code === localeWithoutVariant
) || {};
const locale = getBrowserLocale(this.enabledLanguages);
if (locale) {
this.locale = locale;
this.setLocale(locale);
}
},
setTimezone() {
const browserTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
if (!this.intelligentData) {
this.timezone = browserTimezone;
return;
}
const { timezone } = this.intelligentData;
const allZones = this.timeZones.map(zone => zone.value);
const matchForIntelligentZone = allZones.find(zone => zone === timezone);
if (matchForIntelligentZone) {
this.timezone = timezone;
}
},
setFromIntelligentData() {
if (!this.intelligentData) return;
const { name: companyName, industry, size } = this.intelligentData;
this.companyName = companyName;
this.industry = industry;
this.companySize = size;
},
setSavedData() {
if (!this.accountDetails) return;
const {
name: companyName,
industry,
size,
locale,
timezone,
custom_attributes: {
industry,
company_size: companySize,
timezone,
} = {},
} = this.accountDetails;
this.companyName = companyName;
this.industry = industry;
this.companySize = size;
this.locale = locale;
this.timezone = timezone;
this.industry = findMatchingOption(
industry,
this.industryOptions,
'other'
);
this.companySize = findCompanySizeMatch(
this.companySizeOptions,
companySize
);
this.timezone = findMatchingOption(
timezone,
this.timeZones.map(zone => zone.value),
getBrowserTimezone()
);
this.locale = locale || this.setLocaleFromBrowser();
this.setLocale(locale);
},
initFormData() {
const { name } = this.accountDetails;
if (!name) {
if (this.hasIntelligentData) {
this.setFromIntelligentData();
} else {
this.setSavedData();
@@ -105,6 +105,7 @@
:label="$t('ONBOARDING.PROFILE.PHONE_NUMBER.LABEL')"
:placeholder="$t('ONBOARDING.PROFILE.PHONE_NUMBER.PLACEHOLDER')"
:error-message="$t('CONTACT_FORM.FORM.PHONE_NUMBER.ERROR')"
@blur="$v.phoneNumber.$touch"
/>
<form-text-area
v-model="signature"
@@ -168,7 +169,7 @@ export default {
},
phoneNumber: {
validOrNoPhone: value =>
!helpers.req(value) || parsePhoneNumber(value).isValid(),
!helpers.req(value) || parsePhoneNumber(value, 'US').isValid(),
},
},
computed: {
@@ -195,6 +196,7 @@ export default {
avatar_url: avatarUrl,
display_name: displayName,
message_signature: signature,
custom_attributes: { phone_number: phoneNumber } = {},
} = this.currentUser || {};
if (!fullName && this.intelligentData && this.intelligentData.name) {
@@ -202,6 +204,8 @@ export default {
} else {
this.fullName = fullName;
}
this.phoneNumber = phoneNumber;
this.displayName = displayName;
this.signature = signature;
this.avatarUrl =
@@ -219,7 +223,7 @@ export default {
}
try {
await this.$store.dispatch('updateProfile', {
name: this.name,
name: this.fullName,
displayName: this.displayName,
phone_number: this.phoneNumber,
avatar: this.avatarFile,