When I am editing the campaign and switching the Welcome Message Type
from Text to Audio it throws this error – Warning: A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
Audio component is a file component –
index.js
import {
Button,
Card,
CardBody,
CardHeader,
Col,
Container,
Row,
} from "reactstrap";
import BreadCrumb from "../../Components/Common/BreadCrumb";
import { Link } from "react-router-dom";
import AddCampaignModal from "./AddCampaignModal";
import { useFormik } from "formik";
import * as Yup from "yup";
import CampaignRemoveModal from "./CampaignRemoveModal";
import {
getCampaigns,
createCampaign,
updateCampaign,
removeCampaign,
} from "../../slices/Campaigns/thunk";
import { useDispatch } from "react-redux";
import { useSelector } from "react-redux";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { getGateway } from "../../slices/Gateway/thunk";
import Loader from "../../Components/Common/Loader";
const Campaigns = () => {
const [modal_list, setmodal_list] = useState(false);
const [modal_delete, setmodal_delete] = useState(false);
const [loading, setLoading] = useState(false);
const [isEditingCampaign, setIsEditingCampaign] = useState(false);
const [listCampaignId, setListCampaignId] = useState(null);
const [welcomeMessageAudio, setWelcomeMessageAudio] = useState("");
const [invalidMessageAudio, setInvalidMessageAudio] = useState(null);
const [timeOutMessageAudio, setTimeOutMessageAudio] = useState(null);
const [selectSingleWelcomeTextOrAudio, setSelectSingleWelcomeTextOrAudio] =
useState(null);
const [selectSingleInvalidTextOrAudio, setSelectSingleInvalidTextOrAudio] =
useState(null);
const [selectSingleTimeOutTextOrAudio, setSelectSingleTimeOutTextOrAudio] =
useState(null);
const [selectedSingleGateway, setSelectedSingleGateway] = useState(null);
const dispatch = useDispatch();
const { campaigns, alreadyRegisteredError } = useSelector(
(state) => state.Campaigns
);
const { gateways } = useSelector((state) => state.Gateways);
function tog_list() {
setmodal_list(!modal_list);
}
function tog_delete() {
setmodal_delete(!modal_delete);
}
useEffect(() => {
if (alreadyRegisteredError) {
setmodal_list(!modal_list);
}
}, [alreadyRegisteredError]);
useEffect(() => {
setLoading(true);
dispatch(getCampaigns()).finally(() => {
setLoading(false);
});
dispatch(getGateway());
}, [dispatch]);
const welcomeMessageTextOrAudioOptions = [
{ label: "Text", value: "Text" },
{ label: "Audio", value: "Audio" },
];
function handleSelectSingleWelcomeMessageTextOrAudio(welcomeMessageType) {
setSelectSingleWelcomeTextOrAudio(welcomeMessageType);
// if (welcomeMessageType?.value === "Audio") {
// validation.setFieldValue("welcomeMessageText", "");
// }
}
const invalidMessageTextOrAudioOptions = [
{ label: "Text", value: "Text" },
{ label: "Audio", value: "Audio" },
];
function handleSelectSingleInvalidMessageTextOrAudio(invalidMessageType) {
setSelectSingleInvalidTextOrAudio(invalidMessageType);
}
const timeOutMessageTextOrAudioOptions = [
{ label: "Text", value: "Text" },
{ label: "Audio", value: "Audio" },
];
function handleSelectSingleTimeOutMessageTextOrAudio(timeOutMessageType) {
setSelectSingleTimeOutTextOrAudio(timeOutMessageType);
}
const gatewayOptions = gateways?.map((gateway) => {
return {
id: gateway.id,
value: gateway.gatewayIpAddress,
label: gateway.gatewayIpAddress,
};
});
function handleSelectSingleGateway(gateway) {
setSelectedSingleGateway(gateway);
}
const validation = useFormik({
initialValues: {
campaignName: "",
gatewayId: "",
welcomeMessageText: "",
InvalidMessageText: "",
timeOutMessageText: "",
},
validationSchema: Yup.object({
campaignName: Yup.string().required("Please enter campaign name"),
gatewayId: Yup.string().required("Gateway is required"),
welcomeMessageText: Yup.string(),
invalidMessageText: Yup.string(),
timeOutMessageText: Yup.string(),
}),
onSubmit: (values, { resetForm }) => {
if (isEditingCampaign) {
dispatch(
updateCampaign({
...values,
campaignId: listCampaignId,
welcomeMessageAudio,
invalidMessageAudio,
timeOutMessageAudio,
gatewayId: selectedSingleGateway.id,
})
);
} else {
dispatch(
createCampaign({
...values,
welcomeMessageAudio,
invalidMessageAudio,
timeOutMessageAudio,
gatewayId: selectedSingleGateway.id,
})
);
}
// if (!isEditingCampaign) {
// resetForm();
// }
resetForm();
setSelectedSingleGateway(null);
setSelectSingleInvalidTextOrAudio(null);
setSelectSingleTimeOutTextOrAudio(null);
setSelectSingleWelcomeTextOrAudio(null);
setmodal_list(false);
},
});
console.log("VALIDATION VALUES ->", validation.values);
function formHandleSubmit(e) {
e.preventDefault();
validation.handleSubmit();
if (!validation.errors) {
setmodal_list(false);
}
return false;
}
function handleEditCampaign(campaignData) {
setIsEditingCampaign(true);
setmodal_list(!modal_list);
setListCampaignId(campaignData.id);
const selectedGateway = gatewayOptions?.find(
(gateway) => (gateway.id = campaignData.gatewayId)
);
if (campaignData.welcomeMessageText) {
const selectedOption = welcomeMessageTextOrAudioOptions.find(
(option) => option.value === "Text"
);
setSelectSingleWelcomeTextOrAudio(selectedOption);
} else {
validation.setFieldValue("welcomeMessageText", ""); // Ensure welcomeMessageText is cleared
}
if (campaignData.invalidMessageText) {
const selectedOption = invalidMessageTextOrAudioOptions.find(
(option) => option.value === "Text"
);
setSelectSingleInvalidTextOrAudio(selectedOption);
}
if (campaignData.timeOutMessageText) {
const selectedOption = timeOutMessageTextOrAudioOptions.find(
(option) => option.value === "Text"
);
setSelectSingleTimeOutTextOrAudio(selectedOption);
}
setSelectedSingleGateway(selectedGateway);
validation.setValues({
campaignName: campaignData.campaignName,
welcomeMessageText: campaignData.welcomeMessageText,
invalidMessageText: campaignData.invalidMessageText,
timeOutMessageText: campaignData.timeOutMessageText,
gatewayId: campaignData.gatewayId,
});
}
function tog_list() {
validation.resetForm();
setSelectedSingleGateway(null);
setSelectSingleInvalidTextOrAudio(null);
setSelectSingleTimeOutTextOrAudio(null);
setSelectSingleWelcomeTextOrAudio(null);
setmodal_list(!modal_list);
}
document.title = "Campaigns";
return (
<React.Fragment>
<div className="page-content">
<Container fluid>
<BreadCrumb title="Campaigns" pageTitle="Management" />
<Row>
<Col lg={12}>
<Card>
<CardHeader>
<h4 className="card-title mb-0">Create a Campaign</h4>
</CardHeader>
<CardBody>
<div className="listjs-table" id="userList">
<Row className="g-4 mb-3">
<Col className="col-sm-auto w-100 d-flex justify-content-between">
<Button
color="primary"
className="add-btn me-1"
onClick={tog_list}
id="create-btn"
>
<i className="ri-add-line align-bottom me-1"></i> Add
Campaign
</Button>
</Col>
</Row>
<div className="table-responsive table-card mt-3 mb-1">
<table
className="table align-middle table-nowrap"
id="userTable"
>
<thead className="table-light">
<tr>
<th>S.No</th>
<th>Campaign Name</th>
<th>Welcome Text</th>
<th>Invalid Text</th>
<th>TimeOut Text</th>
<th>Action</th>
</tr>
</thead>
<tbody className="list form-check-all">
{loading ? (
<tr>
<td
colSpan={7}
style={{
border: "none",
textAlign: "center",
verticalAlign: "middle",
}}
>
<Loader />
</td>
</tr>
) : (
<>
{campaigns?.map((campaign, idx) => (
<tr key={campaign.id}>
<td>{idx + 1}</td>
<td>{campaign.campaignName}</td>
<td>{campaign.welcomeMessageText}</td>
<td>{campaign.invalidMessageText}</td>
<td>{campaign.timeOutMessageText}</td>
<td>
<div className="d-flex gap-2">
<div className="edit">
<button
className="btn btn-sm btn-primary edit-item-btn"
data-bs-toggle="modal"
data-bs-target="#showModal"
onClick={() => {
handleEditCampaign(campaign);
}}
>
Edit
</button>
</div>
<div className="remove">
<button
className="btn btn-sm btn-danger edit-item-btn"
data-bs-toggle="modal"
data-bs-target="#showModal"
onClick={() => {
setListCampaignId(campaign.id);
tog_delete();
}}
>
Remove
</button>
</div>
</div>
</td>
</tr>
))}
</>
)}
</tbody>
</table>
</div>
<div className="d-flex justify-content-end">
<div className="pagination-wrap hstack gap-2">
<Link
className="page-item pagination-prev disabled"
to="#"
>
Previous
</Link>
<ul className="pagination listjs-pagination mb-0"></ul>
<Link className="page-item pagination-next" to="#">
Next
</Link>
</div>
</div>
</div>
</CardBody>
</Card>
</Col>
</Row>
</Container>
</div>
<ToastContainer />
<AddCampaignModal
validation={validation}
isEditingCampaign={isEditingCampaign}
modal_list={modal_list}
tog_list={tog_list}
formHandleSubmit={formHandleSubmit}
alreadyRegisteredError={alreadyRegisteredError}
welcomeMessageAudio={welcomeMessageAudio}
setWelcomeMessageAudio={setWelcomeMessageAudio}
invalidMessageAudio={invalidMessageAudio}
setInvalidMessageAudio={setInvalidMessageAudio}
timeOutMessageAudio={timeOutMessageAudio}
setTimeOutMessageAudio={setTimeOutMessageAudio}
welcomeMessageTextOrAudioOptions={welcomeMessageTextOrAudioOptions}
selectSingleWelcomeTextOrAudio={selectSingleWelcomeTextOrAudio}
handleSelectSingleWelcomeMessageTextOrAudio={
handleSelectSingleWelcomeMessageTextOrAudio
}
invalidMessageTextOrAudioOptions={invalidMessageTextOrAudioOptions}
selectSingleInvalidTextOrAudio={selectSingleInvalidTextOrAudio}
handleSelectSingleInvalidMessageTextOrAudio={
handleSelectSingleInvalidMessageTextOrAudio
}
selectSingleTimeOutTextOrAudio={selectSingleTimeOutTextOrAudio}
timeOutMessageTextOrAudioOptions={timeOutMessageTextOrAudioOptions}
handleSelectSingleTimeOutMessageTextOrAudio={
handleSelectSingleTimeOutMessageTextOrAudio
}
gatewayOptions={gatewayOptions}
handleSelectSingleGateway={handleSelectSingleGateway}
selectedSingleGateway={selectedSingleGateway}
/>
<CampaignRemoveModal
modal_delete={modal_delete}
setmodal_delete={setmodal_delete}
tog_delete={tog_delete}
handleDeleteCampaign={() => {
dispatch(removeCampaign(listCampaignId));
setmodal_delete(false);
}}
/>
</React.Fragment>
);
};
export default Campaigns;
AddCampaignModal.js
import {
Alert,
Input,
Label,
Form,
FormFeedback,
Modal,
ModalBody,
ModalHeader,
Row,
Col,
} from "reactstrap";
import "react-toastify/dist/ReactToastify.css";
import Select from "react-select";
function AddCampaignModal({
modal_list,
tog_list,
formHandleSubmit,
validation,
isEditingCampaign,
alreadyRegisteredError,
welcomeMessageAudio,
setWelcomeMessageAudio,
invalidMessageAudio,
setInvalidMessageAudio,
timeOutMessageAudio,
setTimeOutMessageAudio,
welcomeMessageTextOrAudioOptions,
selectSingleWelcomeTextOrAudio,
handleSelectSingleWelcomeMessageTextOrAudio,
invalidMessageTextOrAudioOptions,
selectSingleInvalidTextOrAudio,
handleSelectSingleInvalidMessageTextOrAudio,
selectSingleTimeOutTextOrAudio,
timeOutMessageTextOrAudioOptions,
handleSelectSingleTimeOutMessageTextOrAudio,
selectedSingleGateway,
handleSelectSingleGateway,
gatewayOptions,
}) {
return (
<Modal
isOpen={modal_list}
toggle={() => {
tog_list();
}}
centered
className="modal-lg"
>
<ModalHeader
className="bg-light p-3"
toggle={() => {
tog_list();
}}
>
{isEditingCampaign ? "Update Campaign" : "Add Campaign"}
</ModalHeader>
<Form className="tablelist-form" onSubmit={(e) => formHandleSubmit(e)}>
<ModalBody style={{ paddingTop: "0px" }}>
{alreadyRegisteredError && (
<Alert color="danger" style={{ marginBlock: "10px" }}>
{alreadyRegisteredError}
</Alert>
)}
<Row>
<Col md={6}>
<div className="mb-2">
<Label htmlFor="campaignName" className="form-label">
Campaign Name
</Label>
<Input
id="campaignName"
name="campaignName"
className="form-control"
placeholder="Enter Campaign Name"
type="text"
onChange={validation.handleChange}
onBlur={validation.handleBlur}
value={validation.values.campaignName || ""}
invalid={
validation.touched.campaignName &&
validation.errors.campaignName
? true
: false
}
/>
{validation.touched.campaignName &&
validation.errors.campaignName ? (
<FormFeedback type="invalid">
{validation.errors.campaignName}
</FormFeedback>
) : null}
</div>
</Col>
<Col md={6}>
<div className="mb-2">
<Label htmlFor="gatewayId" className="form-label">
Gateways
</Label>
<Select
id="gatewayId"
name="gatewayId"
value={selectedSingleGateway}
onChange={(gateway) => {
handleSelectSingleGateway(gateway);
validation.setFieldValue("gatewayId", gateway.id);
}}
gateway
options={gatewayOptions}
placeholder="Select Gateway"
styles={{
control: (provided, state) => ({
...provided,
borderColor: state.isFocused ? "#a8d9f3" : "#ced4da",
"&:hover": {
borderColor: "#ced4da",
},
}),
}}
/>
</div>
</Col>
<Col md={6}>
<div className="mb-2">
<Label
htmlFor="welcomeMessageTextOrAudioSelect"
className="form-label"
>
Welcome Message Type
</Label>
<Select
id="welcomeMessageTextOrAudioSelect"
name="welcomeMessageTextOrAudioSelect"
value={selectSingleWelcomeTextOrAudio}
onChange={(messageOrAudio) => {
handleSelectSingleWelcomeMessageTextOrAudio(messageOrAudio);
}}
options={welcomeMessageTextOrAudioOptions}
placeholder="Select Welcome Message Type"
styles={{
control: (provided, state) => ({
...provided,
borderColor: state.isFocused ? "#a8d9f3" : "#ced4da",
"&:hover": {
borderColor: "#ced4da",
},
}),
}}
/>
</div>
</Col>
{selectSingleWelcomeTextOrAudio?.value === "Text" ? (
<Col md={6}>
<div className="mb-2">
<Label htmlFor="welcomeMessageText" className="form-label">
Welcome Message Text
</Label>
<Input
id="welcomeMessageText"
name="welcomeMessageText"
className="form-control"
placeholder="Enter Welcome Text"
type="text"
onChange={validation.handleChange}
onBlur={validation.handleBlur}
value={validation.values.welcomeMessageText}
invalid={
validation.touched.welcomeMessageText &&
validation.errors.welcomeMessageText
? true
: false
}
/>
{validation.touched.welcomeMessageText &&
validation.errors.welcomeMessageText ? (
<FormFeedback type="invalid">
{validation.errors.welcomeMessageText}
</FormFeedback>
) : null}
</div>
</Col>
) : selectSingleWelcomeTextOrAudio?.value === "Audio" ? (
<Col lg={6}>
<div>
<Label htmlFor="formFile" className="form-label">
Welcome Message Audio
</Label>
<Input
id="welcomeMessageAudio"
name="welcomeMessageAudio"
className="form-control"
type="file"
onChange={(e) => setWelcomeMessageAudio(e.target.files[0])}
/>
</div>
</Col>
) : (
<Col lg={6}></Col>
)}
<Col md={6}>
<div className="mb-2">
<Label htmlFor="invalidMessageText" className="form-label">
Invalid Message Type
</Label>
<Select
id="invalidMessageTextOrAudioSelect"
name="invalidMessageTextOrAudioSelect"
value={selectSingleInvalidTextOrAudio}
onChange={(messageOrAudio) => {
handleSelectSingleInvalidMessageTextOrAudio(messageOrAudio);
}}
options={invalidMessageTextOrAudioOptions}
placeholder="Select Welcome Message Type"
styles={{
control: (provided, state) => ({
...provided,
borderColor: state.isFocused ? "#a8d9f3" : "#ced4da",
"&:hover": {
borderColor: "#ced4da",
},
}),
}}
/>
</div>
</Col>
{selectSingleInvalidTextOrAudio?.value === "Text" ? (
<Col md={6}>
<div className="mb-2">
<Label htmlFor="welcomeMessageText" className="form-label">
Invalid Message Text
</Label>
<Input
id="invalidMessageText"
name="invalidMessageText"
className="form-control"
placeholder="Enter Invalid Text"
type="text"
onChange={validation.handleChange}
onBlur={validation.handleBlur}
value={validation.values.invalidMessageText || ""}
invalid={
validation.touched.invalidMessageText &&
validation.errors.invalidMessageText
? true
: false
}
/>
{validation.touched.invalidMessageText &&
validation.errors.invalidMessageText ? (
<FormFeedback type="invalid">
{validation.errors.invalidMessageText}
</FormFeedback>
) : null}
</div>
</Col>
) : selectSingleInvalidTextOrAudio?.value === "Audio" ? (
<Col lg={6}>
<div>
<Label htmlFor="formFile" className="form-label">
Invalid Message Audio
</Label>
<Input
id="invalidMessageAudio"
name="invalidMessageAudio"
className="form-control"
type="file"
onChange={(e) => setInvalidMessageAudio(e.target.files[0])}
/>
</div>
</Col>
) : (
<Col lg={6}></Col>
)}
<Col md={6}>
<div className="mb-2">
<Label
htmlFor="timeOutMessageTextOrAudioSelect"
className="form-label"
>
TimeOut Message Type
</Label>
<Select
id="timeOutMessageTextOrAudioSelect"
name="timeOutMessageTextOrAudioSelect"
value={selectSingleTimeOutTextOrAudio}
onChange={(messageOrAudio) => {
handleSelectSingleTimeOutMessageTextOrAudio(messageOrAudio);
}}
options={timeOutMessageTextOrAudioOptions}
placeholder="Select Time Out Message Type"
styles={{
control: (provided, state) => ({
...provided,
borderColor: state.isFocused ? "#a8d9f3" : "#ced4da",
"&:hover": {
borderColor: "#ced4da",
},
}),
}}
/>
</div>
</Col>
{selectSingleTimeOutTextOrAudio?.value === "Text" ? (
<Col md={6}>
<div className="mb-2">
<Label htmlFor="timeOutMessageText" className="form-label">
TimeOut Message Text
</Label>
<Input
id="timeOutMessageText"
name="timeOutMessageText"
className="form-control"
placeholder="Enter TimeOut Text"
type="text"
onChange={validation.handleChange}
onBlur={validation.handleBlur}
value={validation.values.timeOutMessageText || ""}
invalid={
validation.touched.timeOutMessageText &&
validation.errors.timeOutMessageText
? true
: false
}
/>
</div>
</Col>
) : selectSingleTimeOutTextOrAudio?.value === "Audio" ? (
<Col lg={6}>
<div>
<Label htmlFor="formFile" className="form-label">
TimeOut Message Audio
</Label>
<Input
id="timeOutMessageAudio"
name="timeOutMessageAudio"
className="form-control"
type="file"
onChange={(e) => setTimeOutMessageAudio(e.target.files[0])}
/>
</div>
</Col>
) : (
<Col lg={6}></Col>
)}
</Row>
<div className="text-end">
<button type="submit" className="btn btn-primary">
{isEditingCampaign ? "Update Campaign" : "Save Campaign"}
</button>
</div>
</ModalBody>
</Form>
</Modal>
);
}
export default AddCampaignModal;