@selfcommunity/react-templates
Version:
React Templates Components to integrate a Community created with SelfCommunity.
187 lines (179 loc) • 11.8 kB
JavaScript
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) }))] })));
}