Skip to content

Commit 7a7efe5

Browse files
committed
Minor style updates in the reports.
1 parent 1a85654 commit 7a7efe5

File tree

14 files changed

+172
-130
lines changed

14 files changed

+172
-130
lines changed

src/components/budget/budget-detail.component.tsx

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Column } from "primereact/column";
33
import { DataTable } from "primereact/datatable";
44
import { Dialog } from "primereact/dialog";
55
import React, { useEffect, useState } from "react";
6+
import { Link } from "react-router";
67
import { i10n } from "../../config/prime-locale";
78
import { useNotification } from "../../context/notification-context";
89
import BudgetRepository, { ComputedExpense } from "../../core/repositories/budget.repository";
@@ -33,7 +34,8 @@ const AddExpenseDialog = ({ onChange }: { onChange: () => void }) => {
3334
}
3435

3536
return <>
36-
<Button severity='success' label='page.budget.group.action.addExpense' icon={ mdiPlus } onClick={ () => setVisible(true) }/>
37+
<Button severity='success' label='page.budget.group.action.addExpense' icon={ mdiPlus }
38+
onClick={ () => setVisible(true) }/>
3739
<Dialog header={ i10n('page.title.budget.group.expense.add') }
3840
visible={ visible }
3941
onHide={ () => setVisible(false) }>
@@ -51,8 +53,8 @@ const AddExpenseDialog = ({ onChange }: { onChange: () => void }) => {
5153
<Button type='reset'
5254
text
5355
onClick={ () => setVisible(false) }
54-
label='common.action.cancel' icon={ mdiCancel } />
55-
<SubmitButton label='common.action.save' icon={ mdiContentSave } />
56+
label='common.action.cancel' icon={ mdiCancel }/>
57+
<SubmitButton label='common.action.save' icon={ mdiContentSave }/>
5658
</div>
5759
</Form>
5860

@@ -129,15 +131,18 @@ const BudgetDetailComponent = ({ range }: { range: DateRange }) => {
129131
</div>
130132

131133
<DataTable value={ budget.expenses } loading={ !budget }>
132-
<Column field='name' header={ i10n('Budget.Expense.name') }/>
134+
<Column field='name' header={ i10n('Budget.Expense.name') }
135+
body={ (expense: BudgetExpense) => budgetName(range.year(), range.month(), expense) }/>
133136
<Column body={ (expense: BudgetExpense) => <MoneyComponent money={ expense.expected }/> }
134137
header={ i10n('page.budget.group.expense.budgeted') }/>
135-
<Column body={ (expense: BudgetExpense) => <MoneyComponent money={ getComputedExpense(expense.id)?.computed.spent }/> }
136-
header={ i10n('page.budget.group.expense.spent') }/>
137-
<Column body={ (expense: BudgetExpense) => <MoneyComponent money={ getComputedExpense(expense.id)?.computed.left }/> }
138-
header={ i10n('page.budget.group.expense.left') }/>
138+
<Column
139+
body={ (expense: BudgetExpense) => <MoneyComponent money={ getComputedExpense(expense.id)?.computed.spent }/> }
140+
header={ i10n('page.budget.group.expense.spent') }/>
141+
<Column
142+
body={ (expense: BudgetExpense) => <MoneyComponent money={ getComputedExpense(expense.id)?.computed.left }/> }
143+
header={ i10n('page.budget.group.expense.left') }/>
139144
<Column className='w-[2rem]'
140-
body={ (expense: BudgetExpense) => <ExpenseActions expense={ expense } callback={ loadBudget } /> }/>
145+
body={ (expense: BudgetExpense) => <ExpenseActions expense={ expense } callback={ loadBudget }/> }/>
141146
</DataTable>
142147

143148
<div className='flex justify-end mt-4'>
@@ -146,4 +151,14 @@ const BudgetDetailComponent = ({ range }: { range: DateRange }) => {
146151
</>
147152
}
148153

154+
const budgetName = (year: number, month: number, expense: BudgetExpense) => {
155+
return <>
156+
<Link to={ `/transactions/income-expense/${ year }/${ month }?budget=${ expense.id }` }
157+
title='go to transactions'
158+
className='text-blue-500 hover:underline hover:text-blue-700'>
159+
{ expense.name }
160+
</Link>
161+
</>
162+
}
163+
149164
export default BudgetDetailComponent

src/components/form/input/PasswordInput.tsx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import { InputIcon } from "primereact/inputicon";
12
import React, { FC } from "react";
23
import Icon from "@mdi/react";
34
import { mdiAlertCircle, mdiCheck } from "@mdi/js";
45
import { useInputField } from "./InputGroup";
56
import { FieldType, ValidatorType } from "../form-types";
67
import { i10n } from "../../../config/prime-locale";
78
import { InputText } from "primereact/inputtext";
9+
import { IconField } from "primereact/iconfield";
810

911
const validations: ValidatorType[] = [
1012
{ label: 'Account.password.at_least_six_chars', validate: value => value && RegExp(/^.{6,63}$/).test(value) },
@@ -37,14 +39,17 @@ export const PasswordInput: FC<PasswordInputProps> = (props) => {
3739
<div className="flex flex-col gap-2 mt-2">
3840
<label htmlFor={ props.id } className='font-bold'
3941
data-testid={ `${ props.id }-label` }>{ i10n(props.title as string) }{ props.required ? ' *' : '' }</label>
40-
<InputText id={ props.id }
41-
type='password'
42-
defaultValue={ field.value || props.value }
43-
required={ props.required }
44-
pattern={ props.pattern }
45-
data-testid={ `${ props.id }-input` }
46-
invalid={ field.touched ? errors.length > 0 : undefined }
47-
onChange={ onChange }/>
42+
<IconField iconPosition='left' className='[&.p-icon-field>.p-inputtext]:w-full'>
43+
<InputIcon className={ 'pi pi-lock' }/>
44+
<InputText id={ props.id }
45+
type='password'
46+
defaultValue={ field.value || props.value }
47+
required={ props.required }
48+
pattern={ props.pattern }
49+
data-testid={ `${ props.id }-input` }
50+
invalid={ field.touched ? errors.length > 0 : undefined }
51+
onChange={ onChange }/>
52+
</IconField>
4853
</div>
4954

5055
<div className='py-4 px-2 my-3 mx-2 rounded-sm border-solid border-[1px] border-separator shadow-xl'>

src/components/form/input/TextInput.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export const TextInput: FC<TextInputProps> = (props) => {
4545
<div className={ `flex flex-col gap-2 mt-2 ${ props.className || '' }` }>
4646
<label htmlFor={ props.id }
4747
className='font-bold'>{ i10n(props.title as string) }{ props.required ? ' *' : '' }</label>
48-
{ props.icon && <IconField iconPosition='left'><InputIcon className={ 'pi pi-'+ props.icon }/>{inputField}</IconField> }
48+
{ props.icon && <IconField iconPosition='left' className='[&.p-icon-field>.p-inputtext]:w-full'><InputIcon className={ 'pi pi-'+ props.icon }/>{inputField}</IconField> }
4949
{ !props.icon && inputField }
5050
{ field.touched && <InputValidationErrors field={ field } errors={ errors }/> }
5151
</div>

src/components/reports/budget-monthly/monthly-table.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const MonthlyPerBudgetTableComponent = ({ budgets, year, currency }: MonthlyPerB
6161

6262
return <>
6363
<DataTable value={ expenses } loading={ !expenses } size='small'>
64-
<Column header={ i10n('Budget.Expense.name') } field='name' />
64+
<Column header={ i10n('Budget.Expense.name') } field='name' sortable />
6565
{ [...new Array(12).keys()].map(month =>
6666
<Column key={ month }
6767
headerClassName='min-w-[7rem]'

src/components/reports/category-monthly/categorized-monthly-spending.component.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ const CategorizedMonthlySpendingComponent = ({ currency, year }: CategorizedMont
5757

5858

5959
return <>
60-
<DataTable value={ expenses } loading={ !expenses } size='small'>
61-
<Column header={ i10n('Category.label') } field='name' bodyClassName='font-bold' frozen={ true } alignFrozen='left' />
60+
<DataTable value={ expenses } loading={ !expenses } size='small' sortField='name' sortOrder={ 1 }>
61+
<Column header={ i10n('Category.label') } field='name' bodyClassName='font-bold' sortable frozen />
6262
{ [...new Array(12).keys()].map(month =>
6363
<Column key={ month }
6464
headerClassName='min-w-[7rem]'

src/components/transaction/list-filters.component.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ export type TransactionFilter = {
1818
export type FilterChangeHandler = (_: TransactionFilter) => void
1919

2020
type TransactionFiltersProps = {
21-
onChange: FilterChangeHandler
21+
onChange: FilterChangeHandler,
22+
activeFilter: TransactionFilter
2223
}
2324

24-
const TransactionFilters: FC<TransactionFiltersProps> = ({ onChange }) => {
25+
const TransactionFilters: FC<TransactionFiltersProps> = ({ onChange, activeFilter }) => {
2526

2627
const onSubmit = (form: any) => {
2728
const filter = {
@@ -63,6 +64,7 @@ const TransactionFilters: FC<TransactionFiltersProps> = ({ onChange }) => {
6364
title='page.transactions.filter.category'/>
6465
<Entity.Budget id='budget'
6566
className='flex-1'
67+
value={ activeFilter.budget }
6668
title='page.transactions.filter.budget'/>
6769
<div className='flex-1'/>
6870
</div>

src/components/transaction/transaction-list.component.tsx

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import React, { FC, useEffect, useState } from "react";
2+
import { useRouteLoaderData } from "react-router";
3+
import { i10n } from "../../config/prime-locale";
24
import { Resolver } from "../../core";
3-
import DateRange from "../../types/date-range.type";
4-
import MoneyComponent from "../format/money.component";
5-
import { Paginator } from "../layout/paginator.component";
6-
import { DailyTransactions, groupTransactionByDay } from "../../reducers";
75
import { TransactionRepository } from "../../core/RestAPI";
8-
import { Pagination } from "../../types/types";
96
import useQueryParam from "../../hooks/query-param.hook";
10-
import TransactionItem from "./transaction-detail.component";
7+
import { DailyTransactions, groupTransactionByDay } from "../../reducers";
8+
import DateRange from "../../types/date-range.type";
9+
import { Pagination } from "../../types/types";
10+
import MoneyComponent from "../format/money.component";
1111
import Loading from "../layout/loading.component";
12-
import Translation from "../localization/translation.component";
12+
import { Paginator } from "../layout/paginator.component";
1313
import TransactionFilters, { TransactionFilter } from "./list-filters.component";
14+
import TransactionItem from "./transaction-detail.component";
1415

1516
type TransactionOverviewProps = {
1617
range: DateRange,
@@ -19,7 +20,10 @@ type TransactionOverviewProps = {
1920

2021
const TransactionOverview: FC<TransactionOverviewProps> = ({ range, transfers }) => {
2122
const [page] = useQueryParam({ key: 'page', initialValue: "1" })
22-
const [searchCommand, setSearchCommand] = useState({})
23+
const [searchCommand, setSearchCommand] = useState<TransactionFilter>(() => {
24+
const { searchCommand } = useRouteLoaderData('income-expense')
25+
return searchCommand
26+
})
2327
const [transactions, setTransactions] = useState<DailyTransactions | undefined>(undefined)
2428
const [pagination, setPagination] = useState<Pagination>()
2529

@@ -60,7 +64,7 @@ const TransactionOverview: FC<TransactionOverviewProps> = ({ range, transfers })
6064
const showPagination = pagination && pagination?.records > pagination?.pageSize
6165

6266
return <>
63-
{ !transfers && <TransactionFilters onChange={ onFilterChange }/> }
67+
{ !transfers && <TransactionFilters onChange={ onFilterChange } activeFilter={ searchCommand }/> }
6468

6569
{ !isLoaded && <Loading/> }
6670

@@ -75,18 +79,14 @@ const TransactionOverview: FC<TransactionOverviewProps> = ({ range, transfers })
7579

7680
return <div key={ key } className='flex flex-col gap-0.5 pb-3'>
7781
<div
78-
className='flex gap-2 items-center border-b-[1px] pb-1 mb-1 px-2 md:rounded-lg bg-blue-300/10 md:bg-blue-200/20'>
79-
<div className='font-bold text-lg[1.5em] text-muted'>
82+
className='flex gap-2 items-center border-b-[1px] py-1 mb-1 px-2 md:rounded-lg bg-blue-300/10 md:bg-blue-200/20'>
83+
<div className='font-bold text-[1.25em] text-muted'>
8084
{ date.getDate() }
8185
</div>
82-
<div className='flex flex-col'>
83-
<span className='text-[.9em] text-neutral-500'>
84-
{ `${ date.getFullYear() }.${ date.getMonth() }` }
85-
</span>
86-
<span className='rounded-sm bg-gray-300 py-0.5 text-[.75em] text-white text-center font-bold'>
87-
<Translation label={ `common.weekday.${ date.getDay() }` }/>
88-
</span>
86+
<div className='rounded-sm bg-gray-300 text-[.75em] text-white text-center font-bold px-1 py-0.25'>
87+
{ i10n(`common.weekday.${ date.getDay() }`) }
8988
</div>
89+
<span className='text-xs text-muted'>{ date.getFullYear() }.{ date.getMonth() }</span>
9090
{ !transfers && <>
9191
<div className='flex-1 justify-end flex gap-16 font-bold'>
9292
{ income !== 0 && <MoneyComponent money={ income }/> }

src/hooks/date-range.hook.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ import DateRangeService from "../service/date-range.service";
66
/**
77
* Consume a range from the path params {@code year} and {@code month}.
88
*/
9-
const useDateRange = () : [DateRange] => {
10-
const { year, month } = useParams()
11-
const [range, setRange] = useState(() => DateRangeService.currentMonth())
9+
const useDateRange = (): [DateRange] => {
10+
const { year, month } = useParams()
11+
const [range, setRange] = useState(() => DateRangeService.currentMonth())
1212

13-
useEffect(() => {
14-
if (year && month) setRange(DateRangeService.forMonth(parseInt(year), parseInt(month)))
15-
}, [year, month])
13+
useEffect(() => {
14+
if (year && !month) setRange(DateRangeService.forYear(parseInt(year)))
15+
if (year && month) setRange(DateRangeService.forMonth(parseInt(year), parseInt(month)))
16+
}, [year, month])
1617

17-
return [range]
18+
return [range]
1819
}
1920

20-
export default useDateRange
21+
export default useDateRange

src/pages/budget/routes.ts

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,25 @@ import { lazy } from "react";
22
import { RouteObject } from "react-router";
33

44
const routes = {
5-
id: 'budget',
6-
path: 'budgets',
7-
children: [
8-
{
9-
id: 'budget-overview',
10-
path: '',
11-
Component: lazy(() => import('./index')),
12-
},
13-
{
14-
id: 'budget-overview-monthly',
15-
path: ':year/:month',
16-
Component: lazy(() => import('./index')),
17-
},
18-
{
19-
id: 'budget-initial',
20-
path: 'first-setup',
21-
Component: lazy(() => import('./initial-budget')),
22-
}
23-
]
5+
id: 'budget',
6+
path: 'budgets',
7+
children: [
8+
{
9+
id: 'budget-overview',
10+
path: '',
11+
Component: lazy(() => import('./index')),
12+
},
13+
{
14+
id: 'budget-overview-monthly',
15+
path: ':year/:month',
16+
Component: lazy(() => import('./index')),
17+
},
18+
{
19+
id: 'budget-initial',
20+
path: 'first-setup',
21+
Component: lazy(() => import('./initial-budget')),
22+
}
23+
]
2424
} as RouteObject
2525

26-
export default routes
26+
export default routes

src/pages/login.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,15 @@ const LoginCard = () => {
3535
{ label: 'Deutsch', icon: () => <Flag language='de'/>, command: () => setLocale('de') }
3636
]
3737

38-
const header = <div className='p-4 flex justify-between relative overflow-hidden'>
39-
<span className="text-2xl font-bold text-primary">Pledger.io</span>
38+
const header = <div className='p-4 flex justify-between items-center relative overflow-hidden bg-gray-700/20 border-b-gray-500/20 border-b-1'>
39+
<span/>
40+
<span className="text-2xl font-bold text-blue-800/70">Pledger.io</span>
4041
<Menu model={ languageMenu } popup ref={ configMenu }/>
4142
<button type='button' className="cursor-pointer z-10 p-2 hover:bg-gray-100 rounded-full transition-all"
4243
onClick={ (e) => configMenu?.current?.toggle(e) }
4344
role='button'>
4445
<Icon path={ mdiWeb } size={ 1 }/>
4546
</button>
46-
<img src='/ui/images/login-bg.png' className='z-[0] opacity-60 absolute left-0 right-0 top-0 bottom-0'
47-
alt='background'/>
4847
</div>
4948

5049
const onSubmit = (entity: LoginForm) =>
@@ -84,15 +83,13 @@ const LoginCard = () => {
8483
autocomplete='username'
8584
type='text'
8685
icon='user'
87-
className='[&>.p-icon-field>.p-inputtext]:w-full'
8886
required/>
8987

9088
<Input.Text id='password'
9189
title='UserAccount.password'
9290
autocomplete='current-password'
9391
icon='lock'
9492
type='password'
95-
className='[&>.p-icon-field>.p-inputtext]:w-full'
9693
required/>
9794

9895
<div className='flex pt-3 items-stretch'>
@@ -107,7 +104,7 @@ const LoginCard = () => {
107104
</Divider>
108105

109106
<div className='flex justify-center mt-3'>
110-
<Link to={ `/register?from=${ from }` } className='p-button p-button-outlined p-button-lg flex gap-2 items-center w-full justify-center'>
107+
<Link to={ `/register?from=${ from }` } className='p-button p-button-info p-button-outlined p-button-lg flex gap-2 items-center w-full justify-center'>
111108
<Icon path={ mdiAccountPlus } size={ 1 }/>
112109
{ i10n('page.login.register') }
113110
</Link>

0 commit comments

Comments
 (0)