Skip to content

Commit

Permalink
v2.4.0 (#104)
Browse files Browse the repository at this point in the history
* kobo toolbox integration

* imported kobotoolbox data to db in bulk

* fix issues with mobilizer approval

* view uploaded excel document

Co-authored-by: rojanbade <[email protected]>
Co-authored-by: Manjik Shrestha <[email protected]>
Co-authored-by: Manjik Shrestha <[email protected]>
  • Loading branch information
4 people authored Oct 29, 2021
1 parent 2b8a456 commit be56037
Show file tree
Hide file tree
Showing 18 changed files with 14,486 additions and 46 deletions.
7 changes: 7 additions & 0 deletions src/assets/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,10 @@ a {
background-color: #2b7ec1;
border-color: #2b7ec1;
}

.kobocard{
display: flex;
align-items: center;
justify-content: center;
color: #2b7ec1;
}
35 changes: 34 additions & 1 deletion src/contexts/AppSettingsContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ const initialState = {
isVerified: false,
loading: false,
openPasscodeModal: false,
walletActionMsg: null
walletActionMsg: null,
pagination: { limit: 10, start: 0, total: 0, currentPage: 1, totalPages: 0 }
};

export const AppContext = createContext(initialState);
Expand Down Expand Up @@ -83,6 +84,34 @@ export const AppContextProvider = ({ children }) => {
dispatch({ type: ACTION.SET_APP_PASSCODE, data: passcode });
}, []);

function setKobotoolbox(payload) {
Service.setKobotoolbox(payload);
}

function getKobotoolboxForms(query) {
return new Promise((resolve, reject) => {
Service.getKobotoolboxForms(query)
.then(res => {
resolve(res);
})
.catch(err => {
reject(err);
});
});
}

function getKoboFormsData(assetId) {
return new Promise((resolve, reject) => {
Service.getKoboFormsData(assetId)
.then(res => {
resolve(res);
})
.catch(err => {
reject(err);
});
});
}

return (
<AppContext.Provider
value={{
Expand All @@ -96,6 +125,7 @@ export const AppContextProvider = ({ children }) => {
loading: state.loading,
openPasscodeModal: state.openPasscodeModal,
walletActionMsg: state.walletActionMsg,
pagination: state.pagination,
setWalletActionMsg,
setPasscodeModal,
setLoading,
Expand All @@ -104,6 +134,9 @@ export const AppContextProvider = ({ children }) => {
setHasWallet,
setWallet,
setWalletPasscode,
setKobotoolbox,
getKobotoolboxForms,
getKoboFormsData,
changeIsverified,
initApp
}}
Expand Down
5 changes: 5 additions & 0 deletions src/contexts/BeneficiaryContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export const BeneficiaryContextProvider = ({ children }) => {
return Service.addBeneficiary(payload);
};

const addBeneficiaryInBulk = payload => {
return Service.addBeneficiaryInBulk(payload);
};

const updateBeneficiary = (id, payload) => {
return Service.updateBeneficiary(id, payload);
};
Expand Down Expand Up @@ -109,6 +113,7 @@ export const BeneficiaryContextProvider = ({ children }) => {
listProject,
issueTokens,
addBeneficiary,
addBeneficiaryInBulk,
updateBeneficiary,
setBeneficiary,
listBeneficiary,
Expand Down
126 changes: 107 additions & 19 deletions src/modules/aid/detail/tab/beneficiaryList.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useContext, useState, useEffect, useCallback } from 'react';
import { Pagination, PaginationItem, PaginationLink, Table, FormGroup, InputGroup, Input } from 'reactstrap';
import { Pagination, PaginationItem, PaginationLink, Table, FormGroup, InputGroup, Input, Col, Row } from 'reactstrap';
import { useToasts } from 'react-toast-notifications';
import QRCode from 'qrcode';

Expand All @@ -10,6 +10,8 @@ import { htmlResponse } from '../../../../utils/printBeneficiary';
import ModalWrapper from '../../../global/CustomModal';
import PasscodeModal from '../../../global/PasscodeModal';
import GrowSpinner from '../../../global/GrowSpinner';
import UploadList from './uploadList';
import * as XLSX from 'xlsx';

const ACTION = {
BULK_QR: 'bulk_qrcode_export',
Expand All @@ -27,14 +29,75 @@ const List = ({ beneficiaries, projectId }) => {
const [beneficiaryPhones, setBeneficiaryPhones] = useState([]); // For bulk issue
const [beneficiaryTokens, setBeneficiaryTokens] = useState([]); // For bulk issue
const [passcodeModal, setPasscodeModal] = useState(false);
const [benefUploadFile, setBenefUploadFile] = useState('');
const [uploadListModal, setUploadListModal] = useState(false);
const [uploadData, setUploadData] = useState(null);

const hiddenFileInput = React.useRef(null);

const togglePasscodeModal = () => setPasscodeModal(!passcodeModal);
const toggleUploadListModal = () => setUploadListModal(!uploadListModal);

const toggleAmountModal = action => {
if (action) setCurrentAction(action);
setAmountModal(!amountModal);
};

const handleFileUploadClick = event => {
hiddenFileInput.current.click();
};

const handleUploadListSubmit = () => {
};

const handleFileChange = e => {
setUploadListModal(true);
readFile(e.target.files[0]);
e.target.value = '';
//setBenefUploadFile(e.target.files[0]);
};

const readFile = file => {
const reader = new FileReader();
reader.onload = evt => {
// evt = on_file_select event
/* Parse data */
const bstr = evt.target.result;
const wb = XLSX.read(bstr, { type: 'binary' });
/* Get first worksheet */
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
/* Convert array of arrays */
const data = XLSX.utils.sheet_to_csv(ws, { header: 1 });
/* Update state */
const jsonData = convertToJson(data);
setUploadData(jsonData);
};
reader.readAsBinaryString(file);
};

const convertToJson = csv => {
var lines = csv.split('\n');

var result = [];

var headers = lines[0].split(',');

for (var i = 1; i < lines.length; i++) {
var obj = {};
var currentline = lines[i].split(',');

for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j];
}

result.push(obj);
}

//return result; //JavaScript object
return result; //JSON
};

const handleAmountChange = e => setAmount(e.target.value);

const handleModalFormSubmit = e => {
Expand Down Expand Up @@ -161,27 +224,52 @@ const List = ({ beneficiaries, projectId }) => {
</InputGroup>
</FormGroup>
</ModalWrapper>
<div className="toolbar-flex-container">

<ModalWrapper
toggle={toggleUploadListModal}
open={uploadListModal}
title="Beneficiaries List"
handleSubmit={handleUploadListSubmit}
loading={loading}
size="xl"
>
<UploadList data={uploadData} />
</ModalWrapper>

<div>
{loading ? (
<GrowSpinner />
) : (
<div style={{ flex: 1, padding: 10 }}>
<button
onClick={() => toggleAmountModal(ACTION.BULK_ISSUE)}
type="button"
class="btn waves-effect waves-light btn-outline-info"
style={{ borderRadius: '8px', marginRight: '20px' }}
>
Bulk Token Issue
</button>
<button
type="button"
onClick={() => toggleAmountModal(ACTION.BULK_QR)}
class="btn waves-effect waves-light btn-outline-info"
style={{ borderRadius: '8px' }}
>
Bulk Generate QR Code
</button>
<div className="row">
<div style={{ flex: 1, padding: 10 }}>
<button
onClick={() => toggleAmountModal(ACTION.BULK_ISSUE)}
type="button"
class="btn waves-effect waves-light btn-outline-info"
style={{ borderRadius: '8px', marginRight: '20px' }}
>
Bulk Token Issue
</button>
<button
type="button"
onClick={() => toggleAmountModal(ACTION.BULK_QR)}
class="btn waves-effect waves-light btn-outline-info"
style={{ borderRadius: '8px' }}
>
Bulk Generate QR Code
</button>
</div>
<div style={{ padding: 10, float: 'right' }}>
<button
type="button"
onClick={handleFileUploadClick}
class="btn waves-effect waves-light btn-outline-info"
style={{ borderRadius: '8px' }}
>
Upload Beneficiaries
</button>
<input type="file" ref={hiddenFileInput} onChange={handleFileChange} style={{ display: 'none' }} />
</div>
</div>
)}

Expand Down
89 changes: 89 additions & 0 deletions src/modules/aid/detail/tab/uploadList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React, { useContext, useEffect, useCallback } from 'react';
import { Pagination, PaginationItem, PaginationLink, Table } from 'reactstrap';

import { AidContext } from '../../../../contexts/AidContext';

const List = ({ data }) => {
//const { vendor_pagination, vendors_list, vendorsByAid } = useContext(AidContext);

const handlePagination = current_page => {
// let _start = (current_page - 1) * vendor_pagination.limit;
// console.log({ _start });
};

// const fetchVendorsByAId = useCallback(async () => {
// // await vendorsByAid(projectId);
// }, [projectId, vendorsByAid]);

useEffect(() => {

}, [data]);

return (
<>


<Table className="no-wrap v-middle" responsive>
<thead>
<tr className="border-0">
<th className="border-0">Name</th>
<th className="border-0">Address</th>
<th className="border-0">Phone number</th>
<th className="border-0">Email</th>
<th className="border-0">Shop</th>
</tr>
</thead>
<tbody>
{data && data.length > 0 ? (
data.map(d => {
return (
<tr key={d._id}>
<td>{d.name}</td>
<td>{d.address || '-'}</td>
<td>{d.phone}</td>
<td>{d.email}</td>
<td>{d.shop_name || '-'}</td>
</tr>
);
})
) : (
<tr>
<td colSpan={2}></td>
<td>No data available.</td>
</tr>
)}
</tbody>
</Table>
{/*
{data.totalPages > 1 ? (
<Pagination
style={{
display: 'flex',
justifyContent: 'center',
marginTop: '50px'
}}
>
<PaginationItem>
<PaginationLink first href="#first_page" onClick={() => handlePagination(1)} />
</PaginationItem>
{[...Array(data.totalPages)].map((p, i) => (
<PaginationItem
key={i}
active={data.currentPage === i + 1 ? true : false}
onClick={() => handlePagination(i + 1)}
>
<PaginationLink href={`#page=${i + 1}`}>{i + 1}</PaginationLink>
</PaginationItem>
))}
<PaginationItem>
<PaginationLink last href="#last_page" onClick={() => handlePagination(data.totalPages)} />
</PaginationItem>
</Pagination>
) : (
''
)} */}
</>
);
};

export default List;
2 changes: 1 addition & 1 deletion src/modules/aid/list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ const List = () => {
</FormGroup>
</AidModal>
<Card>
<CardTitle className="mb-0">
<CardTitle className="mb-0 pt-3">
<span style={{ paddingLeft: 26 }}>Projects</span>
</CardTitle>
<CardTitle className="mb-0 p-3">
Expand Down
4 changes: 2 additions & 2 deletions src/modules/global/CustomModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import PropTypes from 'prop-types';
import Loading from './Loading';

export default function CustomModal(props) {
const { open, toggle, title, children, loading, hideFooter } = props;
const { open, toggle, title, children, loading, hideFooter,size } = props;
return (
<>
<Modal isOpen={open} toggle={toggle.bind(null)} className={props.className || ''} centered>
<Modal isOpen={open} toggle={toggle.bind(null)} className={props.className || ''} size={size ? size : ''} centered>
<Form onSubmit={props.handleSubmit}>
<ModalHeader toggle={toggle.bind(null)}>{title || 'Modal Title'}</ModalHeader>
<ModalBody>{children || 'No child elements supplied.'}</ModalBody>
Expand Down
Loading

0 comments on commit be56037

Please sign in to comment.