UNPKG

@selfcommunity/react-templates

Version:

React Templates Components to integrate a Community created with SelfCommunity.

187 lines (179 loc) • 11.8 kB
import { __rest } from "tslib"; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { useContext, useEffect, useMemo, useState } from 'react'; import { http, Endpoints, UserService, LoyaltyService } from '@selfcommunity/api-services'; import { SCUserContext } from '@selfcommunity/react-core'; import { Box, Button, Card, CardActions, CardContent, CardMedia, Grid, Typography, useMediaQuery, useTheme, styled, Chip } from '@mui/material'; import { FormattedMessage } from 'react-intl'; import classNames from 'classnames'; import { useThemeProps } from '@mui/system'; import Skeleton from './Skeleton'; import PrizeItemSkeleton from './PrizeItemSkeleton'; import PointsList from './PointsList'; import { useSnackbar } from 'notistack'; import { InfiniteScroll, ConfirmDialog } from '@selfcommunity/react-ui'; import { PREFIX } from './constants'; const classes = { root: `${PREFIX}-root`, userPoints: `${PREFIX}-user-points`, title: `${PREFIX}-title`, sectionTitle: `${PREFIX}-section-title`, sectionInfo: `${PREFIX}-section-info`, pointsSection: `${PREFIX}-points-section`, prizeSection: `${PREFIX}-prize-section`, card: `${PREFIX}-card`, cardTitle: `${PREFIX}-card-title`, cardContent: `${PREFIX}-card-content`, prizePoints: `${PREFIX}-prize-points`, actionButton: `${PREFIX}-card-action-button`, notRequestable: `${PREFIX}-not-requestable`, endMessage: `${PREFIX}-end-message` }; const Root = styled(Box, { name: PREFIX, slot: 'Root' })(() => ({})); /** * > API documentation for the Community-JS Loyalty Program Detail Template. Learn about the available props and the CSS API. * * * This component renders the loyalty program detail template. * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-templates/Components/LoyaltyProgramDetail) #### Import ```jsx import {LoyaltyProgramDetail} from '@selfcommunity/react-templates'; ``` #### Component Name The name `SCLoyaltyProgramDetailTemplate` can be used when providing style overrides in the theme. #### CSS |Rule Name|Global class|Description| |---|---|---| |root|.SCLoyaltyProgramDetailTemplate-root|Styles applied to the root element.| |userPoints|.SCLoyaltyProgramDetailTemplate-user-points|Styles applied to the chip element.| |title|.SCLoyaltyProgramDetailTemplate-title|Styles applied to the title element.| |sectionTitle|.SCLoyaltyProgramDetailTemplate-section-title|Styles applied to the section title element.| |sectionInfo|.SCLoyaltyProgramDetailTemplate-section-info|Styles applied to the section info element.| |pointsSection|.SCLoyaltyProgramDetailTemplate-points-section|Styles applied to the points section.| |prizeSection|.SCLoyaltyProgramDetailTemplate-prize-section|Styles applied to the prize section.| |card|.SCLoyaltyProgramDetailTemplate-card|Styles applied to the card elements.| |cardTitle|.SCLoyaltyProgramDetailTemplate-card-title|Styles applied to the card title element.| |cardContent|.SCLoyaltyProgramDetailTemplate-card-content|Styles applied to the card content section.| |prizePoints|.SCLoyaltyProgramDetailTemplate-prize-points|Styles applied to the prize points element.| |actionButton|.SCLoyaltyProgramDetailTemplate-action-button|Styles applied to the action button element.| |notRequestable|.SCLoyaltyProgramDetailTemplate-not-requestable|Styles applied to elements that are not requestable.| |endMessage|.SCLoyaltyProgramDetailTemplate-end-message|Styles applied to the infinity scroll final section.| /** * * @param inProps * @constructor */ export default function LoyaltyProgramDetail(inProps) { // PROPS const props = useThemeProps({ props: inProps, name: PREFIX }); const { className } = props, rest = __rest(props, ["className"]); // STATE const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('md')); // STATE const [loading, setLoading] = useState(true); const [next, setNext] = useState(null); const [prizes, setPrizes] = useState([]); const [points, setPoints] = useState(0); const [open, setOpen] = useState(false); const [prizeRequested, setPrizeRequested] = useState(null); const { enqueueSnackbar, closeSnackbar } = useSnackbar(); // CONTEXT const scUserContext = useContext(SCUserContext); // CONST const authUserId = scUserContext.user ? scUserContext.user.id : null; // HANDLERS const handleScrollUp = () => { window.scrollTo({ left: 0, top: 0, behavior: 'smooth' }); }; const requestPrize = (id) => { return LoyaltyService.createPrizeRequest(id) .then((data) => { setPoints((prev) => prev - data.prize_points); setOpen(false); let _snackBar = enqueueSnackbar(_jsx(FormattedMessage, { id: "templates.loyaltyProgramDetail.prize.request.success", defaultMessage: "templates.loyaltyProgramDetail.prize.request.success" }), { variant: 'success', autoHideDuration: 3000, SnackbarProps: { onClick: () => { closeSnackbar(_snackBar); } } }); }) .catch(() => { setOpen(false); let _snackBar = enqueueSnackbar(_jsx(FormattedMessage, { id: "templates.loyaltyProgramDetail.prize.request.error", defaultMessage: "templates.loyaltyProgramDetail.prize.request.error" }), { variant: 'error', autoHideDuration: 3000, SnackbarProps: { onClick: () => { closeSnackbar(_snackBar); } } }); }); }; const handleOpenAlert = (id) => { setPrizeRequested(id); setOpen(true); }; const handleNext = useMemo(() => () => { if (!next) { return; } return http .request({ url: next, method: Endpoints.GetPrizes.method }) .then((res) => { setPrizes([...prizes, ...res.data.results]); setNext(res.data.next); }) .catch((error) => console.log(error)) .then(() => setLoading(false)); }, [next]); const fetchUserPoints = () => { UserService.getUserLoyaltyPoints(authUserId) .then((data) => { setPoints(data.points); }) .catch((error) => { console.log(error); }); }; const fetchPrizes = () => { LoyaltyService.getPrizes({ limit: 8 }).then((res) => { setPrizes(res.results); setNext(res.next); setLoading(false); }); }; /** * On mount, fetches loyalty prizes and user points */ useEffect(() => { if (authUserId) { fetchUserPoints(); fetchPrizes(); } }, [authUserId]); /** * Renders the component (if not hidden by autoHide prop) */ if (!authUserId) { return null; } if (loading) { return _jsx(Skeleton, {}); } return (_jsxs(Root, Object.assign({ className: classNames(classes.root, className) }, rest, { children: [points !== 0 && (_jsxs(Typography, Object.assign({ className: classes.title, variant: "h5" }, { children: [!isMobile && _jsx(FormattedMessage, { id: "ui.loyaltyProgramWidget.title", defaultMessage: "ui.loyaltyProgramWidget.title" }), _jsx(Chip, { className: classes.userPoints, component: "span", label: _jsx(FormattedMessage, { id: "templates.loyaltyProgramDetail.userPoints", defaultMessage: "templates.loyaltyProgramDetail.userPoints", values: { total: points } }) })] }))), _jsx(Typography, Object.assign({ className: classes.sectionTitle }, { children: _jsx(FormattedMessage, { id: "templates.loyaltyProgramDetail.community", defaultMessage: "templates.loyaltyProgramDetail.community" }) })), _jsx(Typography, Object.assign({ className: classes.sectionInfo }, { children: _jsx(FormattedMessage, { id: "templates.loyaltyProgramDetail.description", defaultMessage: "templates.loyaltyProgramDetail.description" }) })), _jsx(Typography, Object.assign({ className: classes.sectionTitle }, { children: _jsx(FormattedMessage, { id: "templates.loyaltyProgramDetail.listTitle", defaultMessage: "templates.loyaltyProgramDetail.listTitle" }) })), _jsx(PointsList, { className: classes.pointsSection }), prizes.length !== 0 && (_jsx(Typography, Object.assign({ className: classes.sectionTitle }, { children: _jsx(FormattedMessage, { id: "templates.loyaltyProgramDetail.prizes", defaultMessage: "templates.loyaltyProgramDetail.prizes" }) }))), _jsx(InfiniteScroll, Object.assign({ dataLength: prizes.length, next: handleNext, hasMoreNext: Boolean(next), loaderNext: _jsx(PrizeItemSkeleton, {}), endMessage: _jsx(_Fragment, { children: prizes.length !== 0 ? (_jsxs(Typography, Object.assign({ className: classes.endMessage }, { children: [_jsx(FormattedMessage, { id: "templates.loyaltyProgramDetail.content.end.message", defaultMessage: "templates.loyaltyProgramDetail.content.end.message" }), _jsx(Button, Object.assign({ color: "secondary", onClick: handleScrollUp }, { children: _jsx(FormattedMessage, { id: "templates.loyaltyProgramDetail.content.end.button", defaultMessage: "templates.loyaltyProgramDetail.content.end.button" }) }))] }))) : null }) }, { children: _jsx(Grid, Object.assign({ container: true, width: "100%", spacing: !isMobile ? 3 : 0, direction: isMobile ? 'column' : 'row', className: classes.prizeSection }, { children: prizes.map((prize) => (_jsx(Grid, Object.assign({ size: { xs: 12, md: 6, lg: 4, xl: 3 } }, { children: _jsxs(Card, Object.assign({ className: classes.card }, { children: [_jsx(CardMedia, { component: "img", image: prize.image }), _jsx(Box, Object.assign({ className: classes.prizePoints }, { children: _jsx(Chip, { className: points <= prize.points ? classes.notRequestable : null, label: _jsx(FormattedMessage, { id: "templates.loyaltyProgramDetail.prize.points", defaultMessage: "templates.loyaltyProgramDetail.prize.points", values: { total: prize.points } }) }) })), _jsxs(CardContent, { children: [_jsx(Typography, Object.assign({ variant: "body1", className: classes.cardTitle }, { children: prize.title })), _jsx(Typography, Object.assign({ variant: "body2", className: classes.cardContent }, { children: prize.description }))] }), _jsxs(CardActions, { children: [prize.link && (_jsx(Button, Object.assign({ size: "medium", color: "secondary", href: prize.link, target: "_blank", className: classes.actionButton }, { children: _jsx(FormattedMessage, { id: "templates.loyaltyProgramDetail.button.more", defaultMessage: "templates.loyaltyProgramDetail.button.more" }) }))), ((!prize.link && prize.active && points >= prize.points) || (prize.active && points >= prize.points)) && (_jsx(Button, Object.assign({ size: "small", variant: "outlined", className: classes.actionButton, disabled: points < prize.points, onClick: () => handleOpenAlert(prize.id) }, { children: _jsx(FormattedMessage, { id: "templates.loyaltyProgramDetail.button.request", defaultMessage: "templates.loyaltyProgramDetail.button.request" }) })))] })] })) }), prize.id))) })) })), open && (_jsx(ConfirmDialog, { open: open, title: _jsx(FormattedMessage, { id: "templates.loyaltyProgramDetail.dialog.msg", defaultMessage: "templates.loyaltyProgramDetail.dialog.msg" }), btnConfirm: _jsx(FormattedMessage, { id: "templates.loyaltyProgramDetail.dialog.confirm", defaultMessage: "templates.loyaltyProgramDetail.dialog.confirm" }), onConfirm: () => requestPrize(prizeRequested), onClose: () => setOpen(false) }))] }))); }