Skip to content

Commit d36865a

Browse files
authored
Adjust some styling and layouting issues in the front-end (#25)
* Fix styling issue on the pills on the dashboard collapsing wrong. * Fix styling issue on larger displays on transaction-item.tsx * Improve the usability of the pie chart in the transaction page. * Update tooltip default style for charts. * Add currency indication in the graphs on the reports. * Prevent an issue from losing the route when reloading the page. * Make sure the cards on the liability detail page wrap correctly. * Reduce code duplication and fix unused import.
1 parent 5a80b39 commit d36865a

16 files changed

+234
-146
lines changed

src/App.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import TwoFactorCard from "./security/two-factor.card";
2222
import SecurityRepository from "./core/repositories/security-repository";
2323
import RestAPI from "./core/repositories/rest-api";
2424
import { AxiosError } from "axios";
25+
import { CurrencyRepository } from "./core/RestAPI";
2526

2627
const LoginCard = lazy(() => import("./security/login-card"));
2728
const RegisterCard = lazy(() => import("./security/RegisterCard"));
@@ -45,9 +46,13 @@ function App() {
4546
const authenticated = () => {
4647
RestAPI.profile()
4748
.then(() => {
48-
console.log('Profile loaded')
4949
setAuthenticate(true)
5050
setTwoFactor(false)
51+
CurrencyRepository.list().then(() => {
52+
const profile: any = RestAPI.user()
53+
profile.defaultCurrency = CurrencyRepository.cached(profile.currency)
54+
})
55+
5156
})
5257
.catch((ex: AxiosError) => {
5358
if (ex.response?.status === 403) {
@@ -104,6 +109,12 @@ function App() {
104109
);
105110
}
106111

112+
if (sessionStorage.getItem('token')) {
113+
return <div className='h-[100vh] w-full flex justify-center items-center'>
114+
<Layout.Loading />
115+
</div>
116+
}
117+
107118
return (
108119
<Suspense>
109120
<BrowserRouter basename='/ui'>

src/account/liability/liability-detail-page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const LiabilityDetailView = () => {
5151
<BreadCrumbItem label='page.nav.transactions'/>
5252
</BreadCrumbs>
5353

54-
<div className="flex gap-2">
54+
<div className="flex gap-2 flex-wrap">
5555
<Layout.Card className='flex-1'>
5656
<h1 className='font-bold'>{ account.name }</h1>
5757
<div className="flex">

src/config/global-chart-config.js

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,17 @@ const GlobalChartConfig = {
6666
enabled: true,
6767
usePointStyle: true,
6868
position: 'nearest',
69+
backgroundColor: 'white',
70+
bodyColor: 'black',
71+
titleColor: 'black',
72+
borderColor: 'black',
73+
borderWidth: .5,
6974
callbacks: {
75+
title: (context) => context.label,
76+
label: (context) => {
77+
const value = context.parsed?.y ?? context.parsed.value;
78+
return `${value}`
79+
},
7080
labelPointStyle: (_) => {
7181
return {
7282
pointStyle: 'triangle',
@@ -189,28 +199,17 @@ const Service = {
189199
}
190200

191201
export const defaultGraphColors = [
192-
'#E0FFFF',
193-
'#00CED1',
194-
'#40E0D0',
195-
'#48D1CC',
196-
'#AFEEEE',
197-
'#7FFFD4',
198-
'#B0E0E6',
199-
'#5F9EA0',
200-
'#66CDAA',
201-
'#3CB371',
202-
'#20B2AA',
203-
'#2F4F4F',
204-
'#008080',
205-
'#008B8B',
206-
'#32CD32',
207-
'#90EE90',
208-
'#ADFF2F',
209-
'#90EE90',
210-
'#ADFF2F',
211-
'#7FFF00',
212-
'#7FFF00',
213-
'#6B8E23',
202+
'rgba(25, 25, 112, 0.8)', // Midnight Blue
203+
'rgba(0, 0, 128, 0.8)', // Navy Blue
204+
'rgba(0, 0, 139, 0.8)', // Dark Blue
205+
'rgba(0, 0, 156, 0.8)', // Medium Blue
206+
'rgba(0, 0, 205, 0.8)', // Medium Blue
207+
'rgba(0, 0, 255, 0.8)', // Blue
208+
'rgba(70, 130, 180, 0.8)', // Steel Blue
209+
'rgba(100, 149, 237, 0.8)', // Cornflower Blue
210+
'rgba(135, 206, 235, 0.8)', // Sky Blue
211+
'rgba(135, 206, 250, 0.8)', // Light Sky Blue
212+
'rgba(240, 248, 255, 0.8)', // Alice Blue
214213
]
215214

216215
export {

src/core/RestAPI.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,20 @@ const TransactionRepository = (api => {
4242
})(RestApi)
4343

4444
const CurrencyRepository = (api => {
45+
let knownCurrencies = []
4546
return {
46-
list: () => api.get('settings/currencies'),
47+
list: () => api.get('settings/currencies').then(currencies => {
48+
knownCurrencies = currencies
49+
return currencies
50+
}),
4751
get: code => api.get(`settings/currencies/${code}`),
4852
change: (code, enabled) => api.patch(`settings/currencies/${code}`, { enabled: enabled })
53+
.then(response => {
54+
const currency = knownCurrencies.find(currency => currency.code === code)
55+
currency.enabled = enabled
56+
return response
57+
}),
58+
cached: (code) => knownCurrencies.find(currency => currency.code === code)
4959
}
5060
})(RestApi)
5161

src/core/graphs/categorized-pie-chart.tsx

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { isArray } from "chart.js/helpers";
55
import { Account } from "../types";
66
import StatisticalRepository from "../repositories/statistical-repository";
77
import { Chart } from "react-chartjs-2";
8-
import { ChartData } from "chart.js";
8+
import { ChartData, Tooltip, TooltipPosition } from "chart.js";
99
import { defaultGraphColors } from "../../config/global-chart-config";
1010

1111
type CategorizedPieChartProps = {
@@ -15,8 +15,17 @@ type CategorizedPieChartProps = {
1515
accounts?: Account[] | Account
1616
}
1717

18+
let lastPosition: TooltipPosition
19+
(Tooltip.positioners as any)['center'] = (_: any[], eventPosition: any) => {
20+
const chartArea = eventPosition.chart?.chartArea
21+
if (!chartArea) return lastPosition
22+
23+
lastPosition = { x: chartArea.right / 2 - 40, y: chartArea.bottom / 2 }
24+
return lastPosition
25+
}
26+
1827
const CategorizedPieChart: FC<CategorizedPieChartProps> = ({ id, split, incomeOnly, accounts = [] }) => {
19-
const [pieSeries, setPieSeries] = useState<ChartData | undefined>(undefined)
28+
const [pieSeries, setPieSeries] = useState<ChartData<'doughnut'> | undefined>(undefined)
2029
const [range] = useDateRange()
2130

2231
useEffect(() => {
@@ -44,39 +53,46 @@ const CategorizedPieChart: FC<CategorizedPieChartProps> = ({ id, split, incomeOn
4453
})
4554
}, [split, incomeOnly, range]) // eslint-disable-line react-hooks/exhaustive-deps
4655

56+
const currency = accounts && !isArray(accounts) ? accounts.account.currency : '€'
57+
4758
if (!pieSeries) return <Layout.Loading />
4859
return <>
4960
<Chart id={ id }
50-
type='pie'
61+
type='doughnut'
5162
height={ 300 }
5263
data={ pieSeries }
5364
options={
5465
{
66+
cutout: '65%',
5567
elements: {
5668
arc: {
69+
hoverOffset: 15,
70+
borderWidth: .5,
5771
backgroundColor: (context : any) => defaultGraphColors[context.dataIndex]
5872
}
5973
},
6074
plugins: {
6175
legend: {
62-
display: true,
63-
position: 'right'
76+
display: false,
6477
},
6578
tooltip: {
79+
backgroundColor: 'white',
80+
bodyColor: 'black',
81+
titleColor: 'black',
82+
cornerRadius: 0,
83+
caretSize: 0,
84+
position: 'center',
85+
bodyAlign: 'left',
6686
callbacks: {
6787
title: (context : any) => context.label,
6888
label: (context: any) => {
69-
if (accounts && !isArray(accounts)) {
70-
return `${context.raw} ${accounts?.account?.currency}`
71-
}
72-
73-
return context.raw
89+
return ` ${currency}${context.raw}`
7490
}
7591
}
7692
}
7793
},
7894
maintainAspectRatio: false
79-
}}/>
95+
} as any }/>
8096
</>
8197
}
8298

src/core/layout/Card.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const Card: FC<CardProps> = ({ title, actions, buttons, children, className = ''
3232
{actions && <div className='font-normal text-sm'>{ actions }</div>}
3333
</header>
3434
)}
35-
<article className='bg-white p-5 first:rounded-t-lg last:rounded-b-lg'>
35+
<article className='bg-white p-4 first:rounded-t-lg last:rounded-b-lg'>
3636
{children}
3737
</article>
3838
{buttons &&
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Chart } from "react-chartjs-2";
2+
import { DefaultChartConfig, Service } from "../../config/global-chart-config";
3+
import React from "react";
4+
import { ChartData } from "chart.js";
5+
6+
const BudgetChart = ({ dataSet, currencySymbol = '' } : { dataSet: ChartData, currencySymbol: string }) => {
7+
return <Chart type='line'
8+
height={ 300 }
9+
options={ Service.mergeOptions(DefaultChartConfig.line,{
10+
scales: {
11+
x: {
12+
time: {
13+
unit: 'month'
14+
}
15+
},
16+
y: {
17+
ticks: {
18+
callback: (value: any) => `${currencySymbol}${value}`
19+
}
20+
}
21+
},
22+
plugins: {
23+
legend: {
24+
display: true
25+
}
26+
}
27+
}) }
28+
data={ dataSet } />
29+
}
30+
31+
export default BudgetChart

src/reports/budget-monthly/budget-yearly-expense.tsx

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,19 @@ import { Dates, Layout, Translations } from "../../core";
33
import { ChartData } from "chart.js";
44
import { Budget, BudgetExpense } from "../../core/types";
55
import StatisticalRepository from "../../core/repositories/statistical-repository";
6-
import { Chart } from "react-chartjs-2";
7-
import { DefaultChartConfig, Service } from "../../config/global-chart-config";
6+
import BudgetChart from "./budget-chart";
87

98
type BudgetYearlyExpenseProps = {
109
year: number,
11-
budgets: Budget[]
10+
budgets: Budget[],
11+
currencySymbol: string
1212
}
1313

14-
const BudgetYearlyExpense = ({ year, budgets } : BudgetYearlyExpenseProps) => {
14+
const BudgetYearlyExpense = ({ year, budgets, currencySymbol } : BudgetYearlyExpenseProps) => {
1515
const [chartData, setChartData] = useState<ChartData | undefined>()
1616

1717
useEffect(() => {
1818
if (budgets.length === 0) return
19-
console.info(`BudgetYearlyExpense: ${year} ${budgets.length}`)
2019
setChartData(undefined)
2120

2221
const uniqueExpenses = budgets.reduce((left, right) => [...left, ...right.expenses], new Array<BudgetExpense>())
@@ -54,25 +53,7 @@ const BudgetYearlyExpense = ({ year, budgets } : BudgetYearlyExpenseProps) => {
5453
return <>
5554
<Layout.Card title='page.reports.budget.expensePercent'>
5655
{ !chartData && <Layout.Loading /> }
57-
{ chartData && <>
58-
<Chart type='line'
59-
height={ 300 }
60-
options={ Service.mergeOptions(DefaultChartConfig.line,{
61-
scales: {
62-
x: {
63-
time: {
64-
unit: 'month'
65-
}
66-
}
67-
},
68-
plugins: {
69-
legend: {
70-
display: true
71-
}
72-
}
73-
}) }
74-
data={ chartData } />
75-
</> }
56+
{ chartData && <BudgetChart dataSet={ chartData } currencySymbol={ currencySymbol } /> }
7657
</Layout.Card>
7758
</>
7859
}

src/reports/budget-monthly/budget-yearly-income.tsx

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ import React, { useEffect, useState } from "react";
22
import { Dates, Layout, Statistical, Translations } from "../../core";
33
import { Budget } from "../../core/types";
44
import { ChartData } from "chart.js";
5-
import { Chart } from "react-chartjs-2";
6-
import { DefaultChartConfig, Service } from "../../config/global-chart-config";
5+
import BudgetChart from "./budget-chart";
76

87
type BudgetYearlyExpenseProps = {
98
year: number,
10-
budgets: Budget[]
9+
budgets: Budget[],
10+
currencySymbol: string
1111
}
1212

13-
const YearlyIncomeGraphComponent = ({ year = 1970, budgets = [] } : BudgetYearlyExpenseProps) => {
13+
const YearlyIncomeGraphComponent = ({ year = 1970, budgets = [], currencySymbol = '' } : BudgetYearlyExpenseProps) => {
1414
const [chartData, setChartData] = useState<ChartData | undefined>()
1515

1616
useEffect(() => {
@@ -46,25 +46,7 @@ const YearlyIncomeGraphComponent = ({ year = 1970, budgets = [] } : BudgetYearly
4646
return <>
4747
<Layout.Card title='page.reports.budget.incomePercent'>
4848
{ !chartData && <Layout.Loading /> }
49-
{ chartData && <>
50-
<Chart type='line'
51-
height={ 300 }
52-
options={ Service.mergeOptions(DefaultChartConfig.line,{
53-
scales: {
54-
x: {
55-
time: {
56-
unit: 'month'
57-
}
58-
}
59-
},
60-
plugins: {
61-
legend: {
62-
display: true
63-
}
64-
}
65-
}) }
66-
data={ chartData } />
67-
</> }
49+
{ chartData && <BudgetChart dataSet={ chartData } currencySymbol={ currencySymbol } /> }
6850
</Layout.Card>
6951
</>
7052
}

src/reports/budget-monthly/index.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ import BudgetYearlyExpense from "./budget-yearly-expense";
1818

1919
import '../../assets/css/BudgetReportView.scss'
2020
import BudgetRepository from "../../core/repositories/budget.repository";
21+
import { CurrencyRepository } from "../../core/RestAPI";
2122

2223
export const BudgetReportView = () => {
24+
const [currencySymbol, setCurrencySymbol] = useState('')
2325
const [range, setRange] = useState(() => Dates.Ranges.currentYear())
2426
const { currency = 'EUR', year = new Date().getFullYear() } = useParams()
2527
const [budgets, setBudgets] = useState([])
@@ -36,6 +38,10 @@ export const BudgetReportView = () => {
3638
.catch(console.error)
3739
}
3840
}, [year])
41+
useEffect(() => {
42+
CurrencyRepository.get(currency)
43+
.then((c) => setCurrencySymbol(c.symbol))
44+
}, [currency])
3945

4046
const onDateChanged = ({
4147
newYear = year,
@@ -60,8 +66,8 @@ export const BudgetReportView = () => {
6066
</Layout.Grid>
6167

6268
<Layout.Grid type='column' minWidth='25em'>
63-
<YearlyIncomeGraphComponent year={parseInt(year)} budgets={budgets}/>
64-
<BudgetYearlyExpense year={parseInt(year)} budgets={budgets}/>
69+
<YearlyIncomeGraphComponent year={parseInt(year)} budgets={budgets} currencySymbol={ currencySymbol } />
70+
<BudgetYearlyExpense year={parseInt(year)} budgets={budgets} currencySymbol={ currencySymbol }/>
6571
</Layout.Grid>
6672

6773
<Layout.Card>

0 commit comments

Comments
 (0)