UNPKG

@selfcommunity/react-core

Version:

React Core Components useful for integrating UI Community components (react-ui).

145 lines (143 loc) 5.54 kB
"use strict"; 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;