UNPKG

@selfcommunity/react-ui

Version:

React UI Components to integrate a Community created with SelfCommunity Platform.

145 lines (144 loc) • 7.09 kB
import { __rest } from "tslib"; import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import { Button, CardActions, CardContent, Typography, useTheme, useThemeProps } from '@mui/material'; import { styled } from '@mui/system'; import { Endpoints, http, SuggestionService } from '@selfcommunity/api-services'; import { Link, SCRoutes, useSCRouting } from '@selfcommunity/react-core'; import { Logger } from '@selfcommunity/utils'; import classNames from 'classnames'; import { useCallback, useEffect, useRef, useState } from 'react'; import { FormattedMessage } from 'react-intl'; import { Swiper, SwiperSlide } from 'swiper/react'; import { SCOPE_SC_UI } from '../../constants/Errors'; import { DEFAULT_PAGINATION_OFFSET } from '../../constants/Pagination'; import HiddenPlaceholder from '../../shared/HiddenPlaceholder'; import { SCEventTemplateType } from '../../types/event'; import Event from '../Event'; import Widget from '../Widget'; import Arrow from './Arrow'; import { PREFIX } from './constants'; import Skeleton from './Skeleton'; import PubSub from 'pubsub-js'; import { SCGroupEventType, SCTopicType } from '../../constants/PubSub'; const classes = { root: `${PREFIX}-root`, content: `${PREFIX}-content`, title: `${PREFIX}-title`, swiper: `${PREFIX}-swiper`, swiperSlide: `${PREFIX}-swiper-slide`, swiperArrow: `${PREFIX}-swiper-arrow`, swiperPrevArrow: `${PREFIX}-swiper-prev-arrow`, swiperNextArrow: `${PREFIX}-swiper-next-arrow`, event: `${PREFIX}-event`, actions: `${PREFIX}-actions`, actionButton: `${PREFIX}-action-button` }; const Root = styled(Widget, { name: PREFIX, slot: 'Root', overridesResolver: (_props, styles) => styles.root })(() => ({})); export default function SuggestedEventsWidget(inProps) { // PROPS const props = useThemeProps({ props: inProps, name: PREFIX }); const { endpointQueryParams = { limit: 3, offset: DEFAULT_PAGINATION_OFFSET } } = props, rest = __rest(props, ["endpointQueryParams"]); // STATE const [count, setCount] = useState(null); const [next, setNext] = useState(null); const [events, setEvents] = useState(null); const [loading, setLoading] = useState(true); const [showSkeleton, setShowSkeleton] = useState(false); const [currentItem, setCurrentItem] = useState(0); const [hideMarginLeft, setHideMarginLeft] = useState(false); const [hideMarginRight, setHideMarginRight] = useState(true); // CONTEXT const scRoutingContext = useSCRouting(); //HOOKS const theme = useTheme(); // REFS const updatesSubscription = useRef(null); useEffect(() => { SuggestionService.getEventSuggestion(Object.assign({}, endpointQueryParams)) .then((payload) => { setCount(payload.count); setNext(payload.next); setEvents(payload.results); setLoading(false); }) .catch((error) => { Logger.error(SCOPE_SC_UI, error); }); }, []); const handleReachBeginning = useCallback(() => { setHideMarginLeft(false); }, []); const handleReachEnd = useCallback(() => { if (count > events.length && next) { setShowSkeleton(true); http .request({ url: next, method: Endpoints.GetEventSuggestedUsers.method }) .then((res) => { setCount(res.data.count); setNext(res.data.next); setEvents((prevEvents) => [...prevEvents, ...res.data.results]); setShowSkeleton(false); }) .catch((error) => { Logger.error(SCOPE_SC_UI, error); }); } else { setHideMarginRight(false); } }, [count, events, next]); const handleChange = useCallback((swiper) => { setCurrentItem(swiper.snapIndex); if (swiper.snapIndex > 0 && swiper.snapIndex < count) { if (!hideMarginLeft) { setHideMarginLeft(true); } if (!hideMarginRight) { setHideMarginRight(true); } } }, [count, hideMarginLeft, hideMarginRight]); /** * Subscriber for pubsub callback */ const onDeleteEventHandler = useCallback((_msg, deleted) => { setEvents((prev) => { if (prev.some((e) => e.id === deleted)) { return prev.filter((e) => e.id !== deleted); } return prev; }); }, [events]); /** * On mount, subscribe to receive event updates (only delete) */ useEffect(() => { if (events) { updatesSubscription.current = PubSub.subscribe(`${SCTopicType.EVENT}.${SCGroupEventType.DELETE}`, onDeleteEventHandler); } return () => { updatesSubscription.current && PubSub.unsubscribe(updatesSubscription.current); }; }, [events]); // RENDER if (!events && loading) { return _jsx(Skeleton, {}); } if (!events || count === 0) { return _jsx(HiddenPlaceholder, {}); } return (_jsxs(Root, Object.assign({ className: classes.root }, rest, { children: [_jsxs(CardContent, Object.assign({ className: classes.content }, { children: [_jsx(Typography, Object.assign({ variant: "h5", className: classes.title }, { children: _jsx(FormattedMessage, { id: "ui.suggestedEventsWidget.title", defaultMessage: "ui.suggestedEventsWidget.title" }) })), _jsxs(Swiper, Object.assign({ spaceBetween: 8, slidesPerView: "auto", grabCursor: true, onReachBeginning: handleReachBeginning, onReachEnd: handleReachEnd, onSlideChange: handleChange, className: classes.swiper, style: { marginLeft: hideMarginLeft ? `-${theme.spacing(2)}` : 0, marginRight: hideMarginRight ? `-${theme.spacing(2)}` : 0 } }, { children: [(showSkeleton ? [...events, undefined] : events).map((event, i) => (_jsx(SwiperSlide, Object.assign({ className: classes.swiperSlide }, { children: _jsx(Event, { event: event, template: SCEventTemplateType.PREVIEW, actions: _jsx(_Fragment, {}), variant: "outlined", className: classes.event }) }), i))), _jsx(Arrow, { className: classNames(classes.swiperArrow, classes.swiperPrevArrow), type: "prev", currentItem: currentItem, setCurrentItem: setCurrentItem }), _jsx(Arrow, { className: classNames(classes.swiperArrow, classes.swiperNextArrow), type: "next", currentItem: currentItem, setCurrentItem: setCurrentItem })] }))] })), _jsx(CardActions, Object.assign({ className: classes.actions }, { children: _jsx(Button, Object.assign({ component: Link, to: scRoutingContext.url(SCRoutes.EVENTS_SUGGESTED_ROUTE_NAME, {}), className: classes.actionButton }, { children: _jsx(Typography, Object.assign({ variant: "caption" }, { children: _jsx(FormattedMessage, { id: "ui.suggestedEventsWidget.showAll", defaultMessage: "ui.suggestedEventsWidget.showAll" }) })) })) }))] }))); }