Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/app/i18n/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,11 @@
"shared": "Geteilt",
"recents": "Neueste",
"trash": "Papierkorb",
"desktop": "Desktop"
"desktop": "Desktop",
"referralBanner": {
"message": "Denk daran! Verdiene bis zu 1.000 €, indem du einen Freund empfiehlst",
"cta": "Empfehlen und verdienen"
}
},
"views": {
"recents": {
Expand Down Expand Up @@ -396,6 +400,8 @@
"downloadApp": "Download App",
"settings": "Einstellungen",
"logout": "Log-out",
"referAndEarn": "Empfehlen und verdienen",
"earnReferral": "Verdiene 1.000 €",
"spaceUsed": "{{space}}% Platz verbraucht"
},
"tabs": {
Expand Down
8 changes: 7 additions & 1 deletion src/app/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,11 @@
"shared": "Shared",
"recents": "Recents",
"trash": "Trash",
"desktop": "Desktop"
"desktop": "Desktop",
"referralBanner": {
"message": "Remember! Earn up to €1,000 by refering a friend",
"cta": "Refer and Earn"
}
},
"views": {
"recents": {
Expand Down Expand Up @@ -456,6 +460,8 @@
"downloadApp": "Download app",
"settings": "Settings",
"logout": "Log out",
"referAndEarn": "Refer and Earn",
"earnReferral": "Earn €1,000",
"spaceUsed": "{{space}}% space used"
},
"tabs": {
Expand Down
8 changes: 7 additions & 1 deletion src/app/i18n/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,11 @@
"shared": "Compartido",
"recents": "Recientes",
"trash": "Papelera",
"desktop": "Escritorio"
"desktop": "Escritorio",
"referralBanner": {
"message": "¡Recuerda! Gana hasta 1.000 € recomendando a un amigo",
"cta": "Recomienda y gana"
}
},
"views": {
"recents": {
Expand Down Expand Up @@ -439,6 +443,8 @@
"downloadApp": "Descargar app",
"settings": "Ajustes",
"logout": "Cerrar sesión",
"referAndEarn": "Recomienda y gana",
"earnReferral": "Gana 1.000 €",
"spaceUsed": "{{space}}% espacio usado"
},
"tabs": {
Expand Down
8 changes: 7 additions & 1 deletion src/app/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,11 @@
"shared": "Partagé",
"recents": "Récent",
"trash": "Corbeille",
"desktop": "App de bureau"
"desktop": "App de bureau",
"referralBanner": {
"message": "N'oubliez pas ! Gagnez jusqu'à 1 000 € en parrainant un ami",
"cta": "Parrainez et gagnez"
}
},
"views": {
"recents": {
Expand Down Expand Up @@ -408,6 +412,8 @@
"downloadApp": "Télécharger l'app",
"settings": "Paramètres",
"logout": "Déconnexion",
"referAndEarn": "Parrainez et gagnez",
"earnReferral": "Gagnez 1 000 €",
"spaceUsed": "{{space}}% d'espace utilisé"
},
"tabs": {
Expand Down
8 changes: 7 additions & 1 deletion src/app/i18n/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,11 @@
"shared": "Condiviso",
"recents": "Recenti",
"trash": "Cestino",
"desktop": "Applicazione desktop"
"desktop": "Applicazione desktop",
"referralBanner": {
"message": "Ricorda! Guadagna fino a 1.000 € invitando un amico",
"cta": "Invita e guadagna"
}
},
"views": {
"recents": {
Expand Down Expand Up @@ -499,6 +503,8 @@
"downloadApp": "Scarica l'app",
"settings": "Impostazioni",
"logout": "Disconnettersi",
"referAndEarn": "Invita e guadagna",
"earnReferral": "Guadagna 1.000 €",
"spaceUsed": "{{space}}% spazio usato"
},
"tabs": {
Expand Down
8 changes: 7 additions & 1 deletion src/app/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,11 @@
"shared": "Общий",
"recents": "Недавние",
"trash": "Корзина",
"desktop": "Рабочий стол"
"desktop": "Рабочий стол",
"referralBanner": {
"message": "Помните! Заработайте до 1 000 €, пригласив друга",
"cta": "Приглашайте и зарабатывайте"
}
},
"views": {
"recents": {
Expand Down Expand Up @@ -408,6 +412,8 @@
"downloadApp": "Рабочий стол",
"settings": "Настройки",
"logout": "Выйти",
"referAndEarn": "Приглашайте и зарабатывайте",
"earnReferral": "Заработайте 1 000 €",
"spaceUsed": "{{space}}% памяти использовано"
},
"tabs": {
Expand Down
8 changes: 7 additions & 1 deletion src/app/i18n/locales/tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,11 @@
"shared": "共享",
"recents": "最近",
"trash": "垃圾桶",
"desktop": "桌面"
"desktop": "桌面",
"referralBanner": {
"message": "別忘了!推薦朋友最高可賺取 €1,000",
"cta": "推薦賺取"
}
},
"views": {
"recents": {
Expand Down Expand Up @@ -424,6 +428,8 @@
"downloadApp": "下載應用程式",
"settings": "設定",
"logout": "登出",
"referAndEarn": "推薦賺取",
"earnReferral": "賺取 €1,000",
"spaceUsed": "已使用 {{space}}% 的空間"
},
"tabs": {
Expand Down
8 changes: 7 additions & 1 deletion src/app/i18n/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,11 @@
"shared": "共享的",
"recents": "最近",
"trash": "垃圾箱",
"desktop": "桌面应用程序"
"desktop": "桌面应用程序",
"referralBanner": {
"message": "别忘了!推荐朋友最高可赚取 €1,000",
"cta": "推荐赚取"
}
},
"views": {
"recents": {
Expand Down Expand Up @@ -422,6 +426,8 @@
"downloadApp": "桌面应用程序",
"settings": "设置",
"logout": "登出",
"referAndEarn": "推荐赚取",
"earnReferral": "赚取 €1,000",
"spaceUsed": "已使用储存空间的{{space}}%"
},
"tabs": {
Expand Down
2 changes: 2 additions & 0 deletions src/services/env.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ const variableList = {
vpnId: 'REACT_APP_VPN_ID',
impactApiUrl: 'REACT_APP_IMPACT_API',
dontRedirect: 'REACT_APP_DONT_REDIRECT',
celloProductId: 'REACT_APP_CELLO_PRODUCT_ID',
celloAssetsUrl: 'REACT_APP_CELLO_ASSETS_URL',
};

function getVariable(variable: keyof typeof variableList): string {
Expand Down
129 changes: 129 additions & 0 deletions src/services/referral.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import localStorageService from './local-storage.service';
import envService from './env.service';
import { SdkFactory } from 'app/core/factory/sdk';
import { loadExternalScript } from 'utils/loadExternalScript';

interface ReferralUser {
name: string;
lastname: string;
email: string;
}

interface ReferralBootOptions {
productId: string;
token: string;
language?: string;
productUserDetails: {
firstName: string;
lastName?: string;
fullName?: string;
email: string;
};
hideDefaultLauncher?: boolean;
themeMode?: 'light' | 'dark';
}

declare global {
interface Window {
cello?: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmd: Array<(cello: { boot: (options: ReferralBootOptions) => Promise<void> }) => void>;
};
Cello?: (command: string, ...args: unknown[]) => Promise<unknown>;
}
}

const UCC_STORAGE_KEY = 'cello_ucc';

let booted = false;

const fetchReferralToken = async (): Promise<string> => {
const referralsClient = SdkFactory.getNewApiInstance().createReferralsClient();
const { token } = await referralsClient.createReferralToken();
return token;
};

const buildReferralConfig = (
user: ReferralUser,
token: string,
productId: string,
language?: string,
): ReferralBootOptions => ({
productId,
token,
language: language ?? 'en',
productUserDetails: {
firstName: user.name,
lastName: user.lastname,
fullName: `${user.name} ${user.lastname}`.trim(),
email: user.email,
},
hideDefaultLauncher: true,
});

const initializeSdk = (options: ReferralBootOptions): Promise<void> => {
globalThis.cello = globalThis.cello || { cmd: [] };

return new Promise<void>((resolve, reject) => {
globalThis.cello!.cmd.push(async (cello) => {
try {
await cello.boot(options);
booted = true;
resolve();
} catch (error) {
reject(error);
}
});
});
};

const loadAndBoot = async (user: ReferralUser, language?: string): Promise<void> => {
if (booted) return;

const assetsUrl = envService.getVariable('celloAssetsUrl');
await loadExternalScript(`${assetsUrl}/app/latest/cello.js`);

const productId = envService.getVariable('celloProductId');
if (!productId) {
console.error('Referral product ID is not configured');
return;
}

const token = await fetchReferralToken();
const options = buildReferralConfig(user, token, productId, language);
await initializeSdk(options);
};

const openPanel = async (user: ReferralUser, language?: string): Promise<void> => {
if (!booted) {
await loadAndBoot(user, language);
}
if (!globalThis.Cello) {
console.error('Referral is not initialized');
return;
}
await globalThis.Cello('open');
};

const captureUccFromUrl = (): string | null => {
const params = new URLSearchParams(globalThis.location.search);
const uccFromUrl = params.get('ucc');

if (uccFromUrl) {
localStorageService.set(UCC_STORAGE_KEY, uccFromUrl);
return uccFromUrl;
}

return localStorageService.get(UCC_STORAGE_KEY) ?? null;
};

const getStoredUcc = (): string | null => {
return localStorageService.get(UCC_STORAGE_KEY) ?? null;
};

const referralService = {
openPanel,
captureUccFromUrl,
getStoredUcc,
};

export default referralService;
11 changes: 11 additions & 0 deletions src/utils/loadExternalScript.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const loadExternalScript = (src: string): Promise<void> => {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.type = 'module';
script.src = src;
script.async = true;
script.onload = () => resolve();
script.onerror = () => reject(new Error(`Failed to load script: ${src}`));
document.head.appendChild(script);
});
};
2 changes: 2 additions & 0 deletions src/views/Checkout/services/checkout.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const createCustomer = async ({
postalCode,
captchaToken,
companyVatId,
metadata,
}: CreateCustomerPayload): Promise<{
customerId: string;
token: string;
Expand All @@ -63,6 +64,7 @@ const createCustomer = async ({
postalCode,
captchaToken,
companyVatId,
metadata,
});
};

Expand Down
15 changes: 14 additions & 1 deletion src/views/Checkout/views/CheckoutViewWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import longNotificationsService from 'app/notifications/services/longNotification.service';
import notificationsService, { ToastType } from 'app/notifications/services/notifications.service';
import { paymentService, checkoutService } from 'views/Checkout/services';
import { RootState } from 'app/store';
import { RootState, store } from 'app/store';
import { useAppDispatch, useAppSelector } from 'app/store/hooks';
import { planThunks } from 'app/store/slices/plan';
import { useThemeContext } from 'app/theme/ThemeProvider';
Expand All @@ -30,6 +30,7 @@
import { useActionDialog } from 'app/contexts/dialog-manager/useActionDialog';
import { generateCaptchaToken } from 'utils/generateCaptchaToken';
import gaService from 'app/analytics/ga.service';
import referralService from 'services/referral.service';
import metaService from 'app/analytics/meta.service';
import { useCheckoutQueryParams } from '../hooks/useCheckoutQueryParams';
import { useInitializeCheckout } from '../hooks/useInitializeCheckout';
Expand Down Expand Up @@ -127,6 +128,7 @@
document.cookie = `gclid=${gclid}; expires=${expiryDate.toUTCString()}; path=/`;
localStorageService.set(STORAGE_KEYS.GCLID, gclid);
}
referralService.captureUccFromUrl();
}, []);

useEffect(() => {
Expand Down Expand Up @@ -265,7 +267,7 @@
event: BaseSyntheticEvent<object, any, any> | undefined,
stripeSDK: Stripe | null,
elements: StripeElements | null,
) => {

Check failure on line 270 in src/views/Checkout/views/CheckoutViewWrapper.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 17 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=internxt_drive-web&issues=AZzlyLrctUTrntRZmEtF&open=AZzlyLrctUTrntRZmEtF&pullRequest=1887
event?.preventDefault();

if (!selectedPlan?.price?.id) {
Expand Down Expand Up @@ -316,6 +318,16 @@
}

const customerToken = await generateCaptchaToken();
const ucc = referralService.getStoredUcc();
const currentUser = store.getState().user.user;
const hasMetadata = ucc || currentUser?.uuid;
const metadata = hasMetadata
? {
...(ucc && { cello_ucc: ucc }),
...(currentUser?.uuid && { new_user_id: currentUser.uuid }),
}
: undefined;

const { customerId, token } = await checkoutService.createCustomer({
customerName,
lineAddress1: address?.line1,
Expand All @@ -325,6 +337,7 @@
city: address?.city,
companyVatId,
captchaToken: customerToken,
metadata,
});

if (paramMobileToken) {
Expand Down
Loading
Loading