Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat dashboard #48

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions client/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
24 changes: 24 additions & 0 deletions client/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
30 changes: 30 additions & 0 deletions client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

## Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:

- Configure the top-level `parserOptions` property like this:

```js
export default {
// other rules...
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: ['./tsconfig.json', './tsconfig.node.json'],
tsconfigRootDir: __dirname,
},
}
```

- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
13 changes: 13 additions & 0 deletions client/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
38 changes: 38 additions & 0 deletions client/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "client",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.5.2",
"@fortawesome/fontawesome-svg-core": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.0",
"@reduxjs/toolkit": "^2.2.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^9.1.2",
"react-router-dom": "^6.23.1"
},
"devDependencies": {
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"@vitejs/plugin-react": "^4.2.1",
"autoprefixer": "^10.4.19",
"eslint": "^8.57.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.3",
"typescript": "^5.2.2",
"vite": "^5.2.0"
}
}
6 changes: 6 additions & 0 deletions client/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
43 changes: 43 additions & 0 deletions client/src/Pages/Dashboard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useSelector, useDispatch } from 'react-redux';
import { logout } from '../../userSlice.tsx';
import { RootState } from '../../store';
import ArgentBank, { ArgentBankProps } from '../../components/ArgentBank';


const Dashboard = () => {
const user = useSelector((state: RootState) => state.user);
const dispatch = useDispatch();

const handleSignOut = () => {
dispatch(logout());
window.location.href = '/';
};

const argentBank: ArgentBankProps[] = [{
title: 'Argent Bank Checking (x8349)',
money: '$2,082.79',
balance: 'Available Balance'
}, {
title: 'Argent Bank Savings (x6712)',
money: '$10,928.42',
balance: 'Available Balance'
}, {
title: 'Argent Bank Credit Card (x8349)',
money: '$184.30',
balance: 'Current Balance'
}]

return (
<div className='flex flex-col items-center bg-dark-blue flex-1 text-white'>
<div className="mb-8">
<h1 className='text-3.5xl font-bold my-4 leading-tight'>Welcome back<br />{user.name} !</h1>
<button className="bg-blue-green font-bold p-2.5 text-sm border-solid border-2 border-l-blue-green border-t-blue-green border-b-blue-green-border border-r-blue-green-border leading-none">Edit Name</button>
</div>
{argentBank.map((bank, index) => (
<ArgentBank key={index} title={bank.title} money={bank.money} balance={bank.balance} />
))}
</div>
);
}

export default Dashboard;
14 changes: 14 additions & 0 deletions client/src/Pages/Home/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Hero from '../../components/Home/Hero';
import Features from '../../components/Home/Features';
import { Fragment } from 'react/jsx-runtime';

const Home = () => {
return (
<Fragment>
<Hero />
<Features />
</Fragment>
);
}

export default Home;
41 changes: 41 additions & 0 deletions client/src/Pages/SignIn/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { FormEvent } from 'react';
import { useDispatch } from 'react-redux';
import { login } from '../../userSlice.tsx';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCircleUser } from '@fortawesome/free-solid-svg-icons';

const SignIn = () => {
const dispatch = useDispatch();

const handleSignIn = (event: FormEvent) => {
event.preventDefault();
dispatch(login('Tony Jarvis'));
window.location.href = '/dashboard';
};

return (
<div className='flex flex-col items-center bg-dark-blue flex-1'>
<section className="bg-white w-75 mx-auto mt-12 p-8">
<FontAwesomeIcon icon={faCircleUser} />
<h1 className='text-2xl font-bold my-4'>Sign In</h1>
<form onSubmit={handleSignIn}>
<div className="flex flex-col text-left mb-4">
<label htmlFor="username" className="font-bold">Username</label>
<input type="text" id="username" className="p-1.5 text-xl border border-gray-500" />
</div>
<div className="flex flex-col text-left mb-4">
<label htmlFor="password" className="font-bold">Password</label>
<input type="password" id="password" className="p-1.5 text-xl border border-gray-500" />
</div>
<div className="flex items-center mb-4">
<input type="checkbox" id="remember-me" className="mr-2" />
<label htmlFor="remember-me">Remember me</label>
</div>
<button className="block w-full p-2 font-bold mt-4 bg-blue-green text-white">Sign In</button>
</form>
</section>
</div>
);
}

export default SignIn;
Binary file added client/src/assets/images/argentBankLogo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/src/assets/images/bank-tree.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/src/assets/images/icon-chat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/src/assets/images/icon-money.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/src/assets/images/icon-security.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions client/src/components/ArgentBank/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export type ArgentBankProps = {
title: string,
money: string,
balance: string
}

const ArgentBank = ({title, money, balance}: ArgentBankProps) => {
return (
<section className="flex flex-col text-left justify-between w-4/5 mb-8 border-1 border-black bg-white text-blue-grey p-6 medium:flex-row">
<div className='flex flex-col'>
<h3 className="font-normal">{title}</h3>
<p className="text-4.5xl leading-none font-bold m-0">{money}</p>
<p className="m-0 leading-6">{balance}</p>
</div>
<div className="self-start medium:self-center">
<button className="w-50 bg-blue-green text-white text-lg font-bold p-2 mt-4 border-2 border-l-blue-green border-t-blue-green border-b-blue-green-border border-r-blue-green-border leading-5">View transactions</button>
</div>
</section>
)
}

export default ArgentBank
9 changes: 9 additions & 0 deletions client/src/components/Footer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const Footer = () => {
return (
<footer className="flex justify-center border-t-2 border-gray-300 pt-8 pb-6">
<p className="m-0">Copyright 2020 Argent Bank</p>
</footer>
);
}

export default Footer;
20 changes: 20 additions & 0 deletions client/src/components/Home/FeatureText/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export type FeatureTextProps = {
img: {
src: string,
alt: string
},
title: string,
text: string
}

const FeatureText = ({img, title, text}: FeatureTextProps) => {
return (
<div className="flex flex-col items-center p-10">
<img className="w-25 border-10 border-blue-green box-content rounded-full p-4" src={`/src/assets/images/${img.src}`} alt={img.alt} />
<h3 className="text-dark-grey text-xl font-bold mb-2 mt-4">{title}</h3>
<p>{text}</p>
</div>
)
}

export default FeatureText
37 changes: 37 additions & 0 deletions client/src/components/Home/Features/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import FeatureText, { FeatureTextProps } from "../FeatureText";

const Features = () => {
const texts: FeatureTextProps[] = [{
img: {
src: 'icon-chat.png',
alt: 'Chat Icon',
},
title: 'You are our #1 priority',
text: 'Need to talk to a representative? You can get in touch through our 24/7 chat or through a phone call in less than 5 minutes.'
}, {
img: {
src: 'icon-money.png',
alt: 'Money Icon',
},
title: 'More savings means higher rates',
text: 'The more you save with us, the higher your interest rate will be!'
}, {
img: {
src: 'icon-security.png',
alt: 'Security Icon',
},
title: 'Security you can trust',
text: 'We use top of the line encryption to make sure your data and money is always safe.'
},]

return (
<section className="flex-1 large:grid large:grid-cols-3">
<h2 className="sr-only">Features</h2>
{texts.map((text, index) => (
<FeatureText key={index} img={text.img} title={text.title} text={text.text} />
))}
</section>
);
}

export default Features;
15 changes: 15 additions & 0 deletions client/src/components/Home/Hero/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const Hero = () => {
return (
<div className="bg-cover bg-no-repeat h-75 large:h-100 relative hero">
<section className="relative top-8 w-50 bg-white p-8 my-0 mx-auto text-left box-content large:absolute large:top-12 large:right-12 large:w-75 large:m-8">
<h2 className="sr-only">Promoted Content</h2>
<p className="font-bold large:text-2xl">No fees.</p>
<p className="font-bold large:text-2xl">No minimum deposit.</p>
<p className="font-bold large:text-2xl">High interest rates.</p>
<p className="text-sm large:text-xl mt-2.5">Open a savings account with Argent Bank today!</p>
</section>
</div>
);
}

export default Hero;
29 changes: 29 additions & 0 deletions client/src/components/NavBar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Link, Location, useLocation } from 'react-router-dom';

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCircleUser, faRightFromBracket } from '@fortawesome/free-solid-svg-icons';


const NavBar = () => {
const loc: Location = useLocation();
return (
<nav className="flex justify-between items-center py-1.5 px-5">
<Link className="flex items-center" to="/">
<img className="max-w-full w-50" src="/src/assets/images/argentBankLogo.png" alt="Argent Bank Logo" />
<h1 className="sr-only">Argent Bank</h1>
</Link>
<Link className="font-bold text-blue-grey mr-2" to="/sign-in">
<span className='mr-2'>
<FontAwesomeIcon icon={faCircleUser} /> Sign In
</span>
{loc.pathname === '/dashboard' && (
<span>
<FontAwesomeIcon icon={faRightFromBracket} /> Sign out
</span>
)}
</Link>
</nav>
);
}

export default NavBar;
Loading