Skip to content

Commit ad5a778

Browse files
Merge branch 'main' into environment/staging
2 parents 0154ad4 + 0595911 commit ad5a778

File tree

77 files changed

+2517
-515
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+2517
-515
lines changed

packages/admin/src/components/Header.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,7 @@ export const Header: React.FC = () => {
9797
<Tabs.Item value="commons" label="Commons"/>
9898
<Tabs.Item value="proposals" label="Proposals"/>
9999
<Tabs.Item value="users" label="Users"/>
100-
<Tabs.Item value="financials/payments" label="Payments"/>
101-
<Tabs.Item value="financials/payouts" label="Payouts"/>
100+
<Tabs.Item value="financials" label="Financials"/>
102101
<Tabs.Item value="events" label="Events"/>
103102
{/*<Tabs.Item value="development/playground" label="Playground"/>*/}
104103
</Tabs>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from 'react';
2+
3+
import { Modal, Text } from '@geist-ui/react';
4+
5+
interface ICreateBankAccountModalProps {
6+
open: boolean;
7+
8+
onCreated?: (bankAccountId: string) => void;
9+
onAbondon?: () => void;
10+
}
11+
12+
export const CreateBankAccount: React.FC<ICreateBankAccountModalProps> = ({ open, onCreated, onAbondon }) => {
13+
return (
14+
<Modal open={open} onClose={onAbondon} width="800px">
15+
<div style={{ textAlign: 'start' }}>
16+
<Text h2>Create new bank account</Text>
17+
</div>
18+
19+
<Modal.Action passive onClick={onAbondon}>Cancel</Modal.Action>
20+
<Modal.Action loading>Create</Modal.Action>
21+
</Modal>
22+
);
23+
};
24+
Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,331 @@
1+
import React from 'react';
2+
3+
import { Centered } from '@components/Centered';
4+
import { Link } from '@components/Link';
5+
import { Card, Row, Col, Text, Spacer, Tag, User, Divider, useTheme } from '@geist-ui/react';
6+
import { ChevronLeftCircle, ChevronRightCircle, ChevronDownCircle, ChevronUpCircle } from '@geist-ui/react-icons';
7+
import { gql } from '@apollo/client';
8+
import { useGetPaymentDetailsLazyQuery, useGetPaymentsQuery } from '@graphql';
9+
import { useRouter } from 'next/router';
10+
11+
12+
export const PaymentsTableQuery = gql`
13+
query GetPayments($page: Int = 1) {
14+
payments: payments(page: $page) {
15+
id
16+
17+
type
18+
status
19+
20+
user {
21+
id
22+
23+
firstName
24+
lastName
25+
26+
photoURL
27+
28+
email
29+
}
30+
31+
amount {
32+
amount
33+
currency
34+
}
35+
}
36+
}
37+
`;
38+
39+
const GetPaymentDetailsQuery = gql`
40+
query GetPaymentDetails($paymentId: ID!) {
41+
payment(id: $paymentId) {
42+
type
43+
44+
common {
45+
id
46+
47+
name
48+
}
49+
50+
amount {
51+
amount
52+
currency
53+
}
54+
55+
fees {
56+
amount
57+
currency
58+
}
59+
60+
card {
61+
id
62+
63+
metadata {
64+
digits
65+
network
66+
}
67+
}
68+
}
69+
}
70+
`;
71+
72+
interface IPaymentTableProps {
73+
hideNavigation?: boolean;
74+
}
75+
76+
export const PaymentsTable: React.FC<IPaymentTableProps> = ({ hideNavigation }) => {
77+
const router = useRouter();
78+
const theme = useTheme();
79+
80+
// --- State
81+
const [page, setPage] = React.useState<number>(1);
82+
const [selectedPayment, setSelectedPayment] = React.useState<string>();
83+
84+
85+
const [getPayment, { data: payment, loading: paymentLoading }] = useGetPaymentDetailsLazyQuery();
86+
const { data: payments } = useGetPaymentsQuery({
87+
variables: {
88+
page
89+
}
90+
});
91+
92+
// Effects
93+
React.useEffect(() => {
94+
if (selectedPayment) {
95+
getPayment({
96+
variables: {
97+
paymentId: selectedPayment
98+
}
99+
});
100+
}
101+
}, [selectedPayment]);
102+
103+
// --- Actions
104+
const onNextPage = () => {
105+
setPage((currentPage) => {
106+
if (payments.payments.length === 10) {
107+
return currentPage + 1;
108+
}
109+
110+
return currentPage;
111+
});
112+
};
113+
114+
const onPreviousPage = () => {
115+
setPage((currentPage) => {
116+
if (currentPage > 1) {
117+
return currentPage - 1;
118+
}
119+
120+
return currentPage;
121+
});
122+
};
123+
124+
const toggleSelectedPayment = (paymentId: string): () => void => {
125+
return () => {
126+
setSelectedPayment((currentPayment) => {
127+
if (paymentId !== currentPayment) {
128+
return paymentId;
129+
}
130+
});
131+
};
132+
};
133+
134+
135+
return (
136+
<React.Fragment>
137+
<Card style={{ backgroundColor: theme.palette.accents_1, padding: 10 }}>
138+
<Card.Content style={{ paddingTop: 0, paddingBottom: 0 }}>
139+
<Row style={{ padding: 0 }}>
140+
<Col span={3}>
141+
<Text small style={{ margin: 0 }}>Amount</Text>
142+
</Col>
143+
144+
<Col span={4}>
145+
<Text small style={{ margin: 0 }}>Status</Text>
146+
</Col>
147+
148+
149+
<Col span={6}>
150+
<Text small style={{ margin: 0 }}>User</Text>
151+
</Col>
152+
</Row>
153+
</Card.Content>
154+
</Card>
155+
156+
<div style={{ margin: '1rem 0' }}>
157+
{payments?.payments?.map((p) => {
158+
return (
159+
<Card key={p.id} style={{ margin: '.5rem 0' }}>
160+
<Card.Content>
161+
<Row style={{ padding: 0 }}>
162+
<Col span={3}>
163+
<Centered vertical>
164+
<Text b>
165+
{(p.amount.amount / 100).toLocaleString('en-US', {
166+
style: 'currency',
167+
currency: p.amount.currency
168+
})}
169+
</Text>
170+
</Centered>
171+
</Col>
172+
173+
<Col span={4}>
174+
<Centered vertical>
175+
{p.status === 'pending' && (
176+
<Tag type="warning" invert>
177+
Pending
178+
</Tag>
179+
)}
180+
181+
{(p.status === 'confirmed' || p.status === 'paid') && (
182+
<Tag type="success" invert>
183+
Successful
184+
</Tag>
185+
)}
186+
187+
{(p.status === 'failed') && (
188+
<Tag type="error" invert>
189+
Failed
190+
</Tag>
191+
)}
192+
</Centered>
193+
</Col>
194+
195+
<Col span={6}>
196+
<User
197+
src={p.user.photoURL}
198+
name={`${p.user.firstName} ${p.user.lastName}`}
199+
>
200+
<User.Link href={`mailto:${p.user.email}`}>{p.user.email}</User.Link>
201+
</User>
202+
</Col>
203+
204+
<Col span={8}/>
205+
206+
<Col span={3}>
207+
<Centered vertical>
208+
<div style={{ cursor: 'pointer' }} onClick={toggleSelectedPayment(p.id)}>
209+
{selectedPayment !== p.id ? (
210+
<ChevronDownCircle/>
211+
) : (
212+
<ChevronUpCircle/>
213+
)}
214+
</div>
215+
</Centered>
216+
</Col>
217+
</Row>
218+
</Card.Content>
219+
220+
{selectedPayment === p.id && (
221+
<React.Fragment>
222+
<Divider y={0}/>
223+
224+
<Card.Content>
225+
<Row>
226+
{paymentLoading && (
227+
<div/>
228+
)}
229+
230+
{payment && (
231+
<React.Fragment>
232+
<Col span={12}>
233+
<Text h4 style={{ margin: 0 }}>Billing Plan</Text>
234+
<Text
235+
h2
236+
style={{ margin: 0 }}
237+
>
238+
{payment.payment.type === 'oneTime' ? 'One Time' : 'Subscription'} Payment
239+
</Text>
240+
241+
<Text style={{ margin: 0 }}>
242+
For {payment.payment.type === 'oneTime' ? 'joining' : 'participating in'}{' '}
243+
244+
<Link to={`/commons/details/${payment.payment.common.id}`}>
245+
{payment.payment.common.name}
246+
</Link>
247+
</Text>
248+
249+
<div style={{ display: 'flex', marginTop: 15 }}>
250+
<div>
251+
<Text h6>Fees</Text>
252+
<Text h4>
253+
{(payment.payment.fees.amount / 100).toLocaleString('en-US', {
254+
style: 'currency',
255+
currency: payment.payment.fees.currency
256+
})}
257+
</Text>
258+
</div>
259+
260+
<Spacer x={1}/>
261+
262+
<div>
263+
<Text h6>Money left</Text>
264+
<Text h4>
265+
{((payment.payment.amount.amount - payment.payment.fees.amount) / 100).toLocaleString('en-US', {
266+
style: 'currency',
267+
currency: payment.payment.fees.currency
268+
})}
269+
</Text>
270+
</div>
271+
</div>
272+
</Col>
273+
274+
<Col span={12}>
275+
<Row>
276+
<Col span={16}>
277+
{/*<Row>*/}
278+
{/* <Col span={24}>*/}
279+
{/* <Text h6>Payment Instrument</Text>*/}
280+
{/* <Text h4>{payment.payment.card.metadata.network} {payment.payment.card.metadata.digits}</Text>*/}
281+
{/* </Col>*/}
282+
{/*</Row>*/}
283+
</Col>
284+
285+
<Col span={8}>
286+
<div style={{ display: 'flex', flexFlow: 'column', alignItems: 'flex-end' }}>
287+
<Text h4>Amount due</Text>
288+
<Text h2>
289+
{(payment.payment.amount.amount / 100).toLocaleString('en-US', {
290+
style: 'currency',
291+
currency: payment.payment.amount.currency
292+
})}
293+
</Text>
294+
</div>
295+
</Col>
296+
</Row>
297+
</Col>
298+
</React.Fragment>
299+
)}
300+
</Row>
301+
</Card.Content>
302+
</React.Fragment>
303+
)}
304+
</Card>
305+
);
306+
})}
307+
</div>
308+
309+
{!hideNavigation && (
310+
<Centered>
311+
<div style={{ display: 'flex', alignContent: 'center' }}>
312+
<div style={{ cursor: page > 1 ? 'pointer' : 'not-allowed' }} onClick={onPreviousPage}>
313+
<ChevronLeftCircle/>
314+
</div>
315+
316+
<Spacer x={0.8}/>
317+
318+
<Text b>Page {page}</Text>
319+
320+
<Spacer x={0.8}/>
321+
322+
<div style={{ cursor: payments?.payments.length === 10 ? 'pointer' : 'not-allowed' }} onClick={onNextPage}>
323+
<ChevronRightCircle/>
324+
</div>
325+
</div>
326+
</Centered>
327+
)}
328+
329+
</React.Fragment>
330+
)
331+
}

0 commit comments

Comments
 (0)