diff --git a/src/config/global-chart-config.js b/src/config/global-chart-config.js
index c969d5c8..9cabfe4c 100644
--- a/src/config/global-chart-config.js
+++ b/src/config/global-chart-config.js
@@ -66,7 +66,17 @@ const GlobalChartConfig = {
enabled: true,
usePointStyle: true,
position: 'nearest',
+ backgroundColor: 'white',
+ bodyColor: 'black',
+ titleColor: 'black',
+ borderColor: 'black',
+ borderWidth: .5,
callbacks: {
+ title: (context) => context.label,
+ label: (context) => {
+ const value = context.parsed?.y ?? context.parsed.value;
+ return `${value}`
+ },
labelPointStyle: (_) => {
return {
pointStyle: 'triangle',
@@ -189,28 +199,17 @@ const Service = {
}
export const defaultGraphColors = [
- '#E0FFFF',
- '#00CED1',
- '#40E0D0',
- '#48D1CC',
- '#AFEEEE',
- '#7FFFD4',
- '#B0E0E6',
- '#5F9EA0',
- '#66CDAA',
- '#3CB371',
- '#20B2AA',
- '#2F4F4F',
- '#008080',
- '#008B8B',
- '#32CD32',
- '#90EE90',
- '#ADFF2F',
- '#90EE90',
- '#ADFF2F',
- '#7FFF00',
- '#7FFF00',
- '#6B8E23',
+ 'rgba(25, 25, 112, 0.8)', // Midnight Blue
+ 'rgba(0, 0, 128, 0.8)', // Navy Blue
+ 'rgba(0, 0, 139, 0.8)', // Dark Blue
+ 'rgba(0, 0, 156, 0.8)', // Medium Blue
+ 'rgba(0, 0, 205, 0.8)', // Medium Blue
+ 'rgba(0, 0, 255, 0.8)', // Blue
+ 'rgba(70, 130, 180, 0.8)', // Steel Blue
+ 'rgba(100, 149, 237, 0.8)', // Cornflower Blue
+ 'rgba(135, 206, 235, 0.8)', // Sky Blue
+ 'rgba(135, 206, 250, 0.8)', // Light Sky Blue
+ 'rgba(240, 248, 255, 0.8)', // Alice Blue
]
export {
diff --git a/src/core/RestAPI.js b/src/core/RestAPI.js
index 7c963a5c..01bd7b54 100644
--- a/src/core/RestAPI.js
+++ b/src/core/RestAPI.js
@@ -42,10 +42,20 @@ const TransactionRepository = (api => {
})(RestApi)
const CurrencyRepository = (api => {
+ let knownCurrencies = []
return {
- list: () => api.get('settings/currencies'),
+ list: () => api.get('settings/currencies').then(currencies => {
+ knownCurrencies = currencies
+ return currencies
+ }),
get: code => api.get(`settings/currencies/${code}`),
change: (code, enabled) => api.patch(`settings/currencies/${code}`, { enabled: enabled })
+ .then(response => {
+ const currency = knownCurrencies.find(currency => currency.code === code)
+ currency.enabled = enabled
+ return response
+ }),
+ cached: (code) => knownCurrencies.find(currency => currency.code === code)
}
})(RestApi)
diff --git a/src/core/graphs/categorized-pie-chart.tsx b/src/core/graphs/categorized-pie-chart.tsx
index 5a999327..38277c59 100644
--- a/src/core/graphs/categorized-pie-chart.tsx
+++ b/src/core/graphs/categorized-pie-chart.tsx
@@ -5,7 +5,7 @@ import { isArray } from "chart.js/helpers";
import { Account } from "../types";
import StatisticalRepository from "../repositories/statistical-repository";
import { Chart } from "react-chartjs-2";
-import { ChartData } from "chart.js";
+import { ChartData, Tooltip, TooltipPosition } from "chart.js";
import { defaultGraphColors } from "../../config/global-chart-config";
type CategorizedPieChartProps = {
@@ -15,8 +15,17 @@ type CategorizedPieChartProps = {
accounts?: Account[] | Account
}
+let lastPosition: TooltipPosition
+(Tooltip.positioners as any)['center'] = (_: any[], eventPosition: any) => {
+ const chartArea = eventPosition.chart?.chartArea
+ if (!chartArea) return lastPosition
+
+ lastPosition = { x: chartArea.right / 2 - 40, y: chartArea.bottom / 2 }
+ return lastPosition
+}
+
const CategorizedPieChart: FC
= ({ id, split, incomeOnly, accounts = [] }) => {
- const [pieSeries, setPieSeries] = useState(undefined)
+ const [pieSeries, setPieSeries] = useState | undefined>(undefined)
const [range] = useDateRange()
useEffect(() => {
@@ -44,39 +53,46 @@ const CategorizedPieChart: FC = ({ id, split, incomeOn
})
}, [split, incomeOnly, range]) // eslint-disable-line react-hooks/exhaustive-deps
+ const currency = accounts && !isArray(accounts) ? accounts.account.currency : '€'
+
if (!pieSeries) return
return <>
defaultGraphColors[context.dataIndex]
}
},
plugins: {
legend: {
- display: true,
- position: 'right'
+ display: false,
},
tooltip: {
+ backgroundColor: 'white',
+ bodyColor: 'black',
+ titleColor: 'black',
+ cornerRadius: 0,
+ caretSize: 0,
+ position: 'center',
+ bodyAlign: 'left',
callbacks: {
title: (context : any) => context.label,
label: (context: any) => {
- if (accounts && !isArray(accounts)) {
- return `${context.raw} ${accounts?.account?.currency}`
- }
-
- return context.raw
+ return ` ${currency}${context.raw}`
}
}
}
},
maintainAspectRatio: false
- }}/>
+ } as any }/>
>
}
diff --git a/src/core/layout/Card.tsx b/src/core/layout/Card.tsx
index 6786ef71..5aeff60d 100644
--- a/src/core/layout/Card.tsx
+++ b/src/core/layout/Card.tsx
@@ -32,7 +32,7 @@ const Card: FC = ({ title, actions, buttons, children, className = ''
{actions && { actions }
}
)}
-
+
{children}
{buttons &&
diff --git a/src/reports/budget-monthly/budget-chart.tsx b/src/reports/budget-monthly/budget-chart.tsx
new file mode 100644
index 00000000..d09aa799
--- /dev/null
+++ b/src/reports/budget-monthly/budget-chart.tsx
@@ -0,0 +1,31 @@
+import { Chart } from "react-chartjs-2";
+import { DefaultChartConfig, Service } from "../../config/global-chart-config";
+import React from "react";
+import { ChartData } from "chart.js";
+
+const BudgetChart = ({ dataSet, currencySymbol = '' } : { dataSet: ChartData, currencySymbol: string }) => {
+ return `${currencySymbol}${value}`
+ }
+ }
+ },
+ plugins: {
+ legend: {
+ display: true
+ }
+ }
+ }) }
+ data={ dataSet } />
+}
+
+export default BudgetChart
\ No newline at end of file
diff --git a/src/reports/budget-monthly/budget-yearly-expense.tsx b/src/reports/budget-monthly/budget-yearly-expense.tsx
index 350deee9..ecd06f25 100644
--- a/src/reports/budget-monthly/budget-yearly-expense.tsx
+++ b/src/reports/budget-monthly/budget-yearly-expense.tsx
@@ -3,20 +3,19 @@ import { Dates, Layout, Translations } from "../../core";
import { ChartData } from "chart.js";
import { Budget, BudgetExpense } from "../../core/types";
import StatisticalRepository from "../../core/repositories/statistical-repository";
-import { Chart } from "react-chartjs-2";
-import { DefaultChartConfig, Service } from "../../config/global-chart-config";
+import BudgetChart from "./budget-chart";
type BudgetYearlyExpenseProps = {
year: number,
- budgets: Budget[]
+ budgets: Budget[],
+ currencySymbol: string
}
-const BudgetYearlyExpense = ({ year, budgets } : BudgetYearlyExpenseProps) => {
+const BudgetYearlyExpense = ({ year, budgets, currencySymbol } : BudgetYearlyExpenseProps) => {
const [chartData, setChartData] = useState()
useEffect(() => {
if (budgets.length === 0) return
- console.info(`BudgetYearlyExpense: ${year} ${budgets.length}`)
setChartData(undefined)
const uniqueExpenses = budgets.reduce((left, right) => [...left, ...right.expenses], new Array())
@@ -54,25 +53,7 @@ const BudgetYearlyExpense = ({ year, budgets } : BudgetYearlyExpenseProps) => {
return <>
{ !chartData && }
- { chartData && <>
-
- > }
+ { chartData && }
>
}
diff --git a/src/reports/budget-monthly/budget-yearly-income.tsx b/src/reports/budget-monthly/budget-yearly-income.tsx
index ad0d7cac..24a9789c 100644
--- a/src/reports/budget-monthly/budget-yearly-income.tsx
+++ b/src/reports/budget-monthly/budget-yearly-income.tsx
@@ -2,15 +2,15 @@ import React, { useEffect, useState } from "react";
import { Dates, Layout, Statistical, Translations } from "../../core";
import { Budget } from "../../core/types";
import { ChartData } from "chart.js";
-import { Chart } from "react-chartjs-2";
-import { DefaultChartConfig, Service } from "../../config/global-chart-config";
+import BudgetChart from "./budget-chart";
type BudgetYearlyExpenseProps = {
year: number,
- budgets: Budget[]
+ budgets: Budget[],
+ currencySymbol: string
}
-const YearlyIncomeGraphComponent = ({ year = 1970, budgets = [] } : BudgetYearlyExpenseProps) => {
+const YearlyIncomeGraphComponent = ({ year = 1970, budgets = [], currencySymbol = '' } : BudgetYearlyExpenseProps) => {
const [chartData, setChartData] = useState()
useEffect(() => {
@@ -46,25 +46,7 @@ const YearlyIncomeGraphComponent = ({ year = 1970, budgets = [] } : BudgetYearly
return <>
{ !chartData && }
- { chartData && <>
-
- > }
+ { chartData && }
>
}
diff --git a/src/reports/budget-monthly/index.js b/src/reports/budget-monthly/index.js
index 86c31bb9..adf4291e 100644
--- a/src/reports/budget-monthly/index.js
+++ b/src/reports/budget-monthly/index.js
@@ -18,8 +18,10 @@ import BudgetYearlyExpense from "./budget-yearly-expense";
import '../../assets/css/BudgetReportView.scss'
import BudgetRepository from "../../core/repositories/budget.repository";
+import { CurrencyRepository } from "../../core/RestAPI";
export const BudgetReportView = () => {
+ const [currencySymbol, setCurrencySymbol] = useState('')
const [range, setRange] = useState(() => Dates.Ranges.currentYear())
const { currency = 'EUR', year = new Date().getFullYear() } = useParams()
const [budgets, setBudgets] = useState([])
@@ -36,6 +38,10 @@ export const BudgetReportView = () => {
.catch(console.error)
}
}, [year])
+ useEffect(() => {
+ CurrencyRepository.get(currency)
+ .then((c) => setCurrencySymbol(c.symbol))
+ }, [currency])
const onDateChanged = ({
newYear = year,
@@ -60,8 +66,8 @@ export const BudgetReportView = () => {
-
-
+
+
diff --git a/src/reports/dashboard/balance-chart.tsx b/src/reports/dashboard/balance-chart.tsx
index f8fe530a..ef9bb421 100644
--- a/src/reports/dashboard/balance-chart.tsx
+++ b/src/reports/dashboard/balance-chart.tsx
@@ -4,11 +4,13 @@ import { Range } from "../../core/Dates";
import { BalanceSeries } from "../../core/graphs/balance-series";
import { ChartData } from "chart.js";
import { Chart } from "react-chartjs-2";
-import { DefaultChartConfig } from "../../config/global-chart-config";
+import { DefaultChartConfig, Service as ChartService } from "../../config/global-chart-config";
+import RestAPI from "../../core/repositories/rest-api";
const BalanceChart = ({ range } : { range: Range }) => {
const [balanceSeries, setBalanceSeries] = useState()
+
useEffect(() => {
BalanceSeries({
title: 'graph.series.balance',
@@ -19,6 +21,21 @@ const BalanceChart = ({ range } : { range: Range }) => {
}))
}, [range])
+ const config = ChartService.mergeOptions(
+ DefaultChartConfig.line,
+ {
+ scales: {
+ y: {
+ ticks: {
+ callback: (value: number) => {
+ return `${(RestAPI.user() as any).defaultCurrency?.symbol}${value.toFixed(2)}`
+ }
+ }
+ }
+ }
+ }
+ )
+
return <>
{ !balanceSeries && }
@@ -26,7 +43,7 @@ const BalanceChart = ({ range } : { range: Range }) => {
{ balanceSeries &&
}
diff --git a/src/reports/dashboard/budget-balance.tsx b/src/reports/dashboard/budget-balance.tsx
index 8c063529..3084037a 100644
--- a/src/reports/dashboard/budget-balance.tsx
+++ b/src/reports/dashboard/budget-balance.tsx
@@ -6,8 +6,9 @@ import { Range } from "../../core/Dates";
import { ChartData } from "chart.js";
import { Budget, BudgetExpense } from "../../core/types";
import StatisticalRepository from "../../core/repositories/statistical-repository";
-import { DefaultChartConfig, Service } from "../../config/global-chart-config";
+import { DefaultChartConfig, Service as ChartService } from "../../config/global-chart-config";
import BudgetRepository from "../../core/repositories/budget.repository";
+import RestAPI from "../../core/repositories/rest-api";
const percentageOfYear = 90 / 365
@@ -44,6 +45,27 @@ function BudgetBalance({ range } : { range : Range }) {
.catch(_ => setBudgetSeries({ labels: [], datasets: [] }))
}, [range])
+ const config = ChartService.mergeOptions(
+ DefaultChartConfig.bar,
+ {
+ scales: {
+ y: {
+ ticks: {
+ callback: (value: number) => {
+ return `${(RestAPI.user() as any).defaultCurrency?.symbol}${value.toFixed(2)}`
+ }
+ }
+ }
+ },
+ plugins: {
+ legend: {
+ position: 'bottom',
+ display: true
+ }
+ }
+ }
+ )
+
return <>
{ !budgetSeries && }
@@ -51,14 +73,7 @@ function BudgetBalance({ range } : { range : Range }) {
}
diff --git a/src/reports/dashboard/categories-balance.tsx b/src/reports/dashboard/categories-balance.tsx
index 625b6b68..6c84d761 100644
--- a/src/reports/dashboard/categories-balance.tsx
+++ b/src/reports/dashboard/categories-balance.tsx
@@ -7,7 +7,8 @@ import { ChartData } from "chart.js";
import { Category } from "../../core/types";
import StatisticalRepository from "../../core/repositories/statistical-repository";
import { Chart } from "react-chartjs-2";
-import { DefaultChartConfig } from "../../config/global-chart-config";
+import { DefaultChartConfig, Service as ChartService } from "../../config/global-chart-config";
+import RestAPI from "../../core/repositories/rest-api";
const CategoriesBalance = ({ range } : { range: Range }) => {
const [categorySeries, setCategorySeries] = useState()
@@ -34,13 +35,28 @@ const CategoriesBalance = ({ range } : { range: Range }) => {
.catch(_ => setCategorySeries({ labels: [], datasets: [] }))
}, [range])
+ const config = ChartService.mergeOptions(
+ DefaultChartConfig.bar,
+ {
+ scales: {
+ y: {
+ ticks: {
+ callback: (value: number) => {
+ return `${(RestAPI.user() as any).defaultCurrency?.symbol}${value.toFixed(2)}`
+ }
+ }
+ }
+ }
+ }
+ )
+
return <>
{ !categorySeries && }
{ categorySeries &&
}
diff --git a/src/reports/dashboard/summary-component.tsx b/src/reports/dashboard/summary-component.tsx
index 72874f5c..1639b6da 100644
--- a/src/reports/dashboard/summary-component.tsx
+++ b/src/reports/dashboard/summary-component.tsx
@@ -34,7 +34,7 @@ const SummaryComponent: FC = ({ title, icon, currency, cu
}, [current, previous])
return <>
-
+
@@ -45,10 +45,10 @@ const SummaryComponent: FC = ({ title, icon, currency, cu
{ previous !== null && (
-
+ Comparison ${comparisonClass}`} style={ { lineHeight: '1.5rem' } }>
+
)}
diff --git a/src/reports/dashboard/summary.js b/src/reports/dashboard/summary.js
index 6768107f..0861ca2d 100644
--- a/src/reports/dashboard/summary.js
+++ b/src/reports/dashboard/summary.js
@@ -18,50 +18,54 @@ const Summary = ({ range, compareRange }) => {
}
return <>
-
-
balance)
- }
- previousPromise={
- Statistical.Service.balance({ ...compareBaseCommand, onlyIncome: true })
- .then(({ balance }) => balance)
- }
- currency='EUR' />
+
+
+ balance)
+ }
+ previousPromise={
+ Statistical.Service.balance({ ...compareBaseCommand, onlyIncome: true })
+ .then(({ balance }) => balance)
+ }
+ currency='EUR' />
- Math.abs(balance))
- }
- previousPromise={
- Statistical.Service.balance({ ...compareBaseCommand, onlyIncome: false })
- .then(({ balance }) => Math.abs(balance))
- }
- currency='EUR' />
+ Math.abs(balance))
+ }
+ previousPromise={
+ Statistical.Service.balance({ ...compareBaseCommand, onlyIncome: false })
+ .then(({ balance }) => Math.abs(balance))
+ }
+ currency='EUR' />
+
-
balance)
- }
- previousPromise={
- Statistical.Service.balance({ dateRange: { start: '1970-01-01', end: compareRange.endString() }, allMoney: true })
- .then(({ balance }) => balance)
- }
- currency='EUR' />
+
+ balance)
+ }
+ previousPromise={
+ Statistical.Service.balance({ dateRange: { start: '1970-01-01', end: compareRange.endString() }, allMoney: true })
+ .then(({ balance }) => balance)
+ }
+ currency='EUR' />
-
+
+
>
}
diff --git a/src/transactions/transaction-item.tsx b/src/transactions/transaction-item.tsx
index 8bca8847..f68f5e3e 100644
--- a/src/transactions/transaction-item.tsx
+++ b/src/transactions/transaction-item.tsx
@@ -49,7 +49,7 @@ const TransactionItem: FC = ({ transaction, className = ''
if (deleted) return null
return
-
+
{ transaction.metadata.budget &&
{ transaction.metadata.budget }
@@ -63,7 +63,7 @@ const TransactionItem: FC
= ({ transaction, className = ''
}
- { transaction.description }
+ { transaction.description }
{ transaction.metadata.tags &&
{ transaction.metadata.tags.map(t => ) }
}