Skip to content

Commit

Permalink
Merge pull request #25 from Giveth/feat/recurring_donations_integration
Browse files Browse the repository at this point in the history
feat: add recurring donations (count & USD totals statistics)
  • Loading branch information
Meriem-BM authored Jul 24, 2024
2 parents ebba441 + 42d8302 commit cfe0727
Show file tree
Hide file tree
Showing 11 changed files with 662 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/components/views/home/Home.index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import DonationsCount from './DonationsCount';
import NewDonorsCount from './NewDonorsCount';
import NewDonorsDonationTotalUsd from './NewDonorsDonationTotalUsd';
import MultisigSessionsCount from './MultisigSessionsCount';
import RecurringDonationsCount from './RecurringDonationsCount';
import RecurringDonationsTotalUsd from './RecurringDonationsTotalUsd';

const HomeIndex = () => {
return (
Expand All @@ -20,6 +22,10 @@ const HomeIndex = () => {
<hr />
<TotalDonations />
<hr />
<RecurringDonationsCount />
<hr />
<RecurringDonationsTotalUsd />
<hr />
<NewDonorsCount />
<hr />
<NewDonorsDonationTotalUsd />
Expand Down
106 changes: 106 additions & 0 deletions src/components/views/home/RecurringDonationsCount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import React, { useState } from 'react';
import {
H2,
H4,
H6,
IconHelpFilled16,
neutralColors,
Subline,
} from '@giveth/ui-design-system';
import styled from 'styled-components';
import {
firstOfNextMonth,
firstOfGiveth,
thousandsSeparator,
} from '../../../lib/helpers';
import { Col, Row } from '../../styled-components/grid';
import { FlexCenter } from '../../styled-components/flex';
import { IconWithTooltip } from '../../IconWithTooltip';
import Spinner from '../../Spinner';
import useRecurringDonationsCount from '../../../hooks/useRecurringDonationsCount';
import RecurringDonationsCountChat from './charts/RecurringDonationsCountChat';
import CheckBox from '../../CheckBox';
import DatePicker from '../../DatePicker';
import RecurringDonationsCountTokenChart from './charts/RecurringDonationsCountTokenChart';

const RecurringDonationsCount = () => {
const [fromDate, setFromDate] = useState(firstOfGiveth());
const [toDate, setToDate] = useState(firstOfNextMonth());
const [onlyVerified, setOnlyVerified] = useState(false);
const { recurringDonationsCount, loading } = useRecurringDonationsCount(
fromDate,
toDate,
undefined,
onlyVerified,
);

const { total, totalPerMonthAndYear, totalPerToken } =
recurringDonationsCount || {};

return (
<RowStyled>
<Col md={4}>
<FlexCenter gap='10px'>
<H4>Recurring Donations Count </H4>
<IconWithTooltip
icon={<IconHelpFilled16 />}
direction={'top'}
>
<TooltipBody>
Total number of recurring donations during the
selected timeframe, including anonymous recurring
donations.
</TooltipBody>
</IconWithTooltip>
</FlexCenter>
</Col>
<Col md={4}>
<div>
From: <DatePicker date={fromDate} setDate={setFromDate} />
</div>
<br />
<div>
To: <DatePicker date={toDate} setDate={setToDate} />
</div>
<br />
<CheckBox
checked={onlyVerified}
onChange={setOnlyVerified}
label='To verified projects only'
/>
</Col>
<Col md={1} />
<Col md={2}>
<H6>Total:</H6>
{loading ? <Spinner /> : <H2>{thousandsSeparator(total)}</H2>}
</Col>
{loading ? (
<Spinner />
) : (
<RecurringDonationsCountChat
totalPerMonthAndYear={totalPerMonthAndYear!}
/>
)}
{loading ? (
<Spinner />
) : (
<RecurringDonationsCountTokenChart
rDonationsPerToken={totalPerToken}
/>
)}
</RowStyled>
);
};

const TooltipBody = styled(Subline)`
color: ${neutralColors.gray[100]};
width: 270px;
`;

const RowStyled = styled(Row)`
margin-top: 40px;
align-items: center;
margin-bottom: 40px;
`;

export default RecurringDonationsCount;
110 changes: 110 additions & 0 deletions src/components/views/home/RecurringDonationsTotalUsd.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import styled from 'styled-components';
import React, { useState } from 'react';
import {
H2,
H4,
H6,
IconHelpFilled16,
neutralColors,
Subline,
} from '@giveth/ui-design-system';
import { Col, Row } from '../../styled-components/grid';
import Spinner from '../../Spinner';
import useRecurringDonationsTotalUsd from '../../../hooks/useRecurringDonationsTotalUsd';
import {
firstOfNextMonth,
firstOfGiveth,
thousandsSeparator,
} from '../../../lib/helpers';
import { IconWithTooltip } from '../../IconWithTooltip';
import { FlexCenter } from '../../styled-components/flex';
import RecurringDonationsTotalChart from './charts/RecurringDonationsTotalChart';
import CheckBox from '../../CheckBox';
import DatePicker from '../../DatePicker';
import RecurringDonationsTotalTokenChart from './charts/RecurringDonationsTotalTokenChart';

const RecurringDonationsTotalUsd = () => {
const [fromDate, setFromDate] = useState(firstOfGiveth());
const [toDate, setToDate] = useState(firstOfNextMonth());
const [onlyVerified, setOnlyVerified] = useState(false);
const { recurringDonationsTotaStreanedlUsd, loading } =
useRecurringDonationsTotalUsd(
fromDate,
toDate,
undefined,
onlyVerified,
);

const { total, totalPerMonthAndYear, totalPerToken } =
recurringDonationsTotaStreanedlUsd || {};

return (
<RowStyled>
<Col md={4}>
<FlexCenter gap='14px'>
<H4>Total Recurring Donations ($)</H4>
<IconWithTooltip
icon={<IconHelpFilled16 />}
direction={'top'}
>
<TooltipBody>
Total sum of all recurring donations value in USD
during the selected timeframe.
</TooltipBody>
</IconWithTooltip>
</FlexCenter>
</Col>
<Col md={4}>
<div>
From: <DatePicker date={fromDate} setDate={setFromDate} />
</div>
<br />
<div>
To: <DatePicker date={toDate} setDate={setToDate} />
</div>
<br />
<CheckBox
checked={onlyVerified}
onChange={setOnlyVerified}
label='To verified projects only'
/>
</Col>
<Col md={1} />
<Col md={2}>
<H6>Total (USD):</H6>
{loading ? (
<Spinner />
) : (
<H2>{thousandsSeparator(total?.toFixed(2))}</H2>
)}
</Col>
{loading ? (
<Spinner />
) : (
<RecurringDonationsTotalChart
totalPerMonthAndYear={totalPerMonthAndYear!}
/>
)}
{loading ? (
<Spinner />
) : (
<RecurringDonationsTotalTokenChart
rDonationsPerToken={totalPerToken}
/>
)}
</RowStyled>
);
};

const TooltipBody = styled(Subline)`
color: ${neutralColors.gray[100]};
width: 270px;
`;

const RowStyled = styled(Row)`
margin-top: 40px;
align-items: center;
margin-bottom: 40px;
`;

export default RecurringDonationsTotalUsd;
60 changes: 60 additions & 0 deletions src/components/views/home/charts/RecurringDonationsCountChat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { FC } from 'react';
import Highcharts from 'highcharts';
import HighchartsReact from 'highcharts-react-official';
import styled from 'styled-components';
import { IMonthlyData } from '../../../../types/gql';

const RecurringDonationsCountChat: FC<IMonthlyData> = ({
totalPerMonthAndYear,
}) => {
const data = totalPerMonthAndYear?.map(i => ({
name: i.date,
y: i.total,
}));
const options = {
chart: {
type: 'column',
zoomType: 'x',
},
title: {
text: 'Recurring donations count per month',
},
subtitle: {
text: '(Click and drag to zoom in)',
},
xAxis: {
type: 'category',
min: 0,
},
yAxis: {
title: {
text: 'Number of donations',
},
},
tooltip: {
enabled: true,
pointFormat: '<b>Recurring Donations: {point.y}</b>',
},
legend: {
enabled: false,
},
series: [{ data }],
plotOptions: {
series: {
pointWidth: 15,
},
},
};

return (
<ChartContainer>
<HighchartsReact highcharts={Highcharts} options={options} />
</ChartContainer>
);
};

const ChartContainer = styled.div`
margin-top: 60px;
`;

export default RecurringDonationsCountChat;
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { FC } from 'react';
import Highcharts from 'highcharts';
import HighchartsReact from 'highcharts-react-official';
import styled from 'styled-components';
import {
H5,
IconHelpFilled16,
neutralColors,
Subline,
} from '@giveth/ui-design-system';
import { IconWithTooltip } from '../../../IconWithTooltip';
import { FlexCenter } from '../../../styled-components/flex';
import { IRecurringDonationdPerTokenRecord } from '../../../../types/gql';

interface IProps {
rDonationsPerToken?: IRecurringDonationdPerTokenRecord[];
}

const RecurringDonationsCountTokenChart: FC<IProps> = ({
rDonationsPerToken,
}) => {
const data = rDonationsPerToken?.map(i => ({
name: i.token,
y: i.total,
}));
const options = {
chart: {
plotBackgroundColor: null,
type: 'pie',
},
title: {
text: null,
},
tooltip: {
enabled: true,
pointFormat: '<b>{point.y}</b>',
},
series: [
{
colorByPoint: true,
data: data,
},
],
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %',
},
},
},
};

return (
<Container>
<FlexCenter gap='10px'>
<H5>Recurring Donations Count Per Token</H5>
<IconWithTooltip icon={<IconHelpFilled16 />} direction={'top'}>
<TooltipBody>
Current distribution of all recurring donations by token
during the selected timeframe.
</TooltipBody>
</IconWithTooltip>
</FlexCenter>
<HighchartsReact highcharts={Highcharts} options={options} />
</Container>
);
};

const TooltipBody = styled(Subline)`
color: ${neutralColors.gray[100]};
width: 270px;
`;

const Container = styled.div`
margin-top: 50px;
text-align: center;
`;

export default RecurringDonationsCountTokenChart;
Loading

0 comments on commit cfe0727

Please sign in to comment.