diff --git a/client/.eslintrc.cjs b/client/.eslintrc.cjs
new file mode 100644
index 000000000..d6c953795
--- /dev/null
+++ b/client/.eslintrc.cjs
@@ -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 },
+ ],
+ },
+}
diff --git a/client/.gitignore b/client/.gitignore
new file mode 100644
index 000000000..a547bf36d
--- /dev/null
+++ b/client/.gitignore
@@ -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?
diff --git a/client/README.md b/client/README.md
new file mode 100644
index 000000000..0d6babedd
--- /dev/null
+++ b/client/README.md
@@ -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
diff --git a/client/index.html b/client/index.html
new file mode 100644
index 000000000..e4b78eae1
--- /dev/null
+++ b/client/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite + React + TS
+
+
+
+
+
+
diff --git a/client/package.json b/client/package.json
new file mode 100644
index 000000000..638e54493
--- /dev/null
+++ b/client/package.json
@@ -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"
+ }
+}
diff --git a/client/postcss.config.js b/client/postcss.config.js
new file mode 100644
index 000000000..2e7af2b7f
--- /dev/null
+++ b/client/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/client/src/Pages/Dashboard/index.tsx b/client/src/Pages/Dashboard/index.tsx
new file mode 100644
index 000000000..099415cc0
--- /dev/null
+++ b/client/src/Pages/Dashboard/index.tsx
@@ -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 (
+
+
+
Welcome back {user.name} !
+ Edit Name
+
+ {argentBank.map((bank, index) => (
+
+ ))}
+
+ );
+}
+
+export default Dashboard;
diff --git a/client/src/Pages/Home/index.tsx b/client/src/Pages/Home/index.tsx
new file mode 100644
index 000000000..395cea33c
--- /dev/null
+++ b/client/src/Pages/Home/index.tsx
@@ -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 (
+
+
+
+
+ );
+}
+
+export default Home;
diff --git a/client/src/Pages/SignIn/index.tsx b/client/src/Pages/SignIn/index.tsx
new file mode 100644
index 000000000..5fc918e6b
--- /dev/null
+++ b/client/src/Pages/SignIn/index.tsx
@@ -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 (
+
+ );
+}
+
+export default SignIn;
\ No newline at end of file
diff --git a/client/src/assets/images/argentBankLogo.png b/client/src/assets/images/argentBankLogo.png
new file mode 100644
index 000000000..89ce0f0b6
Binary files /dev/null and b/client/src/assets/images/argentBankLogo.png differ
diff --git a/client/src/assets/images/bank-tree.jpeg b/client/src/assets/images/bank-tree.jpeg
new file mode 100644
index 000000000..42619f4e8
Binary files /dev/null and b/client/src/assets/images/bank-tree.jpeg differ
diff --git a/client/src/assets/images/icon-chat.png b/client/src/assets/images/icon-chat.png
new file mode 100644
index 000000000..13e80a37c
Binary files /dev/null and b/client/src/assets/images/icon-chat.png differ
diff --git a/client/src/assets/images/icon-money.png b/client/src/assets/images/icon-money.png
new file mode 100644
index 000000000..16eef314e
Binary files /dev/null and b/client/src/assets/images/icon-money.png differ
diff --git a/client/src/assets/images/icon-security.png b/client/src/assets/images/icon-security.png
new file mode 100644
index 000000000..5a0e69b8a
Binary files /dev/null and b/client/src/assets/images/icon-security.png differ
diff --git a/client/src/components/ArgentBank/index.tsx b/client/src/components/ArgentBank/index.tsx
new file mode 100644
index 000000000..e785d979b
--- /dev/null
+++ b/client/src/components/ArgentBank/index.tsx
@@ -0,0 +1,22 @@
+export type ArgentBankProps = {
+ title: string,
+ money: string,
+ balance: string
+}
+
+const ArgentBank = ({title, money, balance}: ArgentBankProps) => {
+ return (
+
+
+
{title}
+
{money}
+
{balance}
+
+
+ View transactions
+
+
+ )
+}
+
+export default ArgentBank
\ No newline at end of file
diff --git a/client/src/components/Footer/index.tsx b/client/src/components/Footer/index.tsx
new file mode 100644
index 000000000..8f23226d1
--- /dev/null
+++ b/client/src/components/Footer/index.tsx
@@ -0,0 +1,9 @@
+const Footer = () => {
+ return (
+
+ );
+}
+
+export default Footer;
diff --git a/client/src/components/Home/FeatureText/index.tsx b/client/src/components/Home/FeatureText/index.tsx
new file mode 100644
index 000000000..65a46e37d
--- /dev/null
+++ b/client/src/components/Home/FeatureText/index.tsx
@@ -0,0 +1,20 @@
+export type FeatureTextProps = {
+ img: {
+ src: string,
+ alt: string
+ },
+ title: string,
+ text: string
+}
+
+const FeatureText = ({img, title, text}: FeatureTextProps) => {
+ return (
+
+
+
{title}
+
{text}
+
+ )
+}
+
+export default FeatureText
\ No newline at end of file
diff --git a/client/src/components/Home/Features/index.tsx b/client/src/components/Home/Features/index.tsx
new file mode 100644
index 000000000..5cd4a2f90
--- /dev/null
+++ b/client/src/components/Home/Features/index.tsx
@@ -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 (
+
+ Features
+ {texts.map((text, index) => (
+
+ ))}
+
+ );
+}
+
+export default Features;
diff --git a/client/src/components/Home/Hero/index.tsx b/client/src/components/Home/Hero/index.tsx
new file mode 100644
index 000000000..33a2ab4ae
--- /dev/null
+++ b/client/src/components/Home/Hero/index.tsx
@@ -0,0 +1,15 @@
+const Hero = () => {
+ return (
+
+
+ Promoted Content
+ No fees.
+ No minimum deposit.
+ High interest rates.
+ Open a savings account with Argent Bank today!
+
+
+ );
+}
+
+export default Hero;
diff --git a/client/src/components/NavBar/index.tsx b/client/src/components/NavBar/index.tsx
new file mode 100644
index 000000000..29eb3e6e1
--- /dev/null
+++ b/client/src/components/NavBar/index.tsx
@@ -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 (
+
+
+
+ Argent Bank
+
+
+
+ Sign In
+
+ {loc.pathname === '/dashboard' && (
+
+ Sign out
+
+ )}
+
+
+ );
+}
+
+export default NavBar;
diff --git a/client/src/main.tsx b/client/src/main.tsx
new file mode 100644
index 000000000..0c67ce74b
--- /dev/null
+++ b/client/src/main.tsx
@@ -0,0 +1,51 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client'
+import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
+
+import { Provider } from 'react-redux';
+import { store } from './store';
+
+import Home from './pages/Home';
+import SignIn from './pages/SignIn';
+import Dashboard from './pages/Dashboard';
+import NavBar from './components/NavBar';
+import Footer from './components/Footer';
+
+import './styles/index.css'
+import { library } from '@fortawesome/fontawesome-svg-core';
+import { fas } from '@fortawesome/free-solid-svg-icons';
+
+library.add(fas);
+
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
+
+
+
+ } />
+ } />
+ } />
+
+
+
+
+ ,
+)
+
+// import React from 'react'
+// import ReactDOM from 'react-dom/client'
+// import Menu from './Pages/Menu'
+// import CarteVins from './Pages/Wines';
+// import CarteBoissons from './Pages/Drinks';
+// import './styles/index.css'
+
+// ReactDOM.createRoot(document.getElementById('root')!).render(
+//
+// {/* */}
+//
+// ,
+// )
+
+
+
diff --git a/client/src/store.ts b/client/src/store.ts
new file mode 100644
index 000000000..64afb7c8d
--- /dev/null
+++ b/client/src/store.ts
@@ -0,0 +1,15 @@
+import { configureStore } from '@reduxjs/toolkit';
+import userReducer from './userSlice.tsx';
+
+export const store = configureStore({
+ reducer: {
+ user: userReducer,
+ },
+});
+
+// Get the type of our store variable
+export type AppStore = typeof store
+// Infer the `RootState` and `AppDispatch` types from the store itself
+export type RootState = ReturnType
+// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
+export type AppDispatch = AppStore['dispatch']
\ No newline at end of file
diff --git a/client/src/styles/index.css b/client/src/styles/index.css
new file mode 100644
index 000000000..5be54200c
--- /dev/null
+++ b/client/src/styles/index.css
@@ -0,0 +1,48 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+html, body {
+ height: 100%;
+}
+
+#root {
+ min-height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+html {
+ font-family: Avenir, Helvetica, Arial, sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ text-align: center;
+ color: #2c3e50;
+}
+
+.hero {
+ background-image: url('../src/assets/images/bank-tree.jpeg');
+ background-position: 0 -50px;
+}
+
+@media (min-width:720px) {
+ .hero {
+ background-position: 0 33%;
+ }
+}
+
+/* h1, h2 {
+ font-family: "Cormorant Upright", serif;
+ font-weight: 600;
+ font-style: normal;
+ font-optical-sizing: auto;
+}
+
+h2 {
+ font-size: 32px;
+ font-weight: 500;
+}
+
+h3 {
+ font-size: 28px;
+} */
\ No newline at end of file
diff --git a/client/src/userSlice.tsx b/client/src/userSlice.tsx
new file mode 100644
index 000000000..95b5e51a1
--- /dev/null
+++ b/client/src/userSlice.tsx
@@ -0,0 +1,23 @@
+import { createSlice } from '@reduxjs/toolkit';
+
+export const userSlice = createSlice({
+ name: 'user',
+ initialState: {
+ name: 'Tony Jarvis',
+ isAuthenticated: false,
+ },
+ reducers: {
+ login: (state, action) => {
+ state.name = action.payload;
+ state.isAuthenticated = true;
+ },
+ logout: (state) => {
+ state.name = '';
+ state.isAuthenticated = false;
+ },
+ },
+});
+
+export const { login, logout } = userSlice.actions;
+
+export default userSlice.reducer;
diff --git a/client/src/vite-env.d.ts b/client/src/vite-env.d.ts
new file mode 100644
index 000000000..11f02fe2a
--- /dev/null
+++ b/client/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/client/tailwind.config.js b/client/tailwind.config.js
new file mode 100644
index 000000000..18075feba
--- /dev/null
+++ b/client/tailwind.config.js
@@ -0,0 +1,44 @@
+/** @type {import('tailwindcss').Config} */
+export default {
+ content: [
+ './index.html',
+ './src/**/*.{js,ts,jsx,tsx}',
+ ],
+ theme: {
+ extend: {
+ colors: {
+ 'dark-blue': '#12002b',
+ 'blue-grey': '#2c3e50',
+ 'blue-green': '#42b983',
+ 'blue-green-border': '#006841',
+ 'dark-grey': '#222',
+ },
+ screens: {
+ 'medium': '720px',
+ 'large': '920px',
+ },
+ borderWidth: {
+ '10': '10px',
+ },
+ backgroundPosition: {
+ 'bottom-9': 'center bottom -9rem',
+ 'bottom-16': 'center bottom -16rem',
+ },
+ height: {
+ '75': '300px',
+ '100': '400px',
+ },
+ width: {
+ '25': '100px',
+ '50': '200px',
+ '75': '300px',
+ },
+ fontSize: {
+ '3.5xl': '2em',
+ '4.5xl': '2.5em',
+ }
+ },
+ },
+ plugins: [],
+}
+
diff --git a/client/tsconfig.json b/client/tsconfig.json
new file mode 100644
index 000000000..a7fc6fbf2
--- /dev/null
+++ b/client/tsconfig.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src"],
+ "references": [{ "path": "./tsconfig.node.json" }]
+}
diff --git a/client/tsconfig.node.json b/client/tsconfig.node.json
new file mode 100644
index 000000000..97ede7ee6
--- /dev/null
+++ b/client/tsconfig.node.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/client/vite.config.ts b/client/vite.config.ts
new file mode 100644
index 000000000..5a33944a9
--- /dev/null
+++ b/client/vite.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+})