Skip to content

Commit

Permalink
added campaign expenses chart
Browse files Browse the repository at this point in the history
  • Loading branch information
tongo-angelov committed Sep 23, 2023
1 parent a5efd33 commit 939bcce
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 0 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"@tryghost/content-api": "^1.11.4",
"axios": "0.21.4",
"axios-hooks": "2.7.0",
"chart.js": "^4.4.0",
"date-fns": "2.24.0",
"dompurify": "^3.0.3",
"formik": "2.2.9",
Expand All @@ -62,6 +63,7 @@
"quill-blot-formatter": "^1.0.5",
"quill-html-edit-button": "^2.2.12",
"react": "18.2.0",
"react-chartjs-2": "^5.2.0",
"react-dom": "18.2.0",
"react-gtm-module": "2.0.11",
"react-i18next": "^11.17.1",
Expand Down
8 changes: 8 additions & 0 deletions src/components/client/campaigns/CampaignDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { routes } from 'common/routes'
import { useCanEditCampaign } from 'common/hooks/campaigns'
import { moneyPublic } from 'common/util/money'
import ReceiptLongIcon from '@mui/icons-material/ReceiptLong'
import CampaignPublicExpensesChart from './CampaignPublicExpensesChart'

const ReactQuill = dynamic(() => import('react-quill'), { ssr: false })
const CampaignNewsSection = dynamic(() => import('./CampaignNewsSection'), { ssr: false })
Expand Down Expand Up @@ -143,6 +144,13 @@ export default function CampaignDetails({ campaign }: Props) {
)}
</Typography>
</Grid>
<Grid item xs={12}>
<CampaignPublicExpensesChart
slug={campaign.slug}
reachedAmount={campaign.summary.reachedAmount}
currency={campaign.currency}
/>
</Grid>
<Grid item xs={12}>
<Typography>
<ReceiptLongIcon /> {t('expenses:reported')}:{' '}
Expand Down
100 changes: 100 additions & 0 deletions src/components/client/campaigns/CampaignPublicExpensesChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React from 'react'
import { observer } from 'mobx-react'
import { useTranslation } from 'next-i18next'
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
BarElement,
Title,
Colors,
Tooltip,
Legend,
TooltipItem,
} from 'chart.js'
import { Bar } from 'react-chartjs-2'

import { useCampaignApprovedExpensesList } from 'common/hooks/expenses'
import { fromMoney, moneyPublic, toMoney } from 'common/util/money'

ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Colors, Tooltip, Legend)

type ExpenseDataset = {
type: string
total: number
}

type Props = {
slug: string
reachedAmount: number
currency?: string
}

export default observer(function CampaignPublicExpensesChart({
slug,
reachedAmount,
currency,
}: Props) {
const { t } = useTranslation('')
const { data: campaignExpenses } = useCampaignApprovedExpensesList(slug)

const expenses: ExpenseDataset[] = []

campaignExpenses?.forEach(({ type, amount }) => {
const exists = expenses.find((e) => e.type === type)
if (exists) exists.total += fromMoney(amount)
else expenses.push({ type, total: fromMoney(amount) })
})

expenses.sort((a, b) => b.total - a.total)

const options = {
indexAxis: 'y' as const,
scales: {
x: {
stacked: true,
min: 0,
max: fromMoney(reachedAmount),
},
y: {
stacked: true,
display: false,
},
},
elements: {
bar: {
borderWidth: 1,
},
},
responsive: true,
plugins: {
legend: {
position: 'bottom' as const,
},
colors: {
enabled: true,
},
tooltip: {
callbacks: {
label: (context: TooltipItem<'bar'>) =>
` ${context.dataset.label + ':' || ''} ${moneyPublic(
toMoney(context.parsed.x),
currency,
)}`,
},
},
},
}

const data = {
labels: [''],
datasets: expenses.map((expense) => {
return {
label: t('expenses:field-types.' + expense.type),
data: [expense.total],
}
}),
}

return <Bar options={options} height={80} data={data} />
})
28 changes: 28 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,13 @@ __metadata:
languageName: node
linkType: hard

"@kurkle/color@npm:^0.3.0":
version: 0.3.2
resolution: "@kurkle/color@npm:0.3.2"
checksum: 79e97b31f8f6efb28c69d373f94b0c7480226fe8ec95221f518ac998e156444a496727ce47de6d728eb5c3369288e794cba82cae34253deb0d472d3bfe080e49
languageName: node
linkType: hard

"@lexical/clipboard@npm:0.11.3, @lexical/clipboard@npm:^0.11.1":
version: 0.11.3
resolution: "@lexical/clipboard@npm:0.11.3"
Expand Down Expand Up @@ -4960,6 +4967,15 @@ __metadata:
languageName: node
linkType: hard

"chart.js@npm:^4.4.0":
version: 4.4.0
resolution: "chart.js@npm:4.4.0"
dependencies:
"@kurkle/color": ^0.3.0
checksum: 5ee2d99b78608025525b5790af17178fdaa5adc3294e082deba2718029b0496109ba124f1b08dd1e4c8a04d6e842be7f384f2cfe9a11df8d1c6fe884acece52b
languageName: node
linkType: hard

"chokidar@npm:>=3.0.0 <4.0.0":
version: 3.5.3
resolution: "chokidar@npm:3.5.3"
Expand Down Expand Up @@ -11314,6 +11330,7 @@ __metadata:
all-contributors-cli: ^6.20.0
axios: 0.21.4
axios-hooks: 2.7.0
chart.js: ^4.4.0
date-fns: 2.24.0
depcheck: ^1.4.3
dompurify: ^3.0.3
Expand Down Expand Up @@ -11342,6 +11359,7 @@ __metadata:
quill-blot-formatter: ^1.0.5
quill-html-edit-button: ^2.2.12
react: 18.2.0
react-chartjs-2: ^5.2.0
react-dom: 18.2.0
react-gtm-module: 2.0.11
react-i18next: ^11.17.1
Expand Down Expand Up @@ -11785,6 +11803,16 @@ __metadata:
languageName: node
linkType: hard

"react-chartjs-2@npm:^5.2.0":
version: 5.2.0
resolution: "react-chartjs-2@npm:5.2.0"
peerDependencies:
chart.js: ^4.1.1
react: ^16.8.0 || ^17.0.0 || ^18.0.0
checksum: ace702185be1450e5888a8bcd8b5fc1995067e3b11d236764a67f5567a3d7c32ff16923b8d48d3d39bda6e45135da6c044c9b43fbe8e1978f95aca9d2c0ce348
languageName: node
linkType: hard

"react-devtools-inline@npm:4.4.0":
version: 4.4.0
resolution: "react-devtools-inline@npm:4.4.0"
Expand Down

0 comments on commit 939bcce

Please sign in to comment.