diff --git a/README.md b/README.md
index af77df9..4d2c111 100644
--- a/README.md
+++ b/README.md
@@ -1,31 +1,13 @@
-# mvp-django-react
+# Cash Dash Stacks
-An MVP boilerplate for a django / react app.
+- A simple way to track expenses
+- cash budgeting in digital mode
-# Setup
+# Ideas
-```
-python manage.py migrate
-python manage.py createsuperuser --email admin@example.com --username admin --password whatever
-```
+- put items in your wishlist and track savings to buy big-ticket items
+- view spending trends
-# Boilerplate Features
+# Todo
-- Authentication
-- User Table (username, email, password)
-
-# Extras
-
-- dockerized
-
-# Frontend
-
-- [x] User context
-- [x] auth api
-- [ ] user crud api (new user flow)
-
-# Backend
-
-- user CRUD
-- login / logout / forgot password
-- serve static index (prod)
+https://github.com/dank-inc/cash-stacks/projects
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 5159905..f80277a 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -1,10 +1,9 @@
import { BrowserRouter } from 'react-router-dom'
import { UserContextProvider } from './contexts/UserContext'
-import { CoreLayout } from './app/CoreLayout'
+import { CoreLayout } from './CoreLayout'
import { AppContextProvider } from './contexts/AppContext'
-import { Api } from './api'
-import './scss/app.scss'
+import './app.scss'
const App = () => {
return (
diff --git a/frontend/src/CoreLayout.tsx b/frontend/src/CoreLayout.tsx
new file mode 100644
index 0000000..202a81c
--- /dev/null
+++ b/frontend/src/CoreLayout.tsx
@@ -0,0 +1,38 @@
+import { useUserContext } from './contexts/UserContext'
+import { Route, Switch } from 'react-router'
+import { Link } from 'react-router-dom'
+import { Dashboard } from './pages/Dashboard'
+import { NewUser } from './pages/NewUser'
+import { TransactionList } from './pages/TransactionList'
+import { AccountForm } from './forms/AccountForm'
+import { Login } from './pages/Login'
+import { AppHeader } from './layout/AppHeader'
+import { AppFooter } from './layout/AppFooter'
+
+export const CoreLayout = () => {
+ const { user } = useUserContext()
+
+ if (!user) return
+
+ return (
+
+
+ Home
+ Select Budget
+ Budget Details
+ Transactions
+ New User
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/frontend/src/scss/app.scss b/frontend/src/app.scss
similarity index 76%
rename from frontend/src/scss/app.scss
rename to frontend/src/app.scss
index bd0f2e9..8a411b3 100644
--- a/frontend/src/scss/app.scss
+++ b/frontend/src/app.scss
@@ -1,8 +1,10 @@
+// @include './form.scss';
+
.app {
- display: flex;
- flex-direction: column;
+ display: grid;
+ grid-template: 1fr / auto 1fr auto;
+
align-items: center;
- // justify-content: space-around;
font-size: calc(10px + 2vmin);
color: white;
@@ -12,10 +14,6 @@
}
}
-button {
- cursor: pointer;
-}
-
.funds,
.transactions {
display: grid;
diff --git a/frontend/src/app/CoreLayout.tsx b/frontend/src/app/CoreLayout.tsx
deleted file mode 100644
index e627a8f..0000000
--- a/frontend/src/app/CoreLayout.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import { useUserContext } from '../contexts/UserContext'
-import { Route, Switch } from 'react-router'
-import { Link } from 'react-router-dom'
-import { Dashboard } from './pages/Dashboard'
-import { UserForm } from './components/UserForm'
-import { TransactionList } from './components/TransactionList'
-import { AccountForm } from './components/AccountForm'
-import { Login } from './components/Login'
-import { AppHeader } from './layout/AppHeader'
-import { AppFooter } from './layout/AppFooter'
-
-export const CoreLayout = () => {
- const { user, selectedAccount } = useUserContext()
-
- if (!user) return
-
- return (
-
-
- Home
- Select Budget
- Budget Details
- Transactions
- Profile
-
-
-
-
-
-
-
-
-
-
-
- {/* {showingModal &&
} */}
-
- )
-}
diff --git a/frontend/src/app/components/UserForm.tsx b/frontend/src/app/components/UserForm.tsx
index da18906..3f35ed7 100644
--- a/frontend/src/app/components/UserForm.tsx
+++ b/frontend/src/app/components/UserForm.tsx
@@ -1,15 +1,10 @@
import { useState, useEffect } from 'react'
import { Password, User } from '../../types'
-import '../../scss/form.scss'
import { useUserContext } from '../../contexts/UserContext'
-import { useAppContext } from '../../contexts/AppContext'
-import { useHistory } from 'react-router'
import { message } from 'antd'
export const UserForm = () => {
- const history = useHistory()
- const { api } = useAppContext()
const { user } = useUserContext()
console.log(user)
@@ -43,11 +38,11 @@ export const UserForm = () => {
}
try {
- user?.id
- ? await api.updateUser(user.id, body)
- : await api.createUser(body)
-
- if (!user?.id) history.push('/login')
+ // user?.id
+ // ? await api.updateUser(user.id, body)
+ // : await api.createUser(body)
+ console.log('User form wtf')
+ // if (!user?.id) history.push('/login')
} catch (err) {
message.error('Something went wrong')
}
diff --git a/frontend/src/app/pages/Dashboard.tsx b/frontend/src/app/pages/Dashboard.tsx
deleted file mode 100644
index 99e7f55..0000000
--- a/frontend/src/app/pages/Dashboard.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { FundBar } from '../components/FundBar'
-import { usePromise } from '@dank-inc/use-get'
-import { useAppContext } from '../../contexts/AppContext'
-
-export const Dashboard = () => {
- const { api } = useAppContext()
- const stacks = usePromise(api.getStacks())
-
- if (stacks.loading || !stacks.data) return loading...
-
- return (
- <>
- Remaining Balances
-
- {stacks.data.map((stack, i) => (
-
- ))}
-
- >
- )
-}
diff --git a/frontend/src/contexts/AppContext.tsx b/frontend/src/contexts/AppContext.tsx
index 68b6c8a..aaa2c9b 100644
--- a/frontend/src/contexts/AppContext.tsx
+++ b/frontend/src/contexts/AppContext.tsx
@@ -1,4 +1,4 @@
-import Axios from 'axios'
+import Axios, { AxiosResponse } from 'axios'
import React, { createContext, useContext } from 'react'
type Props = {
@@ -9,7 +9,7 @@ type Props = {
type Context = {
get: (path: string) => Promise
patch: (path: string, body: Partial) => Promise
- post: (path: string, body: Partial) => Promise
+ post: (path: string, body: Partial) => Promise
create: (path: string, body: Partial) => Promise
destroy: (path: string) => Promise
}
@@ -27,8 +27,8 @@ export const AppContextProvider = ({ children, baseURL }: Props) => {
const res = await axios.patch(path, body)
return res.data
}
- async function post(path: string, body: Partial) {
- const res = await axios.post(path, body)
+ async function post(path: string, body: Partial) {
+ const res = await axios.post>(path, body)
return res.data
}
async function create(path: string, body: Partial) {
diff --git a/frontend/src/contexts/UserContext.tsx b/frontend/src/contexts/UserContext.tsx
index f93febc..a7cdeae 100644
--- a/frontend/src/contexts/UserContext.tsx
+++ b/frontend/src/contexts/UserContext.tsx
@@ -21,7 +21,7 @@ type Context = {
const UserContext = createContext(null)
export const UserContextProvider = ({ children }: Props) => {
- const { api } = useAppContext()
+ const api = useAppContext()
const history = useHistory()
const [user, setUser] = useState(null)
@@ -30,14 +30,17 @@ export const UserContextProvider = ({ children }: Props) => {
const handleLogin = async (name: string, password: string) => {
try {
- const { id } = await api.login(name, password)
+ const { id } = await api.post('/login', {
+ name,
+ password,
+ })
if (!id) throw new Error('Problem logging in!')
- const user = await api.getUser(id)
+ const user = await api.get(`/users/${id}`)
if (!user) message.error(`Couldn't find user`)
setUser(user)
- const accounts = await api.getAccounts()
+ const accounts = await api.get('/accounts')
setAccounts(accounts)
message.success(`logged in as ${user?.name}`, 0.5)
diff --git a/frontend/src/elements/Button/index.tsx b/frontend/src/elements/Button/index.tsx
new file mode 100644
index 0000000..629f596
--- /dev/null
+++ b/frontend/src/elements/Button/index.tsx
@@ -0,0 +1,13 @@
+import { Button as AntButton, ButtonProps } from 'antd'
+import React from 'react'
+import './style.scss'
+
+type Props = ButtonProps
+
+export const Button = ({ children, htmlType }: Props) => {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/frontend/src/elements/Button/style.scss b/frontend/src/elements/Button/style.scss
new file mode 100644
index 0000000..afefbdb
--- /dev/null
+++ b/frontend/src/elements/Button/style.scss
@@ -0,0 +1,4 @@
+.dank-button {
+ cursor: pointer;
+ // shit here
+}
diff --git a/frontend/src/elements/Form/index.tsx b/frontend/src/elements/Form/index.tsx
new file mode 100644
index 0000000..98c3bee
--- /dev/null
+++ b/frontend/src/elements/Form/index.tsx
@@ -0,0 +1,8 @@
+import { Form as AntForm, FormProps } from 'antd'
+import './style.scss'
+
+type Props = FormProps
+
+export const Form = ({ children }: Props) => {
+ return {children}
+}
diff --git a/frontend/src/scss/form.scss b/frontend/src/elements/Form/style.scss
similarity index 100%
rename from frontend/src/scss/form.scss
rename to frontend/src/elements/Form/style.scss
diff --git a/frontend/src/elements/Toast/index.tsx b/frontend/src/elements/Toast/index.tsx
new file mode 100644
index 0000000..6676272
--- /dev/null
+++ b/frontend/src/elements/Toast/index.tsx
@@ -0,0 +1,14 @@
+import React from 'react'
+import './style.scss'
+
+type Props = {
+ title: string
+ type: 'success' | 'error'
+ children: React.ReactNode
+}
+
+export const Toast = (props: Props) => {
+ // show me a toast
+
+ return null
+}
diff --git a/frontend/src/scss/status.scss b/frontend/src/elements/Toast/style.scss
similarity index 95%
rename from frontend/src/scss/status.scss
rename to frontend/src/elements/Toast/style.scss
index 01ccc9b..964e7fe 100644
--- a/frontend/src/scss/status.scss
+++ b/frontend/src/elements/Toast/style.scss
@@ -1,4 +1,4 @@
-.status {
+.dank-toast {
position: absolute;
left: 1ch;
bottom: 4ch;
diff --git a/frontend/src/app/components/AccountForm.tsx b/frontend/src/forms/AccountForm.tsx
similarity index 75%
rename from frontend/src/app/components/AccountForm.tsx
rename to frontend/src/forms/AccountForm.tsx
index 3d94612..c8b125c 100644
--- a/frontend/src/app/components/AccountForm.tsx
+++ b/frontend/src/forms/AccountForm.tsx
@@ -1,19 +1,15 @@
import React, { useState } from 'react'
-import { Account } from '../../types'
+import { Account } from '../types'
-import '../../scss/form.scss'
-import { useAppContext } from '../../contexts/AppContext'
import { message } from 'antd'
-import { usePromise } from '@dank-inc/use-get'
+import { useStacks } from '../hooks/getMany/useStacks'
type Props = {
account?: Account
}
export const AccountForm = ({ account }: Props) => {
- const { api } = useAppContext()
-
- const stacks = usePromise(api.getStacks())
+ const stacks = useStacks('')
const [name, setName] = useState(account?.name || '')
const [details, setDetails] = useState(account?.details || '')
@@ -31,9 +27,9 @@ export const AccountForm = ({ account }: Props) => {
details,
}
- account?.id
- ? await api.updateAccount(account.id, body)
- : await api.createAccount(body)
+ // account?.id
+ // ? await api.updateAccount(account.id, body)
+ // : await api.createAccount(body)
message.success('Yaaa')
}
@@ -74,15 +70,7 @@ export const AccountForm = ({ account }: Props) => {
{stacks.data?.map((stack) => (
-
- api.updateStack(stack.id, {
- amount: parseInt(e.target.value),
- })
- }
- >
+
))}
diff --git a/frontend/src/hooks/getMany/useStacks.ts b/frontend/src/hooks/getMany/useStacks.ts
new file mode 100644
index 0000000..34c296c
--- /dev/null
+++ b/frontend/src/hooks/getMany/useStacks.ts
@@ -0,0 +1,5 @@
+import { Stack } from '../../types'
+import { useGet } from '../util/useGet'
+
+export const useStacks = (accountId: string) =>
+ useGet(`/accounts/${accountId}/stacks`)
diff --git a/frontend/src/app/layout/AppFooter/index.tsx b/frontend/src/layout/AppFooter/index.tsx
similarity index 81%
rename from frontend/src/app/layout/AppFooter/index.tsx
rename to frontend/src/layout/AppFooter/index.tsx
index ee2e386..5ed0f7c 100644
--- a/frontend/src/app/layout/AppFooter/index.tsx
+++ b/frontend/src/layout/AppFooter/index.tsx
@@ -1,4 +1,4 @@
-import { useUserContext } from '../../../contexts/UserContext'
+import { useUserContext } from '../../contexts/UserContext'
import './style.scss'
diff --git a/frontend/src/app/layout/AppFooter/style.scss b/frontend/src/layout/AppFooter/style.scss
similarity index 100%
rename from frontend/src/app/layout/AppFooter/style.scss
rename to frontend/src/layout/AppFooter/style.scss
diff --git a/frontend/src/app/layout/AppHeader/index.tsx b/frontend/src/layout/AppHeader/index.tsx
similarity index 96%
rename from frontend/src/app/layout/AppHeader/index.tsx
rename to frontend/src/layout/AppHeader/index.tsx
index 30a7705..5d72a83 100644
--- a/frontend/src/app/layout/AppHeader/index.tsx
+++ b/frontend/src/layout/AppHeader/index.tsx
@@ -2,7 +2,7 @@ import { ReactNode } from 'react'
import { Avatar, Button, Dropdown, Menu } from 'antd'
import { Header } from 'antd/lib/layout/layout'
import { Link, useHistory } from 'react-router-dom'
-import { useUserContext } from '../../../contexts/UserContext'
+import { useUserContext } from '../../contexts/UserContext'
import './style.scss'
diff --git a/frontend/src/app/layout/AppHeader/style.scss b/frontend/src/layout/AppHeader/style.scss
similarity index 100%
rename from frontend/src/app/layout/AppHeader/style.scss
rename to frontend/src/layout/AppHeader/style.scss
diff --git a/frontend/src/pages/Dashboard/index.tsx b/frontend/src/pages/Dashboard/index.tsx
new file mode 100644
index 0000000..0e4ac62
--- /dev/null
+++ b/frontend/src/pages/Dashboard/index.tsx
@@ -0,0 +1,19 @@
+import { FundBar } from '../../widgets/FundBar'
+import { useStacks } from '../../hooks/getMany/useStacks'
+
+export const Dashboard = () => {
+ const stacks = useStacks('')
+
+ if (!stacks.data) return loading...
+
+ return (
+ <>
+ Remaining Balances
+
+ {stacks.data.map((stack, i) => (
+
+ ))}
+
+ >
+ )
+}
diff --git a/frontend/src/app/pages/ForgotPassword.tsx b/frontend/src/pages/ForgotPassword/index.tsx
similarity index 100%
rename from frontend/src/app/pages/ForgotPassword.tsx
rename to frontend/src/pages/ForgotPassword/index.tsx
diff --git a/frontend/src/app/components/Login.tsx b/frontend/src/pages/Login/index.tsx
similarity index 97%
rename from frontend/src/app/components/Login.tsx
rename to frontend/src/pages/Login/index.tsx
index 06ea505..b218114 100644
--- a/frontend/src/app/components/Login.tsx
+++ b/frontend/src/pages/Login/index.tsx
@@ -3,7 +3,7 @@ import FormItem from 'antd/lib/form/FormItem'
import { Link } from 'react-router-dom'
import { User } from '../../types'
-import '../../scss/login.scss'
+import './style.scss'
import { useUserContext } from '../../contexts/UserContext'
type FormValues = Pick & { password: string }
diff --git a/frontend/src/app/pages/Login.tsx b/frontend/src/pages/Login/index.tsx.old
similarity index 97%
rename from frontend/src/app/pages/Login.tsx
rename to frontend/src/pages/Login/index.tsx.old
index 9a6e73e..24571db 100644
--- a/frontend/src/app/pages/Login.tsx
+++ b/frontend/src/pages/Login/index.tsx.old
@@ -1,6 +1,7 @@
import { Button, Form, Input } from 'antd'
import { useForm } from 'antd/lib/form/Form'
import { useUserContext } from '../../contexts/UserContext'
+import './style.scss'
type Credentials = {
username: string
diff --git a/frontend/src/scss/login.scss b/frontend/src/pages/Login/style.scss
similarity index 100%
rename from frontend/src/scss/login.scss
rename to frontend/src/pages/Login/style.scss
diff --git a/frontend/src/app/components/TransactionModal.tsx b/frontend/src/pages/NewTransaction/index.tsx
similarity index 63%
rename from frontend/src/app/components/TransactionModal.tsx
rename to frontend/src/pages/NewTransaction/index.tsx
index 75da348..ae51e70 100644
--- a/frontend/src/app/components/TransactionModal.tsx
+++ b/frontend/src/pages/NewTransaction/index.tsx
@@ -1,32 +1,29 @@
+import { InputNumber } from 'antd'
import { useState } from 'react'
import '../../scss/transaction-modal.scss'
-import { useAppContext } from '../../contexts/AppContext'
-import { uuid } from '../../types'
-
type Props = {
- stackId: uuid
+ stackId: string
}
-export const TransactionModal = ({ stackId }: Props) => {
- const { api } = useAppContext()
-
- const [amount, setAmount] = useState('')
+export const TransactionForm = ({ stackId }: Props) => {
+ const [amount, setAmount] = useState(0)
const [stack, setStack] = useState(stackId)
const [details, setDetails] = useState('')
- const [error, setError] = useState(null)
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
- if (parseFloat(amount)) {
- api.createTransaction({
- stack,
- details,
- amount: parseFloat(amount),
- created_at: new Date().toISOString(),
- })
+ if (!amount) return
+
+ const body = {
+ stack,
+ details,
+ amount: amount,
+ created_at: new Date().toISOString(),
}
+
+ console.log('creating tx', body)
}
return (
@@ -36,11 +33,11 @@ export const TransactionModal = ({ stackId }: Props) => {
Expense for {stack} account
- {error && {error}
}
)
}
diff --git a/frontend/src/scss/transaction-modal.scss b/frontend/src/pages/NewTransaction/style.scss
similarity index 100%
rename from frontend/src/scss/transaction-modal.scss
rename to frontend/src/pages/NewTransaction/style.scss
diff --git a/frontend/src/app/forms/NewUser.tsx b/frontend/src/pages/NewUser/index.tsx
similarity index 100%
rename from frontend/src/app/forms/NewUser.tsx
rename to frontend/src/pages/NewUser/index.tsx
diff --git a/frontend/src/app/components/TransactionList.tsx b/frontend/src/pages/TransactionList/index.tsx
similarity index 89%
rename from frontend/src/app/components/TransactionList.tsx
rename to frontend/src/pages/TransactionList/index.tsx
index 5ec179b..3e5e1da 100644
--- a/frontend/src/app/components/TransactionList.tsx
+++ b/frontend/src/pages/TransactionList/index.tsx
@@ -1,4 +1,4 @@
-import '../../scss/transaction-list.scss'
+import './style.scss'
export const TransactionList = () => {
return (
diff --git a/frontend/src/scss/transaction-list.scss b/frontend/src/pages/TransactionList/style.scss
similarity index 100%
rename from frontend/src/scss/transaction-list.scss
rename to frontend/src/pages/TransactionList/style.scss
diff --git a/frontend/src/app/components/AccountSelect.tsx b/frontend/src/widgets/AccountSelect/index.tsx
similarity index 95%
rename from frontend/src/app/components/AccountSelect.tsx
rename to frontend/src/widgets/AccountSelect/index.tsx
index 417f944..9840027 100644
--- a/frontend/src/app/components/AccountSelect.tsx
+++ b/frontend/src/widgets/AccountSelect/index.tsx
@@ -2,7 +2,7 @@ import { Link } from 'react-router-dom'
import { message } from 'antd'
import { useUserContext } from '../../contexts/UserContext'
-import '../../scss/account-select.scss'
+import './style.scss'
type Props = {
selectProfile: (id: string) => void
diff --git a/frontend/src/scss/account-select.scss b/frontend/src/widgets/AccountSelect/style.scss
similarity index 100%
rename from frontend/src/scss/account-select.scss
rename to frontend/src/widgets/AccountSelect/style.scss
diff --git a/frontend/src/app/components/FundBar.tsx b/frontend/src/widgets/FundBar/index.tsx
similarity index 96%
rename from frontend/src/app/components/FundBar.tsx
rename to frontend/src/widgets/FundBar/index.tsx
index 2d8b94a..292fdb7 100644
--- a/frontend/src/app/components/FundBar.tsx
+++ b/frontend/src/widgets/FundBar/index.tsx
@@ -1,5 +1,5 @@
import { Stack } from '../../types'
-import '../../scss/fund-bar.scss'
+import './style.scss'
type Props = {
col: number
diff --git a/frontend/src/scss/fund-bar.scss b/frontend/src/widgets/FundBar/style.scss
similarity index 100%
rename from frontend/src/scss/fund-bar.scss
rename to frontend/src/widgets/FundBar/style.scss