Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / packages / components / hooks / useGetVtimezonesMap.ts
blob44a9205688d7efffad875ca5dec39d659eed4020
1 import { useCallback } from 'react';
3 import { getVtimezones } from '@proton/shared/lib/api/calendars';
4 import { parse } from '@proton/shared/lib/calendar/vcal';
5 import { GET_VTIMEZONES_API_LIMIT } from '@proton/shared/lib/constants';
6 import type { VcalVtimezoneComponent } from '@proton/shared/lib/interfaces/calendar';
7 import type { GetVTimezonesMap, VTimezoneObject } from '@proton/shared/lib/interfaces/hooks/GetVTimezonesMap';
8 import type { SimpleMap } from '@proton/shared/lib/interfaces/utils';
9 import chunk from '@proton/utils/chunk';
10 import unique from '@proton/utils/unique';
12 import useApi from './useApi';
13 import useCache from './useCache';
14 import { getIsRecordInvalid, getPromiseValue } from './useCachedModelResult';
16 const CACHE_KEY = 'VTIMEZONES';
18 export const useGetVtimezonesMap = () => {
19     const api = useApi();
20     const cache = useCache();
22     const getVTimezonesMap = useCallback(
23         async (tzids: string[]): Promise<SimpleMap<VTimezoneObject>> => {
24             const uniqueTzids = unique(tzids.filter((tzid) => tzid.toLowerCase() !== 'utc'));
25             const encodedTzids = uniqueTzids.map((tzid) => encodeURIComponent(tzid));
27             if (!uniqueTzids.length) {
28                 return Promise.resolve({});
29             }
31             const batchedTimezones = chunk(encodedTzids, GET_VTIMEZONES_API_LIMIT);
33             return (
34                 await Promise.all(
35                     batchedTimezones.map(async (batch) => {
36                         const { Timezones = {} } = await api<{ Timezones: SimpleMap<string> }>(getVtimezones(batch));
38                         return tzids.reduce<SimpleMap<VTimezoneObject>>((acc, tzid) => {
39                             const vtimezoneString = Timezones[tzid];
41                             if (vtimezoneString) {
42                                 acc[tzid] = {
43                                     vtimezoneString,
44                                     vtimezone: parse(vtimezoneString) as VcalVtimezoneComponent,
45                                 };
46                             }
48                             return acc;
49                         }, {});
50                     })
51                 )
52             ).reduce<SimpleMap<VTimezoneObject>>((acc, curr) => ({ ...acc, ...curr }), {});
53         },
54         [api, cache]
55     );
57     return useCallback<GetVTimezonesMap>(
58         (tzids: string[]) => {
59             if (!cache.has(CACHE_KEY)) {
60                 cache.set(CACHE_KEY, new Map());
61             }
62             const subCache = cache.get(CACHE_KEY);
63             const missing = tzids.filter((tzid) => {
64                 return getIsRecordInvalid(subCache.get(tzid));
65             });
66             const promise = getVTimezonesMap(missing);
67             const miss = async (tzid: string) => {
68                 const map = await promise;
69                 return map[tzid];
70             };
71             return Promise.all(
72                 tzids.map(async (tzid) => {
73                     const result = await getPromiseValue(subCache, tzid, miss);
74                     return {
75                         tzid,
76                         result: result as VTimezoneObject,
77                     };
78                 })
79             ).then((result) => {
80                 return result.reduce<SimpleMap<VTimezoneObject>>((acc, { tzid, result }) => {
81                     acc[tzid] = result;
82                     return acc;
83                 }, {});
84             });
85         },
86         [cache, getVTimezonesMap]
87     );