Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / shared / lib / user / storage.ts
blob6339d7709a52c3da42e34edf73b3cfbced25e34b
1 import { c } from 'ttag';
3 import { PLANS } from '@proton/payments';
5 import type { APP_NAMES } from '../constants';
6 import { APPS } from '../constants';
7 import { getHasMailB2BPlan, hasVisionary } from '../helpers/subscription';
8 import type { Subscription, User, UserModel } from '../interfaces';
10 export const getHasStorageSplit = (user: User) => {
11     return user.MaxBaseSpace !== undefined;
14 export const getUsedSpace = (user: User) => {
15     if (getHasStorageSplit(user)) {
16         return user.UsedBaseSpace + user.UsedDriveSpace;
17     }
18     return user.UsedSpace;
21 export const getSpace = (user: User) => {
22     const usedSpace = user.UsedSpace ?? 0;
23     const maxSpace = user.MaxSpace ?? 0;
25     if (!getHasStorageSplit(user)) {
26         const usedDriveSpace = user.ProductUsedSpace?.Drive ?? 0;
27         const usedBaseSpace = usedSpace - usedDriveSpace;
28         return {
29             usedSpace,
30             usedBaseSpace,
31             usedDriveSpace,
32             maxSpace,
33             maxBaseSpace: maxSpace,
34             maxDriveSpace: maxSpace,
35             splitStorage: false,
36         };
37     }
39     const usedDriveSpace = user.UsedDriveSpace ?? 0;
40     const usedBaseSpace = user.UsedBaseSpace ?? 0;
41     const maxDriveSpace = user.MaxDriveSpace ?? maxSpace ?? 0;
42     const maxBaseSpace = user.MaxBaseSpace ?? maxSpace ?? 0;
44     return {
45         usedSpace,
46         usedBaseSpace,
47         usedDriveSpace,
48         maxSpace,
49         maxBaseSpace,
50         maxDriveSpace,
51         splitStorage: true,
52     };
54 const getData = (used: number, max: number) => {
55     const percentage = (used * 100) / max;
56     const safePercentage = Number.isNaN(percentage) ? 0 : percentage;
57     const flooredPercentage = Math.floor(safePercentage);
58     return {
59         percentage: safePercentage,
60         displayed: flooredPercentage,
61     };
64 export enum SpaceState {
65     Good,
66     Warning,
67     Danger,
70 export const getSpaceDetails = (usedSpace: number, maxSpace: number) => {
71     const data = getData(usedSpace, maxSpace);
72     const danger = data.percentage >= 100;
73     const warning = data.percentage >= 80 && data.percentage < 100;
74     return {
75         type: danger ? SpaceState.Danger : warning ? SpaceState.Warning : SpaceState.Good,
76         ...data,
77     };
80 export const getCompleteSpaceDetails = (space: ReturnType<typeof getSpace>) => {
81     return {
82         pooled: getSpaceDetails(space.usedSpace, space.maxSpace),
83         base: getSpaceDetails(space.usedBaseSpace, space.maxBaseSpace),
84         drive: getSpaceDetails(space.usedDriveSpace, space.maxDriveSpace),
85     };
88 export const getAppSpace = (options: ReturnType<typeof getSpace>, app: APP_NAMES) => {
89     if (!options.splitStorage) {
90         return { usedSpace: options.usedSpace, maxSpace: options.maxSpace };
91     }
92     if (app === APPS.PROTONDRIVE) {
93         return { usedSpace: options.usedDriveSpace, maxSpace: options.maxDriveSpace };
94     }
95     return { usedSpace: options.usedBaseSpace, maxSpace: options.maxBaseSpace };
98 export const getCanAddStorage = ({ user, subscription }: { user: UserModel; subscription?: Subscription }) => {
99     if (!subscription) {
100         return false;
101     }
102     if (user.isSubUser) {
103         return false;
104     }
105     if (user.isMember) {
106         return false;
107     }
108     if (!user.canPay) {
109         return false;
110     }
111     if (hasVisionary(subscription) || getHasMailB2BPlan(subscription)) {
112         return false;
113     }
114     return true;
117 export const getAppStorage = (app: string) => {
118     // Translator: Your 'mail storage' or 'drive storage' is full
119     return c('storage_split: info').t`${app} storage`;
122 export const getAppStorageFull = (appStorage: string) => {
123     // Translator: Your 'mail storage' or 'drive storage' is full
124     return c('storage_split: info').t`Your ${appStorage} is full`;
127 export const getAppStorageAlmostFull = (appStorage: string) => {
128     return c('storage_split: info').t`Your ${appStorage} is almost full`;
131 export const getStorageFull = () => {
132     return c('storage_split: info').t`Your storage is full`;
135 export const getPercentageFull = (storage: string, percentage: number) => {
136     // Translator: Drive storage 99% full
137     return c('storage_split: info').t`${storage} ${percentage}% full`;
140 export const getPlanToUpsell = ({
141     storageDetails,
142     app,
143 }: {
144     storageDetails: ReturnType<typeof getCompleteSpaceDetails>;
145     app: APP_NAMES;
146 }) => {
147     if (app === APPS.PROTONDRIVE) {
148         return PLANS.DRIVE;
149     }
151     // Area of experimentation which plan to upsell to.
152     if (false) {
153         if (storageDetails.base.type === SpaceState.Danger && storageDetails.drive.type === SpaceState.Danger) {
154             return PLANS.BUNDLE;
155         }
156         if (storageDetails.base.type === SpaceState.Danger) {
157             return PLANS.MAIL;
158         }
159         if (storageDetails.drive.type === SpaceState.Danger) {
160             return PLANS.DRIVE;
161         }
162     }
164     return PLANS.MAIL;