@selfcommunity/react-core
Version:
React Core Components useful for integrating UI Community components (react-ui).
139 lines (137 loc) • 5.13 kB
JavaScript
import { useEffect, useMemo } from 'react';
import { http, Endpoints } from '@selfcommunity/api-services';
import { Logger } from '@selfcommunity/utils';
import { SCOPE_SC_CORE } from '../constants/Errors';
import useSCCachingManager from './useSCCachingManager';
/**
:::info
This custom hook is used to manage to manage subscribed incubators.
:::
:::tip How to use it:
Follow these steps:
```jsx
1. const scUserContext: SCUserContextType = useSCUser();
2. const scSubscribedIncubatorsManager: SCSubscribedIncubatorsManagerType = scUserContext.managers.incubators;
3. scSubscribedIncubatorsManager.isSubscribed(incubator)
```
:::
*/
export default function useSCSubscribedIncubatorsManager(user) {
const { cache, updateCache, emptyCache, data, setData, loading, setLoading, setUnLoading, isLoading } = useSCCachingManager();
const authUserId = user ? user.id : null;
/**
* Memoized refresh all subscribed
* It makes a single request to the server and retrieves
* all the incubators subscribed by the authenticated user in a single solution
* It might be useful for multi-tab sync
*/
const refresh = useMemo(() => () => {
emptyCache();
if (user) {
// Only if user is authenticated
http
.request({
url: Endpoints.GetAllIncubators.url({}),
method: Endpoints.GetAllIncubators.method,
})
.then((res) => {
if (res.status >= 300) {
return Promise.reject(res);
}
const incubatorIds = res.data.results.map((i) => i.id);
updateCache(incubatorIds);
setData(incubatorIds);
return Promise.resolve(res.data);
})
.catch((e) => {
Logger.error(SCOPE_SC_CORE, 'Unable to refresh incubators subscribed by the authenticated user.');
Logger.error(SCOPE_SC_CORE, e);
});
}
}, [data, user, cache]);
/**
* Memoized subscribe/unsubscribe incubator
* Toggle action
*/
const subscribe = useMemo(() => (incubator) => {
setLoading(incubator.id);
return http
.request({
url: Endpoints.SubscribeToIncubator.url({ id: incubator.id }),
method: Endpoints.SubscribeToIncubator.method,
})
.then((res) => {
if (res.status >= 300) {
return Promise.reject(res);
}
updateCache([incubator.id]);
const isSubscribed = data.includes(incubator.id);
setData((prev) => (isSubscribed ? prev.filter((id) => id !== incubator.id) : [...[incubator.id], ...prev]));
setUnLoading(incubator.id);
return Promise.resolve(res.data);
});
}, [data, loading, cache]);
/**
* Check if the authenticated user has subscribed the incubator
* Update the subscribed cached
* Update subscribed incubators
* @param incubator
*/
const checkIsIncubatorFollowed = (incubator) => {
setLoading(incubator.id);
http
.request({
url: Endpoints.CheckIncubatorSubscription.url({ id: incubator.id }),
method: Endpoints.CheckIncubatorSubscription.method,
})
.then((res) => {
if (res.status >= 300) {
return Promise.reject(res);
}
updateCache([incubator.id]);
setData((prev) => (res.data.subscribed ? [...prev, ...[incubator.id]] : prev.filter((id) => id !== incubator.id)));
setUnLoading(incubator.id);
return Promise.resolve(res.data);
});
};
/**
* Bypass remote check if the incubator is subscribed
*/
const getSubscriptionStatus = useMemo(() => (incubator) => {
const isSubscribed = incubator.subscribed || false;
updateCache([incubator.id]);
setData((prev) => (isSubscribed ? [...prev, ...[incubator.id]] : prev));
return isSubscribed;
}, [data, cache]);
/**
* Memoized isSubscribed
* If incubator is already in cache -> check if the incubator is in subscribed,
* otherwise, check if auth user is subscribed to the incubator
*/
const isSubscribed = useMemo(() => (incubator) => {
if (cache.includes(incubator.id)) {
return Boolean(data.includes(incubator.id));
}
if (authUserId) {
if ('subscribed' in incubator) {
return getSubscriptionStatus(incubator);
}
if (!isLoading(incubator)) {
checkIsIncubatorFollowed(incubator);
}
}
return false;
}, [data, loading, cache, authUserId]);
/**
* Empty cache on logout
*/
useEffect(() => {
if (!authUserId) {
emptyCache();
}
}, [authUserId]);
if (!user) {
return { incubators: data, loading, isLoading };
}
return { incubators: data, loading, isLoading, subscribe, isSubscribed, refresh, emptyCache };
}