From 9fd7e7648612a32cf932b1627880086f906b994e Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Fri, 31 Jan 2020 23:47:52 +0000 Subject: [PATCH] Add UI page for reported transactions, member dropdown --- webclient/src/Admin.js | 36 ++++++++++++++++++++++++++++ webclient/src/App.js | 15 +++++++++++- webclient/src/Members.js | 44 +++++++++++++++++++++++++++++++++++ webclient/src/Transactions.js | 33 +++++++++++++++++++++----- 4 files changed, 121 insertions(+), 7 deletions(-) diff --git a/webclient/src/Admin.js b/webclient/src/Admin.js index e1f88e0..703d00c 100644 --- a/webclient/src/Admin.js +++ b/webclient/src/Admin.js @@ -6,6 +6,42 @@ import moment from 'moment'; import { statusColor, BasicTable, staticUrl, requester } from './utils.js'; import { TransactionList, TransactionEditor } from './Transactions.js'; +export function AdminReportedTransactions(props) { + const { token, user } = props; + const [transactions, setTransactions] = useState(false); + const [error, setError] = useState(false); + + useEffect(() => { + requester('/transactions/', 'GET', token) + .then(res => { + setTransactions(res.results); + setError(false); + }) + .catch(err => { + console.log(err); + setError(true); + }); + }, []); + + return ( + +
Reported Transactions
+ + {!error ? + transactions ? +
+ +
+ : +

Loading...

+ : + + } + +
+ ); +}; + export function AdminTransactions(props) { const { token, result, refreshResult } = props; const transactions = result.transactions; diff --git a/webclient/src/App.js b/webclient/src/App.js index 6a3498b..40803ef 100644 --- a/webclient/src/App.js +++ b/webclient/src/App.js @@ -3,12 +3,13 @@ import { BrowserRouter as Router, Switch, Route, Link, useParams, useHistory } f import './semantic-ui/semantic.min.css'; import './light.css'; import { Container, Divider, Dropdown, Form, Grid, Header, Icon, Image, Menu, Message, Segment, Table } from 'semantic-ui-react'; -import { requester } from './utils.js'; +import { isAdmin, requester } from './utils.js'; import { Home } from './Home.js'; import { Account } from './Account.js'; import { Transactions, TransactionDetail } from './Transactions.js'; import { Cards } from './Cards.js'; import { Training } from './Training.js'; +import { AdminReportedTransactions } from './Admin.js'; import { Courses, CourseDetail } from './Courses.js'; import { Classes, ClassDetail } from './Classes.js'; import { Members, MemberDetail } from './Members.js'; @@ -116,6 +117,12 @@ function App() { as={Link} to='/classes' /> + + {user && isAdmin(user) && } @@ -177,6 +184,12 @@ function App() { + {user && isAdmin(user) && + + + + } + diff --git a/webclient/src/Members.js b/webclient/src/Members.js index f6d4afa..23442e2 100644 --- a/webclient/src/Members.js +++ b/webclient/src/Members.js @@ -6,6 +6,50 @@ import { statusColor, isAdmin, BasicTable, staticUrl, requester } from './utils. import { NotFound, PleaseLogin } from './Misc.js'; import { AdminMemberInfo, AdminMemberPause, AdminMemberForm, AdminMemberCards, AdminTransactions } from './Admin.js'; +export function MembersDropdown(props) { + const { token, name, onChange, value, initial } = props; + const [response, setResponse] = useState({ results: [] }); + const searchDefault = {seq: 0, q: initial || ''}; + const [search, setSearch] = useState(searchDefault); + + useEffect(() => { + requester('/search/', 'POST', token, search) + .then(res => { + if (!search.seq || res.seq > response.seq) { + setResponse(res); + } + }) + .catch(err => { + console.log(err); + }); + }, [search]); + + const options = response.results.map((x, i) => ({ + key: x.member.id, + value: x.member.id, + text: x.member.preferred_name + ' ' + x.member.last_name, + image: { avatar: true, src: x.member.photo_small ? staticUrl + '/' + x.member.photo_small : '/nophoto.png' }, + })); + + console.log(value, initial); + + return ( + setSearch({seq: parseInt(e.timeStamp), q: v.searchQuery})} + /> + + ); +}; + export function Members(props) { const [response, setResponse] = useState(false); const searchDefault = {seq: 0, q: ''}; diff --git a/webclient/src/Transactions.js b/webclient/src/Transactions.js index 00f1e97..2bdbe27 100644 --- a/webclient/src/Transactions.js +++ b/webclient/src/Transactions.js @@ -2,11 +2,12 @@ import React, { useState, useEffect } from 'react'; import { BrowserRouter as Router, Switch, Route, Link, useParams } from 'react-router-dom'; import './light.css'; import { Container, Divider, Dropdown, Form, Grid, Header, Icon, Image, Menu, Message, Segment, Table } from 'semantic-ui-react'; +import { MembersDropdown } from './Members.js'; import { isAdmin, BasicTable, requester } from './utils.js'; import { NotFound, PleaseLogin } from './Misc.js'; export function TransactionEditor(props) { - const { input, setInput, error } = props; + const { token, input, setInput, error } = props; const handleValues = (e, v) => setInput({ ...input, [v.name]: v.value }); const handleUpload = (e, v) => setInput({ ...input, [v.name]: e.target.files[0] }); @@ -26,7 +27,7 @@ export function TransactionEditor(props) { { key: '2', text: 'Square (Credit)', value: 'Square Pmt' }, { key: '3', text: 'Dream Payments (Debit/Credit)', value: 'Dream Pmt' }, { key: '4', text: 'Deposit to TD (Not Interac)', value: 'TD Chequing' }, - { key: '5', text: 'PayPal', value: 'Paypal' }, + { key: '5', text: 'PayPal', value: 'PayPal' }, { key: '6', text: 'Member Balance / Protocash', value: 'Member' }, { key: '7', text: 'Supense (Clearing) Acct / Membership Adjustment', value: 'Clearing' }, ]; @@ -37,7 +38,7 @@ export function TransactionEditor(props) { { key: '2', text: 'System', value: 'System' }, { key: '3', text: 'Receipt or Statement', value: 'Receipt or Stmt' }, { key: '4', text: 'Quicken Import', value: 'Quicken Import' }, - { key: '5', text: 'PayPal IPN', value: 'Paypal IPN' }, + { key: '5', text: 'PayPal IPN', value: 'PayPal IPN' }, { key: '6', text: 'Auto', value: 'Auto' }, { key: '7', text: 'Nexus Database Bulk', value: 'Nexus DB Bulk' }, { key: '8', text: 'IPN Trigger', value: 'IPN Trigger' }, @@ -60,6 +61,16 @@ export function TransactionEditor(props) { return (
+ + + + + { setLoading(true); setSuccess(false); - requester('/transactions/'+id+'/', 'PUT', token, input) + const data = { ...input, report_type: null, report_memo: '' }; + requester('/transactions/'+id+'/', 'PUT', token, data) .then(res => { setLoading(false); setSuccess(true); @@ -167,7 +179,7 @@ function EditTransaction(props) {
Edit Transaction
- + Save @@ -201,7 +213,7 @@ export function TransactionList(props) { ${x.amount} {x.account_type} - {x.memo} + {x.memo || x.report_memo} ) : @@ -295,6 +307,15 @@ export function TransactionDetail(props) { Memo: {transaction.memo} + + {transaction.report_type && + Report Type: + {transaction.report_type} + } + {transaction.report_memo && + Report Memo: + {transaction.report_memo} + }