Fixes broken flow
This commit is contained in:
@@ -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');
|
||||
});
|
||||
});
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user