update api done
This commit is contained in:
parent
490314ef24
commit
61da636a2d
@ -40,6 +40,7 @@
|
||||
"classnames": "^2.5.1",
|
||||
"core-js": "^3.37.1",
|
||||
"date-fns": "^3.6.0",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
|
@ -2,15 +2,38 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import { useEffect } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { jwtDecode } from 'jwt-decode'
|
||||
|
||||
const isTokenExpired = (token) => {
|
||||
try {
|
||||
const decodedToken = jwtDecode(token)
|
||||
console.log('Decoded Token:', decodedToken) // Debugging
|
||||
const currentTime = Date.now() / 1000
|
||||
console.log('Current Time:', currentTime) // Debugging
|
||||
console.log('Token Expiration Time:', decodedToken.exp) // Debugging
|
||||
return decodedToken.exp < currentTime
|
||||
} catch (error) {
|
||||
console.error('Error decoding token:', error) // Debugging
|
||||
return true // If there's an error decoding the token, consider it expired
|
||||
}
|
||||
}
|
||||
|
||||
const ProtectedRoute = ({ element: Element }) => {
|
||||
const navigate = useNavigate()
|
||||
console.log('req came here ')
|
||||
|
||||
useEffect(() => {
|
||||
if (!localStorage.getItem('authToken')) {
|
||||
const checkToken = () => {
|
||||
const token = localStorage.getItem('authToken')
|
||||
console.log('Token:', token) // Debugging
|
||||
if (!token || isTokenExpired(token)) {
|
||||
console.log('Token is expired or not present, redirecting to login')
|
||||
navigate('/login')
|
||||
} else {
|
||||
console.log('Token is valid')
|
||||
}
|
||||
}
|
||||
|
||||
checkToken()
|
||||
}, [navigate])
|
||||
|
||||
return <Element />
|
||||
|
@ -14,7 +14,7 @@ const routes = [
|
||||
{ path: '/shop', name: 'Shop', element: Shop },
|
||||
{ path: '/order', name: 'Order', element: Order },
|
||||
// KYC
|
||||
{ path: '/kyc', name: 'Kyc', element: Kyc },
|
||||
{ path: '/kyc', name: 'KYC', element: Kyc },
|
||||
{ path: '/kyc/details/:id', name: 'Kyc details', element: KycDetails },
|
||||
|
||||
{ path: '/my-profile', name: 'Profile', element: MyProfile },
|
||||
|
29
src/views/pages/Kyc/MessageList.js
Normal file
29
src/views/pages/Kyc/MessageList.js
Normal file
@ -0,0 +1,29 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import React from 'react'
|
||||
|
||||
const MessageList = ({ messages }) => {
|
||||
return (
|
||||
<>
|
||||
{messages.map((msg, index) => (
|
||||
<div
|
||||
key={index}
|
||||
style={{
|
||||
marginBottom: '10px',
|
||||
padding: '10px',
|
||||
borderRadius: '5px',
|
||||
backgroundColor: msg.user === 'Principal Distributer' ? '#212631' : 'blue',
|
||||
boxShadow: '0px 3px 6px rgba(0,0,0,0.1)',
|
||||
}}
|
||||
>
|
||||
<div style={{ fontWeight: 'bold', marginBottom: '5px', color: 'white' }}>{msg.user}</div>
|
||||
<div style={{ fontWeight: 'bold', marginBottom: '5px', color: 'white' }}>
|
||||
{msg.replyDate}
|
||||
</div>
|
||||
<div style={{ color: 'white' }}>{msg.message}</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default MessageList
|
@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import {
|
||||
Box,
|
||||
Table,
|
||||
@ -10,34 +10,51 @@ import {
|
||||
Paper,
|
||||
TablePagination,
|
||||
Button,
|
||||
IconButton,
|
||||
Tooltip,
|
||||
Tabs,
|
||||
Tab,
|
||||
Modal,
|
||||
TextField,
|
||||
DialogActions,
|
||||
Typography,
|
||||
} from '@mui/material'
|
||||
import { Visibility, ThumbUp, ThumbDown } from '@mui/icons-material'
|
||||
import { format } from 'date-fns'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
const generateRandomData = (numRows) => {
|
||||
const statuses = ['New', 'Pending', 'Rejected', 'Approved']
|
||||
const data = []
|
||||
|
||||
for (let i = 0; i < numRows; i++) {
|
||||
data.push({
|
||||
id: i + 1,
|
||||
tradeName: `Trade ${i + 1}`,
|
||||
createdOn: new Date(),
|
||||
status: statuses[Math.floor(Math.random() * statuses.length)],
|
||||
})
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
import Axios from '../../../axios'
|
||||
import { isAutheticated } from '../../../auth'
|
||||
import Swal from 'sweetalert2'
|
||||
|
||||
const Kyc = () => {
|
||||
const [rows, setRows] = useState(generateRandomData(50))
|
||||
const [rows, setRows] = useState([])
|
||||
const [page, setPage] = useState(0)
|
||||
const [rowsPerPage, setRowsPerPage] = useState(5)
|
||||
const [rowsPerPage, setRowsPerPage] = useState(10)
|
||||
const [tabIndex, setTabIndex] = useState(0)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [openModal, setOpenModal] = useState(false)
|
||||
const [openModal2, setOpenModal2] = useState(false)
|
||||
const [rejectionReason, setRejectionReason] = useState('')
|
||||
const [selectedRowId, setSelectedRowId] = useState(null)
|
||||
const [selectedRowId2, setSelectedRowId2] = useState(null)
|
||||
const navigate = useNavigate()
|
||||
const token = isAutheticated()
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const response = await Axios.get('/api/kyc/getAll/', {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
console.log(response)
|
||||
setRows(response.data)
|
||||
} catch (error) {
|
||||
console.error('Error fetching data: ', error)
|
||||
}
|
||||
}
|
||||
|
||||
fetchData()
|
||||
}, [])
|
||||
|
||||
const handleChangePage = (event, newPage) => {
|
||||
setPage(newPage)
|
||||
@ -48,13 +65,124 @@ const Kyc = () => {
|
||||
setPage(0)
|
||||
}
|
||||
|
||||
// const handleViewClick = (id) => {
|
||||
// navigate(`/kyc/details/${id}`)
|
||||
// }
|
||||
const handleViewClick = (id) => {
|
||||
navigate(`/kyc/details/${id}`)
|
||||
}
|
||||
|
||||
const handleTabChange = (event, newValue) => {
|
||||
setTabIndex(newValue)
|
||||
}
|
||||
|
||||
const filterRowsByStatus = (status) => {
|
||||
return rows.filter((row) => row.status === status)
|
||||
}
|
||||
|
||||
const filteredRows = filterRowsByStatus(
|
||||
tabIndex === 0 ? 'new' : tabIndex === 1 ? 'approved' : 'reject',
|
||||
)
|
||||
|
||||
const handleRejectClick = async (id) => {
|
||||
setSelectedRowId(id)
|
||||
setOpenModal(true)
|
||||
}
|
||||
|
||||
const handleApproveClick = async (id) => {
|
||||
setSelectedRowId2(id)
|
||||
setOpenModal2(true)
|
||||
}
|
||||
|
||||
const handleApproveConfirm = async () => {
|
||||
try {
|
||||
setLoading(true)
|
||||
console.log(selectedRowId2)
|
||||
await Axios.patch(
|
||||
`/api/kyc/update/${selectedRowId2}`,
|
||||
{
|
||||
status: 'approved',
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
)
|
||||
setRows((prevRows) =>
|
||||
prevRows.map((row) => (row._id === selectedRowId2 ? { ...row, status: 'approved' } : row)),
|
||||
)
|
||||
setLoading(true)
|
||||
Swal.fire('Success', 'Approved', 'success')
|
||||
handleModalClose2()
|
||||
} catch (error) {
|
||||
setLoading(false)
|
||||
console.error('Error approving KYC: ', error)
|
||||
Swal.fire('Error!', error.message, 'error')
|
||||
handleModalClose2()
|
||||
}
|
||||
}
|
||||
|
||||
const handleModalClose = () => {
|
||||
setOpenModal(false)
|
||||
setRejectionReason('')
|
||||
}
|
||||
|
||||
const handleModalClose2 = () => {
|
||||
setOpenModal2(false)
|
||||
}
|
||||
|
||||
const handleRejectionReasonChange = (event) => {
|
||||
setRejectionReason(event.target.value)
|
||||
}
|
||||
|
||||
const handleRejectConfirm = async () => {
|
||||
try {
|
||||
setLoading(true)
|
||||
await Axios.patch(
|
||||
`/api/kyc/update/${selectedRowId}`,
|
||||
{
|
||||
status: 'reject',
|
||||
rejectionReason,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
)
|
||||
setRows((prevRows) =>
|
||||
prevRows.map((row) => (row._id === selectedRowId ? { ...row, status: 'reject' } : row)),
|
||||
)
|
||||
setLoading(true)
|
||||
Swal.fire('Success', 'Rejected', 'success')
|
||||
handleModalClose()
|
||||
} catch (error) {
|
||||
setLoading(false)
|
||||
console.error('Error rejecting KYC: ', error)
|
||||
Swal.fire('Error!', error.message, 'error')
|
||||
handleModalClose()
|
||||
}
|
||||
}
|
||||
|
||||
const formatAMPM = (date) => {
|
||||
var hours = new Date(date).getHours()
|
||||
var minutes = new Date(date).getMinutes()
|
||||
var ampm = hours >= 12 ? 'PM' : 'AM'
|
||||
hours = hours % 12
|
||||
hours = hours ? hours : 12 // the hour '0' should be '12'
|
||||
minutes = minutes < 10 ? '0' + minutes : minutes
|
||||
var strTime = hours + ':' + minutes + ' ' + ampm
|
||||
return strTime
|
||||
}
|
||||
|
||||
return (
|
||||
<Box sx={{ width: '100%' }}>
|
||||
<Paper sx={{ width: '100%', mb: 2 }}>
|
||||
<Tabs value={tabIndex} onChange={handleTabChange}>
|
||||
<Tab label="New" sx={{ textTransform: 'unset' }} />
|
||||
<Tab label="Approved" sx={{ textTransform: 'unset' }} />
|
||||
<Tab label="Rejected" sx={{ textTransform: 'unset' }} />
|
||||
</Tabs>
|
||||
<TableContainer>
|
||||
<Table>
|
||||
<TableHead>
|
||||
@ -67,42 +195,52 @@ const Kyc = () => {
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((row) => (
|
||||
<TableRow key={row.id}>
|
||||
<TableCell>{row.id}</TableCell>
|
||||
<TableCell>{row.tradeName}</TableCell>
|
||||
<TableCell>{format(row.createdOn, 'yyyy-MM-dd HH:mm:ss')}</TableCell>
|
||||
{filteredRows
|
||||
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
||||
.map((row) => (
|
||||
<TableRow key={row._id}>
|
||||
<TableCell>{row._id}</TableCell>
|
||||
<TableCell>{row.trade_name}</TableCell>
|
||||
<TableCell>
|
||||
{new Date(`${row?.createdAt}`).toDateString()}
|
||||
<span> , {`${formatAMPM(row?.createdAt)}`}</span>
|
||||
</TableCell>
|
||||
<TableCell>{row.status}</TableCell>
|
||||
<TableCell>
|
||||
<Tooltip title="View">
|
||||
{/* <IconButton color="primary">
|
||||
<Visibility />
|
||||
</IconButton> */}
|
||||
<Button
|
||||
sx={{ mr: '1rem' }}
|
||||
sx={{ mr: '1rem', textTransform: 'unset' }}
|
||||
color="primary"
|
||||
variant="contained"
|
||||
// onClick={() => handleViewClick(row.id)}
|
||||
onClick={() => handleViewClick(row._id)}
|
||||
>
|
||||
View
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{tabIndex === 0 && (
|
||||
<>
|
||||
<Tooltip title="Approve">
|
||||
{/* <IconButton color="success">
|
||||
<ThumbUp />
|
||||
</IconButton> */}
|
||||
<Button sx={{ mr: '1rem' }} color="success" variant="contained">
|
||||
<Button
|
||||
sx={{ mr: '1rem', textTransform: 'unset' }}
|
||||
color="success"
|
||||
variant="contained"
|
||||
onClick={() => handleApproveClick(row._id)}
|
||||
>
|
||||
Approve
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title="Reject">
|
||||
{/* <IconButton color="error">
|
||||
<ThumbDown />
|
||||
</IconButton> */}
|
||||
<Button sx={{ mr: '1rem' }} color="error" variant="contained">
|
||||
<Button
|
||||
sx={{ mr: '1rem', textTransform: 'unset' }}
|
||||
color="error"
|
||||
variant="contained"
|
||||
onClick={() => handleRejectClick(row._id)}
|
||||
>
|
||||
Reject
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
@ -110,17 +248,90 @@ const Kyc = () => {
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<TablePagination
|
||||
rowsPerPageOptions={[5, 10, 25]}
|
||||
rowsPerPageOptions={[10, 15, 25]}
|
||||
component="div"
|
||||
count={rows.length}
|
||||
count={filteredRows.length}
|
||||
rowsPerPage={rowsPerPage}
|
||||
page={page}
|
||||
onPageChange={handleChangePage}
|
||||
onRowsPerPageChange={handleChangeRowsPerPage}
|
||||
/>
|
||||
</Paper>
|
||||
<Modal
|
||||
open={openModal}
|
||||
onClose={handleModalClose}
|
||||
aria-labelledby="modal-modal-title"
|
||||
aria-describedby="modal-modal-description"
|
||||
>
|
||||
<Box sx={{ ...modalStyle, width: 400 }}>
|
||||
<h2 id="modal-modal-title">Rejection Reason</h2>
|
||||
<TextField
|
||||
fullWidth
|
||||
multiline
|
||||
rows={4}
|
||||
value={rejectionReason}
|
||||
onChange={handleRejectionReasonChange}
|
||||
variant="outlined"
|
||||
label="Enter rejection reason"
|
||||
/>
|
||||
<DialogActions>
|
||||
<Button onClick={handleModalClose} sx={{ textTransform: 'unset' }} color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleRejectConfirm}
|
||||
sx={{ textTransform: 'unset' }}
|
||||
color="error"
|
||||
variant="contained"
|
||||
>
|
||||
Confirm
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Box>
|
||||
</Modal>
|
||||
<Modal
|
||||
open={openModal2}
|
||||
onClose={handleModalClose2}
|
||||
aria-labelledby="modal-modal-title"
|
||||
aria-describedby="modal-modal-description"
|
||||
>
|
||||
<Box sx={{ ...modalStyle, width: 400 }}>
|
||||
<h2 id="modal-modal-title">Approval Confirmation</h2>
|
||||
<Typography id="modal-modal-description" sx={{ mt: 2 }}>
|
||||
Are you sure you want to approve this KYC?
|
||||
</Typography>
|
||||
<DialogActions>
|
||||
<Button
|
||||
onClick={handleModalClose2}
|
||||
sx={{ textTransform: 'unset' }}
|
||||
color="primary"
|
||||
// variant="contained"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleApproveConfirm}
|
||||
sx={{ textTransform: 'unset' }}
|
||||
color="success"
|
||||
variant="contained"
|
||||
>
|
||||
Confirm
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Box>
|
||||
</Modal>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
const modalStyle = {
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
bgcolor: 'background.paper',
|
||||
boxShadow: 24,
|
||||
p: 4,
|
||||
}
|
||||
|
||||
export default Kyc
|
||||
|
@ -1,51 +1,180 @@
|
||||
import React from 'react'
|
||||
import { Box, Typography, Grid, Paper, Avatar } from '@mui/material'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import axios from 'axios'
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
Grid,
|
||||
Paper,
|
||||
Avatar,
|
||||
Button,
|
||||
TextField,
|
||||
Modal,
|
||||
DialogActions,
|
||||
} from '@mui/material'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { format } from 'date-fns'
|
||||
|
||||
const generateRandomRetailerDetails = (id) => ({
|
||||
id,
|
||||
tradeName: `Trade ${id}`,
|
||||
name: `Retailer ${id}`,
|
||||
address: '123 Main St',
|
||||
townCity: 'Townsville',
|
||||
district: 'District A',
|
||||
state: 'State B',
|
||||
pincode: '123456',
|
||||
mobileNumber: '123-456-7890',
|
||||
mappedDistributor: `Distributor ${id}`,
|
||||
documents: {
|
||||
panNumber: 'ABCDE1234F',
|
||||
panCard:
|
||||
'https://www.shutterstock.com/shutterstock/photos/2329691987/display_1500/stock-vector-blank-pan-card-vector-image-income-tax-card-personal-account-number-image-translation-income-2329691987.jpg',
|
||||
aadharNumber: '1234-5678-9101',
|
||||
aadharCard: 'https://via.placeholder.com/100',
|
||||
gstNumber: '22AAAAA0000A1Z5',
|
||||
gstRegistration: 'https://via.placeholder.com/100',
|
||||
pesticideLicense: 'https://via.placeholder.com/100',
|
||||
fertilizerLicense: 'https://via.placeholder.com/100',
|
||||
entranceBoardSelfie: 'https://via.placeholder.com/100',
|
||||
},
|
||||
salesCoordinator: {
|
||||
designation: 'Sales Coordinator',
|
||||
name: `Coordinator ${id}`,
|
||||
employeeId: `EMP${id}`,
|
||||
uploadedOn: new Date(),
|
||||
resubmittedOn: new Date(),
|
||||
},
|
||||
notes: ['Note 1', 'Note 2', 'Note 3'],
|
||||
})
|
||||
import Axios from '../../../axios'
|
||||
import { isAutheticated } from '../../../auth'
|
||||
import MessageList from './MessageList'
|
||||
import Swal from 'sweetalert2'
|
||||
|
||||
const KycDetails = () => {
|
||||
const { id } = useParams()
|
||||
console.log(id)
|
||||
const retailerDetails = generateRandomRetailerDetails(id)
|
||||
const [openRejectModal, setOpenRejectModal] = useState(false)
|
||||
const [openApproveModal, setOpenApproveModal] = useState(false)
|
||||
const [rejectionReason, setRejectionReason] = useState('')
|
||||
const [selectedRowId, setSelectedRowId] = useState(null)
|
||||
const [retailerDetails, setRetailerDetails] = useState(null)
|
||||
const token = isAutheticated()
|
||||
|
||||
const navigate = useNavigate()
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const response = await Axios.get(`/api/kyc/get-single-kyc/${id}`, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'multipart/formdata',
|
||||
},
|
||||
})
|
||||
console.log(response.data)
|
||||
setRetailerDetails(response.data)
|
||||
} catch (error) {
|
||||
console.error('Error fetching data: ', error)
|
||||
}
|
||||
}
|
||||
|
||||
fetchData()
|
||||
}, [id])
|
||||
|
||||
const [msg, setMsg] = useState('')
|
||||
const handelSend = async () => {
|
||||
try {
|
||||
const resp = await Axios.patch(
|
||||
`/api/kyc/update/${id}`,
|
||||
{
|
||||
rejectionReason: msg,
|
||||
|
||||
user: 'Principal Distributer', // Replace with actual user type
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
)
|
||||
setRetailerDetails(resp.data.kyc)
|
||||
setMsg('')
|
||||
Swal.fire('Success', 'Message sent', 'success')
|
||||
} catch (error) {
|
||||
console.error('Error sending message: ', error)
|
||||
Swal.fire('Error!', error.message, 'error')
|
||||
}
|
||||
}
|
||||
|
||||
const handleModalClose = () => {
|
||||
setOpenRejectModal(false)
|
||||
setOpenApproveModal(false)
|
||||
setRejectionReason('')
|
||||
}
|
||||
|
||||
const handleRejectionReasonChange = (event) => {
|
||||
setRejectionReason(event.target.value)
|
||||
}
|
||||
|
||||
const handleRejectConfirm = async () => {
|
||||
try {
|
||||
const res = await Axios.patch(
|
||||
`/api/kyc/update/${id}`,
|
||||
{
|
||||
status: 'reject',
|
||||
rejectionReason,
|
||||
|
||||
user: 'Principal Distributer', // Replace with actual user type
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
)
|
||||
setRetailerDetails(res.data.kyc)
|
||||
Swal.fire('Success', 'Rejected', 'success')
|
||||
handleModalClose()
|
||||
} catch (error) {
|
||||
console.error('Error rejecting KYC: ', error)
|
||||
Swal.fire('Error!', error.message, 'error')
|
||||
handleModalClose()
|
||||
}
|
||||
}
|
||||
|
||||
const handleApproveConfirm = async () => {
|
||||
try {
|
||||
const res = await Axios.patch(
|
||||
`/api/kyc/update/${id}`,
|
||||
{
|
||||
status: 'approved',
|
||||
user: 'Principal Distributer', // Replace with actual user type
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
)
|
||||
setRetailerDetails(res.data.kyc)
|
||||
Swal.fire('Success', 'Approved', 'success')
|
||||
handleModalClose()
|
||||
} catch (error) {
|
||||
console.error('Error approving KYC: ', error)
|
||||
Swal.fire('Error!', error.message, 'error')
|
||||
handleModalClose()
|
||||
}
|
||||
}
|
||||
|
||||
const formatAMPM = (date) => {
|
||||
var hours = new Date(date).getHours()
|
||||
var minutes = new Date(date).getMinutes()
|
||||
var ampm = hours >= 12 ? 'PM' : 'AM'
|
||||
hours = hours % 12
|
||||
hours = hours ? hours : 12 // the hour '0' should be '12'
|
||||
minutes = minutes < 10 ? '0' + minutes : minutes
|
||||
var strTime = hours + ':' + minutes + ' ' + ampm
|
||||
return strTime
|
||||
}
|
||||
|
||||
const handleRejectClick = () => {
|
||||
setOpenRejectModal(true)
|
||||
}
|
||||
|
||||
const handleApproveClick = () => {
|
||||
setOpenApproveModal(true)
|
||||
}
|
||||
|
||||
if (!retailerDetails) {
|
||||
return <Typography>Loading...</Typography>
|
||||
}
|
||||
|
||||
return (
|
||||
<Box sx={{ p: 3 }}>
|
||||
<Typography variant="h4" gutterBottom>
|
||||
<Box sx={{ display: 'flex', mb: '1rem' }}>
|
||||
<Typography variant="h4" flex={1} gutterBottom>
|
||||
Retailer Details
|
||||
</Typography>
|
||||
<Button
|
||||
onClick={() => navigate('/kyc')}
|
||||
color="primary"
|
||||
sx={{ padding: '0.5rem 1rem' }}
|
||||
variant="contained"
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
<Paper sx={{ p: 2, mb: 3 }}>
|
||||
<Typography variant="h5" gutterBottom>
|
||||
@ -54,7 +183,7 @@ const KycDetails = () => {
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={6}>
|
||||
<Typography>
|
||||
<strong>Trade Name:</strong> {retailerDetails.tradeName}
|
||||
<strong>Trade Name:</strong> {retailerDetails.trade_name}
|
||||
</Typography>
|
||||
<Typography>
|
||||
<strong>Name:</strong> {retailerDetails.name}
|
||||
@ -63,7 +192,7 @@ const KycDetails = () => {
|
||||
<strong>Address:</strong> {retailerDetails.address}
|
||||
</Typography>
|
||||
<Typography>
|
||||
<strong>Town/City:</strong> {retailerDetails.townCity}
|
||||
<strong>Town/City:</strong> {retailerDetails.city}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
@ -77,10 +206,11 @@ const KycDetails = () => {
|
||||
<strong>Pincode:</strong> {retailerDetails.pincode}
|
||||
</Typography>
|
||||
<Typography>
|
||||
<strong>Mobile Number:</strong> {retailerDetails.mobileNumber}
|
||||
<strong>Mobile Number:</strong> {retailerDetails.mobile_number}
|
||||
</Typography>
|
||||
<Typography>
|
||||
<strong>Mapped Principal Distributor:</strong> {retailerDetails.mappedDistributor}
|
||||
<strong>Mapped Principal Distributor:</strong>{' '}
|
||||
{retailerDetails.principal_distributer.name}
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
@ -93,27 +223,27 @@ const KycDetails = () => {
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={6}>
|
||||
<Typography>
|
||||
<strong>PAN Number:</strong> {retailerDetails.documents.panNumber}
|
||||
<strong>PAN Number:</strong> {retailerDetails.pan_number}
|
||||
</Typography>
|
||||
<Avatar
|
||||
variant="square"
|
||||
src={retailerDetails.documents.panCard}
|
||||
src={retailerDetails.pan_img.url}
|
||||
sx={{ width: 100, height: 100, mb: 2 }}
|
||||
/>
|
||||
<Typography>
|
||||
<strong>Aadhar Number:</strong> {retailerDetails.documents.aadharNumber}
|
||||
<strong>Aadhar Number:</strong> {retailerDetails.aadhar_number}
|
||||
</Typography>
|
||||
<Avatar
|
||||
variant="square"
|
||||
src={retailerDetails.documents.aadharCard}
|
||||
src={retailerDetails.aadhar_img.url}
|
||||
sx={{ width: 100, height: 100, mb: 2 }}
|
||||
/>
|
||||
<Typography>
|
||||
<strong>GST Number:</strong> {retailerDetails.documents.gstNumber}
|
||||
<strong>GST Number:</strong> {retailerDetails.gst_number}
|
||||
</Typography>
|
||||
<Avatar
|
||||
variant="square"
|
||||
src={retailerDetails.documents.gstRegistration}
|
||||
src={retailerDetails.gst_img.url}
|
||||
sx={{ width: 100, height: 100, mb: 2 }}
|
||||
/>
|
||||
</Grid>
|
||||
@ -123,23 +253,27 @@ const KycDetails = () => {
|
||||
</Typography>
|
||||
<Avatar
|
||||
variant="square"
|
||||
src={retailerDetails.documents.pesticideLicense}
|
||||
src={retailerDetails.pesticide_license_img.url}
|
||||
sx={{ width: 100, height: 100, mb: 2 }}
|
||||
/>
|
||||
<Typography>
|
||||
<strong>Fertilizer License (optional):</strong>
|
||||
</Typography>
|
||||
{retailerDetails.fertilizer_license_img ? (
|
||||
<Avatar
|
||||
variant="square"
|
||||
src={retailerDetails.documents.fertilizerLicense}
|
||||
src={retailerDetails.fertilizer_license_img.url}
|
||||
sx={{ width: 100, height: 100, mb: 2 }}
|
||||
/>
|
||||
) : (
|
||||
<Typography>Img not available</Typography>
|
||||
)}
|
||||
<Typography>
|
||||
<strong>Selfie of Entrance Board:</strong>
|
||||
</Typography>
|
||||
<Avatar
|
||||
variant="square"
|
||||
src={retailerDetails.documents.entranceBoardSelfie}
|
||||
src={retailerDetails.selfie_entrance_img.url}
|
||||
sx={{ width: 100, height: 100, mb: 2 }}
|
||||
/>
|
||||
</Grid>
|
||||
@ -148,43 +282,158 @@ const KycDetails = () => {
|
||||
|
||||
<Paper sx={{ p: 2, mb: 3 }}>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
Block 3: Sales Coordinators/Territory Manager Details
|
||||
Sales Coordinators/Territory Manager Details
|
||||
</Typography>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={6}>
|
||||
<Typography>
|
||||
<strong>Designation:</strong> {retailerDetails.salesCoordinator.designation}
|
||||
<strong>Designation:</strong>{' '}
|
||||
{retailerDetails.userType === 'SalesCoOrdinator'
|
||||
? 'Sales Coordinator'
|
||||
: 'Territory Manager'}
|
||||
</Typography>
|
||||
<Typography>
|
||||
<strong>Name:</strong> {retailerDetails.salesCoordinator.name}
|
||||
<strong>Name:</strong> {retailerDetails.addedBy.name}
|
||||
</Typography>
|
||||
<Typography>
|
||||
<strong>Employee ID:</strong> {retailerDetails.salesCoordinator.employeeId}
|
||||
<strong>Employee ID:</strong> {retailerDetails.addedBy.uniqueId}
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography>
|
||||
<strong>Uploaded on:</strong>{' '}
|
||||
{format(retailerDetails.salesCoordinator.uploadedOn, 'yyyy-MM-dd HH:mm:ss')}
|
||||
{new Date(`${retailerDetails?.createdAt}`).toDateString()}
|
||||
<span> , {`${formatAMPM(retailerDetails?.createdAt)}`}</span>
|
||||
</Typography>
|
||||
<Typography>
|
||||
<strong>Resubmitted on:</strong>{' '}
|
||||
{format(retailerDetails.salesCoordinator.resubmittedOn, 'yyyy-MM-dd HH:mm:ss')}
|
||||
{new Date(`${retailerDetails?.createdAt}`).toDateString()}
|
||||
<span> , {`${formatAMPM(retailerDetails?.createdAt)}`}</span>
|
||||
</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Paper>
|
||||
|
||||
{retailerDetails.notes.length > 0 && retailerDetails.status === 'reject' && (
|
||||
<Paper sx={{ p: 2, mb: 3 }}>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
Block 4: Notes
|
||||
Notes:
|
||||
</Typography>
|
||||
{retailerDetails.notes.map((note, index) => (
|
||||
<Typography key={index}>{note}</Typography>
|
||||
))}
|
||||
|
||||
<MessageList messages={retailerDetails.notes} />
|
||||
|
||||
<TextField
|
||||
fullWidth
|
||||
multiline
|
||||
rows={4}
|
||||
value={msg}
|
||||
onChange={(e) => setMsg(e.target.value)}
|
||||
variant="outlined"
|
||||
label="send message"
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
sx={{ textTransform: 'unset', mt: '2rem' }}
|
||||
onClick={() => handelSend()}
|
||||
>
|
||||
Send
|
||||
</Button>
|
||||
</Paper>
|
||||
)}
|
||||
{retailerDetails.status === 'new' && (
|
||||
<>
|
||||
<Modal
|
||||
open={openRejectModal}
|
||||
onClose={handleModalClose}
|
||||
aria-labelledby="modal-modal-title"
|
||||
aria-describedby="modal-modal-description"
|
||||
>
|
||||
<Box sx={{ ...modalStyle, width: 400 }}>
|
||||
<h2 id="modal-modal-title">Rejection Reason</h2>
|
||||
<TextField
|
||||
fullWidth
|
||||
multiline
|
||||
rows={4}
|
||||
value={rejectionReason}
|
||||
onChange={handleRejectionReasonChange}
|
||||
variant="outlined"
|
||||
label="Enter rejection reason"
|
||||
/>
|
||||
<DialogActions>
|
||||
<Button onClick={handleModalClose} sx={{ textTransform: 'unset' }} color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleRejectConfirm}
|
||||
sx={{ textTransform: 'unset' }}
|
||||
color="error"
|
||||
variant="contained"
|
||||
>
|
||||
Confirm
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Box>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
open={openApproveModal}
|
||||
onClose={handleModalClose}
|
||||
aria-labelledby="modal-modal-title"
|
||||
aria-describedby="modal-modal-description"
|
||||
>
|
||||
<Box sx={{ ...modalStyle, width: 400 }}>
|
||||
<h2 id="modal-modal-title">Approval Confirmation</h2>
|
||||
<Typography id="modal-modal-description" sx={{ mt: 2 }}>
|
||||
Are you sure you want to approve this KYC?
|
||||
</Typography>
|
||||
<DialogActions>
|
||||
<Button onClick={handleModalClose} sx={{ textTransform: 'unset' }} color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleApproveConfirm}
|
||||
sx={{ textTransform: 'unset' }}
|
||||
color="success"
|
||||
variant="contained"
|
||||
>
|
||||
Confirm
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Box>
|
||||
</Modal>
|
||||
|
||||
<Paper sx={{ p: 2, mb: 3 }}>
|
||||
<Button
|
||||
sx={{ mr: '1rem', textTransform: 'unset' }}
|
||||
color="success"
|
||||
variant="contained"
|
||||
onClick={handleApproveClick}
|
||||
>
|
||||
Approve
|
||||
</Button>
|
||||
<Button
|
||||
sx={{ mr: '1rem', textTransform: 'unset' }}
|
||||
color="error"
|
||||
variant="contained"
|
||||
onClick={handleRejectClick}
|
||||
>
|
||||
Reject
|
||||
</Button>
|
||||
</Paper>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
const modalStyle = {
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
bgcolor: 'background.paper',
|
||||
boxShadow: 24,
|
||||
p: 4,
|
||||
}
|
||||
|
||||
export default KycDetails
|
||||
|
@ -95,27 +95,25 @@ const Login = () => {
|
||||
if (!(auth.email && auth.password)) {
|
||||
return Swal.fire('Error!', 'All fields are required', 'error')
|
||||
}
|
||||
setLoading({ loading: true })
|
||||
setLoading(true)
|
||||
try {
|
||||
const res = await Axios.post('/api/v1/user/login/', auth)
|
||||
console.log(res)
|
||||
if (res.data.success == true && res.data.user.role === 'principal-Distributor') {
|
||||
if (res.data.success === true && res.data.user.role === 'principal-Distributor') {
|
||||
localStorage.setItem('authToken', res.data.token)
|
||||
navigate('/dashboard')
|
||||
setLoading(false)
|
||||
Swal.fire('success', 'logged in successfuly ', 'success')
|
||||
|
||||
// console.log(response.data)
|
||||
} else if (res.data.success == true && res.data.user.role !== 'principal-Distributor') {
|
||||
Swal.fire('success', 'logged in successfully ', 'success')
|
||||
} else if (res.data.success === true && res.data.user.role !== 'principal-Distributor') {
|
||||
setLoading(false)
|
||||
Swal.fire('error', 'Please login through the PD Credentials ', 'error')
|
||||
}
|
||||
} catch (error) {
|
||||
setLoading(false)
|
||||
|
||||
Swal.fire('Error!', 'Invalid Credentials', 'error')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-body-tertiary min-vh-100 d-flex flex-row align-items-center">
|
||||
<CContainer>
|
||||
|
Loading…
Reference in New Issue
Block a user