From 4a1507eba47359a3ddba8bd9673759a3d7cfb8ef Mon Sep 17 00:00:00 2001 From: Elijah Lucian Date: Sat, 17 Jul 2021 11:52:03 -0600 Subject: [PATCH] new form and form tweaks --- frontend/src/MainLayout.tsx | 4 +- frontend/src/app.scss | 5 -- frontend/src/contexts/AppContext.tsx | 10 +++- frontend/src/elements/Form/style.scss | 23 ++++++-- frontend/src/elements/FormItem/index.tsx | 1 + frontend/src/elements/FormItem/style.scss | 5 ++ frontend/src/elements/InputNumber/index.tsx | 4 +- frontend/src/elements/InputNumber/style.scss | 33 +++++++++++ frontend/src/forms/TransactionForm.tsx | 53 +++++++++++++++++ frontend/src/hooks/create/useCreateAccount.ts | 2 +- frontend/src/hooks/create/useCreateStack.ts | 2 +- .../src/hooks/create/useCreateTransaction.ts | 6 +- frontend/src/hooks/create/useCreateUser.ts | 2 +- frontend/src/hooks/getMany/useTransactions.ts | 3 +- frontend/src/layout/Modal/index.tsx | 15 +++-- frontend/src/layout/Modal/style.scss | 15 ++++- frontend/src/layout/Row/index.tsx | 10 ++++ frontend/src/layout/Row/style.scss | 6 ++ frontend/src/pages/Dashboard/index.tsx | 2 +- frontend/src/pages/Dashboard/style.scss | 1 - frontend/src/scss/variables.scss | 1 + frontend/src/types/index.ts | 4 +- frontend/src/widgets/AccountSelect/index.tsx | 3 +- frontend/src/widgets/FundBar/index.tsx | 57 +++++++++++-------- frontend/src/widgets/FundBar/style.scss | 6 +- 25 files changed, 215 insertions(+), 58 deletions(-) create mode 100644 frontend/src/elements/FormItem/style.scss create mode 100644 frontend/src/elements/InputNumber/style.scss create mode 100644 frontend/src/forms/TransactionForm.tsx create mode 100644 frontend/src/layout/Row/index.tsx create mode 100644 frontend/src/layout/Row/style.scss diff --git a/frontend/src/MainLayout.tsx b/frontend/src/MainLayout.tsx index d625e06..396bdc6 100644 --- a/frontend/src/MainLayout.tsx +++ b/frontend/src/MainLayout.tsx @@ -30,7 +30,9 @@ export const MainLayout = () => { -
loading...
+ +
loading...
+
) : ( diff --git a/frontend/src/app.scss b/frontend/src/app.scss index b39ef06..07bab6c 100644 --- a/frontend/src/app.scss +++ b/frontend/src/app.scss @@ -6,11 +6,6 @@ align-items: center; - h1 { - margin-top: 2.5vmin; - margin-bottom: 1vmin; - } - main { height: 100%; } diff --git a/frontend/src/contexts/AppContext.tsx b/frontend/src/contexts/AppContext.tsx index 2f1530b..d3dde19 100644 --- a/frontend/src/contexts/AppContext.tsx +++ b/frontend/src/contexts/AppContext.tsx @@ -9,7 +9,7 @@ type Props = { type AppContextInterface = { 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 baseURL?: string @@ -39,8 +39,12 @@ export const AppContextProvider = ({ children, baseURL }: Props) => { return res.data } async function post(path: string, body: Partial) { - const res = await api.post>(path, body) - return res.data + try { + const res = await api.post>(path, body) + return res.data + } catch (err) { + return null + } } async function create(path: string, body: Partial) { // unauthed POST diff --git a/frontend/src/elements/Form/style.scss b/frontend/src/elements/Form/style.scss index 6e908b9..920d4a3 100644 --- a/frontend/src/elements/Form/style.scss +++ b/frontend/src/elements/Form/style.scss @@ -1,11 +1,30 @@ +@import '../../scss/variables.scss'; + .dank-form { display: flex; flex-direction: column; padding: 3ch; + input { + border-radius: 0.25rem; + width: 100%; + font-size: 2rem; + border: 1px solid $color-grey; + + &:focus { + outline: 2px solid $color-primary; + } + } + button { + width: 40%; + font-size: 2rem; + border-radius: 0.25rem; + } + label { margin: 0.5ch; display: flex; + font-size: 1.5rem; flex-direction: row; justify-content: space-between; @@ -13,8 +32,4 @@ margin-left: 2ch; } } - - button { - margin: 4ch 1ch; - } } diff --git a/frontend/src/elements/FormItem/index.tsx b/frontend/src/elements/FormItem/index.tsx index 05c853d..4def640 100644 --- a/frontend/src/elements/FormItem/index.tsx +++ b/frontend/src/elements/FormItem/index.tsx @@ -1,5 +1,6 @@ import { FormItemProps } from 'antd' import AntFormItem from 'antd/lib/form/FormItem' +import './style.scss' type Props = FormItemProps diff --git a/frontend/src/elements/FormItem/style.scss b/frontend/src/elements/FormItem/style.scss new file mode 100644 index 0000000..838554b --- /dev/null +++ b/frontend/src/elements/FormItem/style.scss @@ -0,0 +1,5 @@ +.dank-form-item { + label { + color: white; + } +} diff --git a/frontend/src/elements/InputNumber/index.tsx b/frontend/src/elements/InputNumber/index.tsx index 8cbc351..91291cd 100644 --- a/frontend/src/elements/InputNumber/index.tsx +++ b/frontend/src/elements/InputNumber/index.tsx @@ -1,7 +1,9 @@ import { InputNumber as AntInputNumber, InputNumberProps } from 'antd' +import './style.scss' + type Props = InputNumberProps export const InputNumber = (props: Props) => { - return + return } diff --git a/frontend/src/elements/InputNumber/style.scss b/frontend/src/elements/InputNumber/style.scss new file mode 100644 index 0000000..59b038f --- /dev/null +++ b/frontend/src/elements/InputNumber/style.scss @@ -0,0 +1,33 @@ +.ant-input-number { + display: grid; + grid-template: 1fr / 1fr; + + div { + grid-area: 1/1/2/2; + } + + &-handler { + &-wrap { + z-index: 2; + width: 100%; + pointer-events: none; + display: flex; + flex-direction: row; + justify-content: flex-end; + align-items: center; + } + + &-up, + &-down { + pointer-events: all; + cursor: pointer; + margin: auto 0.5rem auto 0; + svg { + } + } + } + + &-input-wrap { + z-index: 1; + } +} diff --git a/frontend/src/forms/TransactionForm.tsx b/frontend/src/forms/TransactionForm.tsx new file mode 100644 index 0000000..e9a7dfb --- /dev/null +++ b/frontend/src/forms/TransactionForm.tsx @@ -0,0 +1,53 @@ +import { useForm } from 'antd/lib/form/Form' +import { Button } from '../elements/Button' +import { Form } from '../elements/Form' +import { FormItem } from '../elements/FormItem' +import { Input } from '../elements/Input' +import { InputNumber } from '../elements/InputNumber' +import { + useCreateTransaction, + NewTransaction, +} from '../hooks/create/useCreateTransaction' +import { DankFormProps } from '../layout/Modal' +import { Row } from '../layout/Row' + +type Props = DankFormProps & { + stackId: string +} + +export const TransactionForm = ({ stackId, onSave, onCancel }: Props) => { + const [form] = useForm() + const create = useCreateTransaction() + + const handleFinish = async (tx: NewTransaction) => { + console.log('transaction', tx) + const res = await create(tx) + + if (!res) { + console.log("couldn't create transaction") + return + } + + onSave?.() + } + + return ( +
+

New Transaction

+ + + + + + + + + + +
+ ) +} diff --git a/frontend/src/hooks/create/useCreateAccount.ts b/frontend/src/hooks/create/useCreateAccount.ts index a006005..eb2c824 100644 --- a/frontend/src/hooks/create/useCreateAccount.ts +++ b/frontend/src/hooks/create/useCreateAccount.ts @@ -4,6 +4,6 @@ import { Account } from '../../types' export const useCreateAccount = () => { const api = useAppContext() - return (body: Omit): Promise => + return (body: Omit): Promise => api.post('/accounts', body) } diff --git a/frontend/src/hooks/create/useCreateStack.ts b/frontend/src/hooks/create/useCreateStack.ts index 85e6472..660e3d4 100644 --- a/frontend/src/hooks/create/useCreateStack.ts +++ b/frontend/src/hooks/create/useCreateStack.ts @@ -4,6 +4,6 @@ import { Stack } from '../../types' export const useCreateStack = () => { const api = useAppContext() - return (body: Omit): Promise => + return (body: Omit): Promise => api.post('/stacks', body) } diff --git a/frontend/src/hooks/create/useCreateTransaction.ts b/frontend/src/hooks/create/useCreateTransaction.ts index 2c20439..159ab9a 100644 --- a/frontend/src/hooks/create/useCreateTransaction.ts +++ b/frontend/src/hooks/create/useCreateTransaction.ts @@ -1,9 +1,11 @@ import { useAppContext } from '../../contexts/AppContext' import { Transaction } from '../../types' +export type NewTransaction = Omit + export const useCreateTransaction = () => { const api = useAppContext() - return (body: Omit): Promise => - api.post('/transactions', body) + return (body: NewTransaction): Promise => + api.post('/transactions/', body) } diff --git a/frontend/src/hooks/create/useCreateUser.ts b/frontend/src/hooks/create/useCreateUser.ts index d20e820..1e897fa 100644 --- a/frontend/src/hooks/create/useCreateUser.ts +++ b/frontend/src/hooks/create/useCreateUser.ts @@ -4,6 +4,6 @@ import { User } from '../../types' export const useCreateUser = () => { const api = useAppContext() - return (body: Omit): Promise => + return (body: Omit): Promise => api.post('/users', body) } diff --git a/frontend/src/hooks/getMany/useTransactions.ts b/frontend/src/hooks/getMany/useTransactions.ts index 6d47633..b918089 100644 --- a/frontend/src/hooks/getMany/useTransactions.ts +++ b/frontend/src/hooks/getMany/useTransactions.ts @@ -1,4 +1,5 @@ import { Transaction } from '../../types' import { useGet } from '../util/useGet' -export const useTransactions = () => useGet(`/transactions/`) +export const useTransactions = () => + useGet(`/transactions/`, { mode: 'list' }) diff --git a/frontend/src/layout/Modal/index.tsx b/frontend/src/layout/Modal/index.tsx index 5557663..3e0076a 100644 --- a/frontend/src/layout/Modal/index.tsx +++ b/frontend/src/layout/Modal/index.tsx @@ -1,9 +1,16 @@ import { ModalProps } from 'antd' -import { ReactNode } from 'react' +import { ReactElement, cloneElement } from 'react' import './style.scss' -type Props = ModalProps & { children: ReactNode } +type Props = ModalProps & { children: ReactElement } -export const Modal = ({ children, ...props }: Props) => { - return
{children}
+export type DankFormProps = { + onSave?: () => void + onCancel?: () => void +} + +export const Modal = ({ children, visible }: Props) => { + const el = cloneElement(children, (props: DankFormProps) => ({ ...props })) + + return visible ?
{el}
: null } diff --git a/frontend/src/layout/Modal/style.scss b/frontend/src/layout/Modal/style.scss index 3fa21e7..5ceb1a2 100644 --- a/frontend/src/layout/Modal/style.scss +++ b/frontend/src/layout/Modal/style.scss @@ -1,11 +1,20 @@ @import '../../scss/variables.scss'; .dank-modal { - display: flex; + position: absolute; + width: 70%; + height: 70%; + background-color: transparentize(#222, 0.07); + border-radius: 1rem; + padding: 1rem; + margin: auto; border: 1px solid $color-grey; - h3 { - text-align: center; + h1, + h2, + h3, + h4, + h5 { color: $color-light; } diff --git a/frontend/src/layout/Row/index.tsx b/frontend/src/layout/Row/index.tsx new file mode 100644 index 0000000..dc005d6 --- /dev/null +++ b/frontend/src/layout/Row/index.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import './style.scss' + +type Props = { + children: React.ReactNode +} + +export const Row = ({ children }: Props) => { + return
{children}
+} diff --git a/frontend/src/layout/Row/style.scss b/frontend/src/layout/Row/style.scss new file mode 100644 index 0000000..daaae4b --- /dev/null +++ b/frontend/src/layout/Row/style.scss @@ -0,0 +1,6 @@ +.dank-row { + display: flex; + flex-direction: row; + justify-content: space-between; + margin: 1rem 0; +} diff --git a/frontend/src/pages/Dashboard/index.tsx b/frontend/src/pages/Dashboard/index.tsx index 5490831..04af36d 100644 --- a/frontend/src/pages/Dashboard/index.tsx +++ b/frontend/src/pages/Dashboard/index.tsx @@ -11,7 +11,7 @@ export const Dashboard = () => {

Remaining Balances

{accounts.data?.map((account) => ( -
+

{account.name}

{account.stacks.map((stack) => ( diff --git a/frontend/src/pages/Dashboard/style.scss b/frontend/src/pages/Dashboard/style.scss index cfa50cf..67ea191 100644 --- a/frontend/src/pages/Dashboard/style.scss +++ b/frontend/src/pages/Dashboard/style.scss @@ -5,7 +5,6 @@ border: 1px solid $color-grey; flex-direction: column; align-items: center; - text-align: center; margin: 1rem 0; padding: 1rem; background: $color-alt; diff --git a/frontend/src/scss/variables.scss b/frontend/src/scss/variables.scss index d8fa705..3881e96 100644 --- a/frontend/src/scss/variables.scss +++ b/frontend/src/scss/variables.scss @@ -3,4 +3,5 @@ $color-alt: #c9d8b6; $color-light: #f1ecc3; $color-white: #fff; $color-grey: #515e63; +$color-black: #111; $color-dark: #333; diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index e030bed..b544bb1 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -28,7 +28,7 @@ export type Stack = { account: string //'38485982-87f3-4a11-a963-2202983809e3' name: string // 'House Fund' details: string //'buy furniture' - amount: number // '200.00' + amount: string // number // '200.00' transactions: Transaction[] } @@ -36,7 +36,7 @@ export type Transaction = { id: string stack: string // '0058cece-3ff3-4ee1-b71d-075a0bc73bc0' details: string // 'by ghetto couch off Kijiji' - amount: number // '30.44' + amount: string // number // '30.44' created_at: string // '2021-04-15T00:02:45.096071Z' } diff --git a/frontend/src/widgets/AccountSelect/index.tsx b/frontend/src/widgets/AccountSelect/index.tsx index 61c3b1d..cd146f0 100644 --- a/frontend/src/widgets/AccountSelect/index.tsx +++ b/frontend/src/widgets/AccountSelect/index.tsx @@ -1,9 +1,10 @@ import { Link } from 'react-router-dom' import { message } from 'antd' -import './style.scss' import { Button } from '../../elements/Button' import { useAccounts } from '../../hooks/getMany/useAccounts' +import './style.scss' + type Props = { selectProfile: (id: string) => void } diff --git a/frontend/src/widgets/FundBar/index.tsx b/frontend/src/widgets/FundBar/index.tsx index f92d138..45535a9 100644 --- a/frontend/src/widgets/FundBar/index.tsx +++ b/frontend/src/widgets/FundBar/index.tsx @@ -1,40 +1,47 @@ import { Stack } from '../../types' import './style.scss' import _ from 'lodash' +import { useState } from 'react' +import { Modal } from '../../layout/Modal' +import { TransactionForm } from '../../forms/TransactionForm' type Props = { stack: Stack } export const FundBar = ({ stack }: Props) => { - const amount = _.sumBy(stack.transactions, 'amount') - console.log('amount', stack.id, amount) - const max = stack.amount + const amount = _.sumBy(stack.transactions, (tx) => parseFloat(tx.amount)) + const max = parseFloat(stack.amount) const current = max - amount - const percent = Math.max(current / max, 0) - const hue = percent * 120 + const u = Math.max(current / max, 0) + + const [newTx, setNewTx] = useState(false) + + const addTransaction = () => { + console.log(`adding transaction to => ${stack.name}`) + setNewTx(true) + } return ( -
-
console.log(`adding transaction to => ${stack.name}`)} - >
-
-

{stack.name}

-
-
- ${Math.floor(current)} / ${max} + <> +
+
+

{stack.name}

+
+
+
+ ${Math.floor(current)} / ${max} +
-
+ setNewTx(false)}> + + + ) } diff --git a/frontend/src/widgets/FundBar/style.scss b/frontend/src/widgets/FundBar/style.scss index dd0aa25..7423e0d 100644 --- a/frontend/src/widgets/FundBar/style.scss +++ b/frontend/src/widgets/FundBar/style.scss @@ -6,6 +6,7 @@ margin: 1rem; display: grid; grid-template: 1fr / 1fr; + height: 20vh; .totals { pointer-events: none; @@ -18,17 +19,20 @@ .front { grid-area: 1/1/2/2; + margin: auto auto 0; border-radius: 1ch; pointer-events: none; transition: all 0.2s ease-out; border: 2px solid $color-dark; display: flex; flex-direction: column; - padding: 2ch; + width: 100%; + min-height: 1rem; text-shadow: 2px 2px #2223, -1px -1px #fffa; } .back { + padding: 0.25rem; grid-area: 1/1/2/2; background: #222; border-radius: 1ch;