give
/
src
/
Campaigns
/
resources
/
admin
/
components
/
CampaignDetailsPage
/
Components
/
RevenueChart.tsx
give
/
src
/
Campaigns
/
resources
/
admin
/
components
/
CampaignDetailsPage
/
Components
Last commit date
CampaignDetailsErrorBoundary
1 year ago
CampaignStats
7 months ago
ColorControl
1 year ago
DefaultForm
1 year ago
GoalProgressChart
1 year ago
Notices
7 months ago
TextareaControl
1 year ago
ArchiveCampaignDialog.tsx
1 year ago
HeaderSubText.tsx
1 year ago
HeaderText.tsx
1 year ago
RevenueChart.tsx
1 year ago
RevenueChart.tsx
119 lines
| 1 | import React, {useEffect, useState} from 'react'; |
| 2 | import Chart from 'react-apexcharts'; |
| 3 | import apiFetch from '@wordpress/api-fetch'; |
| 4 | import {addQueryArgs} from '@wordpress/url'; |
| 5 | import {amountFormatter, getCampaignOptionsWindowData} from '@givewp/campaigns/utils'; |
| 6 | import {__} from '@wordpress/i18n'; |
| 7 | |
| 8 | const campaignId = new URLSearchParams(window.location.search).get('id'); |
| 9 | |
| 10 | const getDefaultData = (days = 7) => { |
| 11 | const data = []; |
| 12 | |
| 13 | for (let i = 0; i < days; i++) { |
| 14 | const date = new Date(); |
| 15 | date.setDate(date.getDate() - i); |
| 16 | data.push({x: date.toISOString().split('T')[0], y: 0}); |
| 17 | } |
| 18 | |
| 19 | return data; |
| 20 | }; |
| 21 | |
| 22 | const RevenueChart = () => { |
| 23 | const {currency} = getCampaignOptionsWindowData(); |
| 24 | const currencyFormatter = amountFormatter(currency); |
| 25 | const [max, setMax] = useState(100); |
| 26 | const [series, setSeries] = useState([{name: __('Revenue', 'give'), data: getDefaultData()}]); |
| 27 | |
| 28 | useEffect(() => { |
| 29 | apiFetch({path: addQueryArgs('/givewp/v3/campaigns/' + campaignId + '/revenue')}).then( |
| 30 | (data: {date: string; amount: number}[]) => { |
| 31 | if (data?.length > 0) { |
| 32 | // By default we set a max value so the chart does not look empty. |
| 33 | // once we have data we can reset the max value for the chart to auto calculate |
| 34 | setMax(undefined); |
| 35 | setSeries([ |
| 36 | { |
| 37 | name: __('Revenue', 'give'), |
| 38 | data: data.map((item) => { |
| 39 | return { |
| 40 | x: item.date, |
| 41 | y: item.amount, |
| 42 | }; |
| 43 | }), |
| 44 | }, |
| 45 | ]); |
| 46 | } |
| 47 | } |
| 48 | ); |
| 49 | }, []); |
| 50 | |
| 51 | const options = { |
| 52 | chart: { |
| 53 | id: 'campaign-revenue', |
| 54 | zoom: { |
| 55 | enabled: false, |
| 56 | }, |
| 57 | toolbar: { |
| 58 | show: false, |
| 59 | }, |
| 60 | }, |
| 61 | xaxis: { |
| 62 | type: 'datetime' as 'datetime' | 'category' | 'numeric', |
| 63 | }, |
| 64 | yaxis: { |
| 65 | min: 0, |
| 66 | max, |
| 67 | showForNullSeries: false, |
| 68 | labels: { |
| 69 | formatter: (value) => { |
| 70 | return currencyFormatter.format(Number(value)); |
| 71 | }, |
| 72 | }, |
| 73 | }, |
| 74 | stroke: { |
| 75 | color: ['#60a1e2'], |
| 76 | width: 1.5, |
| 77 | curve: 'smooth' as |
| 78 | | 'straight' |
| 79 | | 'smooth' |
| 80 | | 'monotoneCubic' |
| 81 | | 'stepline' |
| 82 | | 'linestep' |
| 83 | | ('straight' | 'smooth' | 'monotoneCubic' | 'stepline' | 'linestep')[], |
| 84 | lineCap: 'butt' as 'butt' | 'square' | 'round', |
| 85 | }, |
| 86 | dataLabels: { |
| 87 | enabled: false, |
| 88 | }, |
| 89 | fill: { |
| 90 | type: 'gradient', |
| 91 | gradient: { |
| 92 | colorStops: [ |
| 93 | [ |
| 94 | { |
| 95 | offset: 0, |
| 96 | color: '#eee', |
| 97 | opacity: 1, |
| 98 | }, |
| 99 | { |
| 100 | offset: 0.6, |
| 101 | color: '#b7d4f2', |
| 102 | opacity: 50, |
| 103 | }, |
| 104 | { |
| 105 | offset: 100, |
| 106 | color: '#f0f7ff', |
| 107 | opacity: 1, |
| 108 | }, |
| 109 | ], |
| 110 | ], |
| 111 | }, |
| 112 | }, |
| 113 | }; |
| 114 | |
| 115 | return <Chart options={options} series={series} type="area" width="100%" height="100%" />; |
| 116 | }; |
| 117 | |
| 118 | export default RevenueChart; |
| 119 |