diff --git a/package.json b/package.json index 2510668b..45d8703a 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ }, "dependencies": { "add": "^2.0.6", + "apexcharts": "^3.28.3", "axios": "^0.21.1", "bootstrap-switch-button-react": "^1.2.0", "chart.js": "^2.9.3", @@ -52,6 +53,7 @@ "qrcode.react": "^1.0.0", "query-string": "^6.13.1", "react": "^16.13.1", + "react-apexcharts": "1.3.7", "react-chartjs-2": "^2.10.0", "react-digit-input": "^2.1.0", "react-dom": "^16.13.1", @@ -64,6 +66,7 @@ "react-select": "^2.2.0", "react-stepzilla": "^6.0.2", "react-table-v6": "^6.8.6", + "react-to-print": "^2.13.0", "react-toast-notifications": "^2.4.0", "reactstrap": "^8.4.1", "redux-devtools-extension": "^2.13.8", diff --git a/src/constants/index.js b/src/constants/index.js index 63b01c2f..a2931cc7 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -21,6 +21,10 @@ module.exports = { SUCCESS: { appearance: 'success', autoDismiss: true + }, + WARNING: { + appearance: 'warning', + autoDismiss: true } }, PROJECT_STATUS: { diff --git a/src/contexts/BeneficiaryContext.js b/src/contexts/BeneficiaryContext.js index 43dc11b1..88041265 100644 --- a/src/contexts/BeneficiaryContext.js +++ b/src/contexts/BeneficiaryContext.js @@ -4,7 +4,6 @@ import * as Service from '../services/beneficiary'; import * as AidService from '../services/aid'; import ACTION from '../actions/beneficiary'; import { AppContext } from './AppSettingsContext'; -import { APP_CONSTANTS } from '../constants'; const initialState = { list: [], @@ -38,15 +37,11 @@ export const BeneficiaryContextProvider = ({ children }) => { return Service.getBeneficiaryBalance(phone, contract_address); }, []); - const listAid = useCallback(() => { - return AidService.listAid({ limit: APP_CONSTANTS.FETCH_LIMIT }); - }, []); - - // async function listAid() { - // const d = await AidService.listAid({ start: 0, limit: 50 }); - // dispatch({ type: ACTION.LIST_AID, data: { projectList: d.data } }); - // return d; - // } + async function listProject() { + const d = await AidService.listAid({ start: 0, limit: 50 }); + dispatch({ type: ACTION.LIST_AID, data: { projectList: d.data } }); + return d; + } function setAid(aid) { dispatch({ type: ACTION.SET_AID, data: aid }); @@ -79,23 +74,6 @@ export const BeneficiaryContextProvider = ({ children }) => { return Service.updateBeneficiary(id, payload); }; - // const addBeneficiary = async event => { - // event.preventDefault(); - // const formData = new FormData(event.target); - - // let payload = { - // name: formData.get('name'), - // phone: formData.get('phone'), - // govt_id: formData.get('govt_id'), - // email: formData.get('email'), - // address: formData.get('address'), - // wallet_address: formData.get('wallet_address'), - // project_id: formData.get('aid') - // }; - // let d = await Service.addBeneficiary(payload); - // return d; - // }; - async function listBeneficiary(params) { let res = await Service.listBeneficiary(params); if (res) { @@ -112,8 +90,9 @@ export const BeneficiaryContextProvider = ({ children }) => { for (let b of beneficiaries) await Service.addBeneficiary(b); }; - const getBeneficiaryDetails = useCallback(id => { - return Service.get(id); + const getBeneficiaryDetails = useCallback(async id => { + const data = await Service.get(id); + return data; }, []); return ( @@ -124,10 +103,10 @@ export const BeneficiaryContextProvider = ({ children }) => { list: state.list, pagination: state.pagination, tokenBalance: state.tokenBalance, - beneficiary_detail: state.beneficiary, + beneficiary: state.beneficiary, clear, setAid, - listAid, + listProject, issueTokens, addBeneficiary, updateBeneficiary, diff --git a/src/contexts/MobilizerContext.js b/src/contexts/MobilizerContext.js index 45a5abb9..f79ab927 100644 --- a/src/contexts/MobilizerContext.js +++ b/src/contexts/MobilizerContext.js @@ -1,167 +1,159 @@ -import React, { createContext, useReducer,useContext } from "react"; -import mobilizerReduce from "../reducers/mobilizerReducer"; -import * as Service from "../services/mobilizer"; -import * as AidService from "../services/aid"; -import ACTION from "../actions/mobilizer"; -import {AppContext} from './AppSettingsContext'; +import React, { createContext, useReducer, useContext, useCallback } from 'react'; +import mobilizerReduce from '../reducers/mobilizerReducer'; +import * as Service from '../services/mobilizer'; +import * as AidService from '../services/aid'; +import ACTION from '../actions/mobilizer'; +import { AppContext } from './AppSettingsContext'; const initialState = { - list: [], - pagination: { limit: 10, start: 0, total: 0, currentPage: 1, totalPages: 0 }, - aid: "", - aids: [], - mobilizer: {}, - loading: false, - transactionHistory: [], + list: [], + pagination: { limit: 10, start: 0, total: 0, currentPage: 1, totalPages: 0 }, + aid: '', + aids: [], + mobilizer: {}, + loading: false, + transactionHistory: [] }; export const MobilizerContext = createContext(initialState); export const MobilizerContextProvider = ({ children }) => { - const [state, dispatch] = useReducer(mobilizerReduce, initialState); - const {wallet,appSettings,changeIsverified} = useContext(AppContext); - - async function getMobilizerBalance(contract_addr, wallet_address) { - return Service.getMobilizerBalance(contract_addr, wallet_address); - } - - - async function getAvailableBalance(proejctId, rahatAdminContractAddr) { - const { rahat:rahatContractAddr } = appSettings.agency.contracts; - return AidService.loadAidBalance(proejctId, rahatContractAddr); - } - - async function listAid() { - const d = await AidService.listAid({ start: 0, limit: 20 }); - dispatch({ type: ACTION.LIST_AID, data: { aids: d.data } }); - return d; - } - - function setAid(aid) { - dispatch({ type: ACTION.SET_AID, data: aid }); - } - - function clear() { - dispatch({ - type: ACTION.LIST, - data: { - limit: 10, - start: 0, - total: 0, - data: [], - page: 0, - name: "", - phone: "", - }, - }); - } - - async function approveMobilizer( payload) { - const { rahat:rahatContractAddr } = appSettings.agency.contracts; - const res = await Service.approveMobilizer(wallet,payload,rahatContractAddr); - changeIsverified(false); - if (res) { - setMobilizer(res.data); - return res.data; - } - } - - async function changeMobilizerStatus(mobilizerId, status) { - const res = await Service.changeMobilizerStaus(mobilizerId, status); - setMobilizer(res.data); - return res.data; - } - - function setMobilizer(b) { - dispatch({ type: ACTION.SET_MOBILIZER, data: b }); - } - - async function getMobilizerDetails(id) { - const data = await Service.get(id); - setMobilizer(data); - return data; - } - - function addMobilizer(e) { - e.preventDefault(); - const formData = new FormData(e.target); - let payload = { - name: formData.get("name"), - phone: formData.get("phone"), - wallet_address: formData.get("ethaddress"), - email: formData.get("email"), - address: formData.get("address"), - govt_id: formData.get("govt_id"), - organization:formData.get("organization") - }; - - return new Promise((resolve, reject) => { - Service.add(payload) - .then((res) => { - resolve(res); - }) - .catch((err) => { - reject(err); - }); - }); - } - - function setLoading() { - dispatch({ type: ACTION.SET_LOADING }); - } - - function resetLoading() { - dispatch({ type: ACTION.RESET_LOADING }); - } - - async function listMobilizer(params) { - let res = await Service.list(params); - if (res) { - dispatch({ - type: ACTION.LIST, - data: res, - }); - return res; - } - } - - async function getMobilizerTransactions(mobilizerId) { - let res = await Service.mobilizerTransactions(mobilizerId); - if (res) { - dispatch({ - type: ACTION.MOBILIZER_TX, - data: res, - }); - return res; - } - } - - return ( - - {children} - - ); + const [state, dispatch] = useReducer(mobilizerReduce, initialState); + const { wallet, appSettings, changeIsverified } = useContext(AppContext); + + async function getMobilizerBalance(contract_addr, wallet_address) { + return Service.getMobilizerBalance(contract_addr, wallet_address); + } + + async function getAvailableBalance(proejctId, rahatAdminContractAddr) { + const { rahat: rahatContractAddr } = appSettings.agency.contracts; + return AidService.loadAidBalance(proejctId, rahatContractAddr); + } + + async function listAid() { + const d = await AidService.listAid({ start: 0, limit: 20 }); + dispatch({ type: ACTION.LIST_AID, data: { aids: d.data } }); + return d; + } + + function setAid(aid) { + dispatch({ type: ACTION.SET_AID, data: aid }); + } + + function clear() { + dispatch({ + type: ACTION.LIST, + data: { + limit: 10, + start: 0, + total: 0, + data: [], + page: 0, + name: '', + phone: '' + } + }); + } + + async function approveMobilizer(payload) { + const { rahat: rahatContractAddr } = appSettings.agency.contracts; + const res = await Service.approveMobilizer(wallet, payload, rahatContractAddr); + changeIsverified(false); + if (res) { + setMobilizer(res.data); + return res.data; + } + } + + async function changeMobilizerStatus(mobilizerId, status) { + const res = await Service.changeMobilizerStaus(mobilizerId, status); + setMobilizer(res.data); + return res.data; + } + + function setMobilizer(b) { + dispatch({ type: ACTION.SET_MOBILIZER, data: b }); + } + + const getMobilizerDetails = useCallback(async id => { + const data = await Service.get(id); + setMobilizer(data); + return data; + }, []); + + function addMobilizer(payload) { + return new Promise((resolve, reject) => { + Service.add(payload) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + + const updateMobilizer = (id, payload) => { + return Service.updateMobilizer(id, payload); + }; + + function setLoading() { + dispatch({ type: ACTION.SET_LOADING }); + } + + function resetLoading() { + dispatch({ type: ACTION.RESET_LOADING }); + } + + async function listMobilizer(params) { + let res = await Service.list(params); + if (res) { + dispatch({ + type: ACTION.LIST, + data: res + }); + return res; + } + } + + async function getMobilizerTransactions(mobilizerId) { + let res = await Service.mobilizerTransactions(mobilizerId); + if (res) { + dispatch({ + type: ACTION.MOBILIZER_TX, + data: res + }); + return res; + } + } + + return ( + + {children} + + ); }; diff --git a/src/contexts/UserContext.js b/src/contexts/UserContext.js index cd6b9651..f7fbfafe 100644 --- a/src/contexts/UserContext.js +++ b/src/contexts/UserContext.js @@ -28,6 +28,18 @@ export const UserContextProvider = ({ children }) => { }); } + function signUp(payload) { + return new Promise((resolve, reject) => { + Service.signUp(payload) + .then(res => { + resolve(res); + }) + .catch(err => { + reject(err); + }); + }); + } + function loginUsingMetamask(payload) { return new Promise((resolve, reject) => { Service.loginUsingMetamask(payload) @@ -82,7 +94,8 @@ export const UserContextProvider = ({ children }) => { verifyToken, checkExistingUser, getDashboardStats, - loginUsingMetamask + loginUsingMetamask, + signUp }} > {children} diff --git a/src/contexts/VendorContext.js b/src/contexts/VendorContext.js index d2c0b2b9..1954d73c 100644 --- a/src/contexts/VendorContext.js +++ b/src/contexts/VendorContext.js @@ -89,16 +89,6 @@ export const VendorContextProvider = ({ children }) => { }, []); function addVendor(payload) { - // const formData = new FormData(e.target); - // let payload = { - // name: formData.get("name"), - // phone: formData.get("phone"), - // wallet_address: formData.get("ethaddress"), - // email: formData.get("email"), - // address: formData.get("address"), - // govt_id: formData.get("govt_id"), - // }; - return new Promise((resolve, reject) => { Service.add(payload) .then(res => { diff --git a/src/modules/aid/detail/projectInfo.js b/src/modules/aid/detail/projectInfo.js index 3987607f..63365873 100644 --- a/src/modules/aid/detail/projectInfo.js +++ b/src/modules/aid/detail/projectInfo.js @@ -1,17 +1,88 @@ -import React from 'react'; +import React, { useRef ,useState} from 'react'; import moment from 'moment'; -import { Card, CardTitle, Col, Row } from 'reactstrap'; +import { Card, CardTitle, Col, Row ,FormGroup, InputGroup, Input,Label } from 'reactstrap'; +import ReactDOM from 'react-dom'; import { History } from '../../../utils/History'; import '../../../assets/css/project.css'; +import QRGenerator from './qrGenerator'; +import ReactToPrint from 'react-to-print'; +import ModalWrapper from '../../global/CustomModal'; + export default function ProjectInfo({ projectDetails }) { - const { _id, social_mobilizer, project_manager, location, description, created_at } = projectDetails; + const { _id, social_mobilizer, project_manager, location, description, created_at ,serial_index} = projectDetails; const handleEditClick = () => History.push(`/edit-project/${_id}`); + const [qrGenModal, setQrGenModal] = useState(false); + const [qrGenData,setQrGenData] = useState({ min: 0, max: 0, projectVersion: 0, amount:null }); + const [qrGenLoading,setQrGenLoading] = useState(false); + + const toggleQrGen = () => { + setQrGenModal(!qrGenModal); + setQrGenData({min: 0, max: 0, projectVersion: serial_index, amount:null}) + } + const toggleQrGenLoading = () => setQrGenLoading(!qrGenLoading); + + const qrComponentRef = useRef(); + const printRef = useRef(); + const handleQrGenSubmit = (e) => { + e.preventDefault(); + printRef.current.handleClick(); + } + + // useReactToPrint({ + // content: () => qrComponentRef.current + // }); + const handleQrGenData = e =>{ + console.log(e.target.name); + if (e.target.name==='max'&&e.target.value > 100) return; + + setQrGenData({ ...qrGenData, [e.target.name]: e.target.value || null }); + } + + return (
+
+ + } + content={() => qrComponentRef.current} + ref={printRef} + /> +
+ + + + + + + + + +
@@ -21,14 +92,24 @@ export default function ProjectInfo({ projectDetails }) { - +
+ + +
diff --git a/src/modules/aid/detail/qrGenerator/index.js b/src/modules/aid/detail/qrGenerator/index.js new file mode 100644 index 00000000..9c00b2c7 --- /dev/null +++ b/src/modules/aid/detail/qrGenerator/index.js @@ -0,0 +1,58 @@ +import './style.css'; +import React from 'react'; +import { useEffect, useState } from 'react'; +import QRCode from 'qrcode.react'; +import RahatLogo from '../../../../assets/images/main_logo.png'; + +const QRGenerator = React.forwardRef(({ props }, ref) => { + //send props as {min: 1, max: 5, amount: null} + const [data, setData] = useState([]); + + function getQrData(projectVersion, amount, serialNumber) { + if (projectVersion > 999) throw Error('project version should be less than 1000'); + if (serialNumber > 100) throw Error('cannot generate more than 100 qr codes'); + const id = `555${String(projectVersion).padStart(3, '0')}${String(serialNumber).padStart(4, '0')}`; + return { qrData: `phone:${id}?amount=${amount}`, id }; + } + + useEffect(() => { + if (props && props.max > props.min) { + const dataList = []; + try { + for (let i = props.min; i < props.max; i++) { + const { qrData, id } = getQrData(props.projectVersion, props.amount, i); + dataList.push({ text: qrData, id }); + } + setData(dataList); + } catch (error) { + alert(error); + } + } + }, [props]); + + return ( +
+ {data.map((d, i) => { + return ( +
+ + +
+

{d.id}

+
+
+ ); + })} +
+ ); +}); + +export default QRGenerator; diff --git a/src/modules/aid/detail/qrGenerator/style.css b/src/modules/aid/detail/qrGenerator/style.css new file mode 100644 index 00000000..53afbbea --- /dev/null +++ b/src/modules/aid/detail/qrGenerator/style.css @@ -0,0 +1,46 @@ +.App { + text-align: center; +} +.printQr { + text-align: center; + margin-top: 5em; + margin-bottom: 10em; +} +.wrapper { + display: flex; + flex-wrap: wrap; + align-content: space-between; + vertical-align: middle; +} +.itemWrapper { + flex: 1; + padding: 20px; + justify-content: center; + align-items: center; +} + +.textWrapper { + padding: 2px; + text-align: center; +} +@page { + size: A4; + margin: 70pt 60pt 70pt; +} +@media print { + html, + body { + width: 210mm; + min-height: 297mm; + height: 297mm; + padding: 20px; + } + .no-printme { + display: none; + } + .printme { + width: initial; + min-height: initial; + page-break-after: always; + } +} diff --git a/src/modules/app.js b/src/modules/app.js index bc953c31..82a0079e 100644 --- a/src/modules/app.js +++ b/src/modules/app.js @@ -1,44 +1,42 @@ -import React from "react"; -import indexRoutes from "../routes"; -import { Router, Route, Switch } from "react-router-dom"; -import { ToastProvider } from "react-toast-notifications"; +import React from 'react'; +import indexRoutes from '../routes'; +import { Router, Route, Switch } from 'react-router-dom'; +import { ToastProvider } from 'react-toast-notifications'; -import { History } from "../utils/History"; -import { PrivateRoute } from "../routes/PrivateRoutes"; -import { AppContextProvider } from "../contexts/AppSettingsContext"; -import { UserContextProvider } from "../contexts/UserContext"; -import { AidContextProvider } from "../contexts/AidContext"; +import { History } from '../utils/History'; +import { PrivateRoute } from '../routes/PrivateRoutes'; +import { AppContextProvider } from '../contexts/AppSettingsContext'; +import { UserContextProvider } from '../contexts/UserContext'; +import { AidContextProvider } from '../contexts/AidContext'; -import AgencyRegistration from "../modules/agency/register"; -import AuthWallet from "../modules/authentication/Wallet"; -import PassportControl from "../modules/passport"; +import AgencyRegistration from '../modules/agency/register'; +import AuthWallet from '../modules/authentication/Wallet'; +import PassportControl from '../modules/passport'; +import SignUp from '../modules/authentication/SignUp'; +import Approval from '../modules/authentication/Approval'; const App = () => { - return ( - - - - - - - - - - {indexRoutes.map((prop, key) => { - return ( - - ); - })} - - - - - - - ); + return ( + + + + + + + + + + + + {indexRoutes.map((prop, key) => { + return ; + })} + + + + + + + ); }; export default App; diff --git a/src/modules/authentication/Approval.js b/src/modules/authentication/Approval.js new file mode 100644 index 00000000..4991d3f0 --- /dev/null +++ b/src/modules/authentication/Approval.js @@ -0,0 +1,40 @@ +import React, { useState } from 'react'; + +import { Row, Col} from 'reactstrap'; +import Logo from '../../assets/images/rahat-logo-blue.png'; +import qs from 'query-string'; + + + +export default function SignUp(props) { + const search = qs.parse(props.location.search); + + const[wallet,setWallet]=useState(search.wallet_address) + return ( + <> + + +
+ rahat logo + +
+

+ Supporting vulnerable communities with a simple and efficient relief distribution platform. +

+
+
+ + +
+

Rahat Agency App

+

Account not Activated

+ {wallet &&

Wallet: {wallet}

} + +

Please contact hello@esatya.io to activate your account

+
+

Copyright © 2021 Rumsan Group of Companies | All Rights Reserved.

+ +
+ + ); +} diff --git a/src/modules/authentication/SignUp.js b/src/modules/authentication/SignUp.js new file mode 100644 index 00000000..e8a82c15 --- /dev/null +++ b/src/modules/authentication/SignUp.js @@ -0,0 +1,114 @@ +import React, { useState,useContext,useEffect } from 'react'; +import { Form, Row, Col, FormGroup, Label, Input, Button } from 'reactstrap'; +import Logo from '../../assets/images/rahat-logo-blue.png'; +import qs from 'query-string'; +// import { TOAST } from '../../constants'; +// import { useToasts } from 'react-toast-notifications'; +import { AppContext } from '../../contexts/AppSettingsContext'; +import { UserContext } from '../../contexts/UserContext'; + +import * as Service from '../../services/appSettings'; +import { useToasts } from 'react-toast-notifications'; +import { TOAST } from '../../constants'; +import { History } from '../../utils/History'; + + +export default function SignUp(props) { + const { addToast } = useToasts(); + const search = qs.parse(props.location.search); + const [formData, setFormData] = useState({ + name: '', + email: '', + phone: '', + wallet_address: search.wallet_address, + agency:'', + }); + const {appSettings,getAppSettings} = useContext(AppContext); + const {signUp} = useContext(UserContext); + const [loading, setLoading] = useState(false); + + const handleInputChange = e => { + setFormData({ ...formData, [e.target.name]: e.target.value }); + }; + + const handleFormSubmit = async e => { + e.preventDefault(); + try{ + console.log(appSettings); + setLoading(true) + const payload = { ...formData ,agency:appSettings.agency.id}; + const user = await signUp(payload); + if(user.sucess){ + setLoading(false); + } + addToast('Successfully Registered', TOAST.SUCCESS); + + History.push('/auth/login'); + } + catch(e){ + addToast(e.error, TOAST.ERROR); + setLoading(false) + } + + }; + const loadAppSettings = () => { + getAppSettings().then() + }; + + +useEffect(loadAppSettings,[]); + + return ( + <> + + +
+ rahat logo + +
+

+ Supporting vulnerable communities with a simple and efficient relief distribution platform. +

+
+
+ + +
+

Rahat Agency App

+

Create an account

+
+
+ + + + + + + + + + + + + + + + + {loading ? ( + + ) : ( + + )} +
+
+
+

Copyright © 2021 Rumsan Group of Companies | All Rights Reserved.

+ +
+ + ); +} diff --git a/src/modules/authentication/Wallet.js b/src/modules/authentication/Wallet.js index a500739f..d71081a7 100644 --- a/src/modules/authentication/Wallet.js +++ b/src/modules/authentication/Wallet.js @@ -8,6 +8,7 @@ import DataService from '../../services/db'; import './wallet.css'; import { useToasts } from 'react-toast-notifications'; import { TOAST } from '../../constants'; +import { Link } from 'react-router-dom'; const API_SERVER = process.env.REACT_APP_API_SERVER; const WSS_SERVER = API_SERVER.replace('http', 'ws'); @@ -76,7 +77,12 @@ const Wallet = () => { ws.current.onmessage = async e => { const data = JSON.parse(e.data); if (data.action === 'unauthorized') { - return addToast('User not authorized!', TOAST.ERROR); + addToast('User not authorized! please Signup', TOAST.WARNING); + window.location.replace(`/sign_up?wallet_address=${data.publicKey}`); + } + if (data.action === 'account-locked') { + addToast('User not activated! ', TOAST.WARNING); + window.location.replace(`/approval?wallet_address=${data.publicKey}`); } if (data.data && data.data.token) { const { id, token } = data.data; @@ -127,9 +133,12 @@ const Wallet = () => {
-

- Haven’t registered? Sign up now -

+ {/*

+ Haven’t registered?{' '} + + Sign up + +

*/}

Rahat Agency App

diff --git a/src/modules/authentication/wallet.css b/src/modules/authentication/wallet.css index 5bc6ddab..ce3d922f 100644 --- a/src/modules/authentication/wallet.css +++ b/src/modules/authentication/wallet.css @@ -45,6 +45,11 @@ color: #fff; font-size: 14px; } +.text-subheader { + color: #fff; + font-size: 16px; + text-align: left; +} .text-tutorial { color: #3f9eeb; font-size: 14px; diff --git a/src/modules/beneficary/add/add.js b/src/modules/beneficary/add/add.js index 1d565d6a..42c32f10 100644 --- a/src/modules/beneficary/add/add.js +++ b/src/modules/beneficary/add/add.js @@ -12,7 +12,7 @@ import { blobToBase64 } from '../../../utils'; const Add = () => { const { addToast } = useToasts(); - const { listAid, addBeneficiary } = useContext(BeneficiaryContext); + const { listProject, addBeneficiary } = useContext(BeneficiaryContext); const [formData, setFormData] = useState({ name: '', @@ -96,7 +96,7 @@ const Add = () => { const handleCancelClick = () => History.push('/beneficiaries'); const loadProjects = useCallback(async () => { - const projects = await listAid(); + const projects = await listProject(); if (projects && projects.data.length) { const select_options = projects.data.map(p => { return { @@ -106,7 +106,7 @@ const Add = () => { }); setProjectList(select_options); } - }, [listAid]); + }, [listProject]); useEffect(() => { loadProjects(); @@ -179,13 +179,13 @@ const Add = () => { - + - + diff --git a/src/modules/beneficary/detail/beneficiaryInfo.js b/src/modules/beneficary/detail/beneficiaryInfo.js index e921cd8e..99407cca 100644 --- a/src/modules/beneficary/detail/beneficiaryInfo.js +++ b/src/modules/beneficary/detail/beneficiaryInfo.js @@ -5,6 +5,7 @@ import '../../../assets/css/project.css'; import IdImgPlaceholder from '../../../assets/images/id-icon-1.png'; import { formatWord } from '../../../utils'; import { History } from '../../../utils/History'; +import moment from 'moment'; const IPFS_GATEWAY = process.env.REACT_APP_IPFS_GATEWAY; @@ -36,6 +37,10 @@ export default function BeneficiaryInfo({ basicInfo, extras }) {

{basicInfo.address || '-'}

Address
+
+

{extras && extras.education ? extras.education : '-'}

+
Education
+

{basicInfo.govt_id || '-'}

Government ID number
@@ -51,8 +56,12 @@ export default function BeneficiaryInfo({ basicInfo, extras }) {
-

{extras && extras.education ? extras.education : '-'}

-
Education
+

{basicInfo.phone || '-'}

+
Phone
+
+
+

{extras && extras.profession ? extras.profession : '-'}

+
Profession

{basicInfo.gender || '-'}

@@ -66,12 +75,9 @@ export default function BeneficiaryInfo({ basicInfo, extras }) {

{extras && extras.child ? extras.child : '-'}

Number of family member(Child)
+ -
-

{extras && extras.profession ? extras.profession : '-'}

-
Profession
-
certificate +
+

{ moment(extras.created_at).format('MMM Do YYYY, hh:mm A') || '-'}

+
Registration Date
+
diff --git a/src/modules/beneficary/detail/detail.js b/src/modules/beneficary/detail/detail.js index 52977051..46a771a6 100644 --- a/src/modules/beneficary/detail/detail.js +++ b/src/modules/beneficary/detail/detail.js @@ -78,6 +78,7 @@ const BenefDetails = ({ params }) => { setAssignTokenAmount(''); let newWindow = window.open('', 'Print QR', 'fullscreen=yes'), document = newWindow.document.open(); + console.log({newWindow}); document.write(html); document.close(); setTimeout(function () { diff --git a/src/modules/beneficary/edit/edit.js b/src/modules/beneficary/edit/edit.js index a57aff2f..a7957c44 100644 --- a/src/modules/beneficary/edit/edit.js +++ b/src/modules/beneficary/edit/edit.js @@ -14,7 +14,7 @@ const IPFS_GATEWAY = process.env.REACT_APP_IPFS_GATEWAY; const Edit = ({ beneficiaryId }) => { const { addToast } = useToasts(); - const { listAid, updateBeneficiary, getBeneficiaryDetails } = useContext(BeneficiaryContext); + const { listProject, updateBeneficiary, getBeneficiaryDetails } = useContext(BeneficiaryContext); const [formData, setFormData] = useState({ name: '', @@ -60,6 +60,7 @@ const Edit = ({ beneficiaryId }) => { }; const handleInputChange = e => { + console.log('event', e.target.name, e.target.value); setFormData({ ...formData, [e.target.name]: e.target.value }); }; @@ -125,19 +126,19 @@ const Edit = ({ beneficiaryId }) => { } setExtras(extras); if (extras.group) setSelectedGroup(extras.group); - delete d.extras; + // delete d.extras; setFormData({ name, phone, email, address, address_temporary, govt_id }); const { gender } = d; if (gender !== 'U') setSelectedGender(gender); - }, [beneficiaryId, getBeneficiaryDetails]); + }, [getBeneficiaryDetails, beneficiaryId]); const loadProjects = useCallback(async () => { - const projects = await listAid(); + const projects = await listProject(); if (projects && projects.data.length) { const select_options = createProjectSelectOptions(projects.data); setProjectList(select_options); } - }, [listAid]); + }, [listProject]); useEffect(() => { loadProjects(); diff --git a/src/modules/beneficary/list.js b/src/modules/beneficary/list.js index e1e31d6f..ec2f68ae 100644 --- a/src/modules/beneficary/list.js +++ b/src/modules/beneficary/list.js @@ -18,6 +18,8 @@ import { } from 'reactstrap'; import displayPic from '../../assets/images/users/user_avatar.svg'; import { History } from '../../utils/History'; +import moment from 'moment'; + const searchOptions = { PHONE: 'phone', NAME: 'name', PROJECT: 'project' }; @@ -30,7 +32,8 @@ const Beneficiary = () => { }); const [selectedProject, setSelectedProject] = useState(''); - const { listBeneficiary, list, pagination, listAid, projectList } = useContext(BeneficiaryContext); + + const { listBeneficiary, list, pagination, listProject, projectList } = useContext(BeneficiaryContext); const handleFilterChange = e => { let { value } = e.target; @@ -83,8 +86,9 @@ const Beneficiary = () => { }); }; + const fetchProjectList = () => { - listAid() + listProject() .then() .catch(() => { addToast('Something went wrong!', { @@ -179,7 +183,7 @@ const Beneficiary = () => { Name Phone Address - Govt. ID + Registration Date Action @@ -202,7 +206,7 @@ const Beneficiary = () => { {d.phone} {d.address} - {d.govt_id ? d.govt_id : '-'} + {moment(d.created_at).format('MMM Do YYYY, hh:mm A')} diff --git a/src/modules/dashboard/Dashboard.js b/src/modules/dashboard/Dashboard.js index ba388340..c0909da6 100644 --- a/src/modules/dashboard/Dashboard.js +++ b/src/modules/dashboard/Dashboard.js @@ -1,13 +1,12 @@ import React, { useContext, useState, useEffect } from 'react'; import { Row, Col } from 'reactstrap'; import { useToasts } from 'react-toast-notifications'; - import TokenByProject from './tokens_by_project'; import BeneficiaryByProject from './beneficiary_by_project'; import { StatsCard } from '../ui_components/cards'; import { TOAST } from '../../constants'; - import { UserContext } from '../../contexts/UserContext'; +import TransactionChart from '../ui_components/chart'; const Dashboard = () => { const { addToast } = useToasts(); @@ -127,6 +126,7 @@ const Dashboard = () => { /> + ); }; diff --git a/src/modules/global/LiteModal.js b/src/modules/global/LiteModal.js index e6f432e9..e5e5ab8c 100644 --- a/src/modules/global/LiteModal.js +++ b/src/modules/global/LiteModal.js @@ -1,28 +1,37 @@ -import React, { useState } from 'react'; -import { Form, Modal, ModalBody,ModalHeader } from 'reactstrap'; +import React from // ,{ useState } +'react'; +import { Form, Modal, ModalBody, ModalHeader } from 'reactstrap'; import PropTypes from 'prop-types'; -import useDigitInput from 'react-digit-input'; +// import useDigitInput from 'react-digit-input'; export default function CustomModal(props) { - const { children,toggle, title, loadingMessage, open, size, handleSubmit } = props; - const [value, onChange] = useState(''); - const digits = useDigitInput({ - acceptedCharacters: /^[0-9]$/, - length: 6, - value, - onChange - }); + const { + children, + // toggle, + title, + loadingMessage, + open, + size, + handleSubmit + } = props; + // const [value, onChange] = useState(''); + // const digits = useDigitInput({ + // acceptedCharacters: /^[0-9]$/, + // length: 6, + // value, + // onChange + // }); return ( <> - -
- {title || 'Modal Title'} - {children || 'No child elements supplied.'} -
- {loadingMessage ? loadingMessage : ''} -
-
-
+ +
+ {title || 'Modal Title'} + {children || 'No child elements supplied.'} +
+ {loadingMessage ? loadingMessage : ''} +
+
+
); } diff --git a/src/modules/global/PasscodeModal.js b/src/modules/global/PasscodeModal.js index 6dca1edc..e8d72406 100644 --- a/src/modules/global/PasscodeModal.js +++ b/src/modules/global/PasscodeModal.js @@ -32,7 +32,7 @@ export default function PasscodeModal(props) { changeIsverified(true); setLoadingMessage('Wallet verified!'); } else { - setLoadingMessage('Verifying wallet, please wallet...'); + setLoadingMessage('Verifying wallet, please wait...'); const w = await Wallet.loadWallet(input_value); setWalletPasscode(input_value); changeIsverified(true); @@ -68,7 +68,7 @@ export default function PasscodeModal(props) { {/* {children || 'No child elements supplied.'} */} {/* Close */}
-

+

{title || 'Verify Passcode'}   @@ -78,6 +78,10 @@ export default function PasscodeModal(props) {

+
+ Enter you passcode from RUMSAN WALLET to proceed transaction +
+
diff --git a/src/modules/mobilizer/add/add.js b/src/modules/mobilizer/add/add.js new file mode 100644 index 00000000..7b3c0018 --- /dev/null +++ b/src/modules/mobilizer/add/add.js @@ -0,0 +1,175 @@ +import React, { useState, useContext } from 'react'; +import { Card, CardBody, Row, Col, Form, FormGroup, Label, Input, Button } from 'reactstrap'; +import { useToasts } from 'react-toast-notifications'; +import { MobilizerContext } from '../../../contexts/MobilizerContext'; +import { History } from '../../../utils/History'; +import { TOAST } from '../../../constants'; +import WalletUnlock from '../../../modules/global/walletUnlock'; +import { blobToBase64 } from '../../../utils'; +import AvatarIcon from '../../../assets/images/download.png'; +import BreadCrumb from '../../ui_components/breadcrumb'; + +const Add = () => { + const { addToast } = useToasts(); + const { addMobilizer } = useContext(MobilizerContext); + const [passcodeModal, setPasscodeModal] = useState(false); + const [formData, setFormData] = useState({ + name: '', + phone: '', + email: '', + address: '', + organization: '', + wallet_address: '' + }); + const [loading, setLoading] = useState(false); + const [govtIdImg, setGovtIdImg] = useState(''); + const [profileUpload, setProfileUpload] = useState(''); + + const handleInputChange = e => { + setFormData({ ...formData, [e.target.name]: e.target.value }); + }; + + async function handleProfileUpload(e) { + const base64Url = await blobToBase64(e.target.files[0]); + setProfileUpload(base64Url); + } + + async function handleGovtIdImage(e) { + const base64Url = await blobToBase64(e.target.files[0]); + setGovtIdImg(base64Url); + } + const handleFormSubmit = e => { + e.preventDefault(); + const payload = { ...formData }; + if (profileUpload) payload.photo = profileUpload; + if (govtIdImg) payload.govt_id_image = govtIdImg; + setLoading(true); + addMobilizer(payload) + .then(() => { + setLoading(false); + addToast('Mobilizer added successfully', TOAST.SUCCESS); + History.push('/mobilizers'); + }) + .catch(err => { + setLoading(false); + addToast(err.message, TOAST.ERROR); + }); + }; + + const handleCancelClick = () => History.push('/users'); + + return ( +
+ setPasscodeModal(e)}> +

Mobilizers

+ + + + + +
+ + + + +
+ {profileUpload ? ( + Profile + ) : ( + Profile + )} + +
+ + + + + + + + + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
+ {govtIdImg ? ( + Profile + ) : ( + Profile + )} + +
+ + + {loading ? ( + + ) : ( +
+ + +
+ )} +
+
+
+
+ +
+
+ ); +}; + +export default Add; diff --git a/src/modules/mobilizer/add/index.js b/src/modules/mobilizer/add/index.js new file mode 100644 index 00000000..fa188267 --- /dev/null +++ b/src/modules/mobilizer/add/index.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { MobilizerContextProvider } from '../../../contexts/MobilizerContext'; +import AddMobilizer from './add'; + +const index = () => { + return ( + + + + ); +}; + +export default index; diff --git a/src/modules/mobilizer/detail/detail.js b/src/modules/mobilizer/detail/detail.js index cafc7810..4f7697d3 100644 --- a/src/modules/mobilizer/detail/detail.js +++ b/src/modules/mobilizer/detail/detail.js @@ -2,22 +2,37 @@ import React, { useContext, useEffect, useState } from 'react'; import { useToasts } from 'react-toast-notifications'; import Select from 'react-select'; import { Link } from 'react-router-dom'; - -import { Card, - CardBody, Row, Col, Input, ButtonGroup, Button, Table, CardSubtitle, CardTitle,Label,FormGroup, - InputGroup, +import Loading from '../../global/Loading'; +import ProjectInvovled from '../../ui_components/projects'; + +import { + Card, + CardBody, + Row, + Col, + // Input, + // ButtonGroup, + Button, + Table, + CardSubtitle, + CardTitle, + Label, + FormGroup, Modal, ModalBody, ModalHeader, - ModalFooter } from 'reactstrap'; -import Swal from 'sweetalert2'; + ModalFooter +} from 'reactstrap'; +// import Swal from 'sweetalert2'; import { MobilizerContext } from '../../../contexts/MobilizerContext'; import { AppContext } from '../../../contexts/AppSettingsContext'; import profilePhoto from '../../../assets/images/users/user_avatar.svg'; -import IdPhoto from '../../../assets/images/id-icon-1.png'; -import UnlockWallet from '../../global/walletUnlock'; -import Loading from '../../global/Loading'; +// import IdPhoto from '../../../assets/images/id-icon-1.png'; +// import UnlockWallet from '../../global/walletUnlock'; +import PasscodeModal from '../../global/PasscodeModal'; +import MobilizerInfo from './mobilizerInfo'; +import BreadCrumb from '../../ui_components/breadcrumb'; const EXPLORER_URL = process.env.REACT_APP_BLOCKCHAIN_EXPLORER; const IPFS_GATEWAY = process.env.REACT_APP_IPFS_GATEWAY; @@ -29,12 +44,12 @@ export default function DetailsForm(props) { mobilizer, getMobilizerDetails, approveMobilizer, - changeMobilizerStatus, + // changeMobilizerStatus, getMobilizerBalance, getMobilizerTransactions, transactionHistory, getAvailableBalance, - listAid, + listAid } = useContext(MobilizerContext); const { appSettings, isVerified, changeIsverified } = useContext(AppContext); const [mobilizerBalance, setMobilizerBalance] = useState(''); @@ -43,17 +58,25 @@ export default function DetailsForm(props) { const togglePasscodeModal = () => setPasscodeModal(!passcodeModal); const [modal, setModal] = useState(false); const [projectOptions, setProjectOptions] = useState([]); - const [inputTokens, setInputTokens] = useState(null); + // const [inputTokens, setInputTokens] = useState(null); const [selectedProject, setSelectedProject] = useState(''); const [availableBalance, setAvailableBalance] = useState(null); const [showAlert, setShowAlert] = useState(false); - + const [fetchingBalance, setFetchingBalance] = useState(false); + const [projectList, setProjectList] = useState([]); const loadMobilizerDetails = () => { getMobilizerDetails(mobilizerId) .then(d => { getMobilizerTransactions(mobilizerId); getBalance(d.wallet_address); + + if (d.projects && d.projects.length) { + const projects = d.projects.map(d => { + return { id: d._id, name: d.name }; + }); + setProjectList(projects); + } }) .catch(() => { addToast('Something went wrong on server!', { @@ -66,9 +89,12 @@ export default function DetailsForm(props) { const getBalance = async wallet => { if (appSettings && appSettings.agency) { try { + setFetchingBalance(true); + const { token } = appSettings.agency.contracts; let d = await getMobilizerBalance(token, wallet); setMobilizerBalance(d); + setFetchingBalance(false); } catch { addToast('Invalid Mobilizer wallet address!', { appearance: 'error', @@ -78,36 +104,35 @@ export default function DetailsForm(props) { } }; - const handleChangeStatus = async status => { - let swal = await Swal.fire({ - title: 'Are you sure?', - text: `Mobilizer will be marked as ${status}`, - icon: 'warning', - showCancelButton: true, - confirmButtonColor: '#3085d6', - cancelButtonColor: '#d33', - confirmButtonText: 'Yes' - }); - if (swal.isConfirmed) { - try { - await changeMobilizerStatus(mobilizerId, status); - addToast(`Mobilizer marked as ${status}`, { - appearance: 'success', - autoDismiss: true - }); - } catch (e) { - addToast('Something went wrong on server!', { - appearance: 'error', - autoDismiss: true - }); - } - } - }; - - const handleTokenChange = e => { - setInputTokens(e.target.value); - }; - + // const handleChangeStatus = async status => { + // let swal = await Swal.fire({ + // title: 'Are you sure?', + // text: `Mobilizer will be marked as ${status}`, + // icon: 'warning', + // showCancelButton: true, + // confirmButtonColor: '#3085d6', + // cancelButtonColor: '#d33', + // confirmButtonText: 'Yes' + // }); + // if (swal.isConfirmed) { + // try { + // await changeMobilizerStatus(mobilizerId, status); + // addToast(`Mobilizer marked as ${status}`, { + // appearance: 'success', + // autoDismiss: true + // }); + // } catch (e) { + // addToast('Something went wrong on server!', { + // appearance: 'error', + // autoDismiss: true + // }); + // } + // } + // }; + + // const handleTokenChange = e => { + // setInputTokens(e.target.value); + // }; const handleSelectProject = async e => { try { @@ -163,12 +188,11 @@ export default function DetailsForm(props) { }; const resetTokenIssueForm = () => { - setInputTokens(null); + // setInputTokens(null); setAvailableBalance(''); setShowAlert(false); }; - const handleMobilizerApprove = async e => { e.preventDefault(); // let swal = await Swal.fire({ @@ -180,12 +204,11 @@ export default function DetailsForm(props) { // cancelButtonColor: '#d33', // confirmButtonText: 'Yes' // }); - // if (swal.isConfirmed) + // if (swal.isConfirmed) toggleModal(); togglePasscodeModal(); }; - const fetchProjectList = () => { listAid() .then(d => { @@ -223,10 +246,12 @@ export default function DetailsForm(props) { return ( <> - setPasscodeModal(e)}> - + +

Mobilizers

+ + {/* setPasscodeModal(e)}> */} Issue Token @@ -241,7 +266,6 @@ export default function DetailsForm(props) { placeholder="--Select Project--" />
- {showAlert && availableBalance > 0 ? ( @@ -262,24 +286,99 @@ export default function DetailsForm(props) { - - - <> - - - - - + <> + + +
- - + + +
+ + Mobilizer Detail + + + + +
+ user +
+

{mobilizer ? mobilizer.name : ''}

+
Name
+
+
+ + + {loading ? ( + + ) : mobilizer_status === 'active' ? ( + + ) : ( + + )} + +
+
+
+ + + +
+ Token + + + {fetchingBalance ? :

{mobilizerBalance || 0}

} + +
Total Balance
+ + +

0

+
Total Redeemed
+ +
+
+
+ +
+ + + + {/* @@ -428,7 +527,7 @@ export default function DetailsForm(props) { - + */} diff --git a/src/modules/mobilizer/detail/mobilizerInfo.js b/src/modules/mobilizer/detail/mobilizerInfo.js new file mode 100644 index 00000000..b8100604 --- /dev/null +++ b/src/modules/mobilizer/detail/mobilizerInfo.js @@ -0,0 +1,83 @@ +import React from 'react'; +import { Card, CardTitle, Col, Row } from 'reactstrap'; +import '../../../assets/css/project.css'; +import image from '../../../assets/images/id-icon-1.png'; +import { History } from '../../../utils/History'; +import moment from 'moment' +const IPFS_GATEWAY = process.env.REACT_APP_IPFS_GATEWAY; + +export default function MobilizerInfo(props) { + const { information } = props; + const { id } = props.information; + const handleEditClick = () => History.push(`/edit-mobilizer/${id}`); + return ( +
+ +
+
+ + More Information + +
+ +
+
+ + +
+

{information.email || '-'}

+
Email
+
+
+

{information.bank_name || '-'}

+
Government ID
+
+
+

{information.wallet_address || '-'}

+
Wallet address
+
+ + +
+

{information.phone || '-'}

+
Phone number
+
+
+

{information.address || '-'}

+
Address
+
+
+

{information.organization || '-'}

+
Organization
+
+ + + goverment_id +
+

{ moment(information.created_at).format('MMM Do YYYY, hh:mm A') || '-'}

+
Registration Date
+
+ +
+
+
+
+ ); +} diff --git a/src/modules/mobilizer/edit/edit.js b/src/modules/mobilizer/edit/edit.js new file mode 100644 index 00000000..69ef6425 --- /dev/null +++ b/src/modules/mobilizer/edit/edit.js @@ -0,0 +1,221 @@ +import React, { useState, useEffect, useContext, useCallback } from 'react'; +import { Card, CardBody, Row, Col, Form, FormGroup, Label, Input, Button } from 'reactstrap'; +import { useToasts } from 'react-toast-notifications'; +import { MobilizerContext } from '../../../contexts/MobilizerContext'; +import { History } from '../../../utils/History'; +import { TOAST } from '../../../constants'; +import WalletUnlock from '../../../modules/global/walletUnlock'; +import AvatarIcon from '../../../assets/images/download.png'; +import { blobToBase64 } from '../../../utils'; +import BreadCrumb from '../../ui_components/breadcrumb'; + +const IPFS_GATEWAY = process.env.REACT_APP_IPFS_GATEWAY; + +const Edit = ({ mobilizerId }) => { + const { addToast } = useToasts(); + const { updateMobilizer, getMobilizerDetails } = useContext(MobilizerContext); + const [passcodeModal, setPasscodeModal] = useState(false); + const [loading, setLoading] = useState(false); + const [formData, setFormData] = useState({ + name: '', + phone: '', + email: '', + address: '', + wallet_address: '', + organization: '' + }); + + const [govtIdentity, setGovtIdentity] = useState(''); + const [profileUpload, setProfileUpload] = useState(''); + const [existingProfilePhoto, setExistingProfilePhoto] = useState(''); + const [existingIdentity, setExistingIdentity] = useState(''); + + const handleInputChange = e => { + setFormData({ ...formData, [e.target.name]: e.target.value }); + }; + const handleCancelClick = () => History.push('/mobilizers'); + + async function handleProfileUpload(e) { + const base64Url = await blobToBase64(e.target.files[0]); + setProfileUpload(base64Url); + } + + async function handleGovtIdentity(e) { + const base64Url = await blobToBase64(e.target.files[0]); + setGovtIdentity(base64Url); + } + + const handleFormSubmit = e => { + e.preventDefault(); + console.log('form data', formData); + const payload = { ...formData }; + if (profileUpload) payload.photo = profileUpload; + if (govtIdentity) payload.govt_id_image = govtIdentity; + + setLoading(true); + updateMobilizer(mobilizerId, payload) + .then(() => { + setLoading(false); + addToast('Mobilizer updated successfully', TOAST.SUCCESS); + History.push('/mobilizers'); + }) + .catch(err => { + setLoading(false); + addToast(err.message, TOAST.ERROR); + }); + }; + + const loadMobilizersDetails = useCallback(async () => { + const d = await getMobilizerDetails(mobilizerId); + const { name, phone, email, address, wallet_address, organization, photo, govt_id_image } = d; + + if (photo && photo.length) setExistingProfilePhoto(photo[0]); + if (govt_id_image) setExistingIdentity(govt_id_image); + setFormData({ + name, + phone, + email, + address, + wallet_address, + organization + }); + }, [getMobilizerDetails, mobilizerId]); + + useEffect(() => { + loadMobilizersDetails(); + }, [loadMobilizersDetails]); + + return ( +
+ setPasscodeModal(e)}> +

Mobilizers

+ + + + + + +
+ + + + +
+ {profileUpload ? ( + Profile + ) : existingProfilePhoto ? ( + Profile + ) : ( + Profile + )} + +
+ + + + + + + + + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ {govtIdentity ? ( + Profile + ) : existingIdentity ? ( + Profile + ) : ( + Profile + )} + +
+ + + {loading ? ( + + ) : ( +
+ + +
+ )} +
+
+
+
+ +
+
+ ); +}; + +export default Edit; diff --git a/src/modules/mobilizer/edit/index.js b/src/modules/mobilizer/edit/index.js new file mode 100644 index 00000000..01be37b5 --- /dev/null +++ b/src/modules/mobilizer/edit/index.js @@ -0,0 +1,14 @@ +import React from 'react'; +import { MobilizerContextProvider } from '../../../contexts/MobilizerContext'; +import EditVendor from './edit'; + +export default function Index({ match }) { + const { id } = match.params; + return ( + <> + + + + + ); +} diff --git a/src/modules/mobilizer/list.js b/src/modules/mobilizer/list.js index 4989cdcd..ba670d37 100644 --- a/src/modules/mobilizer/list.js +++ b/src/modules/mobilizer/list.js @@ -2,6 +2,9 @@ import React, { useState, useEffect, useContext } from 'react'; import { MobilizerContext } from '../../contexts/MobilizerContext'; import { useToasts } from 'react-toast-notifications'; import { Link } from 'react-router-dom'; +import { History } from '../../utils/History'; +import moment from 'moment'; + import { Card, @@ -40,9 +43,7 @@ const Mobilizer = () => { const toggle = () => setModel(!model); const fetchList = query => { - console.log('LSIISHD'); - let params = { ...pagination, ...query }; - console.log({ params }); + let params = { start:pagination.start,limit:pagination.limit, ...query }; listMobilizer(params) .then() .catch(() => { @@ -88,6 +89,8 @@ const Mobilizer = () => { return fetchList({ start: _start, limit: pagination.limit }); }; + const handleAddClick = () => History.push('/add-mobilizers'); + return (
@@ -108,7 +111,7 @@ const Mobilizer = () => { name="customSelect" defaultValue="" onChange={handleFilterChange} - style={{ width: 'auto' }} + style={{ width: 'auto', marginRight: '5px' }} > @@ -124,7 +127,7 @@ const Mobilizer = () => {
-
@@ -135,15 +138,18 @@ const Mobilizer = () => { + + {list.length ? ( list.map((e, i) => ( + - + diff --git a/src/modules/ui_components/chart/index.js b/src/modules/ui_components/chart/index.js new file mode 100644 index 00000000..0aa09f01 --- /dev/null +++ b/src/modules/ui_components/chart/index.js @@ -0,0 +1,95 @@ +import React from 'react'; +import { Card, CardTitle } from 'reactstrap'; +import '../../../assets/css/project.css'; +import Chart from 'react-apexcharts'; +// import Loading from '../../global/Loading'; + +//Line chart +const optionssalesummary = { + chart: { + id: 'basic-bar', + type: 'area', + toolbar: { + show: false + } + }, + + dataLabels: { + enabled: false + }, + stroke: { + curve: 'smooth', + width: 2 + }, + colors: ['#4fc3f7', '#7460ee'], + legend: { + show: false + }, + markers: { + size: 3 + }, + xaxis: { + categories: [1, 2, 3, 4, 5, 6, 7, 8, 9], + labels: { + show: true, + style: { + colors: ['#99abb4', '#99abb4', '#99abb4', '#99abb4', '#99abb4', '#99abb4', '#99abb4', '#99abb4'], + fontSize: '12px', + fontFamily: "'Nunito Sans', sans-serif" + } + } + }, + yaxis: { + labels: { + show: true, + style: { + colors: ['#99abb4', '#99abb4', '#99abb4', '#99abb4', '#99abb4', '#99abb4', '#99abb4', '#99abb4'], + fontSize: '12px', + fontFamily: "'Nunito Sans', sans-serif" + } + } + }, + grid: { + borderColor: 'rgba(0,0,0,0.1)', + xaxis: { + lines: { + show: true + } + }, + yaxis: { + lines: { + show: true + } + } + }, + tooltip: { + theme: 'dark' + } +}; +const seriessalessummry = [ + { + name: 'Site A view', + data: [0, 5, 6, 8, 25, 9, 8, 24] + }, + { + name: 'Site B view', + data: [0, 3, 1, 2, 8, 1, 5, 1] + } +]; + +export default function TransactionChart() { + return ( +
+ +
+ Transactions +
+
+ +
+
+
+
+
+ ); +} diff --git a/src/modules/user/edit/index.js b/src/modules/user/edit/index.js index c1c39fb7..2f988963 100644 --- a/src/modules/user/edit/index.js +++ b/src/modules/user/edit/index.js @@ -1,6 +1,6 @@ import React, { useCallback, useState, useContext, useEffect } from 'react'; import { useToasts } from 'react-toast-notifications'; -import { Card, CardBody, CardTitle, Row, Col, Form, FormGroup, Label, Input, Button } from 'reactstrap'; +import { Card, CardBody, CardTitle,CardSubtitle, Row, Col, Form, FormGroup, Label, Input, Button } from 'reactstrap'; import { TOAST, ROLES } from '../../../constants'; import { UserContext } from '../../../contexts/UserContext'; @@ -90,11 +90,11 @@ const UserDetails = props => { }; const sanitizeAndSetRoles = roles => { + if(!roles) return; let data = roles.map(d => { return { label: d, value: d }; }); - if (data.length > 1) data = data.filter(f => f.value === ROLES.ADMIN); - + //if (data.length > 1) data = data.filter(f => f.value === ROLES.ADMIN); setExsitingRoles(data); }; @@ -214,23 +214,29 @@ const UserDetails = props => { User Roles + {existingRoles.length > 0 ?( + existingRoles.map((roles)=>{ + return {roles.label} + }) + ):( + '' + )}
+ - {existingRoles.length > 0 ? ( + - ) : ( - '' - )} + diff --git a/src/modules/vendor/add/add.js b/src/modules/vendor/add/add.js index 94d0a0eb..c9bd942c 100644 --- a/src/modules/vendor/add/add.js +++ b/src/modules/vendor/add/add.js @@ -270,7 +270,7 @@ const Add = () => { - +
{extras.signature_photo ? ( { alt="user" className="rounded-circle" width="45" + height="45" />

{basicInfo.name}

diff --git a/src/modules/vendor/detail/vendorInfo.js b/src/modules/vendor/detail/vendorInfo.js index 11692034..a4deaaaa 100644 --- a/src/modules/vendor/detail/vendorInfo.js +++ b/src/modules/vendor/detail/vendorInfo.js @@ -3,13 +3,15 @@ import { Card, CardTitle, Col, Row } from 'reactstrap'; import '../../../assets/css/project.css'; import image from '../../../assets/images/id-icon-1.png'; import { History } from '../../../utils/History'; - +import moment from 'moment' const IPFS_GATEWAY = process.env.REACT_APP_IPFS_GATEWAY; export default function VendorInfo(props) { const { information } = props; const { id } = props.information; const handleEditClick = () => History.push(`/edit-vendor/${id}`); + + console.log(information.extra_files && information.extra_files.signature_photo); return (
@@ -52,6 +54,10 @@ export default function VendorInfo(props) {

{information.bank_account || '-'}

Bank account number
+
+

{ moment(information.created_at).format('MMM Do YYYY, hh:mm A') || '-'}

+
Registration Date
+
@@ -79,31 +85,35 @@ export default function VendorInfo(props) {
certificate +
certificate +
certificate { return select_options; }; - const loadBeneficiaryDetails = useCallback(async () => { + const loadVendorsDetails = useCallback(async () => { const d = await getVendorDetails(vendorId); const { projects, @@ -184,8 +184,8 @@ const Edit = ({ vendorId }) => { useEffect(() => { loadProjects(); - loadBeneficiaryDetails(); - }, [loadBeneficiaryDetails, loadProjects]); + loadVendorsDetails(); + }, [loadVendorsDetails, loadProjects]); return (
@@ -277,6 +277,7 @@ const Edit = ({ vendorId }) => { value={formData.wallet_address} name="wallet_address" onChange={handleInputChange} + disabled required /> diff --git a/src/modules/vendor/edit/index.js b/src/modules/vendor/edit/index.js index bcff9c77..282c14cc 100644 --- a/src/modules/vendor/edit/index.js +++ b/src/modules/vendor/edit/index.js @@ -1,5 +1,4 @@ import React from 'react'; - import { VendorContextProvider } from '../../../contexts/VendorContext'; import EditVendor from './edit'; diff --git a/src/modules/vendor/list.js b/src/modules/vendor/list.js index 259815f9..b807a2f6 100644 --- a/src/modules/vendor/list.js +++ b/src/modules/vendor/list.js @@ -3,6 +3,7 @@ import { VendorContext } from '../../contexts/VendorContext'; import { useToasts } from 'react-toast-notifications'; import { Link } from 'react-router-dom'; import { History } from '../../utils/History'; +import moment from 'moment'; import { Card, @@ -41,7 +42,7 @@ const Vendor = () => { const toggle = () => setModel(!model); const fetchList = query => { - let params = { ...pagination, ...query }; + let params = { start: pagination.start, limit: pagination.limit, ...query }; listVendor(params) .then() .catch(() => { @@ -71,6 +72,11 @@ const Vendor = () => { fetchList({ start: 0, limit: pagination.limit }); }; + const handleStatusChange = e => { + let { value } = e.target; + fetchList({ start: 0, limit: pagination.limit, status: value }); + }; + const handleSearchInputChange = e => { const { value } = e.target; if (filter.searchBy === searchOptions.PHONE) { @@ -94,21 +100,33 @@ const Vendor = () => { -
Vendors - + Vendors +
+ + + + + @@ -137,8 +155,10 @@ const Vendor = () => {
+ + @@ -158,11 +178,14 @@ const Vendor = () => { + + + diff --git a/src/routes/Authroutes.js b/src/routes/Authroutes.js index ee458f57..cd903b8c 100644 --- a/src/routes/Authroutes.js +++ b/src/routes/Authroutes.js @@ -1,11 +1,25 @@ -import { lazy } from "react"; -const WalletLogin = lazy(() => import("../modules/authentication/Wallet")); +import { lazy } from 'react'; +const WalletLogin = lazy(() => import('../modules/authentication/Wallet')); +const SignUp = lazy(() => import('../modules/authentication/SignUp')); +const Approval = lazy(() => import('../modules/authentication/Approval')); + + var AuthRoutes = [ - { - path: "/auth/wallet", - name: "Login", - icon: "mdi mdi-account-key", - component: WalletLogin, - }, + { + path: '/auth/wallet', + name: 'Login', + icon: 'mdi mdi-account-key', + component: WalletLogin + }, + { + path: '/sign_up', + name: 'SignUp', + component: SignUp + }, + { + path: '/approval', + name: 'Approval', + component: Approval + } ]; export default AuthRoutes; diff --git a/src/routes/Router.js b/src/routes/Router.js index dcc118cd..aabc81e6 100644 --- a/src/routes/Router.js +++ b/src/routes/Router.js @@ -22,6 +22,8 @@ const Onboard = lazy(() => import('../modules/onboard')); // Mobilizer const Mobilizer = lazy(() => import('../modules/mobilizer')); const MobilizerDetails = lazy(() => import('../modules/mobilizer/detail/index')); +const EditMobilizer = lazy(() => import('../modules/mobilizer/edit')); +const AddMobilizer = lazy(() => import('../modules/mobilizer/add')); // Project const AidList = lazy(() => import('../modules/aid/list')); @@ -175,7 +177,6 @@ let AppRoutes = [ component: Vendor, showInSidebar: true }, - { path: '/mobilizers', name: 'Mobilizers', @@ -183,6 +184,16 @@ let AppRoutes = [ component: Mobilizer, showInSidebar: true }, + { + path: '/add-mobilizers', + name: 'AddMobilizer', + component: AddMobilizer + }, + { + path: '/edit-mobilizer/:id', + name: 'Mobilizer', + component: EditMobilizer + }, { path: '/add_user', name: 'Users', diff --git a/src/services/beneficiary.js b/src/services/beneficiary.js index 0939344f..46c5a5a0 100644 --- a/src/services/beneficiary.js +++ b/src/services/beneficiary.js @@ -54,6 +54,7 @@ export async function listByAid(aid, params) { } export async function addBeneficiary(body) { + if (!body.wallet_address) body.wallet_address = body.phone; const res = await axios({ url: API.BENEFICARIES, method: 'post', diff --git a/src/services/mobilizer.js b/src/services/mobilizer.js index c742c935..c6bc75a1 100644 --- a/src/services/mobilizer.js +++ b/src/services/mobilizer.js @@ -1,146 +1,157 @@ -import axios from "axios"; +import axios from 'axios'; -import API from "../constants/api"; -import { getUserToken } from "../utils/sessionManager"; -import CONTRACT from "../constants/contracts"; -import { getContractByProvider } from "../blockchain/abi"; +import API from '../constants/api'; +import { getUserToken } from '../utils/sessionManager'; +import CONTRACT from '../constants/contracts'; +import { getContractByProvider } from '../blockchain/abi'; const access_token = getUserToken(); const faucet_auth_token = process.env.REACT_APP_BLOCKCHAIN_FAUCET_AUTH_TOKEN; -const mapTestContract = (contract) => ({ - addAdmin: contract.addAdmin, - balanceOf: contract.balanceOf, +const mapTestContract = contract => ({ + addAdmin: contract.addAdmin, + balanceOf: contract.balanceOf }); export async function getMobilizerBalance(contract_address, wallet_addr) { - const contract = await getContractByProvider(contract_address, CONTRACT.AIDTOKEN); - const myContract = mapTestContract(contract); - const data = await myContract.balanceOf(wallet_addr); - if (!data) return "Mobilizer not found!"; - return data.toNumber(); + const contract = await getContractByProvider(contract_address, CONTRACT.AIDTOKEN); + const myContract = mapTestContract(contract); + const data = await myContract.balanceOf(wallet_addr); + if (!data) return 'Mobilizer not found!'; + return data.toNumber(); } -export async function approveMobilizer(wallet, payload,contract_address) { - try{ - const contract = await getContractByProvider(contract_address, CONTRACT.RAHAT); - const signerContract = contract.connect(wallet); - const myContract = mapTestContract(signerContract); - const data = await myContract.addAdmin(payload.wallet_address); - if (!data) return "Mobilizer approve failed!"; - const res = await approveMobilizerToProject(payload.wallet_address, payload.projectId); - getEth({address:payload.wallet_address}); - return res; - } - catch(e){ - console.log(e); - throw Error(e); - } +export async function approveMobilizer(wallet, payload, contract_address) { + try { + const contract = await getContractByProvider(contract_address, CONTRACT.RAHAT); + const signerContract = contract.connect(wallet); + const myContract = mapTestContract(signerContract); + const tx = await myContract.addAdmin(payload.wallet_address); + let minedTx = await tx.wait(); + if (!minedTx) return 'Mobilizer approve failed!'; + const res = await approveMobilizerToProject(payload.wallet_address, payload.projectId); + getEth({ address: payload.wallet_address }); + return res; + } catch (e) { + console.log(e); + throw Error(e); + } } export async function changeMobilizerStaus(mobilizerId, status) { - return axios.patch( - `${API.MOBILIZERS}/${mobilizerId}/status/`, - { status: status }, - { - headers: { access_token: access_token }, - } - ); + return axios.patch( + `${API.MOBILIZERS}/${mobilizerId}/status/`, + { status: status }, + { + headers: { access_token: access_token } + } + ); } - -export async function approveMobilizerToProject(wallet_address,projectId){ - return axios.patch( - `${API.MOBILIZERS}/approve/`, - { wallet_address,projectId }, - { - headers: { access_token: access_token }, - } - ); +export async function approveMobilizerToProject(wallet_address, projectId) { + return axios.patch( + `${API.MOBILIZERS}/approve/`, + { wallet_address, projectId }, + { + headers: { access_token: access_token } + } + ); } export async function list(params) { - console.log("MOBILIXERS") - const res = await axios({ - url: API.MOBILIZERS, - method: "get", - headers: { - access_token, - }, - params, - }); - return res.data; + const res = await axios({ + url: API.MOBILIZERS, + method: 'get', + headers: { + access_token + }, + params + }); + return res.data; } export async function get(id) { - const res = await axios({ - url: API.MOBILIZERS + "/" + id, - method: "get", - headers: { - access_token, - }, - }); - return res.data; + const res = await axios({ + url: API.MOBILIZERS + '/' + id, + method: 'get', + headers: { + access_token + } + }); + return res.data; } export async function mobilizerTransactions(mobilizerId) { - const res = await axios({ - url: `${API.MOBILIZERS}/${mobilizerId}/transactions`, - method: "get", - headers: { access_token }, - }); - return res.data; + const res = await axios({ + url: `${API.MOBILIZERS}/${mobilizerId}/transactions`, + method: 'get', + headers: { access_token } + }); + return res.data; } export async function listByAid(aid, params) { - const res = await axios({ - url: API.MOBILIZERS + `/aid/${aid}/mobilizer`, - method: "get", - headers: { - access_token, - }, - params, - }); - return res.data; + const res = await axios({ + url: API.MOBILIZERS + `/aid/${aid}/mobilizer`, + method: 'get', + headers: { + access_token + }, + params + }); + return res.data; } export function add(payload) { - return new Promise((resolve, reject) => { - axios - .post(`${API.MOBILIZERS}`, payload, { - headers: { access_token: access_token }, - }) - .then((res) => { - if (res.statusText === "OK") { - resolve(res.data); - } - reject(res.data); - }) - .catch((err) => { - reject(err); - }); - }); + return new Promise((resolve, reject) => { + axios + .post(`${API.MOBILIZERS}`, payload, { + headers: { access_token: access_token } + }) + .then(res => { + if (res.statusText === 'OK') { + resolve(res.data); + } + reject(res.data); + }) + .catch(err => { + reject(err); + }); + }); +} + +export async function updateMobilizer(id, body) { + const res = await axios({ + url: `${API.MOBILIZERS}/${id}`, + method: 'put', + headers: { + access_token + }, + data: body + }); + + return res.data; } export async function approve({ mobilizerId }) { - const res = await axios({ - url: API.MOBILIZERS + `/approve`, - method: "post", - headers: { - access_token, - }, - data: { mobilizerId }, - }); - - return res.data; + const res = await axios({ + url: API.MOBILIZERS + `/approve`, + method: 'post', + headers: { + access_token + }, + data: { mobilizerId } + }); + + return res.data; } export async function getEth({ address }) { - const res = await axios({ - url: API.FAUCET, - method: "post", - data: { address,token:faucet_auth_token }, - }); + const res = await axios({ + url: API.FAUCET, + method: 'post', + data: { address, token: faucet_auth_token } + }); - return res.data; + return res.data; } diff --git a/src/services/users.js b/src/services/users.js index d1876fd5..96c7cdce 100644 --- a/src/services/users.js +++ b/src/services/users.js @@ -42,6 +42,25 @@ export function verifyToken(token) { }); } +export function signUp(payload) { + return new Promise((resolve, reject) => { + axios + .post(`${API.USERS}/register`,payload) + .then(res => { + if (res) { + resolve({ sucess: true, status: 200 }); + } + resolve({ + success: false, + status: 500 + }); + }) + .catch(err => { + reject(err.response.data); + }); + }); +} + export function loginUsingMetamask(payload) { return new Promise((resolve, reject) => { axios diff --git a/yarn.lock b/yarn.lock index 524b4a1c..8d8e4294 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3060,6 +3060,18 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" +apexcharts@^3.28.3: + version "3.28.3" + resolved "https://registry.yarnpkg.com/apexcharts/-/apexcharts-3.28.3.tgz#22a6d9b234c82f6c2e1dd4aebba05b7603e2b1d2" + integrity sha512-EhghB2P27/Gjhwct8sSS0V63mdpRMx/ikH34dwUTqZQnkAEyOS/RKDmYjXBNA7zsAKBE/pThOdoTya6ADyk6zQ== + dependencies: + svg.draggable.js "^2.2.2" + svg.easing.js "^2.0.0" + svg.filter.js "^2.0.2" + svg.pathmorphing.js "^0.1.3" + svg.resize.js "^1.4.3" + svg.select.js "^3.0.1" + aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -10471,7 +10483,7 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.4" -prop-types@*, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@*, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -10680,6 +10692,13 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +react-apexcharts@1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/react-apexcharts/-/react-apexcharts-1.3.7.tgz#42c8785e260535a4f8db1aadbe7b66552770944d" + integrity sha512-2OFhEHd70/WHN0kmrJtVx37UfaL71ZogVkwezmDqwQWgwhK6upuhlnEEX7tEq4xvjA+RFDn6hiUTNIuC/Q7Zqw== + dependencies: + prop-types "^15.5.7" + react-app-polyfill@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-1.0.6.tgz#890f8d7f2842ce6073f030b117de9130a5f385f0" @@ -10921,6 +10940,13 @@ react-table-v6@^6.8.6: dependencies: classnames "^2.2.5" +react-to-print@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/react-to-print/-/react-to-print-2.13.0.tgz#f2422a5665e08a9186eb9f7a2fad6ad1efd9f3a0" + integrity sha512-JMX+HrMtBXWDh2ohPT2IeBkaGY4QpFeloXTXBA7hBK7dXJQei/UXMvQqbZHb0rqJwzAHltZ2zXevuSK/ReKI5w== + dependencies: + prop-types "^15.7.2" + react-toast-notifications@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/react-toast-notifications/-/react-toast-notifications-2.4.0.tgz#6213730bd1fe158fc01aeef200687ea94c5c5b24" @@ -12351,6 +12377,61 @@ svg-parser@^2.0.0: resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== +svg.draggable.js@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz#c514a2f1405efb6f0263e7958f5b68fce50603ba" + integrity sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw== + dependencies: + svg.js "^2.0.1" + +svg.easing.js@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/svg.easing.js/-/svg.easing.js-2.0.0.tgz#8aa9946b0a8e27857a5c40a10eba4091e5691f12" + integrity sha1-iqmUawqOJ4V6XEChDrpAkeVpHxI= + dependencies: + svg.js ">=2.3.x" + +svg.filter.js@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/svg.filter.js/-/svg.filter.js-2.0.2.tgz#91008e151389dd9230779fcbe6e2c9a362d1c203" + integrity sha1-kQCOFROJ3ZIwd5/L5uLJo2LRwgM= + dependencies: + svg.js "^2.2.5" + +svg.js@>=2.3.x, svg.js@^2.0.1, svg.js@^2.2.5, svg.js@^2.4.0, svg.js@^2.6.5: + version "2.7.1" + resolved "https://registry.yarnpkg.com/svg.js/-/svg.js-2.7.1.tgz#eb977ed4737001eab859949b4a398ee1bb79948d" + integrity sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA== + +svg.pathmorphing.js@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz#c25718a1cc7c36e852ecabc380e758ac09bb2b65" + integrity sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww== + dependencies: + svg.js "^2.4.0" + +svg.resize.js@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/svg.resize.js/-/svg.resize.js-1.4.3.tgz#885abd248e0cd205b36b973c4b578b9a36f23332" + integrity sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw== + dependencies: + svg.js "^2.6.5" + svg.select.js "^2.1.2" + +svg.select.js@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/svg.select.js/-/svg.select.js-2.1.2.tgz#e41ce13b1acff43a7441f9f8be87a2319c87be73" + integrity sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ== + dependencies: + svg.js "^2.2.5" + +svg.select.js@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/svg.select.js/-/svg.select.js-3.0.1.tgz#a4198e359f3825739226415f82176a90ea5cc917" + integrity sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw== + dependencies: + svg.js "^2.6.5" + svgo@^1.0.0, svgo@^1.2.2: version "1.3.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167"
S.N. Name Phone AddressRegistration Date Action
{(pagination.currentPage - 1) * pagination.limit + i + 1} @@ -159,9 +165,10 @@ const Mobilizer = () => { {e.phone} {e.address} - - Details + {moment(e.created_at).format('MMM Do YYYY, hh:mm A')} + +
S.N. NameStatus Phone AddressRegistration Date Action
{e.agencies[0].status} {e.phone}{e.address}{moment(e.created_at).format('MMM Do YYYY, hh:mm A')} - +