UNPKG

@selfcommunity/react-core

Version:

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

201 lines (200 loc) • 9.44 kB
import { useEffect, useMemo, useState } from 'react'; import { Endpoints, http } from '@selfcommunity/api-services'; import { CacheStrategies, Logger, LRUCache } from '@selfcommunity/utils'; import { SCOPE_SC_CORE } from '../constants/Errors'; import { SCContributionType, } from '@selfcommunity/types'; import { getCommentObjectCacheKey, getFeedObjectCacheKey } from '../constants/Cache'; import { useSCContext } from '../components/provider/SCContextProvider'; import { useSCUser } from '../components/provider/SCUserProvider'; import { useSCVote } from '../components/provider/SCVoteProvider'; /** :::info This custom hook is used to fetch a contribution vote. ::: * @param object * @param object.id * @param object.contribution * @param object.contributionType * @param object.onVote * @param object.cacheStrategy */ export default function useSCFetchVote({ id, contribution = null, contributionType, onVote = null, cacheStrategy = CacheStrategies.CACHE_FIRST, }) { // MEMO const __contributionCacheKey = useMemo(() => (contributionType === SCContributionType.COMMENT ? getCommentObjectCacheKey(id) : getFeedObjectCacheKey(id, contributionType)), [id, contributionType]); const __endpoint = useMemo(() => (contributionType === SCContributionType.COMMENT ? Endpoints.Comment : Endpoints.FeedObject), [id, contributionType]); // STATE const [isLoading, setIsLoading] = useState(false); const [obj, setObj] = useState(cacheStrategy !== CacheStrategies.NETWORK_ONLY ? LRUCache.get(__contributionCacheKey, contribution) : contribution); const [isVoting, setIsVoting] = useState(false); const [voteListNext, setVoteListNext] = useState(Endpoints.VotesList.url({ type: contributionType, id })); const [voteList, setVoteList] = useState([]); const [isLoadingVoteList, setIsLoadingVoteList] = useState(false); const [error, setError] = useState(null); // HOOKS const scContext = useSCContext(); const scUserContext = useSCUser(); const scVoteContext = useSCVote(); const reactions = useMemo(() => { var _a; return { default: (_a = scVoteContext.reactions) === null || _a === void 0 ? void 0 : _a.find((reaction) => reaction.id === 1), reactions: scVoteContext.reactions, isLoading: scVoteContext.isLoading, }; }, [scVoteContext.reactions, scVoteContext.isLoading]); const fetchObject = useMemo(() => () => { setIsLoading(true); return http .request({ url: __endpoint.url({ type: contributionType, id: id }), method: __endpoint.method, }) .then((res) => { setIsLoading(false); if (res.status >= 300) { return Promise.reject(res); } return Promise.resolve(res.data); }); }, [id, contributionType]); const performVote = useMemo(() => (reaction) => { const params = {}; if (reaction && reactions.reactions) { params['reaction'] = reaction.id; } return http .request({ url: Endpoints.Vote.url({ type: obj.type, id: obj.id }), method: Endpoints.Vote.method, params, }) .then((res) => { if (res.status >= 300) { return Promise.reject(res); } return Promise.resolve(res.data); }); }, [obj, scContext]); // EFFECTS useEffect(() => { if (cacheStrategy !== CacheStrategies.CACHE_FIRST || !obj || (scUserContext.user && !Object.prototype.hasOwnProperty.call(obj, 'voted'))) { fetchObject() .then((obj) => { setObj(obj); LRUCache.set(__contributionCacheKey, obj); }) .catch((err) => { LRUCache.delete(__contributionCacheKey); setError(`FeedObject with id ${id} not found`); Logger.error(SCOPE_SC_CORE, `FeedObject with id ${id} not found`); Logger.error(SCOPE_SC_CORE, err.message); }); } }, [id, contributionType, scUserContext.user]); useEffect(() => { if (contribution) { setObj(contribution); } }, [contribution]); // HANDLERS const handleVote = (reaction) => { if (scUserContext.user && obj && !isVoting) { setIsVoting(true); performVote(reaction) .then(() => { var _a, _b; let _obj = { voted: !obj.voted, vote_count: obj.voted ? obj.vote_count - 1 : obj.vote_count + 1, }; if (reaction && ((_a = obj === null || obj === void 0 ? void 0 : obj.reaction) === null || _a === void 0 ? void 0 : _a.id) !== reaction.id) { // AGGUINTA / MODIFICA const add = !(obj === null || obj === void 0 ? void 0 : obj.reaction); const addCount = obj.reactions_count.findIndex((count) => count.reaction.id === reaction.id) === -1; _obj = { voted: add ? true : obj.voted, vote_count: add ? obj.vote_count + 1 : obj.vote_count, reaction, reactions_count: [ ...obj.reactions_count.map((count) => { var _a, _b; if (count.reaction.id === ((_a = obj === null || obj === void 0 ? void 0 : obj.reaction) === null || _a === void 0 ? void 0 : _a.id) && count.count - 1 === 0) { return null; } else if (count.reaction.id === ((_b = obj === null || obj === void 0 ? void 0 : obj.reaction) === null || _b === void 0 ? void 0 : _b.id) && count.count - 1 > 0) { return { count: count.count - 1, reaction: count.reaction }; } else if (count.reaction.id === reaction.id) { return { count: count.count + 1, reaction: count.reaction }; } return count; }), addCount ? { count: 1, reaction } : null, ].filter((count) => Boolean(count)), }; } else if (reaction && (obj === null || obj === void 0 ? void 0 : obj.reaction) && ((_b = obj === null || obj === void 0 ? void 0 : obj.reaction) === null || _b === void 0 ? void 0 : _b.id) === reaction.id) { // RIMOZIONE _obj = Object.assign({}, _obj, { reaction: null, reactions_count: obj.reactions_count .map((count) => { var _a, _b; if (count.reaction.id === ((_a = obj === null || obj === void 0 ? void 0 : obj.reaction) === null || _a === void 0 ? void 0 : _a.id) && count.count - 1 === 0) { return null; } else if (count.reaction.id === ((_b = obj === null || obj === void 0 ? void 0 : obj.reaction) === null || _b === void 0 ? void 0 : _b.id) && count.count - 1 > 0) { return { count: count.count - 1, reaction: count.reaction }; } return count; }) .filter((count) => Boolean(count)), }); } const newObj = Object.assign({}, obj, _obj); setObj(newObj); setIsVoting(false); onVote && onVote(newObj, null); }) .catch((error) => { Logger.error(SCOPE_SC_CORE, error); setIsVoting(false); onVote && onVote(obj, error); }); } }; const handleFetchVoteList = ({ reaction = null, reset = false }) => { const _url = reset ? `${Endpoints.VotesList.url({ type: contributionType, id, })}${reaction ? `?reaction=${reaction.id}` : ''}` : voteListNext; setIsLoadingVoteList(true); http .request({ url: _url, method: Endpoints.VotesList.method, }) .then((res) => { setVoteList(reset ? res.data.results : [...voteList, ...res.data.results]); setVoteListNext(res.data.next); }) .catch((error) => setError(error)) .then(() => setIsLoadingVoteList(false)); }; const data = useMemo(() => ({ contributionVoted: obj ? obj.voted : false, contributionVoteCount: obj ? obj.vote_count : 0, contributionReaction: obj ? obj.reaction : null, contributionReactionsCount: obj ? obj.reactions_count : null, }), [obj]); return Object.assign(Object.assign({}, data), { isLoading, isVoting, handleVote, reactions, error, handleFetchVoteList, voteList, isLoadingVoteList, voteListHasNext: Boolean(voteListNext) }); }