PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 4.16.3
GiveWP – Donation Plugin and Fundraising Platform v4.16.3
4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / src / Admin / components / Charts / TimeSeriesChart.tsx
give / src / Admin / components / Charts Last commit date
TimeSeriesChart.tsx 8 months ago
TimeSeriesChart.tsx
140 lines
1 import React, {useEffect, useState} from 'react';
2 import Chart from 'react-apexcharts';
3 import {ApexOptions} from 'apexcharts';
4 import apiFetch from '@wordpress/api-fetch';
5 import {getDate} from '@wordpress/date';
6 import { formatTimestamp } from '@givewp/admin/common';
7
8 /**
9 * @since 4.4.0
10 */
11 type TimeSeriesChartProps = {
12 endpoint: string;
13 amountFormatter: Intl.NumberFormat;
14 title?: string;
15 };
16
17 /**
18 * @since 4.4.0
19 */
20 type Donation = {
21 createdAt: string;
22 amount: {
23 value: string;
24 };
25 };
26
27 /**
28 * @since 4.4.0
29 */
30 type DataPoint = {
31 x: string;
32 y: number;
33 };
34
35 /**
36 * @since 4.4.0
37 * Generates a range of dates around a target date for displaying a single donation graph.
38 */
39 const getCenteredGraphRange = (targetDate: string) => {
40 const result = [];
41 const date = new Date(targetDate);
42
43 for (let i = -3; i <= 3; i++) {
44 const currentDate = new Date(date);
45 currentDate.setDate(date.getDate() + i);
46 result.push(currentDate.toISOString().split('T')[0]);
47 }
48 return result;
49 };
50
51 /**
52 * @since 4.4.0
53 */
54 const normalizeData = (donations: Donation[]): DataPoint[] => {
55 const map = new Map<string, number>();
56
57 // Group donations by date with sum amounts - fill missing dates with 0.
58 donations.forEach((donation) => {
59 const date = getDate(donation.createdAt);
60 const amount = parseFloat(donation.amount.value);
61 map.set(date.toISOString().split('T')[0], (map.get(date.toISOString().split('T')[0]) || 0) + amount);
62 });
63
64 // Set graph range & points for single donations.
65 if (map.size === 1) {
66 const donationDate = donations[0]?.createdAt.split(' ')[0];
67 const graphRange = getCenteredGraphRange(donationDate);
68
69 return graphRange.map((date) => ({
70 x: date,
71 y: map.get(date) || 0,
72 }));
73 }
74
75 // Convert to sorted array of data points.
76 return Array.from(map.entries())
77 .map(([date, amount]) => ({
78 x: date,
79 y: amount,
80 }))
81 .sort((a, b) => a.x.localeCompare(b.x));
82 };
83
84 /**
85 * @since 4.13.0 updated the date format
86 * @since 4.4.0
87 */
88 export default function TimeSeriesChart({endpoint, amountFormatter, title = ''}: TimeSeriesChartProps) {
89 const [series, setSeries] = useState([{name: title, data: []}]);
90
91 useEffect(() => {
92 apiFetch<Donation[]>({path: endpoint}).then((data) => {
93 const normalized = normalizeData(data);
94 setSeries([{name: title, data: normalized}]);
95 });
96 }, [endpoint]);
97
98 const options: ApexOptions = {
99 chart: {
100 type: 'area' as const,
101 toolbar: {show: false},
102 zoom: {enabled: false},
103 },
104 xaxis: {
105 type: 'datetime',
106 labels: {
107 formatter: (val) => formatTimestamp(val, false),
108 },
109 },
110 yaxis: {
111 min: 0,
112 labels: {
113 formatter: (val) => amountFormatter.format(val),
114 },
115 },
116 dataLabels: {enabled: false},
117 stroke: {
118 curve: 'smooth',
119 width: 2,
120 colors: ['#60a1e2'],
121 },
122 fill: {
123 type: 'gradient',
124 gradient: {
125 shadeIntensity: 1,
126 opacityFrom: 0.3,
127 opacityTo: 0,
128 stops: [0, 100],
129 },
130 },
131 tooltip: {
132 x: {
133 format: 'MMM dd, yyyy',
134 },
135 },
136 };
137
138 return <Chart options={options} series={series} type="area" height="250" />;
139 }
140