@selfcommunity/react-core
Version:
React Core Components useful for integrating UI Community components (react-ui).
145 lines (143 loc) • 5.54 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const react_1 = require("react");
const api_services_1 = require("@selfcommunity/api-services");
const useSCCachingManager_1 = tslib_1.__importDefault(require("./useSCCachingManager"));
const Errors_1 = require("../constants/Errors");
const utils_1 = require("@selfcommunity/utils");
/**
:::info
This custom hook is used to manage the categories followed.
:::
:::tip How to use it:
Follow these steps:
```jsx
1. const scUserContext: SCUserContextType = useSCUser();
2. const scFollowedCategoriesManager: SCFollowedCategoriesManagerType = scUserContext.manager.categories;
3. scFollowedCategoriesManager.isFollowed(category)
```
:::
*/
function useSCFollowedCategoriesManager(user, updateUser) {
const { cache, updateCache, emptyCache, data, setData, loading, setLoading, setUnLoading, isLoading } = (0, useSCCachingManager_1.default)();
const authUserId = user ? user.id : null;
/**
* Memoized refresh all categories
* It makes a single request to the server and retrieves
* all the categories followed by the user in a single solution
* It might be useful for multi-tab sync
*/
const refresh = (0, react_1.useMemo)(() => () => {
emptyCache();
if (user) {
// Only if user is authenticated
api_services_1.http
.request({
url: api_services_1.Endpoints.FollowedCategories.url({ id: user.id }),
method: api_services_1.Endpoints.FollowedCategories.method,
})
.then((res) => {
if (res.status >= 300) {
return Promise.reject(res);
}
const categoryIds = res.data.map((c) => c.id);
updateCache(categoryIds);
setData(categoryIds);
return Promise.resolve(res.data);
})
.catch((e) => {
utils_1.Logger.error(Errors_1.SCOPE_SC_CORE, 'Unable to refresh categories followed by the authenticated user.');
utils_1.Logger.error(Errors_1.SCOPE_SC_CORE, e);
});
}
}, [data, user, cache]);
/**
* Memoized follow/unfollow Category
* Toggle action
*/
const follow = (0, react_1.useMemo)(() => (category) => {
setLoading(category.id);
return api_services_1.http
.request({
url: api_services_1.Endpoints.FollowCategory.url({ id: category.id }),
method: api_services_1.Endpoints.FollowCategory.method,
})
.then((res) => {
if (res.status >= 300) {
return Promise.reject(res);
}
updateCache([category.id]);
const isFollowed = data.includes(category.id);
setData((prev) => (isFollowed ? prev.filter((id) => id !== category.id) : [...[category.id], ...prev]));
setUnLoading(category.id);
updateUser({ categories_counter: isFollowed ? data.length - 1 : data.length + 1 });
return Promise.resolve(res.data);
});
}, [data, loading, cache]);
/**
* Check if the user follow the category
* Update the categories cached
* Update categories followed
* @param category
*/
const checkIsCategoryFollowed = (category) => {
setLoading(category.id);
api_services_1.http
.request({
url: api_services_1.Endpoints.CheckCategoryIsFollowed.url({ id: category.id }),
method: api_services_1.Endpoints.CheckCategoryIsFollowed.method,
})
.then((res) => {
if (res.status >= 300) {
return Promise.reject(res);
}
updateCache([category.id]);
setData((prev) => (res.data.is_followed ? [...[category.id], ...prev] : prev.filter((id) => id !== category.id)));
setUnLoading(category.id);
return Promise.resolve(res.data);
});
};
/**
* Bypass remote check if the category is followed
*/
const getFollowStatus = (0, react_1.useMemo)(() => (category) => {
const isFollowed = category.followed || false;
updateCache([category.id]);
setData((prev) => (isFollowed ? [...prev, ...[category.id]] : prev));
return isFollowed;
}, [data, cache]);
/**
* Memoized isFollowed
* If category is already in cache -> check if the category is in categories,
* otherwise, check if user follow the category
*/
const isFollowed = (0, react_1.useMemo)(() => (category) => {
// Cache is valid also for anonymous user
if (cache.includes(category.id)) {
return Boolean(data.includes(category.id));
}
if (authUserId) {
if ('followed' in category) {
return getFollowStatus(category);
}
if (!isLoading(category)) {
checkIsCategoryFollowed(category);
}
}
return false;
}, [data, loading, cache, authUserId]);
/**
* Empty cache on logout
*/
(0, react_1.useEffect)(() => {
if (!authUserId) {
emptyCache();
}
}, [authUserId]);
if (!user) {
return { categories: data, loading, isLoading };
}
return { categories: data, loading, isLoading, follow, isFollowed, refresh, emptyCache };
}
exports.default = useSCFollowedCategoriesManager;
;