hakeemsyd commited on
Commit
2d4e819
1 Parent(s): f81dc34

setup income and expense statement

Browse files
app/(home)/reports/page.tsx CHANGED
@@ -3,9 +3,16 @@ import { incomeStatements } from "@/app/lib/endpoints";
3
  import moment from "moment";
4
  import { List } from "antd";
5
  import React, { useEffect, useState } from "react";
 
 
 
6
 
7
  const Reports = () => {
 
 
8
  const [statements, setStatements] = useState([]);
 
 
9
  useEffect(() => {
10
  (async () => {
11
  const data = await fetch(incomeStatements)
@@ -13,21 +20,24 @@ const Reports = () => {
13
  setStatements(statements);
14
  })();
15
  }, []);
 
16
  return (
17
  <div style={{ padding: 24 }}>
18
  <h1>Statements</h1>
19
- <List
20
- itemLayout="horizontal"
21
- dataSource={statements}
22
- renderItem={(item: any) => (
23
- <List.Item>
24
- <List.Item.Meta
25
- title={<a href="#">{`${moment(item.date_from).format('MM-DD-YYYY')} until ${moment(item.date_to).format('MM-DD-YYYY')}`}</a>}
26
- // description="This is the description"
27
- />
28
- </List.Item>
29
- )}
30
- />
 
 
31
  </div>
32
  );
33
  }
 
3
  import moment from "moment";
4
  import { List } from "antd";
5
  import React, { useEffect, useState } from "react";
6
+ import { useRouter, useSearchParams } from "next/navigation";
7
+ import IncomeStatement from "@/app/components/IncomeStatement";
8
+ import { DoubleLeftOutlined } from '@ant-design/icons';
9
 
10
  const Reports = () => {
11
+ const searchParams = useSearchParams()
12
+ const statement_id = searchParams.get('statement_id')
13
  const [statements, setStatements] = useState([]);
14
+ const router = useRouter();
15
+
16
  useEffect(() => {
17
  (async () => {
18
  const data = await fetch(incomeStatements)
 
20
  setStatements(statements);
21
  })();
22
  }, []);
23
+
24
  return (
25
  <div style={{ padding: 24 }}>
26
  <h1>Statements</h1>
27
+ {statement_id ?
28
+ <IncomeStatement statementData={statements.find(({id}) => id === Number(statement_id))} />
29
+ :
30
+ <List
31
+ itemLayout="horizontal"
32
+ dataSource={statements}
33
+ renderItem={(item: any) => (
34
+ <List.Item>
35
+ <List.Item.Meta
36
+ title={<a onClick={() => router.push(`?statement_id=${item.id}`)}>{`${moment(item.date_from).format('MM-DD-YYYY')} until ${moment(item.date_to).format('MM-DD-YYYY')}`}</a>}
37
+ />
38
+ </List.Item>
39
+ )}
40
+ />}
41
  </div>
42
  );
43
  }
app/components/IncomeStatement/index.tsx ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Flex, Spin, Table, Typography } from 'antd';
2
+ import Title from 'antd/es/typography/Title';
3
+ import { useEffect, useState } from 'react';
4
+ import styles from './styles.module.css'
5
+
6
+ type Props = {
7
+ statementData: any | undefined;
8
+ };
9
+
10
+ const IncomeStatement = ({ statementData }: Props) => {
11
+ console.log('statementData', statementData);
12
+ const [data, setData] = useState<any | undefined>(undefined);
13
+ const [profit, setProfit] = useState(0);
14
+ const [incomeTotal, setIncomeTotal] = useState(0);
15
+ const [expensesTotal, setExpensesTotal] = useState(0);
16
+ const [summaryData, setSummaryData] = useState<any[]>([]);
17
+
18
+ useEffect(() => {
19
+ // (async () => {
20
+ // const resp = await fetch(incomeStatements);
21
+ // const t = await resp.json();
22
+ // setData(t);
23
+ // })();
24
+
25
+ if (statementData) {
26
+ const calculateTotal = (obj: any) => Object.values(obj).reduce((acc: any, value: any) => acc + value, 0);
27
+ const aggIncome = calculateTotal(statementData.income);
28
+ const expensesTotal = calculateTotal(statementData.expenses);
29
+ const profit = Number(incomeTotal) - Number(expensesTotal);
30
+
31
+ const incomeData = Object.keys(statementData.income).map((key) => ({
32
+ key,
33
+ category: `Income - ${key.charAt(0).toUpperCase() + key.slice(1)}`,
34
+ amount: statementData.income[key],
35
+ }));
36
+
37
+ const expensesData = Object.keys(statementData.expenses).map((key) => ({
38
+ key,
39
+ category: `Expense - ${key.charAt(0).toUpperCase() + key.slice(1)}`,
40
+ amount: statementData.expenses[key],
41
+ }));
42
+
43
+ const summaryData = [
44
+ ...incomeData,
45
+ ...expensesData,
46
+ {
47
+ key: 'total-income',
48
+ category: 'Total Income',
49
+ amount: incomeTotal,
50
+ },
51
+ {
52
+ key: 'total-expenses',
53
+ category: 'Total Expenses',
54
+ amount: expensesTotal,
55
+ },
56
+ {
57
+ key: 'profit',
58
+ category: 'Profit',
59
+ amount: profit,
60
+ },
61
+ ];
62
+
63
+ setProfit(profit);
64
+ setIncomeTotal(Number(aggIncome));
65
+ setSummaryData(summaryData);
66
+ }
67
+ setData(statementData);
68
+ }, []);
69
+
70
+
71
+
72
+ const columns = [
73
+ {
74
+ title: 'Category',
75
+ dataIndex: 'category',
76
+ key: 'category',
77
+ },
78
+ {
79
+ title: 'Amount',
80
+ dataIndex: 'amount',
81
+ key: 'amount',
82
+ render: (amount: Number) => `$${amount.toFixed(2)}`,
83
+ },
84
+ ];
85
+
86
+ const rowClassName = (record: any) => {
87
+ if (record.key === 'total-income') return styles.totalIncomeRow;
88
+ if (record.key === 'total-expenses') return styles.totalExpensesRow;
89
+ if (record.key === 'profit') return styles.profitRow;
90
+ return '';
91
+ };
92
+
93
+
94
+
95
+ if (!data) {
96
+ return (
97
+ <Flex align="center" gap="middle">
98
+ <Spin size="large" />
99
+ </Flex>
100
+ )
101
+ }
102
+
103
+ return (
104
+ <>
105
+ <Title level={3}>Profit & Loss Statement</Title>
106
+ <Table
107
+ columns={columns}
108
+ dataSource={summaryData}
109
+ pagination={false}
110
+ rowClassName={rowClassName}
111
+ summary={() => (
112
+ <Table.Summary.Row>
113
+ <Table.Summary.Cell index={1} colSpan={1}>Net Profit</Table.Summary.Cell>
114
+ <Table.Summary.Cell index={2}>
115
+ <span style={{
116
+ fontWeight: 'bold',
117
+ backgroundColor: '#f6ffed',
118
+ padding: '2px 4px',
119
+ display: 'inline-block',
120
+ }}>
121
+ ${profit.toFixed(2)}
122
+ </span>
123
+ </Table.Summary.Cell>
124
+ </Table.Summary.Row>
125
+ )}
126
+ />
127
+ </>
128
+ );
129
+ };
130
+
131
+
132
+ export default IncomeStatement
app/components/IncomeStatement/styles.module.css ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .totalIncomeRow{
2
+ background-color: #e6f7ff;
3
+ font-weight: bold;
4
+ }
5
+
6
+ .totalExpenseRow {
7
+ background-color: #fff2e8;
8
+ font-weight: bold;
9
+ }
10
+
11
+ .profitRow {
12
+ background-color: #f6ffed;
13
+ font-weight: bold;
14
+ }