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