@proca/widget
Version:
Proca is an open-source campaign toolkit designed to empower activists and organisations in their digital advocacy efforts. It provides a flexible and customisable platform for creating and managing online petitions, email campaigns, and other forms of di
115 lines (102 loc) • 3.18 kB
JavaScript
import React, { useEffect } from "react";
import { makeStyles } from "@material-ui/core/styles";
import { LinearProgress, Box } from "@material-ui/core";
import useCount from "@hooks/useCount";
//3,014,823 have signed. Let’s get to 4,500,000!
import { useTranslation } from "react-i18next";
import { useCampaignConfig } from "@hooks/useConfig";
const useStyles = makeStyles(theme => ({
"@global": {},
"@keyframes procaPrimaryGrey": {
"0%": {
color: theme.palette.text.primary,
},
"100%": {
color: theme.palette.primary.main,
},
},
root: {
fontSize: theme.typography.pxToRem(18),
fontWeight: "bold",
animation: `$procaPrimaryGrey 3s ${theme.transitions.easing.easeOut}`,
color: theme.palette.text.secondary,
width: "100%",
"& > * + *": {
marginTop: theme.spacing(2),
},
},
}));
const nextStep = (value, steps) => {
if (!steps) {
steps = [
100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000,
500000, 1000000, 1200000, 1500000, 2000000, 5000000,
];
}
let next = 1;
steps.some(step => {
if (value < step) {
next = step;
return true;
}
return false;
});
return next;
};
const normalise = (value, max) => {
return value ? (value * 100) / max : 50;
};
export const formatNumber = (value, separator) => {
if (typeof Intl.NumberFormat === "function" && !separator)
return Intl.NumberFormat().format(value);
if (!separator)
// fallback to space
separator = "\u00A0";
return value.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, `$1${separator}`);
};
export default function Progress(props) {
const { t, i18n } = useTranslation();
let count = props.count;
count = useCount(props.actionPage) || props.count;
const config = useCampaignConfig();
const classes = useStyles();
const goal = nextStep(count, config.component.counter?.steps);
const separator = config.component.counter?.separator | " "; //non breaking space
const min = config.component.counter?.min | 0;
const [progress, setProgress] = React.useState(1);
useEffect(() => {
const aim = normalise(count, goal);
const timer = setInterval(() => {
setProgress(prevProgress =>
prevProgress >= aim - 10 ? aim : prevProgress + 10
);
}, 500);
return () => {
clearInterval(timer);
};
}, [count, goal]);
if (!config.test) {
if (!count || count <= min) {
return <Box mt={1}> </Box>;
}
} else {
count = count || 0;
}
// we are checking if the progress key matching button.action exists, if not, we use the default progress.sign
const actionName = config.component.register?.button?.split(".")[1] || "sign";
const progressKey = i18n.exists(`progress.${actionName}`)
? `progress.${actionName}`
: "progress";
return (
<>
<Box className={`${classes.root} proca-progress`}>
{t(progressKey, {
count: formatNumber(count, separator),
total: formatNumber(count, separator),
goal: formatNumber(goal, separator),
})}
<LinearProgress variant="determinate" value={progress} />
</Box>
</>
);
}