parent
1af8209b99
commit
2b94223389
35 changed files with 163 additions and 160 deletions
@ -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 |
||||||
|
|
||||||
``` |
- put items in your wishlist and track savings to buy big-ticket items |
||||||
python manage.py migrate |
- view spending trends |
||||||
python manage.py createsuperuser --email admin@example.com --username admin --password whatever |
|
||||||
``` |
|
||||||
|
|
||||||
# Boilerplate Features |
# Todo |
||||||
|
|
||||||
- Authentication |
https://github.com/dank-inc/cash-stacks/projects |
||||||
- 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) |
|
||||||
|
@ -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 <Login /> |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className="app"> |
||||||
|
<AppHeader> |
||||||
|
<Link to="/">Home</Link> |
||||||
|
<Link to="/select">Select Budget</Link> |
||||||
|
<Link to="/accounts">Budget Details</Link> |
||||||
|
<Link to="/transactions">Transactions</Link> |
||||||
|
<Link to="/new">New User</Link> |
||||||
|
</AppHeader> |
||||||
|
|
||||||
|
<Switch> |
||||||
|
<Route path="/users/new" component={NewUser} /> |
||||||
|
<Route path="/transactions" component={TransactionList} /> |
||||||
|
<Route path="/accounts/new" component={AccountForm} /> |
||||||
|
<Route path="/accounts" component={AccountForm} /> |
||||||
|
<Route path="/" component={Dashboard} /> |
||||||
|
</Switch> |
||||||
|
|
||||||
|
<AppFooter /> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
@ -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 <Login /> |
|
||||||
|
|
||||||
return ( |
|
||||||
<div className="app"> |
|
||||||
<AppHeader> |
|
||||||
<Link to="/">Home</Link> |
|
||||||
<Link to="/select">Select Budget</Link> |
|
||||||
<Link to="/account">Budget Details</Link> |
|
||||||
<Link to="/details">Transactions</Link> |
|
||||||
<Link to="/user">Profile</Link> |
|
||||||
</AppHeader> |
|
||||||
|
|
||||||
<Switch> |
|
||||||
<Route path="/user" component={UserForm} /> |
|
||||||
<Route path="/details" component={TransactionList} /> |
|
||||||
<Route path="/account/new" component={AccountForm} /> |
|
||||||
<Route path="/account" component={AccountForm} /> |
|
||||||
<Route path="/" component={Dashboard} /> |
|
||||||
</Switch> |
|
||||||
|
|
||||||
<AppFooter /> |
|
||||||
{/* {showingModal && <TransactionModal account={account} />} */} |
|
||||||
</div> |
|
||||||
) |
|
||||||
} |
|
@ -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 <div>loading...</div> |
|
||||||
|
|
||||||
return ( |
|
||||||
<> |
|
||||||
<h1>Remaining Balances</h1> |
|
||||||
<div className="funds"> |
|
||||||
{stacks.data.map((stack, i) => ( |
|
||||||
<FundBar key={stack.id} stack={stack} col={i + 1} /> |
|
||||||
))} |
|
||||||
</div> |
|
||||||
</> |
|
||||||
) |
|
||||||
} |
|
@ -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 ( |
||||||
|
<AntButton className="dank-button" htmlType={htmlType}> |
||||||
|
{children} |
||||||
|
</AntButton> |
||||||
|
) |
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
.dank-button { |
||||||
|
cursor: pointer; |
||||||
|
// shit here |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
import { Form as AntForm, FormProps } from 'antd' |
||||||
|
import './style.scss' |
||||||
|
|
||||||
|
type Props = FormProps |
||||||
|
|
||||||
|
export const Form = ({ children }: Props) => { |
||||||
|
return <AntForm className="dank-form">{children}</AntForm> |
||||||
|
} |
@ -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 |
||||||
|
} |
@ -1,4 +1,4 @@ |
|||||||
.status { |
.dank-toast { |
||||||
position: absolute; |
position: absolute; |
||||||
left: 1ch; |
left: 1ch; |
||||||
bottom: 4ch; |
bottom: 4ch; |
@ -0,0 +1,5 @@ |
|||||||
|
import { Stack } from '../../types' |
||||||
|
import { useGet } from '../util/useGet' |
||||||
|
|
||||||
|
export const useStacks = (accountId: string) => |
||||||
|
useGet<Stack[]>(`/accounts/${accountId}/stacks`) |
@ -1,4 +1,4 @@ |
|||||||
import { useUserContext } from '../../../contexts/UserContext' |
import { useUserContext } from '../../contexts/UserContext' |
||||||
|
|
||||||
import './style.scss' |
import './style.scss' |
||||||
|
|
@ -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 <div>loading...</div> |
||||||
|
|
||||||
|
return ( |
||||||
|
<> |
||||||
|
<h1>Remaining Balances</h1> |
||||||
|
<div className="funds"> |
||||||
|
{stacks.data.map((stack, i) => ( |
||||||
|
<FundBar key={stack.id} stack={stack} col={i + 1} /> |
||||||
|
))} |
||||||
|
</div> |
||||||
|
</> |
||||||
|
) |
||||||
|
} |
@ -1,6 +1,7 @@ |
|||||||
import { Button, Form, Input } from 'antd' |
import { Button, Form, Input } from 'antd' |
||||||
import { useForm } from 'antd/lib/form/Form' |
import { useForm } from 'antd/lib/form/Form' |
||||||
import { useUserContext } from '../../contexts/UserContext' |
import { useUserContext } from '../../contexts/UserContext' |
||||||
|
import './style.scss' |
||||||
|
|
||||||
type Credentials = { |
type Credentials = { |
||||||
username: string |
username: string |
@ -1,4 +1,4 @@ |
|||||||
import '../../scss/transaction-list.scss' |
import './style.scss' |
||||||
|
|
||||||
export const TransactionList = () => { |
export const TransactionList = () => { |
||||||
return ( |
return ( |
@ -1,5 +1,5 @@ |
|||||||
import { Stack } from '../../types' |
import { Stack } from '../../types' |
||||||
import '../../scss/fund-bar.scss' |
import './style.scss' |
||||||
|
|
||||||
type Props = { |
type Props = { |
||||||
col: number |
col: number |
Loading…
Reference in new issue