🐱😒💋
This commit is contained in:
		
							
								
								
									
										10540
									
								
								frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10540
									
								
								frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -14,7 +14,7 @@
 | 
				
			|||||||
    "@types/react-dom": "^17.0.0",
 | 
					    "@types/react-dom": "^17.0.0",
 | 
				
			||||||
    "antd": "^4.14.0",
 | 
					    "antd": "^4.14.0",
 | 
				
			||||||
    "axios": "^0.21.1",
 | 
					    "axios": "^0.21.1",
 | 
				
			||||||
    "node-sass": "^5.0.0",
 | 
					    "node-sass": "^4.0.0",
 | 
				
			||||||
    "react": "^17.0.1",
 | 
					    "react": "^17.0.1",
 | 
				
			||||||
    "react-dom": "^17.0.1",
 | 
					    "react-dom": "^17.0.1",
 | 
				
			||||||
    "react-router-dom": "^5.2.0",
 | 
					    "react-router-dom": "^5.2.0",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@ import { Api } from './api'
 | 
				
			|||||||
import './scss/app.scss'
 | 
					import './scss/app.scss'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const App = () => {
 | 
					const App = () => {
 | 
				
			||||||
  const api = new Api({ baseURL: '/api' })
 | 
					  const api = new Api({ mock: true, baseURL: '/api' })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <BrowserRouter>
 | 
					    <BrowserRouter>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										49
									
								
								frontend/src/api/data/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								frontend/src/api/data/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					import { DataBuddy } from '@dank-inc/data-buddy'
 | 
				
			||||||
 | 
					import { Account, Stack, Transaction, User } from '../../types'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const users = new DataBuddy<User>([
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: 'mock-user',
 | 
				
			||||||
 | 
					    name: 'TestUser42',
 | 
				
			||||||
 | 
					    email: 'testuser@email.com',
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const accounts = new DataBuddy<Account>([
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: 'home',
 | 
				
			||||||
 | 
					    name: 'Home Expenses',
 | 
				
			||||||
 | 
					    details: 'ya',
 | 
				
			||||||
 | 
					    users: ['42'],
 | 
				
			||||||
 | 
					    income: 1000,
 | 
				
			||||||
 | 
					    expenses: 500,
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
 | 
					export const stacks = new DataBuddy<Stack>([
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: 'ccrap',
 | 
				
			||||||
 | 
					    name: 'crap',
 | 
				
			||||||
 | 
					    account: 'asdf',
 | 
				
			||||||
 | 
					    amount: 200,
 | 
				
			||||||
 | 
					    details: 'for all my crap!',
 | 
				
			||||||
 | 
					    transactions: [],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: 'shit',
 | 
				
			||||||
 | 
					    name: 'shit',
 | 
				
			||||||
 | 
					    account: 'home',
 | 
				
			||||||
 | 
					    amount: 500,
 | 
				
			||||||
 | 
					    details: 'for all my shit!',
 | 
				
			||||||
 | 
					    transactions: [],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    id: 'poo',
 | 
				
			||||||
 | 
					    name: 'poo',
 | 
				
			||||||
 | 
					    account: 'home',
 | 
				
			||||||
 | 
					    amount: 800,
 | 
				
			||||||
 | 
					    details: 'for all my poo!',
 | 
				
			||||||
 | 
					    transactions: [],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const transactions = new DataBuddy<Transaction>([])
 | 
				
			||||||
@@ -1,14 +0,0 @@
 | 
				
			|||||||
import { DataBuddy } from '@dank-inc/data-buddy'
 | 
					 | 
				
			||||||
import { Account, Stack, Transaction, User } from '../../types'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const users = new DataBuddy<User>([
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    id: '42',
 | 
					 | 
				
			||||||
    name: 'TestUser42',
 | 
					 | 
				
			||||||
    email: 'testuser@email.com',
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const accounts = new DataBuddy<Account>([])
 | 
					 | 
				
			||||||
export const stacks = new DataBuddy<Stack>([])
 | 
					 | 
				
			||||||
export const transactions = new DataBuddy<Transaction>([])
 | 
					 | 
				
			||||||
@@ -2,7 +2,7 @@ import Axios, { AxiosInstance } from 'axios'
 | 
				
			|||||||
import { Account, Password, Stack, Transaction, User, uuid } from '../types'
 | 
					import { Account, Password, Stack, Transaction, User, uuid } from '../types'
 | 
				
			||||||
import { JWT, setJWT, wipeJWT } from '../utils/jwt'
 | 
					import { JWT, setJWT, wipeJWT } from '../utils/jwt'
 | 
				
			||||||
import { DataBuddy } from '@dank-inc/data-buddy'
 | 
					import { DataBuddy } from '@dank-inc/data-buddy'
 | 
				
			||||||
import { users } from './data/users'
 | 
					import { users, accounts, stacks, transactions } from './data'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type ApiParams = {
 | 
					export type ApiParams = {
 | 
				
			||||||
  baseURL?: string
 | 
					  baseURL?: string
 | 
				
			||||||
@@ -14,7 +14,7 @@ export interface Api {
 | 
				
			|||||||
  users: DataBuddy<User>
 | 
					  users: DataBuddy<User>
 | 
				
			||||||
  accounts: DataBuddy<Account>
 | 
					  accounts: DataBuddy<Account>
 | 
				
			||||||
  stacks: DataBuddy<Stack>
 | 
					  stacks: DataBuddy<Stack>
 | 
				
			||||||
  Transactions: DataBuddy<Transaction>
 | 
					  transactions: DataBuddy<Transaction>
 | 
				
			||||||
  axios: AxiosInstance
 | 
					  axios: AxiosInstance
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -22,19 +22,25 @@ export class Api {
 | 
				
			|||||||
  constructor({ mock, baseURL }: ApiParams) {
 | 
					  constructor({ mock, baseURL }: ApiParams) {
 | 
				
			||||||
    this.mock = mock
 | 
					    this.mock = mock
 | 
				
			||||||
    this.users = users
 | 
					    this.users = users
 | 
				
			||||||
 | 
					    this.accounts = accounts
 | 
				
			||||||
 | 
					    this.stacks = stacks
 | 
				
			||||||
 | 
					    this.transactions = transactions
 | 
				
			||||||
    this.axios = Axios.create({ baseURL })
 | 
					    this.axios = Axios.create({ baseURL })
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  login = async (username: string, password: string): Promise<JWT> => {
 | 
					  login = async (name: string, password: string): Promise<JWT> => {
 | 
				
			||||||
    if (this.mock)
 | 
					    if (this.mock) {
 | 
				
			||||||
      return {
 | 
					      const jwt = {
 | 
				
			||||||
        id: 'mock-id',
 | 
					        id: 'mock-user',
 | 
				
			||||||
        token: 'token-token-token',
 | 
					        token: 'token-token-token',
 | 
				
			||||||
        exp: +new Date(),
 | 
					        exp: +new Date(),
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      setJWT(jwt)
 | 
				
			||||||
 | 
					      return jwt
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const { data } = await this.axios.post<JWT>(`/api/dj-rest-auth/login/`, {
 | 
					    const { data } = await this.axios.post<JWT>(`/api/dj-rest-auth/login/`, {
 | 
				
			||||||
      username,
 | 
					      name,
 | 
				
			||||||
      password,
 | 
					      password,
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -65,11 +71,13 @@ export class Api {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getAccounts = async () => {
 | 
					  getAccounts = async () => {
 | 
				
			||||||
 | 
					    if (this.mock) return this.accounts.get()
 | 
				
			||||||
    const { data } = await this.axios.get<Account[]>('accounts')
 | 
					    const { data } = await this.axios.get<Account[]>('accounts')
 | 
				
			||||||
    return data
 | 
					    return data
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getAccount = async (id: uuid) => {
 | 
					  getAccount = async (id: uuid) => {
 | 
				
			||||||
 | 
					    if (this.mock) return this.accounts.getOne(id)
 | 
				
			||||||
    const data = await this.axios.get<Account>(`accounts/${id}`)
 | 
					    const data = await this.axios.get<Account>(`accounts/${id}`)
 | 
				
			||||||
    return data
 | 
					    return data
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -84,20 +92,25 @@ export class Api {
 | 
				
			|||||||
  deleteAccount = async () => {}
 | 
					  deleteAccount = async () => {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getStacks = async (): Promise<Stack[]> => {
 | 
					  getStacks = async (): Promise<Stack[]> => {
 | 
				
			||||||
 | 
					    if (this.mock) return this.stacks.get()
 | 
				
			||||||
    const { data } = await this.axios.get('stacks')
 | 
					    const { data } = await this.axios.get('stacks')
 | 
				
			||||||
    return data
 | 
					    return data
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  updateStack = async (id: uuid, body: Partial<Stack>) => {
 | 
					  updateStack = async (id: uuid, body: Partial<Stack>) => {
 | 
				
			||||||
    const { data } = await this.axios.patch<Stack>(`stacks/${id}`, body)
 | 
					    const { data } = await this.axios.patch<Stack>(`stacks/${id}`, body)
 | 
				
			||||||
    return data
 | 
					    return data
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  createStack = async () => {}
 | 
					  createStack = async () => {}
 | 
				
			||||||
  deleteStack = async () => {}
 | 
					  deleteStack = async () => {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getTransactions = async () => {
 | 
					  getTransactions = async () => {
 | 
				
			||||||
 | 
					    if (this.mock) return this.transactions.get()
 | 
				
			||||||
    const { data } = await this.axios.get('transactions')
 | 
					    const { data } = await this.axios.get('transactions')
 | 
				
			||||||
    return data
 | 
					    return data
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  updateTransaction = async (id: uuid, body: Partial<Transaction>) => {
 | 
					  updateTransaction = async (id: uuid, body: Partial<Transaction>) => {
 | 
				
			||||||
    const { data } = await this.axios.patch<Transaction>(
 | 
					    const { data } = await this.axios.patch<Transaction>(
 | 
				
			||||||
      `transactions/${id}`,
 | 
					      `transactions/${id}`,
 | 
				
			||||||
@@ -105,6 +118,7 @@ export class Api {
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
    return data
 | 
					    return data
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  createTransaction = async (body: Omit<Transaction, 'id'>) => {
 | 
					  createTransaction = async (body: Omit<Transaction, 'id'>) => {
 | 
				
			||||||
    const { data } = await this.axios.post<Transaction>('transactions', body)
 | 
					    const { data } = await this.axios.post<Transaction>('transactions', body)
 | 
				
			||||||
    return data
 | 
					    return data
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,18 +1,19 @@
 | 
				
			|||||||
import { useUserContext } from '../contexts/UserContext'
 | 
					import { useUserContext } from '../contexts/UserContext'
 | 
				
			||||||
import { Redirect, Route, Switch } from 'react-router'
 | 
					import { Route, Switch } from 'react-router'
 | 
				
			||||||
import { Link } from 'react-router-dom'
 | 
					import { Link } from 'react-router-dom'
 | 
				
			||||||
import { Dashboard } from './pages/Dashboard'
 | 
					import { Dashboard } from './pages/Dashboard'
 | 
				
			||||||
import { UserForm } from './components/UserForm'
 | 
					import { UserForm } from './components/UserForm'
 | 
				
			||||||
import { TransactionList } from './components/TransactionList'
 | 
					import { TransactionList } from './components/TransactionList'
 | 
				
			||||||
import { AccountForm } from './components/AccountForm'
 | 
					import { AccountForm } from './components/AccountForm'
 | 
				
			||||||
 | 
					import { Login } from './components/Login'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const CoreLayout = () => {
 | 
					export const CoreLayout = () => {
 | 
				
			||||||
  const { user, accounts, selectedAccount } = useUserContext()
 | 
					  const { user, selectedAccount } = useUserContext()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!accounts?.length) <Redirect to="/account/new" />
 | 
					  if (!user) return <Login />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className="app" id="appElement">
 | 
					    <div className="app">
 | 
				
			||||||
      <nav>
 | 
					      <nav>
 | 
				
			||||||
        <Link to="/">Home</Link>
 | 
					        <Link to="/">Home</Link>
 | 
				
			||||||
        <Link to="/select">Select Budget</Link>
 | 
					        <Link to="/select">Select Budget</Link>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,7 +72,7 @@ export const AccountForm = ({ account }: Props) => {
 | 
				
			|||||||
        </label>
 | 
					        </label>
 | 
				
			||||||
        <h3>Budgets</h3>
 | 
					        <h3>Budgets</h3>
 | 
				
			||||||
        {stacks.data?.map((stack) => (
 | 
					        {stacks.data?.map((stack) => (
 | 
				
			||||||
          <div className="form-item">
 | 
					          <div key={stack.details} className="form-item">
 | 
				
			||||||
            <label>{stack.name}</label>
 | 
					            <label>{stack.name}</label>
 | 
				
			||||||
            <input
 | 
					            <input
 | 
				
			||||||
              type="number"
 | 
					              type="number"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,71 +1,40 @@
 | 
				
			|||||||
import React, { useState, useEffect } from 'react'
 | 
					import { Button, Form, Input } from 'antd'
 | 
				
			||||||
import Axios from 'axios'
 | 
					import FormItem from 'antd/lib/form/FormItem'
 | 
				
			||||||
import { Link } from 'react-router-dom'
 | 
					import { Link } from 'react-router-dom'
 | 
				
			||||||
 | 
					import { User } from '../../types'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					import '../../scss/login.scss'
 | 
				
			||||||
  handleLogin: (v: string) => void
 | 
					import { useUserContext } from '../../contexts/UserContext'
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const Login = ({ handleLogin }: Props) => {
 | 
					type FormValues = Pick<User, 'name'> & { password: string }
 | 
				
			||||||
  const [email, setEmail] = useState('')
 | 
					 | 
				
			||||||
  const [password, setPassword] = useState('')
 | 
					 | 
				
			||||||
  const [valid, setValid] = useState(false)
 | 
					 | 
				
			||||||
  const [error, setError] = useState('')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useEffect(() => {
 | 
					export const Login = () => {
 | 
				
			||||||
    if (window.localStorage.userId) handleLogin(window.localStorage.userId)
 | 
					  const userContext = useUserContext()
 | 
				
			||||||
  }, [handleLogin])
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  useEffect(() => {
 | 
					  const [form] = Form.useForm<FormValues>()
 | 
				
			||||||
    email && password ? setValid(true) : setValid(false)
 | 
					 | 
				
			||||||
  }, [email, password])
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const handleSubmit = async (e: React.FormEvent) => {
 | 
					  const handleFinish = ({ name, password }: FormValues) => {
 | 
				
			||||||
    e.preventDefault()
 | 
					    userContext.handleLogin(name, password)
 | 
				
			||||||
    if (process.env.NODE_ENV === 'development') {
 | 
					 | 
				
			||||||
      handleLogin(email)
 | 
					 | 
				
			||||||
      return
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (!email || !password) {
 | 
					 | 
				
			||||||
      setError('please fill out both fields')
 | 
					 | 
				
			||||||
      return
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      const { data } = await Axios.post('/api/login', { email, password })
 | 
					 | 
				
			||||||
      handleLogin(data.id)
 | 
					 | 
				
			||||||
      window.localStorage.userId = data.id
 | 
					 | 
				
			||||||
    } catch (err) {
 | 
					 | 
				
			||||||
      setError(err.message)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className="login">
 | 
					    <div className="login">
 | 
				
			||||||
      <form onSubmit={handleSubmit}>
 | 
					      <h1>Log In</h1>
 | 
				
			||||||
        <label>
 | 
					      <Form onFinish={handleFinish} form={form}>
 | 
				
			||||||
          Type Yo Email:
 | 
					        <FormItem label="Username" name="username">
 | 
				
			||||||
          <input
 | 
					          <Input />
 | 
				
			||||||
            autoFocus
 | 
					        </FormItem>
 | 
				
			||||||
            onChange={e => setEmail(e.target.value)}
 | 
					        <FormItem label="Password" name="password">
 | 
				
			||||||
            value={email}
 | 
					          <Input type="password" />
 | 
				
			||||||
          ></input>
 | 
					        </FormItem>
 | 
				
			||||||
        </label>
 | 
					
 | 
				
			||||||
        <label>
 | 
					        <div className="form-footer">
 | 
				
			||||||
          Type Yo Password:
 | 
					          <Link to="/sign-up">No Account? Sign Up!</Link>
 | 
				
			||||||
          <input
 | 
					          <Button type="primary" htmlType="submit">
 | 
				
			||||||
            type="password"
 | 
					            Log In!
 | 
				
			||||||
            onChange={e => setPassword(e.target.value)}
 | 
					          </Button>
 | 
				
			||||||
            value={password}
 | 
					        </div>
 | 
				
			||||||
          ></input>
 | 
					      </Form>
 | 
				
			||||||
        </label>
 | 
					 | 
				
			||||||
        <label>
 | 
					 | 
				
			||||||
          <button disabled={!valid} type="submit">
 | 
					 | 
				
			||||||
            Submit
 | 
					 | 
				
			||||||
          </button>
 | 
					 | 
				
			||||||
        </label>
 | 
					 | 
				
			||||||
        {error && <p>{error}</p>}
 | 
					 | 
				
			||||||
        <Link to="/sign-up">No Account? Sign Up!</Link>
 | 
					 | 
				
			||||||
      </form>
 | 
					 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,8 @@ export const UserForm = () => {
 | 
				
			|||||||
  const { api } = useAppContext()
 | 
					  const { api } = useAppContext()
 | 
				
			||||||
  const { user } = useUserContext()
 | 
					  const { user } = useUserContext()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  console.log(user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const [name, setName] = useState(user?.name)
 | 
					  const [name, setName] = useState(user?.name)
 | 
				
			||||||
  const [email, setEmail] = useState(user?.email)
 | 
					  const [email, setEmail] = useState(user?.email)
 | 
				
			||||||
  const [password, setPassword] = useState('')
 | 
					  const [password, setPassword] = useState('')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,7 @@ export const Dashboard = () => {
 | 
				
			|||||||
      <h1>Remaining Balances</h1>
 | 
					      <h1>Remaining Balances</h1>
 | 
				
			||||||
      <div className="funds">
 | 
					      <div className="funds">
 | 
				
			||||||
        {stacks.data.map((stack, i) => (
 | 
					        {stacks.data.map((stack, i) => (
 | 
				
			||||||
          <FundBar stack={stack} col={i + 1} />
 | 
					          <FundBar key={stack.id} stack={stack} col={i + 1} />
 | 
				
			||||||
        ))}
 | 
					        ))}
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </>
 | 
					    </>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,6 @@ type Credentials = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export const Login = () => {
 | 
					export const Login = () => {
 | 
				
			||||||
  const { handleLogin } = useUserContext()
 | 
					  const { handleLogin } = useUserContext()
 | 
				
			||||||
 | 
					 | 
				
			||||||
  const [form] = useForm<Credentials>()
 | 
					  const [form] = useForm<Credentials>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const handleSubmit = ({ username, password }: Credentials) => {
 | 
					  const handleSubmit = ({ username, password }: Credentials) => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +0,0 @@
 | 
				
			|||||||
export const Profile = () => {
 | 
					 | 
				
			||||||
  return <p>Look, A user profile!</p>
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -13,7 +13,7 @@ type Context = {
 | 
				
			|||||||
  user: User | null
 | 
					  user: User | null
 | 
				
			||||||
  accounts: Account[] | null
 | 
					  accounts: Account[] | null
 | 
				
			||||||
  selectedAccount: Account | null
 | 
					  selectedAccount: Account | null
 | 
				
			||||||
  handleLogin: (username: string, password: string) => void
 | 
					  handleLogin: (name: string, password: string) => void
 | 
				
			||||||
  handleLogout: () => void
 | 
					  handleLogout: () => void
 | 
				
			||||||
  handleSelectAccount: (id: uuid) => void
 | 
					  handleSelectAccount: (id: uuid) => void
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -28,11 +28,14 @@ export const UserContextProvider = ({ children }: Props) => {
 | 
				
			|||||||
  const [accounts, setAccounts] = useState<Account[] | null>(null)
 | 
					  const [accounts, setAccounts] = useState<Account[] | null>(null)
 | 
				
			||||||
  const [selectedAccount, setSelectedAccount] = useState<Account | null>(null)
 | 
					  const [selectedAccount, setSelectedAccount] = useState<Account | null>(null)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const handleLogin = async (username: string, password: string) => {
 | 
					  const handleLogin = async (name: string, password: string) => {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const { id } = await api.login(username, password)
 | 
					      const { id } = await api.login(name, password)
 | 
				
			||||||
      if (!id) throw new Error('Problem logging in!')
 | 
					      if (!id) throw new Error('Problem logging in!')
 | 
				
			||||||
      setUser(await api.getUser(id))
 | 
					      const user = await api.getUser(id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (!user) message.error(`Couldn't find user`)
 | 
				
			||||||
 | 
					      setUser(user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const accounts = await api.getAccounts()
 | 
					      const accounts = await api.getAccounts()
 | 
				
			||||||
      setAccounts(accounts)
 | 
					      setAccounts(accounts)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,35 @@
 | 
				
			|||||||
  box-sizing: border-box;
 | 
					  box-sizing: border-box;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#root {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					  height: 100vh;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.col1 {
 | 
				
			||||||
 | 
					  grid-column: 1/1;
 | 
				
			||||||
 | 
					  grid-row: 1/1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.col2 {
 | 
				
			||||||
 | 
					  grid-column: 2/2;
 | 
				
			||||||
 | 
					  grid-row: 1/1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.col3 {
 | 
				
			||||||
 | 
					  grid-column: 3/3;
 | 
				
			||||||
 | 
					  grid-row: 1/1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					h1,
 | 
				
			||||||
 | 
					h2,
 | 
				
			||||||
 | 
					h3,
 | 
				
			||||||
 | 
					h4,
 | 
				
			||||||
 | 
					h5 {
 | 
				
			||||||
 | 
					  color: #222;
 | 
				
			||||||
 | 
					  text-shadow: -1px -1px #444;
 | 
				
			||||||
 | 
					  font-weight: 900;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
body {
 | 
					body {
 | 
				
			||||||
  margin: 0;
 | 
					  margin: 0;
 | 
				
			||||||
  -webkit-font-smoothing: antialiased;
 | 
					  -webkit-font-smoothing: antialiased;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,26 +1,3 @@
 | 
				
			|||||||
h1,
 | 
					 | 
				
			||||||
h2,
 | 
					 | 
				
			||||||
h3,
 | 
					 | 
				
			||||||
h4,
 | 
					 | 
				
			||||||
h5 {
 | 
					 | 
				
			||||||
  color: #222;
 | 
					 | 
				
			||||||
  text-shadow: -1px -1px #444;
 | 
					 | 
				
			||||||
  font-weight: 900;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.col1 {
 | 
					 | 
				
			||||||
  grid-column: 1/1;
 | 
					 | 
				
			||||||
  grid-row: 1/1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.col2 {
 | 
					 | 
				
			||||||
  grid-column: 2/2;
 | 
					 | 
				
			||||||
  grid-row: 1/1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.col3 {
 | 
					 | 
				
			||||||
  grid-column: 3/3;
 | 
					 | 
				
			||||||
  grid-row: 1/1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.app {
 | 
					.app {
 | 
				
			||||||
  display: flex;
 | 
					  display: flex;
 | 
				
			||||||
  flex-direction: column;
 | 
					  flex-direction: column;
 | 
				
			||||||
@@ -89,29 +66,6 @@ nav {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.login {
 | 
					 | 
				
			||||||
  color: #ccc;
 | 
					 | 
				
			||||||
  form {
 | 
					 | 
				
			||||||
    display: flex;
 | 
					 | 
				
			||||||
    flex-direction: column;
 | 
					 | 
				
			||||||
    justify-content: space-around;
 | 
					 | 
				
			||||||
    height: 100%;
 | 
					 | 
				
			||||||
    text-align: center;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    label {
 | 
					 | 
				
			||||||
      input {
 | 
					 | 
				
			||||||
        margin-left: 2ch;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  display: flex;
 | 
					 | 
				
			||||||
  flex-direction: column;
 | 
					 | 
				
			||||||
  width: 70vmin;
 | 
					 | 
				
			||||||
  height: 70vmin;
 | 
					 | 
				
			||||||
  margin: auto;
 | 
					 | 
				
			||||||
  background: #222;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.todo {
 | 
					.todo {
 | 
				
			||||||
  color: #111a;
 | 
					  color: #111a;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										33
									
								
								frontend/src/scss/login.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								frontend/src/scss/login.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					.login {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  box-shadow: 5px 5px #111, 2px 2px #111;
 | 
				
			||||||
 | 
					  flex-direction: column;
 | 
				
			||||||
 | 
					  margin: auto;
 | 
				
			||||||
 | 
					  background: #222;
 | 
				
			||||||
 | 
					  border-radius: 0.2rem;
 | 
				
			||||||
 | 
					  padding: 2rem 2rem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  h1 {
 | 
				
			||||||
 | 
					    margin: 0 auto;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  form {
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    flex-direction: column;
 | 
				
			||||||
 | 
					    justify-content: space-between;
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .ant-row {
 | 
				
			||||||
 | 
					      margin: 1rem 2rem;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .form-footer {
 | 
				
			||||||
 | 
					      margin-top: 1rem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      button {
 | 
				
			||||||
 | 
					        width: 50%;
 | 
				
			||||||
 | 
					        margin: auto 0 auto 1rem;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1802
									
								
								frontend/yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										1802
									
								
								frontend/yarn.lock
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user