mirror of
https://github.com/apotdevin/thunderhub.git
synced 2025-02-23 06:35:05 +01:00
feat: ✨ accounting (#75)
* feat: ✨ accounting * chore: 🔧 accounting params * chore: 🔧 remove log * chore: 🔧 remove null year * chore: 🔧 disabled payment report * chore: 🔧 rebalance filters
This commit is contained in:
parent
4b9a568e63
commit
9a860ee141
13 changed files with 448 additions and 9 deletions
|
@ -2,12 +2,14 @@ import React from 'react';
|
||||||
import { GridWrapper } from 'src/components/gridWrapper/GridWrapper';
|
import { GridWrapper } from 'src/components/gridWrapper/GridWrapper';
|
||||||
import { withApollo } from 'config/client';
|
import { withApollo } from 'config/client';
|
||||||
import { Bakery } from 'src/views/tools/bakery/Bakery';
|
import { Bakery } from 'src/views/tools/bakery/Bakery';
|
||||||
|
import { Accounting } from 'src/views/tools/accounting/Accounting';
|
||||||
import { BackupsView } from '../src/views/tools/backups/Backups';
|
import { BackupsView } from '../src/views/tools/backups/Backups';
|
||||||
import { MessagesView } from '../src/views/tools/messages/Messages';
|
import { MessagesView } from '../src/views/tools/messages/Messages';
|
||||||
import { WalletVersion } from '../src/views/tools/WalletVersion';
|
import { WalletVersion } from '../src/views/tools/WalletVersion';
|
||||||
|
|
||||||
const ToolsView = () => (
|
const ToolsView = () => (
|
||||||
<>
|
<>
|
||||||
|
<Accounting />
|
||||||
<BackupsView />
|
<BackupsView />
|
||||||
<MessagesView />
|
<MessagesView />
|
||||||
<Bakery />
|
<Bakery />
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import { ContextType } from 'server/types/apiTypes';
|
import { ContextType } from 'server/types/apiTypes';
|
||||||
import { getLnd } from 'server/helpers/helpers';
|
import { getLnd } from 'server/helpers/helpers';
|
||||||
import { rebalance } from 'balanceofsatoshis/swaps';
|
|
||||||
import { to } from 'server/helpers/async';
|
import { to } from 'server/helpers/async';
|
||||||
import { logger } from 'server/helpers/logger';
|
import { logger } from 'server/helpers/logger';
|
||||||
import { AuthType } from 'src/context/AccountContext';
|
import { AuthType } from 'src/context/AccountContext';
|
||||||
|
|
||||||
|
import { rebalance } from 'balanceofsatoshis/swaps';
|
||||||
|
import { getAccountingReport } from 'balanceofsatoshis/balances';
|
||||||
|
import request from '@alexbosworth/request';
|
||||||
|
|
||||||
type RebalanceType = {
|
type RebalanceType = {
|
||||||
auth: AuthType;
|
auth: AuthType;
|
||||||
avoid?: String[];
|
avoid?: String[];
|
||||||
|
@ -19,21 +22,79 @@ type RebalanceType = {
|
||||||
target?: Number;
|
target?: Number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type AccountingType = {
|
||||||
|
auth: AuthType;
|
||||||
|
category?: String;
|
||||||
|
currency?: String;
|
||||||
|
fiat?: String;
|
||||||
|
month?: String;
|
||||||
|
year?: String;
|
||||||
|
};
|
||||||
|
|
||||||
export const bosResolvers = {
|
export const bosResolvers = {
|
||||||
|
Query: {
|
||||||
|
getAccountingReport: async (
|
||||||
|
_: undefined,
|
||||||
|
params: AccountingType,
|
||||||
|
context: ContextType
|
||||||
|
) => {
|
||||||
|
const { auth, ...settings } = params;
|
||||||
|
const lnd = getLnd(auth, context);
|
||||||
|
|
||||||
|
const response = await to(
|
||||||
|
getAccountingReport({
|
||||||
|
lnd,
|
||||||
|
logger,
|
||||||
|
request,
|
||||||
|
is_csv: true,
|
||||||
|
...settings,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
},
|
||||||
|
},
|
||||||
Mutation: {
|
Mutation: {
|
||||||
bosRebalance: async (
|
bosRebalance: async (
|
||||||
_: undefined,
|
_: undefined,
|
||||||
params: RebalanceType,
|
params: RebalanceType,
|
||||||
context: ContextType
|
context: ContextType
|
||||||
) => {
|
) => {
|
||||||
const { auth, ...extraparams } = params;
|
const {
|
||||||
|
auth,
|
||||||
|
avoid,
|
||||||
|
in_through,
|
||||||
|
is_avoiding_high_inbound,
|
||||||
|
max_fee,
|
||||||
|
max_fee_rate,
|
||||||
|
max_rebalance,
|
||||||
|
node,
|
||||||
|
out_channels,
|
||||||
|
out_through,
|
||||||
|
target,
|
||||||
|
} = params;
|
||||||
const lnd = getLnd(auth, context);
|
const lnd = getLnd(auth, context);
|
||||||
|
|
||||||
|
const filteredParams = {
|
||||||
|
...(avoid.length > 0 && { avoid }),
|
||||||
|
...(in_through && { in_through }),
|
||||||
|
...(is_avoiding_high_inbound && { is_avoiding_high_inbound }),
|
||||||
|
...(max_fee > 0 && { max_fee }),
|
||||||
|
...(max_fee_rate > 0 && { max_fee_rate }),
|
||||||
|
...(max_rebalance > 0 && { max_rebalance }),
|
||||||
|
...(node && { node }),
|
||||||
|
...(out_channels.length > 0 && { out_channels }),
|
||||||
|
...(out_through && { out_through }),
|
||||||
|
...(target && { target }),
|
||||||
|
};
|
||||||
|
|
||||||
|
logger.info('Rebalance Params: %o', filteredParams);
|
||||||
|
|
||||||
const response = await to(
|
const response = await to(
|
||||||
rebalance({
|
rebalance({
|
||||||
lnd,
|
lnd,
|
||||||
logger,
|
logger,
|
||||||
...extraparams,
|
...filteredParams,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,14 @@ export const generalTypes = gql`
|
||||||
|
|
||||||
export const queryTypes = gql`
|
export const queryTypes = gql`
|
||||||
type Query {
|
type Query {
|
||||||
|
getAccountingReport(
|
||||||
|
auth: authType!
|
||||||
|
category: String
|
||||||
|
currency: String
|
||||||
|
fiat: String
|
||||||
|
month: String
|
||||||
|
year: String
|
||||||
|
): String!
|
||||||
getVolumeHealth(auth: authType!): channelsHealth
|
getVolumeHealth(auth: authType!): channelsHealth
|
||||||
getTimeHealth(auth: authType!): channelsTimeHealth
|
getTimeHealth(auth: authType!): channelsTimeHealth
|
||||||
getFeeHealth(auth: authType!): channelsFeeHealth
|
getFeeHealth(auth: authType!): channelsFeeHealth
|
||||||
|
|
3
server/tests/__mocks__/balanceofsatoshis/balances.ts
Normal file
3
server/tests/__mocks__/balanceofsatoshis/balances.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export const getAccountingReport = jest
|
||||||
|
.fn()
|
||||||
|
.mockReturnValue(Promise.resolve({}));
|
|
@ -21,6 +21,7 @@ const StyledSingleButton = styled.button<StyledSingleProps>`
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: ${multiSelectColor};
|
color: ${multiSelectColor};
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
transition: background-color 0.5s ease;
|
||||||
|
|
||||||
${({ selected, buttonColor }) =>
|
${({ selected, buttonColor }) =>
|
||||||
selected
|
selected
|
||||||
|
|
92
src/graphql/queries/__generated__/getAccountingReport.generated.tsx
generated
Normal file
92
src/graphql/queries/__generated__/getAccountingReport.generated.tsx
generated
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
import gql from 'graphql-tag';
|
||||||
|
import * as ApolloReactCommon from '@apollo/react-common';
|
||||||
|
import * as ApolloReactHooks from '@apollo/react-hooks';
|
||||||
|
import * as Types from '../../types';
|
||||||
|
|
||||||
|
export type GetAccountingReportQueryVariables = Types.Exact<{
|
||||||
|
auth: Types.AuthType;
|
||||||
|
category?: Types.Maybe<Types.Scalars['String']>;
|
||||||
|
currency?: Types.Maybe<Types.Scalars['String']>;
|
||||||
|
fiat?: Types.Maybe<Types.Scalars['String']>;
|
||||||
|
month?: Types.Maybe<Types.Scalars['String']>;
|
||||||
|
year?: Types.Maybe<Types.Scalars['String']>;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export type GetAccountingReportQuery = { __typename?: 'Query' } & Pick<
|
||||||
|
Types.Query,
|
||||||
|
'getAccountingReport'
|
||||||
|
>;
|
||||||
|
|
||||||
|
export const GetAccountingReportDocument = gql`
|
||||||
|
query GetAccountingReport(
|
||||||
|
$auth: authType!
|
||||||
|
$category: String
|
||||||
|
$currency: String
|
||||||
|
$fiat: String
|
||||||
|
$month: String
|
||||||
|
$year: String
|
||||||
|
) {
|
||||||
|
getAccountingReport(
|
||||||
|
auth: $auth
|
||||||
|
category: $category
|
||||||
|
currency: $currency
|
||||||
|
fiat: $fiat
|
||||||
|
month: $month
|
||||||
|
year: $year
|
||||||
|
)
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useGetAccountingReportQuery__
|
||||||
|
*
|
||||||
|
* To run a query within a React component, call `useGetAccountingReportQuery` and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useGetAccountingReportQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
|
* you can use to render your UI.
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const { data, loading, error } = useGetAccountingReportQuery({
|
||||||
|
* variables: {
|
||||||
|
* auth: // value for 'auth'
|
||||||
|
* category: // value for 'category'
|
||||||
|
* currency: // value for 'currency'
|
||||||
|
* fiat: // value for 'fiat'
|
||||||
|
* month: // value for 'month'
|
||||||
|
* year: // value for 'year'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useGetAccountingReportQuery(
|
||||||
|
baseOptions?: ApolloReactHooks.QueryHookOptions<
|
||||||
|
GetAccountingReportQuery,
|
||||||
|
GetAccountingReportQueryVariables
|
||||||
|
>
|
||||||
|
) {
|
||||||
|
return ApolloReactHooks.useQuery<
|
||||||
|
GetAccountingReportQuery,
|
||||||
|
GetAccountingReportQueryVariables
|
||||||
|
>(GetAccountingReportDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export function useGetAccountingReportLazyQuery(
|
||||||
|
baseOptions?: ApolloReactHooks.LazyQueryHookOptions<
|
||||||
|
GetAccountingReportQuery,
|
||||||
|
GetAccountingReportQueryVariables
|
||||||
|
>
|
||||||
|
) {
|
||||||
|
return ApolloReactHooks.useLazyQuery<
|
||||||
|
GetAccountingReportQuery,
|
||||||
|
GetAccountingReportQueryVariables
|
||||||
|
>(GetAccountingReportDocument, baseOptions);
|
||||||
|
}
|
||||||
|
export type GetAccountingReportQueryHookResult = ReturnType<
|
||||||
|
typeof useGetAccountingReportQuery
|
||||||
|
>;
|
||||||
|
export type GetAccountingReportLazyQueryHookResult = ReturnType<
|
||||||
|
typeof useGetAccountingReportLazyQuery
|
||||||
|
>;
|
||||||
|
export type GetAccountingReportQueryResult = ApolloReactCommon.QueryResult<
|
||||||
|
GetAccountingReportQuery,
|
||||||
|
GetAccountingReportQueryVariables
|
||||||
|
>;
|
21
src/graphql/queries/getAccountingReport.ts
Normal file
21
src/graphql/queries/getAccountingReport.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import gql from 'graphql-tag';
|
||||||
|
|
||||||
|
export const GET_ACCOUNTING_REPORT = gql`
|
||||||
|
query GetAccountingReport(
|
||||||
|
$auth: authType!
|
||||||
|
$category: String
|
||||||
|
$currency: String
|
||||||
|
$fiat: String
|
||||||
|
$month: String
|
||||||
|
$year: String
|
||||||
|
) {
|
||||||
|
getAccountingReport(
|
||||||
|
auth: $auth
|
||||||
|
category: $category
|
||||||
|
currency: $currency
|
||||||
|
fiat: $fiat
|
||||||
|
month: $month
|
||||||
|
year: $year
|
||||||
|
)
|
||||||
|
}
|
||||||
|
`;
|
|
@ -45,6 +45,7 @@ export type PermissionsType = {
|
||||||
|
|
||||||
export type Query = {
|
export type Query = {
|
||||||
__typename?: 'Query';
|
__typename?: 'Query';
|
||||||
|
getAccountingReport: Scalars['String'];
|
||||||
getVolumeHealth?: Maybe<ChannelsHealth>;
|
getVolumeHealth?: Maybe<ChannelsHealth>;
|
||||||
getTimeHealth?: Maybe<ChannelsTimeHealth>;
|
getTimeHealth?: Maybe<ChannelsTimeHealth>;
|
||||||
getFeeHealth?: Maybe<ChannelsFeeHealth>;
|
getFeeHealth?: Maybe<ChannelsFeeHealth>;
|
||||||
|
@ -90,6 +91,15 @@ export type Query = {
|
||||||
getLatestVersion?: Maybe<Scalars['String']>;
|
getLatestVersion?: Maybe<Scalars['String']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type QueryGetAccountingReportArgs = {
|
||||||
|
auth: AuthType;
|
||||||
|
category?: Maybe<Scalars['String']>;
|
||||||
|
currency?: Maybe<Scalars['String']>;
|
||||||
|
fiat?: Maybe<Scalars['String']>;
|
||||||
|
month?: Maybe<Scalars['String']>;
|
||||||
|
year?: Maybe<Scalars['String']>;
|
||||||
|
};
|
||||||
|
|
||||||
export type QueryGetVolumeHealthArgs = {
|
export type QueryGetVolumeHealthArgs = {
|
||||||
auth: AuthType;
|
auth: AuthType;
|
||||||
};
|
};
|
||||||
|
|
|
@ -93,12 +93,16 @@ export const getPercent = (
|
||||||
return Math.round(percent);
|
return Math.round(percent);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const saveToPc = (jsonData: string, filename: string) => {
|
export const saveToPc = (
|
||||||
|
jsonData: string,
|
||||||
|
filename: string,
|
||||||
|
isCsv?: boolean
|
||||||
|
) => {
|
||||||
const fileData = jsonData;
|
const fileData = jsonData;
|
||||||
const blob = new Blob([fileData], { type: 'text/plain' });
|
const blob = new Blob([fileData], { type: 'text/plain' });
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
link.download = `${filename}.txt`;
|
link.download = isCsv ? `${filename}.csv` : `${filename}.txt`;
|
||||||
link.href = url;
|
link.href = url;
|
||||||
link.click();
|
link.click();
|
||||||
};
|
};
|
||||||
|
|
|
@ -231,7 +231,7 @@ export const AdvancedBalance = () => {
|
||||||
{hasAvoid ? <Minus size={18} /> : <Plus size={18} />}
|
{hasAvoid ? <Minus size={18} /> : <Plus size={18} />}
|
||||||
</ColorButton>
|
</ColorButton>
|
||||||
</SettingLine>
|
</SettingLine>
|
||||||
<SettingLine title={'In Through Channel'}>
|
<SettingLine title={'Decrease Inbound Of'}>
|
||||||
{hasInChannel ? (
|
{hasInChannel ? (
|
||||||
<RebalanceTag>{state.in_through.alias}</RebalanceTag>
|
<RebalanceTag>{state.in_through.alias}</RebalanceTag>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -247,7 +247,7 @@ export const AdvancedBalance = () => {
|
||||||
</ColorButton>
|
</ColorButton>
|
||||||
</SettingLine>
|
</SettingLine>
|
||||||
{!hasOutChannels && (
|
{!hasOutChannels && (
|
||||||
<SettingLine title={'Out Through Channel'}>
|
<SettingLine title={'Increase Inbound Of'}>
|
||||||
{hasOutChannel ? (
|
{hasOutChannel ? (
|
||||||
<RebalanceTag>{state.out_through.alias}</RebalanceTag>
|
<RebalanceTag>{state.out_through.alias}</RebalanceTag>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -427,7 +427,14 @@ export const AdvancedBalance = () => {
|
||||||
</BetaNotification>
|
</BetaNotification>
|
||||||
<InputWithDeco title={'Type'} noInput={true}>
|
<InputWithDeco title={'Type'} noInput={true}>
|
||||||
<MultiButton>
|
<MultiButton>
|
||||||
{renderButton(() => isDetailedSet(false), 'Auto', !isDetailed)}
|
{renderButton(
|
||||||
|
() => {
|
||||||
|
dispatch({ type: 'clearFilters' });
|
||||||
|
isDetailedSet(false);
|
||||||
|
},
|
||||||
|
'Auto',
|
||||||
|
!isDetailed
|
||||||
|
)}
|
||||||
{renderButton(() => isDetailedSet(true), 'Detailed', isDetailed)}
|
{renderButton(() => isDetailedSet(true), 'Detailed', isDetailed)}
|
||||||
</MultiButton>
|
</MultiButton>
|
||||||
</InputWithDeco>
|
</InputWithDeco>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import { ResponsiveLine } from 'src/components/generic/Styled';
|
||||||
|
|
||||||
export const NoWrap = styled.div`
|
export const NoWrap = styled.div`
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
|
@ -22,3 +23,7 @@ export const Column = styled.div`
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const ToolsResponsiveLine = styled(ResponsiveLine)`
|
||||||
|
margin-bottom: 8px;
|
||||||
|
`;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
Card,
|
Card,
|
||||||
Sub4Title,
|
Sub4Title,
|
||||||
Separation,
|
Separation,
|
||||||
|
DarkSubTitle,
|
||||||
} from '../../components/generic/Styled';
|
} from '../../components/generic/Styled';
|
||||||
import { useStatusState } from '../../context/StatusContext';
|
import { useStatusState } from '../../context/StatusContext';
|
||||||
import { LoadingCard } from '../../components/loading/LoadingCard';
|
import { LoadingCard } from '../../components/loading/LoadingCard';
|
||||||
|
@ -30,7 +31,10 @@ export const WalletVersion = () => {
|
||||||
if (minorVersion < 10) {
|
if (minorVersion < 10) {
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
Update to LND version 0.10.0 or higher to see your wallet build info.
|
<DarkSubTitle>
|
||||||
|
Update to LND version 0.10.0 or higher to see your wallet build
|
||||||
|
info.
|
||||||
|
</DarkSubTitle>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
221
src/views/tools/accounting/Accounting.tsx
Normal file
221
src/views/tools/accounting/Accounting.tsx
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import {
|
||||||
|
CardWithTitle,
|
||||||
|
SubTitle,
|
||||||
|
Card,
|
||||||
|
SingleLine,
|
||||||
|
DarkSubTitle,
|
||||||
|
Separation,
|
||||||
|
} from 'src/components/generic/Styled';
|
||||||
|
import { useGetAccountingReportLazyQuery } from 'src/graphql/queries/__generated__/getAccountingReport.generated';
|
||||||
|
import { useAccountState } from 'src/context/AccountContext';
|
||||||
|
import { ColorButton } from 'src/components/buttons/colorButton/ColorButton';
|
||||||
|
import {
|
||||||
|
MultiButton,
|
||||||
|
SingleButton,
|
||||||
|
} from 'src/components/buttons/multiButton/MultiButton';
|
||||||
|
import { X } from 'react-feather';
|
||||||
|
import { saveToPc } from 'src/utils/helpers';
|
||||||
|
import { ToolsResponsiveLine } from '../Tools.styled';
|
||||||
|
|
||||||
|
type ReportType =
|
||||||
|
| 'chain-fees'
|
||||||
|
| 'chain-receives'
|
||||||
|
| 'chain-sends'
|
||||||
|
| 'forwards'
|
||||||
|
| 'invoices'
|
||||||
|
| 'payments';
|
||||||
|
// type FiatType = 'eur' | 'usd';
|
||||||
|
type YearType = 2017 | 2018 | 2019 | 2020;
|
||||||
|
type MonthType = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | null;
|
||||||
|
|
||||||
|
type StateType = {
|
||||||
|
type: ReportType;
|
||||||
|
// fiat?: FiatType;
|
||||||
|
year?: YearType;
|
||||||
|
month?: MonthType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ActionType =
|
||||||
|
| {
|
||||||
|
type: 'type';
|
||||||
|
report: ReportType;
|
||||||
|
}
|
||||||
|
// | {
|
||||||
|
// type: 'fiat';
|
||||||
|
// fiat: FiatType;
|
||||||
|
// }
|
||||||
|
| {
|
||||||
|
type: 'year';
|
||||||
|
year: YearType;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'month';
|
||||||
|
month: MonthType;
|
||||||
|
};
|
||||||
|
|
||||||
|
const initialState: StateType = {
|
||||||
|
type: 'invoices',
|
||||||
|
// fiat: 'eur',
|
||||||
|
year: 2020,
|
||||||
|
month: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const reducer = (state: StateType, action: ActionType): StateType => {
|
||||||
|
switch (action.type) {
|
||||||
|
case 'type':
|
||||||
|
return { ...state, type: action.report };
|
||||||
|
// case 'fiat':
|
||||||
|
// return { ...state, fiat: action.fiat };
|
||||||
|
case 'year':
|
||||||
|
return { ...state, year: action.year };
|
||||||
|
case 'month':
|
||||||
|
return { ...state, month: action.month };
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Accounting = () => {
|
||||||
|
const { auth } = useAccountState();
|
||||||
|
const [showDetails, setShowDetails] = React.useState(false);
|
||||||
|
const [state, dispatch] = React.useReducer(reducer, initialState);
|
||||||
|
|
||||||
|
const [getReport, { data, loading }] = useGetAccountingReportLazyQuery();
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!loading && data && data.getAccountingReport) {
|
||||||
|
saveToPc(
|
||||||
|
data.getAccountingReport,
|
||||||
|
`accounting-${state.type}-${state.year || ''}-${state.month || ''}`,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [data, loading]);
|
||||||
|
|
||||||
|
const reportButton = (report: ReportType, title: string) => (
|
||||||
|
<SingleButton
|
||||||
|
selected={state.type === report}
|
||||||
|
onClick={() => !loading && dispatch({ type: 'type', report })}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</SingleButton>
|
||||||
|
);
|
||||||
|
|
||||||
|
// const fiatButton = (fiat: FiatType, title: string) => (
|
||||||
|
// <SingleButton
|
||||||
|
// selected={state.fiat === fiat}
|
||||||
|
// onClick={() => !loading && dispatch({ type: 'fiat', fiat })}
|
||||||
|
// >
|
||||||
|
// {title}
|
||||||
|
// </SingleButton>
|
||||||
|
// );
|
||||||
|
|
||||||
|
const yearButton = (year: YearType) => (
|
||||||
|
<SingleButton
|
||||||
|
selected={state.year === year}
|
||||||
|
onClick={() => !loading && dispatch({ type: 'year', year })}
|
||||||
|
>
|
||||||
|
{year}
|
||||||
|
</SingleButton>
|
||||||
|
);
|
||||||
|
|
||||||
|
const monthButton = (month: MonthType) => (
|
||||||
|
<SingleButton
|
||||||
|
selected={state.month === month}
|
||||||
|
onClick={() => !loading && dispatch({ type: 'month', month })}
|
||||||
|
>
|
||||||
|
{month ? month : 'All'}
|
||||||
|
</SingleButton>
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderDetails = () => (
|
||||||
|
<>
|
||||||
|
<Separation />
|
||||||
|
<ToolsResponsiveLine>
|
||||||
|
<DarkSubTitle>Type</DarkSubTitle>
|
||||||
|
<MultiButton>
|
||||||
|
{reportButton('chain-fees', 'Chain Fees')}
|
||||||
|
{reportButton('chain-receives', 'Chain Received')}
|
||||||
|
{reportButton('chain-sends', 'Chain Sent')}
|
||||||
|
{reportButton('forwards', 'Forwards')}
|
||||||
|
{/* {reportButton('payments', 'Payments')} */}
|
||||||
|
{reportButton('invoices', 'Invoices')}
|
||||||
|
</MultiButton>
|
||||||
|
</ToolsResponsiveLine>
|
||||||
|
{/* <ToolsResponsiveLine>
|
||||||
|
<DarkSubTitle>Fiat</DarkSubTitle>
|
||||||
|
<MultiButton>
|
||||||
|
{fiatButton('eur', 'Euro')}
|
||||||
|
{fiatButton('usd', 'US Dollar')}
|
||||||
|
</MultiButton>
|
||||||
|
</ToolsResponsiveLine> */}
|
||||||
|
<ToolsResponsiveLine>
|
||||||
|
<DarkSubTitle>Year</DarkSubTitle>
|
||||||
|
<MultiButton>
|
||||||
|
{yearButton(2017)}
|
||||||
|
{yearButton(2018)}
|
||||||
|
{yearButton(2019)}
|
||||||
|
{yearButton(2020)}
|
||||||
|
</MultiButton>
|
||||||
|
</ToolsResponsiveLine>
|
||||||
|
<ToolsResponsiveLine>
|
||||||
|
<DarkSubTitle>Month</DarkSubTitle>
|
||||||
|
<MultiButton>
|
||||||
|
{monthButton(null)}
|
||||||
|
{monthButton(1)}
|
||||||
|
{monthButton(2)}
|
||||||
|
{monthButton(3)}
|
||||||
|
{monthButton(4)}
|
||||||
|
{monthButton(5)}
|
||||||
|
{monthButton(6)}
|
||||||
|
{monthButton(7)}
|
||||||
|
{monthButton(8)}
|
||||||
|
{monthButton(9)}
|
||||||
|
{monthButton(10)}
|
||||||
|
{monthButton(11)}
|
||||||
|
{monthButton(12)}
|
||||||
|
</MultiButton>
|
||||||
|
</ToolsResponsiveLine>
|
||||||
|
<ColorButton
|
||||||
|
loading={loading}
|
||||||
|
disabled={loading}
|
||||||
|
onClick={() =>
|
||||||
|
getReport({
|
||||||
|
variables: {
|
||||||
|
auth,
|
||||||
|
// fiat: state.fiat,
|
||||||
|
category: state.type,
|
||||||
|
year: state.year.toString(),
|
||||||
|
...(state.month && { month: state.month.toString() }),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fullWidth={true}
|
||||||
|
withMargin={'16px 0 0'}
|
||||||
|
>
|
||||||
|
Generate
|
||||||
|
</ColorButton>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CardWithTitle>
|
||||||
|
<SubTitle>Accounting</SubTitle>
|
||||||
|
<Card>
|
||||||
|
<SingleLine>
|
||||||
|
<DarkSubTitle>Report</DarkSubTitle>
|
||||||
|
<ColorButton
|
||||||
|
arrow={!showDetails}
|
||||||
|
onClick={() =>
|
||||||
|
showDetails ? setShowDetails(false) : setShowDetails(true)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{showDetails ? <X size={18} /> : 'Create'}
|
||||||
|
</ColorButton>
|
||||||
|
</SingleLine>
|
||||||
|
{showDetails && renderDetails()}
|
||||||
|
</Card>
|
||||||
|
</CardWithTitle>
|
||||||
|
);
|
||||||
|
};
|
Loading…
Add table
Reference in a new issue