351 lines
11 KiB
JavaScript
351 lines
11 KiB
JavaScript
import React, { useState, useEffect, useRef, useCallback } from "react";
|
|
import axios from "axios";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { isAutheticated } from "src/auth";
|
|
import Modal from "react-bootstrap/Modal";
|
|
import Button from "react-bootstrap/Button";
|
|
import Form from "react-bootstrap/Form";
|
|
import swal from "sweetalert";
|
|
import debounce from "lodash.debounce";
|
|
|
|
const AddSalesCoOrdinator = () => {
|
|
const navigate = useNavigate();
|
|
const token = isAutheticated();
|
|
|
|
const [formData, setFormData] = useState({
|
|
uniqueId: "",
|
|
name: "",
|
|
email: "",
|
|
countryCode: "+91",
|
|
mobileNumber: "",
|
|
otp: "",
|
|
territoryManager: "", // Add territoryManager field
|
|
});
|
|
|
|
const nameRef = useRef();
|
|
const dropdownRef = useRef(); // Reference for the dropdown
|
|
const [territoryManagers, setTerritoryManagers] = useState([]);
|
|
const [showModal, setShowModal] = useState(false);
|
|
const [showDropdown, setShowDropdown] = useState(false);
|
|
const [tmname, setTmname] = useState("");
|
|
const getTerritoryManagers = async (query = "") => {
|
|
try {
|
|
const res = await axios.get(`/api/territorymanager/getAll-dropdown/`, {
|
|
headers: {
|
|
Authorization: `Bearer ${token}`,
|
|
},
|
|
params: {
|
|
name: query,
|
|
},
|
|
});
|
|
setTerritoryManagers(res.data.territoryManager || []);
|
|
} catch (err) {
|
|
const msg = err?.response?.data?.message || "Something went wrong!";
|
|
swal({
|
|
title: "Error",
|
|
text: msg,
|
|
icon: "error",
|
|
button: "Retry",
|
|
dangerMode: true,
|
|
});
|
|
}
|
|
};
|
|
|
|
// Fetch Territory Managers when the component mounts
|
|
useEffect(() => {
|
|
getTerritoryManagers();
|
|
}, []);
|
|
|
|
const debouncedSearch = useCallback(
|
|
debounce(() => {
|
|
getTerritoryManagers(nameRef.current.value);
|
|
}, 500),
|
|
[]
|
|
);
|
|
|
|
const handleSearchChange = (e) => {
|
|
// const { value } = e.target;
|
|
// setFormData({ ...formData, territoryManager: value });
|
|
setShowDropdown(true);
|
|
setTmname(e.target.value);
|
|
debouncedSearch();
|
|
};
|
|
|
|
const handleDropdownSelect = (tm) => {
|
|
setFormData({ ...formData, territoryManager: tm._id });
|
|
setTmname(tm.name);
|
|
setShowDropdown(false);
|
|
};
|
|
|
|
const handleInputClick = () => {
|
|
setFormData({ ...formData, territoryManager: "" });
|
|
setShowDropdown(true);
|
|
getTerritoryManagers();
|
|
};
|
|
|
|
const handleChange = (e) => {
|
|
setFormData({ ...formData, [e.target.name]: e.target.value });
|
|
};
|
|
|
|
// Listen for clicks outside the dropdown and input field to hide the dropdown
|
|
useEffect(() => {
|
|
const handleClickOutside = (event) => {
|
|
if (
|
|
nameRef.current &&
|
|
dropdownRef.current &&
|
|
!nameRef.current.contains(event.target) &&
|
|
!dropdownRef.current.contains(event.target)
|
|
) {
|
|
setShowDropdown(false); // Hide the dropdown
|
|
}
|
|
};
|
|
|
|
document.addEventListener("mousedown", handleClickOutside);
|
|
|
|
return () => {
|
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
};
|
|
}, []);
|
|
|
|
const validateForm = () => {
|
|
const { uniqueId, name, email, mobileNumber, territoryManager } = formData;
|
|
if (!uniqueId || !name || !email || !mobileNumber || !territoryManager) {
|
|
swal({
|
|
title: "Warning",
|
|
text: "All fields are required!",
|
|
icon: "warning",
|
|
button: "OK",
|
|
});
|
|
return false;
|
|
}
|
|
if (!/^\d{10}$/.test(mobileNumber)) {
|
|
swal({
|
|
title: "Warning",
|
|
text: "Mobile number must be 10 digits!",
|
|
icon: "warning",
|
|
button: "OK",
|
|
});
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
const handleRegister = async (e) => {
|
|
e.preventDefault();
|
|
if (!validateForm()) return;
|
|
|
|
try {
|
|
await axios.post("/api/salescoordinator/register", formData, {
|
|
headers: {
|
|
Authorization: `Bearer ${token}`,
|
|
},
|
|
});
|
|
|
|
setShowModal(true); // Show OTP modal after registration
|
|
} catch (error) {
|
|
console.error(error);
|
|
let msg =
|
|
error?.response?.data?.message ||
|
|
"Failed to register Sales Coordinator. Please try again.";
|
|
swal({
|
|
title: "Warning",
|
|
text: msg,
|
|
icon: "error",
|
|
button: "Retry",
|
|
dangerMode: true,
|
|
});
|
|
}
|
|
};
|
|
|
|
const handleVerifyOTP = async () => {
|
|
try {
|
|
await axios.post("/api/salescoordinator/verify-otp", {
|
|
otp: formData.otp,
|
|
fullMobileNumber: `${formData.countryCode}${formData.mobileNumber}`,
|
|
});
|
|
|
|
setShowModal(false); // Close OTP modal after verification
|
|
swal({
|
|
title: "Success",
|
|
text: "OTP verified successfully!",
|
|
icon: "success",
|
|
button: "OK",
|
|
}).then(() => {
|
|
navigate("/salescoordinators"); // Navigate to success page or desired route
|
|
});
|
|
} catch (error) {
|
|
console.error(error);
|
|
let msg =
|
|
error?.response?.data?.message ||
|
|
"OTP verification failed. Please try again.";
|
|
swal({
|
|
title: "Warning",
|
|
text: msg,
|
|
icon: "error",
|
|
button: "Retry",
|
|
dangerMode: true,
|
|
});
|
|
}
|
|
};
|
|
|
|
const handleCancel = () => {
|
|
navigate("/salescoordinators");
|
|
};
|
|
|
|
return (
|
|
<div className="main-content">
|
|
<div className="my-3 page-content">
|
|
<div className="container-fluid">
|
|
<div className="row">
|
|
<div className="col-12">
|
|
<div className="page-title-box d-flex align-items-center justify-content-between">
|
|
<h4 className="mb-3">Add Sales Coordinator</h4>
|
|
<Button variant="danger" onClick={handleCancel}>
|
|
Cancel
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="row">
|
|
<div className="col-lg-12">
|
|
<div className="card">
|
|
<div className="card-body">
|
|
<form onSubmit={handleRegister}>
|
|
<div className="form-group position-relative">
|
|
<label>Add Territory Manager *</label>
|
|
<input
|
|
type="text"
|
|
className="form-control"
|
|
placeholder="Search and select Territory Manager"
|
|
ref={nameRef}
|
|
value={tmname}
|
|
onChange={handleSearchChange}
|
|
onClick={handleInputClick}
|
|
/>
|
|
{/* Dropdown */}
|
|
{showDropdown && territoryManagers.length > 0 && (
|
|
<ul
|
|
className="dropdown-menu show w-100"
|
|
ref={dropdownRef} // Reference for the dropdown
|
|
style={{
|
|
position: "absolute",
|
|
zIndex: 1000,
|
|
top: "100%",
|
|
left: 0,
|
|
}}
|
|
>
|
|
{territoryManagers.map((tm) => (
|
|
<li
|
|
key={tm._id}
|
|
className="dropdown-item"
|
|
onClick={() => handleDropdownSelect(tm)}
|
|
>
|
|
{tm.name}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
)}
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<label>Employee Code *</label>
|
|
<input
|
|
type="text"
|
|
name="uniqueId"
|
|
className="form-control"
|
|
value={formData.uniqueId}
|
|
onChange={handleChange}
|
|
required
|
|
/>
|
|
</div>
|
|
<div className="form-group">
|
|
<label>Name *</label>
|
|
<input
|
|
type="text"
|
|
name="name"
|
|
className="form-control"
|
|
value={formData.name}
|
|
onChange={handleChange}
|
|
required
|
|
/>
|
|
</div>
|
|
<div className="form-group">
|
|
<label>Email *</label>
|
|
<input
|
|
type="email"
|
|
name="email"
|
|
className="form-control"
|
|
value={formData.email}
|
|
onChange={handleChange}
|
|
required
|
|
/>
|
|
</div>
|
|
<div className="form-group d-flex">
|
|
<div className="mr-2" style={{ flex: 1 }}>
|
|
<label>Country Code *</label>
|
|
<input
|
|
type="text"
|
|
name="countryCode"
|
|
className="form-control"
|
|
value={formData.countryCode}
|
|
onChange={handleChange}
|
|
required
|
|
disabled
|
|
/>
|
|
</div>
|
|
<div style={{ flex: 3 }}>
|
|
<label>Mobile Number *</label>
|
|
<input
|
|
type="text"
|
|
name="mobileNumber"
|
|
className="form-control"
|
|
value={formData.mobileNumber}
|
|
onChange={handleChange}
|
|
required
|
|
/>
|
|
</div>
|
|
</div>
|
|
<button className="btn btn-primary mt-4" type="submit">
|
|
Register
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* OTP Modal */}
|
|
<Modal show={showModal} onHide={() => setShowModal(false)}>
|
|
<Modal.Header closeButton>
|
|
<Modal.Title>Verify OTP</Modal.Title>
|
|
</Modal.Header>
|
|
<Modal.Body>
|
|
<Form.Group controlId="otp">
|
|
<Form.Label>Enter OTP</Form.Label>
|
|
<Form.Control
|
|
type="text"
|
|
name="otp"
|
|
value={formData.otp}
|
|
onChange={handleChange}
|
|
placeholder="Enter OTP"
|
|
required
|
|
/>
|
|
</Form.Group>
|
|
</Modal.Body>
|
|
<Modal.Footer>
|
|
<Button variant="secondary" onClick={() => setShowModal(false)}>
|
|
Close
|
|
</Button>
|
|
<Button variant="primary" onClick={handleVerifyOTP}>
|
|
Verify OTP
|
|
</Button>
|
|
</Modal.Footer>
|
|
</Modal>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default AddSalesCoOrdinator;
|