Skip to content

Commit a6e24c8

Browse files
committed
Links to statements added to tax report
1 parent cba8e4e commit a6e24c8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1186
-416
lines changed

eslint.config.mjs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import eslint from "@eslint/js";
33
import prettier from "eslint-plugin-prettier/recommended";
44
import rxjs from "eslint-plugin-rxjs";
55
// import storybook from "eslint-plugin-storybook";
6+
// import react from "eslint-plugin-react";
67
import tseslint from "typescript-eslint";
78

89
export default tseslint.config(
@@ -49,12 +50,18 @@ export default tseslint.config(
4950
"@typescript-eslint/restrict-plus-operands": "error",
5051
"@typescript-eslint/restrict-template-expressions": "error",
5152
"@typescript-eslint/unbound-method": "error",
53+
"@typescript-eslint/promise-function-async": "warn",
5254
"rxjs/no-async-subscribe": "warn",
5355
"rxjs/no-ignored-observable": "warn",
5456
"rxjs/no-ignored-subscription": "warn",
5557
"rxjs/no-unbound-methods": "warn",
5658
"rxjs/throw-error": "warn",
5759
},
5860
},
59-
{ ignores: ["node_modules/*", "build/*", "dist/*", "**/*.spec.ts", "*.config.mjs"] },
61+
// {
62+
// files: ["**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}"],
63+
// plugins: { react: fixupPluginRules(react) },
64+
// ...react.configs.recommended,
65+
// },
66+
{ ignores: ["node_modules/*", ".storybook/", "build/*", "dist/*", "**/*.spec.ts", "*.config.mjs"] },
6067
);

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
"eslint": "^9.2.0",
8989
"eslint-config-prettier": "^9.1.0",
9090
"eslint-plugin-prettier": "^5.1.3",
91+
"eslint-plugin-react": "^7.34.1",
9192
"eslint-plugin-rxjs": "^5.0.3",
9293
"eslint-plugin-storybook": "^0.8.0",
9394
"http-proxy-middleware": "^3.0.0",

src/app/components/Portfolio/Balance/actions.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import { ActionFunctionArgs, redirect } from "react-router-dom";
66
* @param params
77
* @returns
88
*/
9-
export const balanceSave = ({ request, params }: ActionFunctionArgs): Promise<Response> => {
9+
export const balanceSave = async ({ request, params }: ActionFunctionArgs): Promise<Response> => {
1010
const { portfolioId, balanceId } = params;
1111
return request
1212
.formData()
13-
.then((formData: Iterable<readonly [PropertyKey, any]>) => {
13+
.then(async (formData: Iterable<readonly [PropertyKey, any]>) => {
1414
const data = Object.fromEntries(formData);
1515
// console.log("balance save ", data);
1616
return fetch(`/api/portfolio/${portfolioId}/balances/id/${balanceId}/SaveBalance`, {
@@ -22,7 +22,7 @@ export const balanceSave = ({ request, params }: ActionFunctionArgs): Promise<Re
2222
body: JSON.stringify({ ...data, strategy: parseInt(data.strategy as string) }),
2323
});
2424
})
25-
.then((response: Response) => response.json())
25+
.then(async (response: Response) => response.json())
2626
.then((_data) => redirect("../"));
2727
};
2828

@@ -31,15 +31,15 @@ export const balanceSave = ({ request, params }: ActionFunctionArgs): Promise<Re
3131
* @param params
3232
* @returns
3333
*/
34-
export const balanceDelete = ({ request, params }: ActionFunctionArgs): Promise<Response> => {
34+
export const balanceDelete = async ({ request, params }: ActionFunctionArgs): Promise<Response> => {
3535
const { portfolioId, balanceId } = params;
3636
return request
3737
.formData()
38-
.then((_formData: Iterable<readonly [PropertyKey, any]>) => {
38+
.then(async (_formData: Iterable<readonly [PropertyKey, any]>) => {
3939
return fetch(`/api/portfolio/${portfolioId}/balances/id/${balanceId}/DeleteBalance`, {
4040
method: "DELETE",
4141
});
4242
})
43-
.then((response: Response) => response.text())
43+
.then(async (response: Response) => response.text())
4444
.then((_data) => redirect("../"));
4545
};

src/app/components/Portfolio/Balance/loaders.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import { BalanceEntry } from "../../../../routers/balances.types";
66
* @param params
77
* @returns
88
*/
9-
export const balancesIndexLoader = ({ params }: LoaderFunctionArgs): Promise<BalanceEntry[]> => {
9+
export const balancesIndexLoader = async ({ params }: LoaderFunctionArgs): Promise<BalanceEntry[]> => {
1010
const { portfolioId } = params;
1111
return fetch(`/api/portfolio/${portfolioId}/balances/index`)
12-
.then((response) => response.json())
12+
.then(async (response) => response.json())
1313
.then((data) => data.balances as BalanceEntry[]);
1414
};
1515

@@ -18,10 +18,10 @@ export const balancesIndexLoader = ({ params }: LoaderFunctionArgs): Promise<Bal
1818
* @param params
1919
* @returns
2020
*/
21-
export const balancesShowLoader = ({ params }: LoaderFunctionArgs): Promise<BalanceEntry> => {
21+
export const balancesShowLoader = async ({ params }: LoaderFunctionArgs): Promise<BalanceEntry> => {
2222
const { portfolioId, balanceId } = params;
2323
// console.log("balancesShowLoader", portfolioId, balanceId);
2424
return fetch(`/api/portfolio/${portfolioId}/balances/id/${balanceId}`)
25-
.then((response) => response.json())
25+
.then(async (response) => response.json())
2626
.then((data) => data.balance as BalanceEntry);
2727
};

src/app/components/Portfolio/Contract/loaders.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import { ContractEntry } from "../../../../routers/repository.types";
66
* @param params
77
* @returns
88
*/
9-
export const contractShowLoader = ({ params }: LoaderFunctionArgs): Promise<ContractEntry> => {
9+
export const contractShowLoader = async ({ params }: LoaderFunctionArgs): Promise<ContractEntry> => {
1010
const { portfolioId, contractId } = params;
1111
return fetch(`/api/portfolio/${portfolioId}/contracts/id/${contractId}`)
12-
.then((response) => response.json())
12+
.then(async (response) => response.json())
1313
.then((data) => data.contract as ContractEntry);
1414
};

src/app/components/Portfolio/Layout/PortfolioLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const PortfolioLayout: FunctionComponent<PortfolioLayoutProps> = ({ children, ..
1616

1717
useEffect(() => {
1818
fetch(`/api/portfolio/${portfolioId}`)
19-
.then((response) => response.json())
19+
.then(async (response) => response.json())
2020
.then((data) => setPortfolio(data.portfolio as PortfolioModel))
2121
.catch((error) => console.error("error fetching portfolio:", error));
2222
}, []);

src/app/components/Portfolio/Portfolio/loaders.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import { Portfolio as PortfolioModel } from "../../../../models/portfolio.model"
66
* @param param0
77
* @returns
88
*/
9-
export const portfolioLoader = ({ params }: LoaderFunctionArgs): Promise<PortfolioModel> => {
9+
export const portfolioLoader = async ({ params }: LoaderFunctionArgs): Promise<PortfolioModel> => {
1010
const { portfolioId } = params;
1111
return fetch(`/api/portfolio/${portfolioId}`)
12-
.then((response) => response.json())
12+
.then(async (response) => response.json())
1313
.then((data) => data.portfolio as PortfolioModel);
1414
};

src/app/components/Portfolio/Position/actions.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import { ActionFunctionArgs, redirect } from "react-router-dom";
55
* @param params
66
* @returns
77
*/
8-
export const positionSave = ({ request, params }: ActionFunctionArgs): Promise<Response> => {
8+
export const positionSave = async ({ request, params }: ActionFunctionArgs): Promise<Response> => {
99
const { portfolioId, positionId } = params;
1010
return request
1111
.formData()
12-
.then((formData: Iterable<readonly [PropertyKey, any]>) => {
12+
.then(async (formData: Iterable<readonly [PropertyKey, any]>) => {
1313
const data = Object.fromEntries(formData);
1414
// console.log("data:", data);
1515
return fetch(`/api/portfolio/${portfolioId}/positions/id/${positionId}/SavePosition`, {
@@ -21,7 +21,7 @@ export const positionSave = ({ request, params }: ActionFunctionArgs): Promise<R
2121
body: JSON.stringify(data),
2222
});
2323
})
24-
.then((response: Response) => response.json())
24+
.then(async (response: Response) => response.json())
2525
.then((_data) => redirect("../"));
2626
};
2727

@@ -30,14 +30,14 @@ export const positionSave = ({ request, params }: ActionFunctionArgs): Promise<R
3030
* @param params
3131
* @returns
3232
*/
33-
export const positionDelete = ({ request, params }: ActionFunctionArgs): Promise<Response> => {
33+
export const positionDelete = async ({ request, params }: ActionFunctionArgs): Promise<Response> => {
3434
const { portfolioId, positionId } = params;
3535
return request
3636
.formData()
37-
.then((_formData: Iterable<readonly [PropertyKey, any]>) => {
37+
.then(async (_formData: Iterable<readonly [PropertyKey, any]>) => {
3838
return fetch(`/api/portfolio/${portfolioId}/positions/id/${positionId}/DeletePosition`);
3939
})
40-
.then((response: Response) => response.text())
40+
.then(async (response: Response) => response.text())
4141
.then((_data) => redirect("../"));
4242
};
4343

@@ -46,15 +46,15 @@ export const positionDelete = ({ request, params }: ActionFunctionArgs): Promise
4646
* @param params
4747
* @returns
4848
*/
49-
export const positionGuessTrade = ({ request, params }: ActionFunctionArgs): Promise<Response> => {
49+
export const positionGuessTrade = async ({ request, params }: ActionFunctionArgs): Promise<Response> => {
5050
const { portfolioId, positionId } = params;
5151
return request
5252
.formData()
53-
.then((formData: Iterable<readonly [PropertyKey, any]>) => {
53+
.then(async (formData: Iterable<readonly [PropertyKey, any]>) => {
5454
const _data = Object.fromEntries(formData);
5555
return fetch(`/api/portfolio/${portfolioId}/positions/${positionId}/GuessTrade`);
5656
})
57-
.then((response: Response) => response.json())
57+
.then(async (response: Response) => response.json())
5858
.then((_data) => redirect("../"));
5959
};
6060

@@ -64,15 +64,15 @@ export const positionGuessTrade = ({ request, params }: ActionFunctionArgs): Pro
6464
* @param request
6565
* @returns
6666
*/
67-
export const positionAddToTrade = ({ request, params }: ActionFunctionArgs): Promise<Response> => {
67+
export const positionAddToTrade = async ({ request, params }: ActionFunctionArgs): Promise<Response> => {
6868
const { portfolioId, positionId, tradeId } = params;
6969
return request
7070
.formData()
71-
.then((formData: Iterable<readonly [PropertyKey, any]>) => {
71+
.then(async (formData: Iterable<readonly [PropertyKey, any]>) => {
7272
const _data = Object.fromEntries(formData);
7373
return fetch(`/api/portfolio/${portfolioId}/positions/${positionId}/AddToTrade/${tradeId}`);
7474
})
75-
.then((response: Response) => response.json())
75+
.then(async (response: Response) => response.json())
7676
.then((_data) => redirect("../"));
7777
};
7878

@@ -82,15 +82,15 @@ export const positionAddToTrade = ({ request, params }: ActionFunctionArgs): Pro
8282
* @param request
8383
* @returns
8484
*/
85-
export const positionUnlinkTrade = ({ request, params }: ActionFunctionArgs): Promise<Response> => {
85+
export const positionUnlinkTrade = async ({ request, params }: ActionFunctionArgs): Promise<Response> => {
8686
const { portfolioId, positionId } = params;
8787
// console.log("positionUnlinkTrade", portfolioId, positionId);
8888
return request
8989
.formData()
90-
.then((formData: Iterable<readonly [PropertyKey, any]>) => {
90+
.then(async (formData: Iterable<readonly [PropertyKey, any]>) => {
9191
const _data = Object.fromEntries(formData);
9292
return fetch(`/api/portfolio/${portfolioId}/positions/${positionId}/UnlinkTrade`);
9393
})
94-
.then((response: Response) => response.json())
94+
.then(async (response: Response) => response.json())
9595
.then((_data) => redirect("../"));
9696
};

src/app/components/Portfolio/Position/loaders.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import { PositionEntry } from "../../../../routers/positions.types";
77
* @param param0
88
* @returns
99
*/
10-
export const positionsIndexLoader = ({ params }: LoaderFunctionArgs): Promise<PositionEntry[]> => {
10+
export const positionsIndexLoader = async ({ params }: LoaderFunctionArgs): Promise<PositionEntry[]> => {
1111
const { portfolioId } = params;
1212
return fetch(`/api/portfolio/${portfolioId}/positions/index`)
13-
.then((response) => response.json())
13+
.then(async (response) => response.json())
1414
.then((data) => data.positions as PositionEntry[]);
1515
};
1616

@@ -19,10 +19,10 @@ export const positionsIndexLoader = ({ params }: LoaderFunctionArgs): Promise<Po
1919
* @param param0
2020
* @returns
2121
*/
22-
export const positionsOptionsLoader = ({ params }: LoaderFunctionArgs): Promise<PositionEntry[]> => {
22+
export const positionsOptionsLoader = async ({ params }: LoaderFunctionArgs): Promise<PositionEntry[]> => {
2323
const { portfolioId } = params;
2424
return fetch(`/api/portfolio/${portfolioId}/positions/index`)
25-
.then((response) => response.json())
25+
.then(async (response) => response.json())
2626
.then((data: { positions: PositionEntry[] }) => data.positions.filter((item) => item.contract.secType == "OPT"));
2727
};
2828

@@ -31,9 +31,9 @@ export const positionsOptionsLoader = ({ params }: LoaderFunctionArgs): Promise<
3131
* @param param0
3232
* @returns
3333
*/
34-
export const positionShowLoader = ({ params }: LoaderFunctionArgs): Promise<Position> => {
34+
export const positionShowLoader = async ({ params }: LoaderFunctionArgs): Promise<Position> => {
3535
const { portfolioId, positionId } = params;
3636
return fetch(`/api/portfolio/${portfolioId}/positions/id/${positionId}`)
37-
.then((response) => response.json())
37+
.then(async (response) => response.json())
3838
.then((data) => data.position as Position);
3939
};

src/app/components/Portfolio/Report/DividendsComponent.tsx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
import { Box, HStack, Spacer, Text, VStack } from "@chakra-ui/react";
1+
import { Box, HStack, Link, Spacer, Text, VStack } from "@chakra-ui/react";
22
import { default as React } from "react";
3+
import { Link as RouterLink, useParams } from "react-router-dom";
34
import { DididendSummary, ReportEntry } from "../../../../routers/reports.types";
45
import Number from "../../Number/Number";
6+
import { StatementLink } from "../Statement/links";
7+
import { formatMonth } from "./utils";
58

69
type Props = { theReports: ReportEntry[] };
710

@@ -12,10 +15,12 @@ const _compareReports = (a: ReportEntry, b: ReportEntry): number => {
1215
};
1316

1417
const OneCountryTable = ({
18+
portfolioId,
1519
theReports,
1620
country,
1721
..._rest
1822
}: {
23+
portfolioId: string;
1924
theReports: ReportEntry[];
2025
country: string;
2126
}): React.ReactNode => {
@@ -36,10 +41,10 @@ const OneCountryTable = ({
3641
report.dividendsSummary
3742
.filter((summary: DididendSummary) => summary.country == country)
3843
.map((item) => (
39-
<HStack key={`${report.year}-${report.month}-${item.country}`}>
40-
<Text width="120px">
41-
{report.year}-{report.month}
42-
</Text>
44+
<HStack key={`${report.year}-${report.month}`}>
45+
<Link to={StatementLink.toMonth(portfolioId, report.year, report.month)} as={RouterLink}>
46+
<Text width="120px">{formatMonth(report.year, report.month)}</Text>
47+
</Link>
4348
<Number value={item.grossAmountInBase} width="120px" />
4449
<Number value={item.taxes} width="120px" />
4550
<Number value={item.grossAmountInBase + item.taxes} width="120px" />
@@ -64,6 +69,8 @@ const OneCountryTable = ({
6469
* @returns
6570
*/
6671
const Dividends = ({ theReports, ..._rest }: Props): React.ReactNode => {
72+
const { portfolioId } = useParams();
73+
6774
let grossTotal = 0;
6875
let taxesTotal = 0;
6976
let netTotal = 0;
@@ -97,7 +104,7 @@ const Dividends = ({ theReports, ..._rest }: Props): React.ReactNode => {
97104
{countries.map((country) => (
98105
<HStack alignContent="left" key={country} borderBottom="1px" borderColor="gray.200">
99106
<Box width="120px">{country}</Box>
100-
<OneCountryTable theReports={theReports} country={country} />
107+
<OneCountryTable portfolioId={portfolioId} theReports={theReports} country={country} />
101108
</HStack>
102109
))}
103110
<HStack>

src/app/components/Portfolio/Report/FeesComponent.tsx

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
1-
import { Box, HStack, Spacer, Text, VStack } from "@chakra-ui/react";
1+
import { Box, HStack, Link, Spacer, Text, VStack } from "@chakra-ui/react";
22
import { default as React } from "react";
3+
import { Link as RouterLink, useParams } from "react-router-dom";
34
import { ReportEntry } from "../../../../routers/reports.types";
45
import Number from "../../Number/Number";
6+
import { StatementLink } from "../Statement/links";
7+
import { formatMonth } from "./utils";
58

69
type Props = { theReports: ReportEntry[] };
710

8-
const _compareReports = (a: ReportEntry, b: ReportEntry): number => {
9-
let result = a.year - b.year;
10-
if (!result) result = a.month - b.month;
11-
return result;
12-
};
13-
1411
/**
1512
* Fees table component
1613
* @param theReports Tax reports to summarize. Assume their summaries are sorted by date
1714
* @returns
1815
*/
1916
const Fees = ({ theReports, ..._rest }: Props): React.ReactNode => {
17+
const { portfolioId } = useParams();
18+
2019
return (
2120
<>
2221
<VStack align="left">
@@ -29,9 +28,9 @@ const Fees = ({ theReports, ..._rest }: Props): React.ReactNode => {
2928
</HStack>
3029
{theReports.map((report) => (
3130
<HStack alignContent="left" key={`${report.year}-${report.month}`}>
32-
<Text width="120px">
33-
{report.year}-{report.month}
34-
</Text>
31+
<Link to={StatementLink.toMonth(portfolioId, report.year, report.month)} as={RouterLink}>
32+
<Text width="120px">{formatMonth(report.year, report.month)}</Text>
33+
</Link>
3534
<Number value={report.feesSummary.totalAmountInBase} width="120px" />
3635
<Spacer />
3736
</HStack>

0 commit comments

Comments
 (0)