1+ import { useState } from 'react' ;
2+ import Head from '../../components/head' ;
3+ import Layout from '../../components/layout' ;
4+ import DatePicker from 'react-datepicker' ;
5+ import { fetchInvoices , markReconciled , unmarkReconciled } from '../../controllers/v2/invoices'
6+ import moment from 'moment' ;
7+ import { useEffect } from 'react' ;
8+ import Table from '@material-ui/core/Table' ;
9+ import TableBody from '@material-ui/core/TableBody' ;
10+ import TableCell from '@material-ui/core/TableCell' ;
11+ import TableContainer from '@material-ui/core/TableContainer' ;
12+ import Grid from "@material-ui/core/Grid" ;
13+ import TableHead from '@material-ui/core/TableHead' ;
14+ import TableRow from '@material-ui/core/TableRow' ;
15+ import Paper from '@material-ui/core/Paper' ;
16+ import TablePagination from "@material-ui/core/TablePagination" ;
17+ import { withStyles } from '@material-ui/core' ;
18+ import { Modal , Box , Typography } from '@material-ui/core' ;
19+ import Button from '@material-ui/core/Button' ;
20+ import Dialog from "@material-ui/core/Dialog" ;
21+ import DialogContent from "@material-ui/core/DialogContent" ;
22+ import Swal from 'sweetalert2' ;
23+
24+ const PaginationTheme = withStyles ( {
25+ actions : {
26+ color : "red" ,
27+ backgroundColor : 'white' ,
28+ }
29+ } ) ( TablePagination ) ;
30+
31+ export default function Reconcile ( ) {
32+ const [ startDate , setStartDate ] = useState ( moment ( ) . toDate ( ) ) ;
33+ const [ endDate , setEndDate ] = useState ( ) ;
34+ const [ comment , setComment ] = useState ( '' )
35+ const [ showModal , setShowModal ] = useState ( false )
36+ const [ offset , setOffset ] = useState ( 0 )
37+ const [ limit , setLimit ] = useState ( 25 )
38+ const [ invoices , setInvoices ] = useState ( [ ] )
39+ const [ selectedInvoiceIds , setSelectedInvoiceIds ] = useState ( [ ] )
40+ const [ paginationMeta , setPaginationMeta ] = useState ( { currentPage : 0 , count : 0 } )
41+
42+ useEffect ( ( ) => {
43+ async function fetchData ( ) {
44+ const response = await fetchInvoices ( { offset, limit } )
45+ setInvoices ( response . data . data )
46+ setPaginationMeta ( { currentPage : response . data . pagesInfo . currentPage , count : response . data . pagesInfo . count } )
47+ }
48+ fetchData ( )
49+ } , [ ] )
50+
51+ function handleChangePage ( event , newPage ) {
52+ setOffset ( newPage * limit )
53+ }
54+
55+ function handleLimitChange ( event ) {
56+ setLimit ( parseInt ( event . target . value , 10 ) )
57+ }
58+
59+ function handleModalClose ( e ) {
60+ console . log ( e )
61+ }
62+
63+ function handleSelectRow ( selected , invoice_id ) {
64+ if ( selected ) {
65+ setSelectedInvoiceIds ( [ ...selectedInvoiceIds , invoice_id ] )
66+ } else {
67+ const selectedIds = [ ...selectedInvoiceIds ]
68+ const index = selectedInvoiceIds . indexOf ( invoice_id )
69+ selectedIds . splice ( index , 1 )
70+ setSelectedInvoiceIds ( selectedIds )
71+ }
72+ }
73+
74+ async function handleMarkReconciled ( ) {
75+ try {
76+ await markReconciled ( { invoiceIds : selectedInvoiceIds , comment } )
77+ setShowModal ( false )
78+ Swal . fire ( {
79+ title : "Invoices reconciled successfully!" ,
80+ type : "success" ,
81+ showConfirmButton : true
82+ } )
83+
84+ const response = await fetchInvoices ( { offset, limit } )
85+ setInvoices ( response . data . data )
86+ setPaginationMeta ( { currentPage : response . data . pagesInfo . currentPage , count : response . data . pagesInfo . count } )
87+
88+ } catch ( err ) {
89+ Swal . fire ( {
90+ title : "Invoices Reconcilation Failed!" ,
91+ type : "error" ,
92+ showConfirmButton : true
93+ } )
94+ }
95+ }
96+
97+ async function handleUnmarkReconciled ( ) {
98+ try {
99+ await unmarkReconciled ( { invoiceIds : selectedInvoiceIds } )
100+ Swal . fire ( {
101+ title : "Invoices reconciled successfully!" ,
102+ type : "success" ,
103+ showConfirmButton : true
104+ } )
105+
106+ const response = await fetchInvoices ( { offset, limit } )
107+ setInvoices ( response . data . data )
108+ setPaginationMeta ( { currentPage : response . data . pagesInfo . currentPage , count : response . data . pagesInfo . count } )
109+ } catch ( err ) {
110+ Swal . fire ( {
111+ title : "Invoices Un-Reconcilation Failed!" ,
112+ type : "error" ,
113+ showConfirmButton : true
114+ } )
115+ }
116+ }
117+
118+ useEffect ( ( ) => {
119+ async function fetchData ( ) {
120+ const response = await fetchInvoices ( { offset, limit } )
121+ setInvoices ( response . data . data )
122+ setPaginationMeta ( { currentPage : response . data . pagesInfo . currentPage , count : response . data . pagesInfo . count } )
123+ }
124+ fetchData ( )
125+ } , [ limit , offset ] )
126+
127+ return (
128+ < div >
129+ < Head title = "Coding Blocks | Dukaan | Coupon" />
130+ < Layout />
131+ < div className = "my-4" >
132+ < h3 className = "t-align-c" > Reconciler</ h3 >
133+
134+ { /* <div className="my-3">
135+ <span>Select Date Range</span>
136+ </div>
137+ <DatePicker
138+ className="border"
139+ selectsRange
140+ onChange={(update) => {
141+ console.log(update)
142+ }}
143+ isClearable={true}
144+ /> */ }
145+
146+ < div className = "my-4 d-flex justify-content-center" >
147+ < Grid xs = { 11 } className = { "mt-5 mr-5" } >
148+ < Paper >
149+ < TableContainer >
150+ < Grid container justify = "center" className = { "mb-1" } >
151+ < div className = "d-flex justify-content-between w-100 p-4" >
152+ < h2 className = { "title" } > Invoices</ h2 >
153+ < li className = "dropdown mt-1 float-right" >
154+ < button className = "dropbtn dropdown-toggle" >
155+ < span className = "font-md" > Actions</ span >
156+ < i className = "fa fa-caret-down pl-2" />
157+ </ button >
158+ < div className = "dropdown-content" >
159+ < div className = "flex-row justify-content-center" >
160+ < button className = "p-2" disabled = { ! ! ! selectedInvoiceIds . length } onClick = { ( ) => setShowModal ( true ) } > Mark Reconciled</ button >
161+ </ div >
162+ < div className = "divider-h" />
163+ < div className = "flex-row justify-content-center" >
164+ < button className = "p-2" disabled = { ! ! ! selectedInvoiceIds . length } onClick = { ( ) => handleUnmarkReconciled ( ) } > Mark Un-Reconcile</ button >
165+ </ div >
166+ </ div >
167+ </ li >
168+ </ div >
169+ </ Grid >
170+ < Table aria-label = "simple table" >
171+ < TableHead >
172+ < TableRow >
173+ < TableCell align = "center" className = { "red" } > Select</ TableCell >
174+ < TableCell align = "center" className = { "red" } > Name</ TableCell >
175+ < TableCell align = "center" className = { "red" } > Email</ TableCell >
176+ < TableCell align = "center" className = { "red" } > Product</ TableCell >
177+ < TableCell align = "center" className = { "red" } > List Price</ TableCell >
178+ < TableCell align = "center" className = { "red" } > Final Price</ TableCell >
179+ < TableCell align = "center" className = { "red" } > CGST</ TableCell >
180+ < TableCell align = "center" className = { "red" } > IGST</ TableCell >
181+ < TableCell align = "center" className = { "red" } > SGST</ TableCell >
182+ < TableCell align = "center" className = { "red" } > Tax</ TableCell >
183+ < TableCell align = "center" className = { "red" } > Final Amount</ TableCell >
184+ < TableCell align = "center" className = { "red" } > RazorPay Order Id</ TableCell >
185+ < TableCell align = "center" className = { "red" } > RazorPay Payment Id</ TableCell >
186+ < TableCell align = "center" className = { "red" } > Status</ TableCell >
187+ < TableCell align = "center" className = { "red" } > Invoice Link</ TableCell >
188+ < TableCell align = "center" className = { "red" } > Reconciled By</ TableCell >
189+ </ TableRow >
190+ </ TableHead >
191+ < TableBody >
192+ { invoices . map ( invoice => (
193+ < TableRow key = { invoice . id }
194+ className = { invoice . reconciled_by ? 'bg-green' : selectedInvoiceIds . includes ( invoice . id ) ? 'bg-blue' : '' } >
195+ < TableCell >
196+ < input type = "checkbox" onChange = { ( e ) => handleSelectRow ( e . target . checked , invoice . id ) } />
197+ </ TableCell >
198+ < TableCell > { invoice . cart . buyer . firstname } { invoice . cart . buyer . lastname } </ TableCell >
199+ < TableCell > { invoice . cart . buyer . email } </ TableCell >
200+ < TableCell > { invoice . product . name } </ TableCell >
201+ < TableCell > { invoice . list_price / 100 } </ TableCell >
202+ < TableCell > { invoice . final_price / 100 } </ TableCell >
203+ < TableCell > { invoice . cgst / 100 } </ TableCell >
204+ < TableCell > { invoice . igst / 100 } </ TableCell >
205+ < TableCell > { invoice . sgst / 100 } </ TableCell >
206+ < TableCell > { invoice . cart . total_tax_collected / 100 } </ TableCell >
207+ < TableCell > { invoice . amount / 100 } </ TableCell >
208+ < TableCell > { invoice . transaction ?. razorpay ?. order_id || invoice . transaction ?. razorpay_order_id } </ TableCell >
209+ < TableCell > { invoice . transaction ?. razorpay ?. payment_id || invoice . transaction ?. razorpay_payment_id } </ TableCell >
210+ < TableCell > < span className = {
211+ invoice . transaction . status === 'captured' ? 'green' : invoice . transaction . status === 'cancelled' ? 'red' : 'yellow'
212+ } > { invoice . transaction ?. status } </ span > </ TableCell >
213+ < TableCell > < a href = { invoice . invoice_link } target = "_blank" > { invoice . invoice_link ? 'Link' : 'N/A' } </ a > </ TableCell >
214+ < TableCell > { invoice . reconciledBy ? `${ invoice . reconciledBy . firstname } ${ invoice . reconciledBy . lastname } (${ invoice . reconciledBy . oneauth_id } ` : 'N/A' } </ TableCell >
215+ </ TableRow >
216+ ) ) }
217+ </ TableBody >
218+ </ Table >
219+ </ TableContainer >
220+ < PaginationTheme
221+ component = "div"
222+ count = { paginationMeta . count }
223+ rowsPerPage = { limit }
224+ page = { paginationMeta . currentPage }
225+ onChangePage = { handleChangePage }
226+ onChangeRowsPerPage = { handleLimitChange }
227+ />
228+ </ Paper >
229+ </ Grid >
230+ </ div >
231+ </ div >
232+ { /* <Modal
233+ open={showModal}
234+ onClose={() => setShowModal(false)}
235+ aria-labelledby="modal-modal-title"
236+ aria-describedby="modal-modal-description">
237+ <Box>
238+ <Typography id="modal-modal-title" variant="h6" component="h2">
239+ Add a comment
240+ </Typography>
241+ <textarea name="" id="" cols="30" rows="10" onChange={(e) => setComment(e.target.value)}>
242+
243+ </textarea>
244+ <Button>Mark as Reconciled</Button>
245+ </Box>
246+ </Modal> */ }
247+ < Dialog
248+ title = "Dialog"
249+ modal = { true }
250+ maxWidth = { "xl" }
251+ open = { showModal }
252+ onClose = { ( ) => setShowModal ( false ) }
253+ aria-labelledby = "simple-modal-title"
254+ aria-describedby = "simple-modal-description" >
255+ < DialogContent >
256+ < h4 > Add Comment</ h4 >
257+ < textarea placeholder = "Comments..." name = "" id = "" cols = "30" rows = "10" onChange = { ( e ) => setComment ( e . target . value ) } > </ textarea >
258+ < Button variant = "outlined" disabled = { ! ! ! comment } onClick = { ( ) => handleMarkReconciled ( ) } > Mark as Reconciled</ Button >
259+ </ DialogContent >
260+ </ Dialog >
261+ </ div >
262+ )
263+ }
0 commit comments