hakeemsyd commited on
Commit
dbf4bc6
·
verified ·
1 Parent(s): 9d94d4d

Topbar UI & login (#4)

Browse files

- setup income and expense statement (cae527dac373f79c4bdbc1f25070a50cf6a67794)
- remove login page (b78b146c6045b0c76b67fc233e53d452c90c9b26)
- Merge branch 'main' into pr/4 (e9add910a499564d58a661669a844f35fec4f58d)
- Revert "remove login page" (e8d90bc63b296d8745ea8a9db1dc3bdeebf8ea93)
- Login page (ac67c7a771e0c69c91ff6e0c13620825d7c8e942)
- hardcode user3 (f81ecbc0efb3e4fe02cfa3741973abae82b9d070)

app/(auth)/login/page.tsx ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client';
2
+ import React from 'react';
3
+ import { Form, Input, Button, Checkbox, Typography, Layout, FormProps } from 'antd';
4
+ import './styles.css';
5
+ import { useRouter } from 'next/navigation';
6
+
7
+ const { Title } = Typography;
8
+ const { Content } = Layout;
9
+
10
+ type FieldType = {
11
+ username?: string;
12
+ password?: string;
13
+ remember?: string;
14
+ };
15
+
16
+ const LoginPage = () => {
17
+ const router = useRouter();
18
+ const onFinish: FormProps<FieldType>['onFinish'] = (values) => {
19
+ console.log('Success:', values);
20
+ router.push('/dashboard');
21
+ };
22
+
23
+ const onFinishFailed: FormProps<FieldType>['onFinishFailed'] = (errorInfo) => {
24
+ console.log('Failed:', errorInfo);
25
+ };
26
+
27
+ return (
28
+ <Layout className="layout">
29
+ <Content className="content">
30
+ <div className="login-container">
31
+ <Title level={2}>Login</Title>
32
+ <Form
33
+ name="basic"
34
+ initialValues={{ remember: true }}
35
+ onFinish={onFinish}
36
+ onFinishFailed={onFinishFailed}
37
+ autoComplete="off"
38
+ >
39
+ <Form.Item
40
+ name="username"
41
+ rules={[{ required: true, message: 'Please input your username!' }]}
42
+ >
43
+ <Input placeholder="Username" />
44
+ </Form.Item>
45
+
46
+ <Form.Item
47
+ name="password"
48
+ rules={[{ required: true, message: 'Please input your password!' }]}
49
+ >
50
+ <Input.Password placeholder="Password" />
51
+ </Form.Item>
52
+
53
+ <Form.Item name="remember" valuePropName="checked">
54
+ <Checkbox>Remember me</Checkbox>
55
+ </Form.Item>
56
+
57
+ <Form.Item>
58
+ <Button type="primary" htmlType="submit" block>
59
+ Log in
60
+ </Button>
61
+ </Form.Item>
62
+ </Form>
63
+ </div>
64
+ </Content>
65
+ </Layout>
66
+ );
67
+ };
68
+
69
+ export default LoginPage;
app/(auth)/login/styles.css ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .layout {
2
+ min-height: 100vh;
3
+ display: flex;
4
+ justify-content: center;
5
+ align-items: center;
6
+ background-color: #f0f2f5; /* Optional: Change the background color as needed */
7
+ }
8
+
9
+ .content {
10
+ width: 100%;
11
+ max-height: 450px;
12
+ max-width: 400px;
13
+ padding: 24px;
14
+ background: white;
15
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
16
+ border-radius: 8px; /* Optional: Add border radius for rounded corners */
17
+ }
18
+
19
+ .login-container {
20
+ width: 100%;
21
+ text-align: center;
22
+ }
23
+
24
+ .login-container .ant-typography {
25
+ margin-bottom: 24px;
26
+ }
app/(home)/layout.tsx CHANGED
@@ -9,6 +9,7 @@ import {
9
  } from '@ant-design/icons';
10
  import { Button, Layout, Menu, theme } from 'antd';
11
  import { useRouter } from "next/navigation";
 
12
  const { Header, Sider, Content } = Layout;
13
 
14
  const Dashboard = ({
@@ -25,12 +26,13 @@ const Dashboard = ({
25
  router.push(route);
26
  }
27
  return (
28
- <main className="flex min-h-screen">
 
 
29
  <Layout>
30
  <Sider trigger={null} collapsible collapsed={collapsed}>
31
  <div className="demo-logo-vertical" />
32
  <Menu
33
- style={{ marginTop: '8rem' }}
34
  theme="dark"
35
  mode="inline"
36
  defaultSelectedKeys={['1']}
@@ -89,6 +91,7 @@ const Dashboard = ({
89
  </Layout>
90
  </Layout>
91
  </main >
 
92
  );
93
  }
94
 
 
9
  } from '@ant-design/icons';
10
  import { Button, Layout, Menu, theme } from 'antd';
11
  import { useRouter } from "next/navigation";
12
+ import TopBar from "../components/Topbar";
13
  const { Header, Sider, Content } = Layout;
14
 
15
  const Dashboard = ({
 
26
  router.push(route);
27
  }
28
  return (
29
+ <>
30
+ <TopBar />
31
+ <main className="flex min-h-screen flex-col">
32
  <Layout>
33
  <Sider trigger={null} collapsible collapsed={collapsed}>
34
  <div className="demo-logo-vertical" />
35
  <Menu
 
36
  theme="dark"
37
  mode="inline"
38
  defaultSelectedKeys={['1']}
 
91
  </Layout>
92
  </Layout>
93
  </main >
94
+ </>
95
  );
96
  }
97
 
app/(home)/reports/page.tsx CHANGED
@@ -2,10 +2,9 @@
2
  import { incomeStatements } from "@/app/lib/endpoints";
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()
@@ -15,30 +14,34 @@ const Reports = () => {
15
 
16
  useEffect(() => {
17
  (async () => {
18
- const data = await fetch(incomeStatements)
 
19
  const statements = await data.json();
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
  }
44
 
 
2
  import { incomeStatements } from "@/app/lib/endpoints";
3
  import moment from "moment";
4
  import { List } from "antd";
5
+ import React, { Suspense, useEffect, useState } from "react";
6
  import { useRouter, useSearchParams } from "next/navigation";
7
  import IncomeStatement from "@/app/components/IncomeStatement";
 
8
 
9
  const Reports = () => {
10
  const searchParams = useSearchParams()
 
14
 
15
  useEffect(() => {
16
  (async () => {
17
+ const data = await fetch(incomeStatements);
18
+ console.log('data', data);
19
  const statements = await data.json();
20
  setStatements(statements);
21
  })();
22
  }, []);
23
 
24
  return (
25
+ <Suspense fallback={<div>Loading...</div>}>
26
+ <div style={{ padding: 24 }}>
27
+ <h1>Statements</h1>
28
+ {statement_id ?
29
+ <IncomeStatement statementData={statements.find(({ id }) => id === Number(statement_id))} />
30
+ :
31
+ <List
32
+ itemLayout="horizontal"
33
+ dataSource={statements}
34
+ renderItem={(item: any) => (
35
+ <List.Item>
36
+ <List.Item.Meta
37
+ 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>}
38
+ />
39
+ </List.Item>
40
+
41
+ )}
42
+ />}
43
+ </div>
44
+ </Suspense>
45
  );
46
  }
47
 
app/components/Topbar/index.tsx ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from 'react';
2
+ import { Layout, Menu, Avatar } from 'antd';
3
+ import { SettingOutlined } from '@ant-design/icons';
4
+ import './styles.css'; // Create a CSS file for any custom styling
5
+ import Link from 'next/link';
6
+
7
+ const { Header } = Layout;
8
+
9
+ const TopBar = () => {
10
+
11
+ return (
12
+ <Layout>
13
+ <Header className="header">
14
+ <div className="logo">
15
+ <Link href={'/dashboard'}>
16
+ <img src="/llama.png" alt="Company Logo" />
17
+ </Link>
18
+ </div>
19
+ <Menu theme="dark" mode="horizontal" style={{ flex: 1 }}>
20
+ {/* You can add menu items here if needed */}
21
+ </Menu>
22
+ <div className="settings">
23
+ <Avatar icon={<SettingOutlined />} />
24
+ </div>
25
+ </Header>
26
+ </Layout>
27
+ );
28
+ };
29
+
30
+ export default TopBar;
app/components/Topbar/styles.css ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .header {
2
+ display: flex;
3
+ align-items: center;
4
+ padding: 0 24px;
5
+ background-color: #3b5998; /* Change this to your desired top bar color */
6
+ }
7
+
8
+ .logo img {
9
+ height: 32px;
10
+ }
11
+
12
+ .settings {
13
+ margin-left: auto;
14
+ }
app/lib/endpoints/index.ts CHANGED
@@ -3,5 +3,6 @@ const url = `${baseUrl}/api/v1`
3
 
4
  export const transactionsEndpoint = `${url}/transactions/3`;
5
  export const fielUploadEndpoint = `${url}/file_upload`;
6
- export const incomeStatements = `${url}/income_statement/3`;
7
- export const statementEndpoint = `${url}/statement`;
 
 
3
 
4
  export const transactionsEndpoint = `${url}/transactions/3`;
5
  export const fielUploadEndpoint = `${url}/file_upload`;
6
+ export const incomeStatements = `${url}/income_statement/user/3`;
7
+ export const statementEndpoint = `${url}/statement/report/1`;
8
+
app/login/page.tsx DELETED
@@ -1,70 +0,0 @@
1
- 'use client';
2
-
3
- import { useState } from "react";
4
- import { useRouter } from "next/navigation";
5
-
6
- const Login = () => {
7
- const [username, setUsername] = useState("");
8
- const [password, setPassword] = useState("");
9
-
10
- const router = useRouter();
11
-
12
- const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
13
- e.preventDefault();
14
-
15
- router.push("/dashboard");
16
- };
17
-
18
- return (
19
- <div className="flex flex-col items-center justify-center h-screen">
20
- <h1 className="text-3xl font-bold mb-4">Login to your Financial Assistant</h1>
21
- <form
22
- className="bg-white shadow-md rounded px-8 pt-6 pb-8 m-4"
23
- onSubmit={handleSubmit}
24
- >
25
- <div className="mb-4">
26
- <label
27
- className="block text-gray-700 text-sm font-bold mb-2"
28
- htmlFor="username"
29
- >
30
- Username
31
- </label>
32
- <input
33
- className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
34
- id="username"
35
- type="text"
36
- placeholder="Username"
37
- value={username}
38
- onChange={(e) => setUsername(e.target.value)}
39
- />
40
- </div>
41
- <div className="mb-6">
42
- <label
43
- className="block text-gray-700 text-sm font-bold mb-2"
44
- htmlFor="password"
45
- >
46
- Password
47
- </label>
48
- <input
49
- className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
50
- id="password"
51
- type="password"
52
- placeholder="Password"
53
- value={password}
54
- onChange={(e) => setPassword(e.target.value)}
55
- />
56
- </div>
57
- <div className="flex items-center justify-between">
58
- <button
59
- className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
60
- type="submit"
61
- >
62
- Sign In
63
- </button>
64
- </div>
65
- </form>
66
- </div>
67
- );
68
- };
69
-
70
- export default Login;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
next.config.json CHANGED
@@ -1,5 +1,6 @@
1
  {
2
  "experimental": {
 
3
  "outputFileTracingIncludes": {
4
  "/*": ["./cache/**/*"]
5
  },
 
1
  {
2
  "experimental": {
3
+ "missingSuspenseWithCSRBailout": false,
4
  "outputFileTracingIncludes": {
5
  "/*": ["./cache/**/*"]
6
  },
public/logo.jpg ADDED