// @flow import React from 'react'; import Button from 'component/button'; import ClaimList from 'component/claimList'; import ClaimPreviewTile from 'component/claimPreviewTile'; import I18nMessage from 'component/i18nMessage'; import * as ICONS from 'constants/icons'; import * as PAGES from 'constants/pages'; import { useIsLargeScreen, useIsMediumScreen } from 'effects/use-screensize'; // TODO: recsysFyp will be moved into 'RecSys', so the redux import in a jsx // violation is just temporary. import { recsysFyp } from 'redux/actions/search'; // **************************************************************************** // RecommendedPersonal // **************************************************************************** const VIEW = { ALL_VISIBLE: 0, COLLAPSED: 1, EXPANDED: 2 }; function getSuitablePageSizeForScreen(defaultSize, isLargeScreen, isMediumScreen) { return isMediumScreen ? 6 : isLargeScreen ? Math.ceil(defaultSize * (3 / 2)) : defaultSize; } type Props = { header: React$Node, onLoad: (displayed: boolean) => void, // --- redux --- userId: ?string, personalRecommendations: { gid: string, uris: Array, fetched: boolean }, hasMembership: ?boolean, doFetchPersonalRecommendations: () => void, }; export default function RecommendedPersonal(props: Props) { const { header, onLoad, userId, personalRecommendations, hasMembership, doFetchPersonalRecommendations } = props; const ref = React.useRef(); const [markedGid, setMarkedGid] = React.useState(''); const [view, setView] = React.useState(VIEW.ALL_VISIBLE); const isLargeScreen = useIsLargeScreen(); const isMediumScreen = useIsMediumScreen(); const count = personalRecommendations.uris.length; const countCollapsed = getSuitablePageSizeForScreen(8, isLargeScreen, isMediumScreen); const finalCount = view === VIEW.ALL_VISIBLE ? count : view === VIEW.COLLAPSED ? countCollapsed : count; // ************************************************************************** // Effects // ************************************************************************** React.useEffect(() => { // -- Update parent's callback request if (typeof onLoad === 'function') { onLoad(count > 0); } }, [count, onLoad]); React.useEffect(() => { // -- Resolve the view state: let newView; if (count <= countCollapsed) { newView = VIEW.ALL_VISIBLE; } else { if (view === VIEW.ALL_VISIBLE) { newView = VIEW.COLLAPSED; } } if (newView && newView !== view) { setView(newView); } }, [count, countCollapsed, view, setView]); React.useEffect(() => { // -- Mark recommendations when rendered: if (userId && markedGid !== personalRecommendations.gid) { setMarkedGid(personalRecommendations.gid); recsysFyp.markPersonalRecommendations(userId, personalRecommendations.gid); } }, [userId, markedGid, personalRecommendations.gid]); React.useEffect(() => { // -- Fetch FYP if (hasMembership) { doFetchPersonalRecommendations(); } }, [hasMembership, doFetchPersonalRecommendations]); // ************************************************************************** // ************************************************************************** if (hasMembership === undefined || !personalRecommendations.fetched) { return ( <> {header}
); } if (!hasMembership) { return (
{header}
}} > Premium membership required. Become a member, or %learn_more%.
); } if (count < 1) { return (
{header}
}} > No recommendations available at the moment. %learn_more%
); } return (
{header} {view !== VIEW.ALL_VISIBLE && (
)}
); }