simplify move money page

This commit is contained in:
Bilal
2020-10-08 16:21:05 +03:00
parent 034c983e3b
commit ff6453e857
11 changed files with 199 additions and 187 deletions

View File

@@ -1,7 +1,6 @@
import React, { useEffect, useState } from 'react';
import './App.css';
import { Navbar, Dropdown, Icon } from 'react-materialize';
import MakeMoneyMove from './cash/MakeMoneyMove';
import Flow from "./homies/Flow";
import Cash from './cash/Cash';
import Homies from './homies/Homies';
@@ -11,15 +10,16 @@ import axios from 'axios';
import {
CRIB,
GANGS,
MAKE_MONEY_MOVE,
HOMIE_FLOW,
HOMIES,
HOMIE_MOVE_MONEY,
PUT_IN_WORK
} from './RouteNames';
import PutInWork from "./cash/PutInWork";
import GangOnboarding from "./gangOnboarding/GangOnboarding";
import Gangs from './gangs/Gangs';
import {errorToast} from "./common/errorHelpers";
import MoveMoney from "./homies/MoveMoney";
const App = (props) => {
@@ -50,7 +50,7 @@ const App = (props) => {
<Route key='2' exact path={GANGS} component={() => <Gangs gangs={gangs} gangsSetter={setGangs} />} />,
<Route key='3' exact path={HOMIES} component={() => <Homies gang={selectedGang} />} />,
<Route key='4' path={HOMIE_FLOW} component={() => <Flow gang={selectedGang} />} />,
<Route key='5' path={MAKE_MONEY_MOVE} component={() => <MakeMoneyMove gang={selectedGang} />} />,
<Route key='5' path={HOMIE_MOVE_MONEY} component={() => <MoveMoney gang={selectedGang} />} />,
<Route key='6' path={PUT_IN_WORK} component={() => <PutInWork gang={selectedGang} />} />
]
);
@@ -117,10 +117,6 @@ const App = (props) => {
Homies
</RoutableNavItem>
<RoutableNavItem href={MAKE_MONEY_MOVE}>
Make Money Move
</RoutableNavItem>
<RoutableNavItem href={PUT_IN_WORK}>
Put in Work
</RoutableNavItem>

View File

@@ -1,6 +1,6 @@
export const CRIB = '/';
export const HOMIES = '/homies';
export const MAKE_MONEY_MOVE = '/make-money-move';
export const HOMIE_MOVE_MONEY = '/homie/:homie_id/move-money';
export const PUT_IN_WORK = '/put-in-work';
export const HOMIE_FLOW = '/homie/:homie_id/flow';
export const GANGS = '/gangs';

View File

@@ -1,8 +1,7 @@
import React, { useState, useEffect } from 'react';
import { Button, Table } from 'react-materialize';
import { Button, Icon, Table } from 'react-materialize';
import './Cash.css';
import axios from 'axios';
import { MAKE_MONEY_MOVE } from '../RouteNames';
import { withRouter } from 'react-router-dom';
import { formatMoney, formatTime } from '../common/formatting';
import RoutableNavItem from "../common/RoutableNavItem";
@@ -21,7 +20,7 @@ const Cash = (props) => {
}
};
getCashForHomies();
}, []);
}, [gang]);
const cashTableBody = homiesCash.map( (homieLine) => {
return (
@@ -35,7 +34,13 @@ const Cash = (props) => {
<td className="cash-cell-right">
{ formatMoney(homieLine.amount, gang) }
</td>
<td className="cash-cell-left">
<td className="cash-cell-right">
<RoutableNavItem href={`/homie/${homieLine.homie.id}/move-money`}>
<Button>
Move money
<Icon left>monetization_on</Icon>
</Button>
</RoutableNavItem>
</td>
</tr>
);
@@ -52,10 +57,10 @@ const Cash = (props) => {
<th>
Work
</th>
<th>
<th className="cash-cell-right">
Cash
</th>
<th>
<th className="cash-cell-right">
Actions
</th>
</tr>
@@ -64,24 +69,8 @@ const Cash = (props) => {
{ cashTableBody }
</tbody>
</Table>
<Button
floating
large
className="green"
fab={{direction: 'bottom'}}
waves="light"
icon="add"
onClick={
() => {
props.history.push(MAKE_MONEY_MOVE)
}
}
/>
</div>
);
}
export default withRouter(Cash);

View File

@@ -1,152 +0,0 @@
import React, {useState, useEffect} from 'react';
import M from 'materialize-css';
import {Icon, Select, Button, Textarea} from 'react-materialize';
import './Cash.css';
import axios from 'axios';
const MakeMoneyMove = (props) => {
const [selectedFrom, setSelectedFrom] = useState("");
const [selectedTo, setSelectedTo] = useState("-1");
const [homiesCash, setHomiesCash] = useState([]);
const [amountToMove, setAmountToMove] = useState('');
const [moveDescription, setMoveDescription] = useState("");
const [submitInProgress, setSubmitInProgress] = useState(false);
const gang = props.gang;
useEffect(() => {
const getCashForHomies = async () => {
try {
const cash = await axios.get(`/api/gangs/${gang.id}/homies/info`);
setHomiesCash(cash.data);
} catch (e) {
console.log("Error fetching", e);
}
};
getCashForHomies();
}, []);
const handleAmountChange = (e) => {
setAmountToMove(parseFloat(e.target.value))
}
const homieToOptionMapper = (homieCash) => {
const homie = homieCash.homie;
return (
<option key={homie.id} value={homie.id}>{homie.name}</option>
);
};
const homieOptions = homiesCash.map(homieToOptionMapper);
const handleFromHomieChange = (e) => {
setSelectedFrom(e.target.value);
if (selectedTo === e.target.value) {
setSelectedTo('-1');
}
};
const notSayingOption = <option value="">NOT SAYIN'</option>
const filteredHomieOptions = () => {
if (selectedFrom === ''){
return homiesCash.map(homieToOptionMapper);
}else{
const filteredHomieCashes = homiesCash.filter((homieCash) => homieCash.homie.id !== parseInt(selectedFrom));
return [
notSayingOption,
...filteredHomieCashes.map(homieToOptionMapper)
];
}
}
const handleToHomieChange = (e) => {
setSelectedTo(e.target.value);
}
const handleDescriptionChange = (e) => {
setMoveDescription(e.target.value);
}
const clearForm = () => {
setAmountToMove("");
setSelectedFrom("");
setSelectedTo("");
setMoveDescription("");
}
const handleSubmit = async (e) => {
e.preventDefault();
setSubmitInProgress(true);
const moneyMoveRequest = {
money_move: {
amount: amountToMove,
from_homie_id: selectedFrom,
to_homie_id: selectedTo,
description: moveDescription
}
}
const submitResponse = await axios.post('/api/money_moves', moneyMoveRequest);
if (submitResponse && submitResponse.status === 200 && submitResponse.data === true) {
M.toast({html: "Money lounde...moved"});
clearForm();
} else {
M.toast({html: "Yo! It ain't workin'"});
}
setSubmitInProgress(false);
}
const formComplete = () => (
selectedFrom !== selectedTo &&
selectedTo !== '-1' &&
amountToMove > 0
);
const disableSubmit = () => (!formComplete() || submitInProgress);
return (
<div className="center-align container">
<form onSubmit={handleSubmit}>
<h3>Make Money Move</h3>
<div className="input-field col s12">
<input id="how-much" type="number" className="validate" step="0.01" required="required" value={amountToMove} onChange={handleAmountChange} pattern="^\\?(([1-9](\\d*|\\d{0,2}(,\\d{3})*))|0)(\\.\\d{1,2})?$" />
<label className="required" htmlFor="how-much">How much?</label>
<span className="helper-text" data-error="Yo! Put some money" />
</div>
<label className="required">From (only if you can say): </label>
<Select value={selectedFrom} name="from_homie" onChange={handleFromHomieChange}>
{notSayingOption}
{homieOptions}
</Select>
<label className="required">To (only if you can say): </label>
<Select value={selectedTo} name="to_homie" onChange={handleToHomieChange} required="required">
<option disabled value="-1">Select Homie</option>
{filteredHomieOptions()}
</Select>
<br/>
<Textarea label="Tag" value={moveDescription} onChange={handleDescriptionChange}/>
<div>
<Button disabled={disableSubmit()} waves="light">
Do it
<Icon left>
attach_money
</Icon>
</Button>
</div>
</form>
</div>
);
}
export default MakeMoneyMove;

View File

@@ -25,7 +25,7 @@ const PutInWork = (props) => {
errorToast();
}
})();
}, []);
}, [gang]);
const homieOptions = homies.map(homie => <option key={homie.id} value={homie.id}>{homie.name}</option>);

View File

@@ -4,7 +4,7 @@ import { withRouter } from 'react-router-dom';
const RoutableNavItem = (props) => {
return (
<NavItem data-target="mobile-nav" className="sidenav-close" onClick={
<NavItem data-target="mobile-nav" className={`sidenav-close ${props.additionalClasses}`} onClick={
() => {
props.history.push(props.href);
}

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React from 'react';
import NewGangForm from "./NewGangForm";
import axios from "axios";
import {errorToast} from "../common/errorHelpers";

View File

@@ -103,6 +103,20 @@ const CashFlow = (props) => {
confirmAction={(settleAmount) => settleFlowForHomie(homie_id, settleAmount)}
triggerNode={<Button className="orange">Settle</Button>}
/>
<Button
floating
large
className="green"
fab={{direction: 'bottom'}}
waves="light"
icon="add"
onClick={
() => {
props.history.push(`/homie/${homie_id}/move-money`);
}
}
/>
</div>
);
}

View File

@@ -36,4 +36,12 @@
.switch-box {
margin-top: 10px;
margin-bottom: 20px;
}
.push {
margin-left: auto;
}
.bump {
margin-left: 1em;
}

View File

@@ -3,9 +3,10 @@ import { withRouter } from 'react-router-dom';
import axios from 'axios';
import { errorToast } from "../common/errorHelpers";
import NewHomieForm from './NewHomieForm';
import { Button } from 'react-materialize';
import { Button, Icon } from 'react-materialize';
import M from 'materialize-css';
import YesNoModal from "../common/YesNoModal";
import RoutableNavItem from "../common/RoutableNavItem";
const Homies = (props) => {
const [homies, setHomies] = useState([]);
@@ -25,7 +26,7 @@ const Homies = (props) => {
errorToast();
}
})();
}, []);
}, [gang]);
const deleteHomie = async (id) => {
try {
@@ -52,6 +53,13 @@ const Homies = (props) => {
<div className="grey-text">{ homie.about }</div>
</div>
<RoutableNavItem additionalClasses="push" href={`/homie/${homie.id}/move-money`}>
<Button>
Move money
<Icon left>monetization_on</Icon>
</Button>
</RoutableNavItem>
<YesNoModal
body={"Maan, y'a sure about this?"}
yesAction={() => deleteHomie(homie.id)}

View File

@@ -0,0 +1,149 @@
import React, {useState, useEffect} from 'react';
import M from 'materialize-css';
import {Icon, Select, Button, Textarea, Switch} from 'react-materialize';
import '../cash/Cash.css';
import axios from 'axios';
import {useParams} from "react-router-dom";
import {errorToast} from "../common/errorHelpers";
import {CRIB} from "../RouteNames";
import { withRouter } from 'react-router-dom';
const MoveMoney = (props) => {
const { homie_id } = useParams();
const gang = props.gang;
const [selectedHomie, setSelectedHomie] = useState(null);
const [secondaryHomie, setSecondaryHomie] = useState("");
const [homies, setHomies] = useState([]);
const [amountToMove, setAmountToMove] = useState('');
const [moveDescription, setMoveDescription] = useState("");
const [submitInProgress, setSubmitInProgress] = useState(false);
const [moveType, setMoveType] = useState('collect');
useEffect(() => {
(async () => {
try {
const homiesInfo = await axios.get(`/api/gangs/${gang.id}/homies/info`);
if (homiesInfo.status === 200 && homiesInfo.data){
const homie = homiesInfo.data.find(homie => homie.homie.id === parseInt(homie_id));
if (homie && homie.homie){
setHomies(homiesInfo.data);
setSelectedHomie(homie.homie);
}else{
window.location.href = CRIB;
}
}else{
errorToast();
}
} catch (e) {
console.log("Error fetching", e);
}
})();
}, [gang, homie_id]);
const homieToOptionMapper = (homieData) => {
const homie = homieData.homie;
return (
<option key={homie.id} value={homie.id}>{homie.name}</option>
);
};
const homieOptions = homies.filter((homieData) => homieData.homie.id !== parseInt(homie_id)).map(homieToOptionMapper);
const notSayingOption = <option value="">NOT SAYIN'</option>
const clearForm = () => {
setAmountToMove("");
setSecondaryHomie("");
setMoveDescription("");
}
const handleSubmit = async (e) => {
e.preventDefault();
setSubmitInProgress(true);
let moneyMoveRequest = {};
if (moveType === 'collect') {
moneyMoveRequest = {
money_move: {
amount: amountToMove,
from_homie_id: secondaryHomie,
to_homie_id: homie_id,
description: moveDescription
}
}
}else{
moneyMoveRequest = {
money_move: {
amount: amountToMove,
from_homie_id: homie_id,
to_homie_id: secondaryHomie,
description: moveDescription
}
}
}
const submitResponse = await axios.post('/api/money_moves', moneyMoveRequest);
if (submitResponse && submitResponse.status === 200 && submitResponse.data === true) {
M.toast({html: "Money lounde...moved"});
props.history.push(`/homie/${homie_id}/flow`);
props.history.push(props.href);
} else {
M.toast({html: "Yo! It ain't workin'"});
}
setSubmitInProgress(false);
}
const formComplete = () => parseFloat(amountToMove) > 0;
const disableSubmit = () => (!formComplete() || submitInProgress);
const homieSelectLabel = () => moveType === 'collect' ? 'From' : 'To';
return (
<div className="center-align container">
<form onSubmit={handleSubmit}>
<h3>{selectedHomie && selectedHomie.name}</h3>
<div className='switch-box'>
<Switch
offLabel="Collect"
onChange={(e) => setMoveType(e.target.checked === true ? 'pay' : 'collect')}
onLabel="Pay"
/>
</div>
<br/>
<h5 className="required">{homieSelectLabel()}</h5>
<Select value={secondaryHomie} name="secondary-homie" onChange={(e) => setSecondaryHomie(e.target.value)}>
{notSayingOption}
{homieOptions}
</Select>
<div className="input-field col s12">
<input id="how-much" type="number" className="validate" step="0.01" required="required" value={amountToMove} onChange={(e) =>setAmountToMove(parseFloat(e.target.value))} pattern="^\\?(([1-9](\\d*|\\d{0,2}(,\\d{3})*))|0)(\\.\\d{1,2})?$" />
<label className="required" htmlFor="how-much">How much?</label>
<span className="helper-text" data-error="Yo! Put some money" />
</div>
<br/>
<Textarea label="Tag" value={moveDescription} onChange={(e) => setMoveDescription(e.target.value)}/>
<div>
<Button disabled={disableSubmit()} waves="light">
Do it
<Icon left>
attach_money
</Icon>
</Button>
</div>
</form>
</div>
);
}
export default withRouter(MoveMoney);