Skip to content
This repository has been archived by the owner on May 11, 2021. It is now read-only.

Commit

Permalink
feat(history): add history fetching and view
Browse files Browse the repository at this point in the history
  • Loading branch information
igorkamyshev committed Mar 26, 2019
1 parent e09473d commit 1d95c39
Show file tree
Hide file tree
Showing 14 changed files with 182 additions and 79 deletions.
5 changes: 2 additions & 3 deletions front/src/features/app/features/history/History.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ import { useMemoState } from '@front/domain/store'
import { GroupBy } from '@shared/enum/GroupBy'
import { wantUTC } from '@front/helpers/wantUTC'
import { LoaderTable } from '@front/ui/components/layout/loader-table'
import { historyToTableData, createColumns } from '@front/features/history'

import { FullHistoryButton } from './components/full-history-button'
import { createColumns } from './helpers/createColumns'
import { historyToTableData } from './helpers/historyToTableData'

interface Props {
className?: string
Expand All @@ -34,7 +33,7 @@ export const History = ({ className }: Props) => {
)

const lastOutcomes = useMemo(
() => historyToTableData(history, historyLength),
() => historyToTableData(history, { maxLength: historyLength }),
[history],
)

Expand Down

This file was deleted.

21 changes: 16 additions & 5 deletions front/src/features/history/History.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,30 @@
display: grid;

grid-template:
'incomes currenct outcomes'
/ 1fr 1fr 1fr;
'incomes outcomes'
/ 1fr 1fr;

gap: 16px;

@media (max-width: 768px) {
grid-template:
'income'
'current'
'outcomes';
'incomes'
'outcomes'
/ 1fr;
}

height: calc(100vh - 97px);
overflow: scroll;
}

.tabs {
height: calc(100vh - 97px);
}

.incomes {
grid-area: incomes;
}

.outcomes {
grid-area: outcomes;
}
31 changes: 11 additions & 20 deletions front/src/features/history/History.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useMemo } from 'react'
import { useMemo } from 'react'
import { useMappedState } from 'redux-react-hook'

import { Container } from '@front/ui/components/layout/container'
Expand All @@ -10,6 +10,7 @@ import { pushRoute } from '../routing'
import * as styles from './History.css'
import { createMonths } from './helpers/createMonths'
import { createMonthTitle } from './helpers/createMonthTitle'
import { TransactionList } from './components/transaction-list'

export const History = () => {
const firstTransactionDate = useMappedState(getFirstTransactionDate)
Expand All @@ -19,24 +20,6 @@ export const History = () => {
])
const defaultMonthTitle = useMemo(() => createMonthTitle(new Date()), [])

const renderMonthes = useCallback(
() =>
months.map(month => (
<Tab title={month.title} className={styles.history} key={month.title}>
<aside>
<p>...</p>
</aside>

<section>...</section>

<aside>
<p>...</p>
</aside>
</Tab>
)),
[months],
)

return (
<Container>
<PageHeader title="History" onBack={() => pushRoute('/app')} />
Expand All @@ -46,7 +29,15 @@ export const History = () => {
defaultSelected={defaultMonthTitle}
vertical
>
{renderMonthes()}
{months.map(month => (
<Tab title={month.title} className={styles.history} key={month.title}>
<TransactionList
from={month.from}
to={month.to}
classNames={styles}
/>
</Tab>
))}
</Tabs>
</Container>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { useMappedState } from 'redux-react-hook'

import { getHistory } from '@front/domain/money/selectors/getHistory'
import { GroupBy } from '@shared/enum/GroupBy'
import { useMemoState } from '@front/domain/store'
import { fetchHistory } from '@front/domain/money/actions/fetchHistory'
import { getHistoryFetchingStatus } from '@front/domain/money/selectors/getHistoryFetchingStatus'
import { Loader } from '@front/ui/components/layout/loader'
import { Table } from '@front/ui/components/layout/table'

import { createColumns } from '../../helpers/createColumns'
import { historyToTableData } from '../../helpers/historyToTableData'

interface ClassNames {
incomes: string
outcomes: string
}

interface Props {
from: Date
to: Date
classNames: ClassNames
}

export const TransactionList = ({ from, to, classNames }: Props) => {
const history = useMemoState(
() => getHistory(from, to, GroupBy.Month),
() => fetchHistory(from, to, GroupBy.Month),
[from, to],
)

const fetching = useMappedState(getHistoryFetchingStatus)

const incomeColumns = createColumns('comment', 'Source')
const incomes = historyToTableData(history, {
filter: transaction => transaction.amount > 0,
})

const outcomesColumns = createColumns('comment', 'Category')
const outcomes = historyToTableData(history, {
filter: transaction => transaction.amount < 0,
})

return (
<Loader status={fetching} dataAvaiable={history.nonEmpty()}>
{outcomes.nonEmpty() && (
<Table
className={classNames.outcomes}
title="Outcomes"
columns={outcomesColumns}
data={outcomes.get()}
/>
)}
{incomes.nonEmpty() && (
<Table
className={classNames.incomes}
title="Incomes"
columns={incomeColumns}
data={incomes.get()}
/>
)}
</Loader>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { TransactionList } from './TransactionList'
8 changes: 8 additions & 0 deletions front/src/features/history/helpers/UnifiedTransaction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Currency } from '@shared/enum/Currency'

export interface UnifiedTransaction {
date: Date | undefined
amount: number
currency: Currency
comment: string
}
11 changes: 7 additions & 4 deletions front/src/features/history/helpers/createMonths.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { startOfMonth, addMonths } from 'date-fns'
import { startOfMonth, addMonths, endOfMonth } from 'date-fns'

import { wantUTC } from '@front/helpers/wantUTC'

import { createMonthTitle } from './createMonthTitle'

export const createMonths = (from: Date, to: Date) => {
const groups = []

let now = startOfMonth(from)
let now = wantUTC(startOfMonth)(from)
while (now < to) {
const next = addMonths(now, 1)
const next = wantUTC(addMonths)(now, 1)
groups.push({
title: createMonthTitle(now),
from: now,
to: next,
to: wantUTC(endOfMonth)(now),
})

now = next
Expand Down
62 changes: 62 additions & 0 deletions front/src/features/history/helpers/historyToTableData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Option } from 'tsoption'
import { take, head, sortBy } from 'lodash'

import { HistoryGroupModel } from '@shared/models/money/HistoryGroupModel'
import { displayMoney } from '@shared/helpers/displayMoney'
import { UnifiedTransaction } from './UnifiedTransaction'

type Filter = (transaction: UnifiedTransaction) => boolean
const normalizedFilter = (filter?: Filter) => (
transaction: UnifiedTransaction,
) => {
if (filter) {
return filter(transaction)
}

return true
}

interface Options {
maxLength?: number
filter?: (transaction: UnifiedTransaction) => boolean
}

export const historyToTableData = (
history: Option<HistoryGroupModel[]>,
{ maxLength, filter }: Options,
) =>
history
.flatMap(items => Option.of(head(items)))
.map(item =>
[
...item.incomes.map(income => ({
date: income.date,
amount: income.amount,
currency: income.currency,
comment: income.source,
})),
...item.outcomes.map(outcome => ({
date: outcome.date,
amount: -outcome.amount,
currency: outcome.currency,
comment: outcome.category,
})),
].filter(normalizedFilter(filter)),
)
.map(transactions =>
sortBy(
transactions,
transaction => transaction.date && -transaction.date.valueOf(),
),
)
.map(transactions =>
maxLength ? take(transactions, maxLength) : transactions,
)
.map(transactions =>
transactions.map(transaction => ({
...transaction,
amount: displayMoney(transaction.currency)(transaction.amount, {
withSign: true,
}),
})),
)
3 changes: 3 additions & 0 deletions front/src/features/history/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export { History } from './History'

export { createColumns } from './helpers/createColumns'
export { historyToTableData } from './helpers/historyToTableData'
4 changes: 2 additions & 2 deletions front/src/helpers/wantUTC.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { addHours } from 'date-fns'

export const wantUTC = <T extends []>(f: (d: Date, ...args: T) => Date) => (
date: Date,
export const wantUTC = <D, T extends any[]>(f: (d: D, ...args: T) => Date) => (
date: D,
...args: T
) => {
const newDate = f(date, ...args)
Expand Down
8 changes: 6 additions & 2 deletions front/src/ui/components/layout/loader/Loader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,23 @@ interface Props {
children: ReactNode
skeleton?: boolean
expectedRows?: number
dataAvaiable?: boolean
}

export const Loader = ({
status: { loading, error },
children,
expectedRows,
skeleton = false,
dataAvaiable = true,
}: Props) => {
if (skeleton && loading) {
const showLoader = loading || !dataAvaiable

if (skeleton && showLoader) {
return <Skeleton rows={expectedRows} />
}

if (loading) {
if (showLoader) {
return <p>loading...</p>
}

Expand Down
2 changes: 0 additions & 2 deletions front/src/ui/components/layout/tabs/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ export const Tabs = ({
return children
}, [children])

console.log(getMode(vertical))

return (
<AntTabs
defaultActiveKey={defaultActiveKey}
Expand Down

0 comments on commit 1d95c39

Please sign in to comment.