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

Commit

Permalink
Merge pull request #41 from igorkamyshev/history-layout
Browse files Browse the repository at this point in the history
History layout
  • Loading branch information
igorkamyshev authored Feb 19, 2019
2 parents 994c221 + 73315bf commit f0c5aad
Show file tree
Hide file tree
Showing 22 changed files with 337 additions and 120 deletions.
16 changes: 13 additions & 3 deletions back/src/money/presentation/http/controller/HistoryController.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Controller, Get, Query } from '@nestjs/common'
import {
ApiBearerAuth,
ApiImplicitQuery,
ApiOkResponse,
ApiOperation,
ApiUseTags,
} from '@nestjs/swagger'
import { reverse, sortBy } from 'lodash'

import { Historian } from '@back/money/application/Historian'
import { AbstractTransaction } from '@back/money/domain/dto/AbstarctTransaction'
import { TokenPayload } from '@back/user/application/dto/TokenPayload'
import { CurrentUser } from '@back/user/presentation/http/decorator/CurrentUser'
import { OnlyForUsers } from '@back/user/presentation/http/security/OnlyForUsers'
Expand Down Expand Up @@ -41,8 +42,17 @@ export class HistoryController {
): Promise<HistoryGroupResponse[]> {
const history = await this.historian.showGroupedHistory(login, range, by)

return history.map(({ title, incomes, outcomes }) =>
HistoryGroupResponse.fromPair(title, incomes, outcomes),
const sorter = (transaction: AbstractTransaction) =>
-transaction.date.valueOf()

return reverse(
history.map(({ title, incomes, outcomes }) =>
HistoryGroupResponse.fromPair(
title,
sortBy(incomes, income => sorter(income)),
sortBy(outcomes, outcome => sorter(outcome)),
),
),
)
}

Expand Down
2 changes: 2 additions & 0 deletions front/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"antd": "^3.13.4",
"args-parser": "^1.1.0",
"axios": "^0.18.0",
"classnames": "^2.2.6",
"cookie-parser": "^1.4.3",
"express": "^4.16.4",
"final-form": "^4.11.1",
Expand All @@ -35,6 +36,7 @@
"utility-types": "^3.4.1"
},
"devDependencies": {
"@types/classnames": "^2.2.7",
"@types/js-cookie": "^2.2.0",
"@types/lodash": "^4.14.120",
"@types/next": "^7.0.7",
Expand Down
54 changes: 42 additions & 12 deletions front/src/features/app/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,54 @@
gap: 16px;
padding: 24px;

& > *:nth-child(odd) {
justify-self: end;
}

& > *:nth-child(even) {
justify-self: start;
}

@media (max-width: 576px) {
grid-template:
'outcome'
'income'
'history'
'stats';
}
}

.income {
grid-area: income;
justify-self: start;

max-width: 500px;

@media (max-width: 768px) {
width: 100%;
}
@media (max-width: 576px) {
justify-self: stretch;
}
}

& > *:nth-child(even),
& > *:nth-child(odd) {
justify-self: stretch;
}
.outcome {
grid-area: outcome;

justify-self: end;
max-width: 500px;

@media (max-width: 768px) {
width: 100%;
}
@media (max-width: 576px) {
justify-self: stretch;
}
}

.history {
grid-area: history;
justify-self: center;

min-width: 1016px;

@media (max-width: 1064px) {
min-width: 100%;
}

@media (max-width: 576px) {
justify-self: stretch;
}
}
6 changes: 3 additions & 3 deletions front/src/features/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import { Stats } from './features/stats'
export const App = () => (
<>
<section className={styles.app}>
<CreateOutcome />
<CreateIncome />
<CreateOutcome className={styles.outcome} />
<CreateIncome className={styles.income} />
<History className={styles.history} />
</section>
<History />
<Stats />
</>
)
8 changes: 0 additions & 8 deletions front/src/features/app/features/create/SimpleForm.css
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
.container {
max-width: 500px;

@media (max-width: 768px) {
width: 100%;
}
}

.form {
display: grid;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import { IncomeModel } from '@shared/models/money/IncomeModel'

import * as styles from '../SimpleForm.css'

export const CreateIncome = () => {
interface Props {
className?: string
}

export const CreateIncome = ({ className }: Props) => {
const create = useCreateIncome()

const fieldsToIncomeModel = useCallback(
Expand All @@ -43,7 +47,7 @@ export const CreateIncome = () => {
{({ handleSubmit, form: { initialize }, values, initialValues }) => (
<form
onSubmit={e => handleSubmit(e)!.then(() => initialize(initialValues))}
className={styles.container}
className={className}
>
<Card title="Create new income" className={styles.form}>
<Label text="Amount" className={styles.amount}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import { OutcomeModel } from '@shared/models/money/OutcomeModel'

import * as styles from '../SimpleForm.css'

export const CreateOutcome = () => {
interface Props {
className?: string
}

export const CreateOutcome = ({ className }: Props) => {
const create = useCreateOutcome()

const fieldsToOutcomeModel = useCallback(
Expand All @@ -43,7 +47,7 @@ export const CreateOutcome = () => {
{({ handleSubmit, form: { initialize }, values, initialValues }) => (
<form
onSubmit={e => handleSubmit(e)!.then(() => initialize(initialValues))}
className={styles.container}
className={className}
>
<Card title="Create new outcome" className={styles.form}>
<Label text="Amount" className={styles.amount}>
Expand Down
50 changes: 50 additions & 0 deletions front/src/features/app/features/history/History.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
.header {
display: flex;
align-items: flex-end;
padding-top: 8px;
padding-bottom: 8px;

& > * {
margin-right: 16px;
}

@media (max-width: 576px) {
flex-direction: column;
align-items: stretch;

& > *:not(:first-child) {
margin-top: 16px;
margin-right: 0px;
}
}
}

.title {
margin-bottom: 0px;
}

.dataSet {
display: grid;

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

@media (max-width: 576px) {
grid-template:
'outcomes'
'incomes';
}

gap: 16px;
padding-top: 8px;
padding-bottom: 8px;
}

.outcomes {
grid-area: outcomes;
}

.incomes {
grid-area: incomes;
}
64 changes: 41 additions & 23 deletions front/src/features/app/features/history/History.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,72 @@
import { useCallback, useEffect, useState } from 'react'
import { endOfMonth, startOfMonth } from 'date-fns'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useDispatch, useMappedState } from 'redux-react-hook'

import { fetchHistory } from '@front/domain/money/actions/fetchHistory'
import { getFirstTransactionDate } from '@front/domain/money/selectors/getFirstTransactionDate'
import { getHistory } from '@front/domain/money/selectors/getHistory'
import { getHistoryFetchingStatus } from '@front/domain/money/selectors/getHistoryFetchingStatus'
import { Loader } from '@front/ui/molecules/loader'
import { Groupment } from '@front/ui/organisms/groupment'
import { Period } from '@front/ui/organisms/period'
import { GroupBy } from '@shared/enum/GroupBy'

import * as styles from './History.css'
import { Incomes } from './organisms/Incomes'
import { Outcomes } from './organisms/Outcomes'

export const History = () => {
const firstTransactionDate = useMappedState(getFirstTransactionDate)
interface Props {
className?: string
}

const groupBy = GroupBy.Month

export const History = ({ className }: Props) => {
const fetching = useMappedState(getHistoryFetchingStatus)
const dispatch = useDispatch()

const [from, setFrom] = useState(firstTransactionDate)
const [to, setTo] = useState(new Date())
const [groupBy, setGroupBy] = useState(GroupBy.Year)
const [from, setFrom] = useState(startOfMonth(new Date()))
const [to, setTo] = useState(endOfMonth(new Date()))

const updateTriggers = [from, to, groupBy]
const [actualFrom, actualTo] = useMemo(
() => [startOfMonth(from), endOfMonth(to)],
[from, to],
)

const historySelector = useCallback(
getHistory(from, to, groupBy),
updateTriggers,
getHistory(actualFrom, actualTo, groupBy),
[actualFrom, actualTo],
)
const history = useMappedState(historySelector)

useEffect(() => {
dispatch(fetchHistory(from, to, groupBy) as any)
}, updateTriggers)
useEffect(
() => {
dispatch(fetchHistory(actualFrom, actualTo, groupBy) as any)
},
[actualFrom, actualTo],
)

return (
<>
<h2>History</h2>
<Groupment groupBy={groupBy} updateGroupBy={setGroupBy} />
<Period start={from} updateStart={setFrom} end={to} updateEnd={setTo} />
<section className={className}>
<header className={styles.header}>
<h2 className={styles.title}>History</h2>
<Period start={from} updateStart={setFrom} end={to} updateEnd={setTo} />
</header>
<Loader status={fetching}>
{history.nonEmpty() &&
history.get().map(({ title, incomes, outcomes }) => (
<div key={title}>
<h3>{title}</h3>
<Incomes incomes={incomes} />
<Outcomes outcomes={outcomes} />
<div key={title} className={styles.dataSet}>
<Outcomes
outcomes={outcomes}
periodName={title}
className={styles.outcomes}
/>
<Incomes
incomes={incomes}
periodName={title}
className={styles.incomes}
/>
</div>
))}
</Loader>
</>
</section>
)
}
43 changes: 28 additions & 15 deletions front/src/features/app/features/history/organisms/Incomes.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
import { Option } from 'tsoption'

import { displayMoney } from '@front/helpers/displayMoney'
import { displayNullableDate } from '@front/helpers/displayNullableDtae'
import { Table } from '@front/ui/molecules/table'
import { IncomeModel } from '@shared/models/money/IncomeModel'

interface Props {
incomes: IncomeModel[]
className?: string
periodName: string
}

const columns = {
date: {
title: 'Date',
transform: displayNullableDate,
},
amount: {
title: 'Amount',
},
source: {
title: 'Source',
},
}

export const Incomes = ({ incomes }: Props) => (
<>
<h4>Incomes</h4>
{incomes.map(({ amount, currency, source, date }) => (
<p key={`${amount}-${date}`}>
{Option.of(date)
.map(_ => _.toDateString())
.getOrElse('')}
{' — '}
{amount / 100} {currency} ({source})
</p>
))}
</>
export const Incomes = ({ incomes, periodName, className }: Props) => (
<Table
title={`Incomes: ${periodName}`}
className={className}
data={incomes.map(income => ({
...income,
amount: displayMoney(income.amount, income.currency),
}))}
columns={columns}
/>
)
Loading

0 comments on commit f0c5aad

Please sign in to comment.