@selfcommunity/react-core
Version:
React Core Components useful for integrating UI Community components (react-ui).
201 lines (200 loc) • 9.44 kB
JavaScript
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) });
}