Handling data for sending mass emails - email

I created a table to display data regarding customer orders that will likely need canceling.
If an order needs canceling, a checkbox will be checked, and the data in question will be handled via a handleCheck function that returns the rows of data in question, and a handleClick function sends the emails in question.
Currently, my handleClick function sends out the appropriate number of emails, but they're all duplicates. I am having trouble determining how to send an email for each unique row selected. Any advice would be greatly appreciated. Thanks!
Here is my handleCheck function, which gets called when a checkbox gets clicked:
const handleCheck = () => {
//R is set as row checked...
if (checked == true) {
setR(row);
setIdx(index);
console.log("row: ", r, idx);
}
//Mail is set to an array containing 'r'...
setMail([r]);
mail.push(r);
console.log("mail: ", mail);
};
This is how I define the state on r, mail, and idx:
const [r, setR]: any = useState();
const [mail, setMail]: any = useState([]);
const [idx, setIdx]: any = useState();
Here is my handleClick function, which gets called when a "send email" button gets clicked:
function EmailSnackbars() {
const [open, setOpen] = useState(false);
const handleClick = () => {
setOpen(true);
//idx is equal to index where checked == true.
//r is equal to row where checked == true.
//Currently sending correct number of emails, but these are duplicates...
for (let i = 0; i <= idx; i++) {
mail.filter((r: any) => [
r.ship_firstname,
r.ship_lastname,
r.product_id,
r.gtin,
r.description,
]);
sendMail(firstname, lastname, email, product_id, eta, gtin, description);
}
};
const handleClose = (
event?: React.SyntheticEvent | Event,
reason?: string
) => {
if (reason === "clickaway") {
return;
}
setOpen(false);
};
return (
<>
<Tooltip title="Send Email(s)">
<Button
variant="text"
size="large"
color="secondary"
onClick={handleClick}
>
<SendIcon />
</Button>
</Tooltip>
<Snackbar
open={open}
autoHideDuration={6000}
onClose={handleClose}
TransitionComponent={TransitionDown}
>
<Alert
onClose={handleClose}
severity="info"
sx={{ width: "100%" }}
elevation={11}
variant="filled"
color="info"
>
Email(s) Sent!
</Alert>
</Snackbar>
</>
);
}
Also, this is where my sendMail function is defined:
let [firstname, setFirstname]: any = useState();
let [lastname, setLastname]: any = useState();
let [email, setEmail]: any = useState();
let [eta, setEta]: any = useState();
let [gtin, setGtin]: any = useState();
let [description, setDescription]: any = useState();
let [product_id, setId]: any = useState();
//Function to send emails to customers on click of 'send email' button.
const sendMail = (
firstname: any,
lastname: any,
email: any,
eta: any,
gtin: any,
description: any,
product_id: any
) => {
const response: any = axios.post(`/api/email`, {
params: {
firstname: r.ship_firstname,
lastname: r.ship_lastname,
email: test_email,
product_id: r.product_id,
eta: r.eta,
gtin: r.gtin,
description: r.description,
},
});
};

Related

fireEvent.click with parameters

I have a radio button that when I click it calls a function with two parameters in the function (value and step), and when I make a test with testing librairy I would like that when I simulate the click of the button I return the two parameters.
Button
<Form.Check
inline
label={'form.email'}
name="media"
value={`LETTER`}
type="radio"
data-testid="EMAIL"
onClick={(e) => {
const target = e.target as HTMLTextAreaElement;
changeMedia(target.value, data);
}}
/>
Function ChangeMedia
const changeMedia = (value: any, step: any) => {
step.definition?.steps
.filter((obj: any) => obj.media.includes(value))
.map((item: any) => {
if (value === 'EMAIL') {
item.media = 'LETTER';
return item;
} else if (value === 'LETTER') {
item.media = 'EMAIL';
return item;
}
return item;
});
return data;
};
Objet Step
const step = {
definition: {
steps: [
{
document_model: 'template_circularization',
email_model: 'email_circularization',
label: {
EN: 'Circularization',
FR: 'Circularisation',
},
media: 'LETTER',
name: 'mail_circularization',
onDemandOnly: true,
},
],
},
};
Test
const radio = screen.getByTestId('EMAIL');
fireEvent.click(radio, { target: { value: 'EMAIL, step: step } });
when I do a console.log of value and step I get this :
value EMAIL
step {}
what would be the solution to retrieve the step object via firevent.click ?

Can't Upload Image with Axios Vue 3

I want to upload image by Vue 3 and Axios with state. But error is: array to string. I don't know what to do know. Please help me. Thank so much.
HTML:
<input
type='file'
class="hidden"
name="avatar"
id="avatar"
#change="updatePreview"
style="display: none;"
/>
Define State
const state = reactive({
user: {},
updateMovie: {
id: '',
name: '',
image: '',
}
Take file image:
function updatePreview(e) {
if (e.target.files.length === 0) {
return
}
console.log(e)
imageFile.value = e.target.files[0]
state.updateMovie.image = e.target.files[0]
}
const submitModal = (type) => {
if (type === 'edit') {
const form = {
image: state.updateMovie.image,
}
const id = state.updateMovie.id
console.log("form: ", form)
console.log(typeof form.image)
axios.post(`movie/update/${id}`, form)
.then((res) => {
if (res.status === 200) {
const data = res.data.data.movie
})
}
})
}
}
That's all. Now i don't know what to do to send data to axios.

disabled submit button after submitting form data to server. in react native

I am new to react native. I have created a form from where I am sending some data to server. Now I want that to disabled submit button after user click on submit . once user submit data then after He unable to send data. means I want to avoid duplicate entry. please help. thanks. if possible also tell how to do it with functional component too.
here is my code
export default function Add(props) {
const { navigation } = props
const offset = (Platform.OS === 'android') ? -200 : 0;
const [AmazonError, setAmazonError] = useState([]);
const [Amazon, setAmazon] = useState('');
const [AmazonCNError, setAmazonCNError] = useState([]);
const [AmazonCN, setAmazonCN] = useState('');
const [AEPSError, setAEPSError] = useState([]);
const [AEPS, setAEPS] = useState('');
const [DMTError, setDMTError] = useState([]);
const [DMT, setDMT] = useState('');
const [BBPSError, setBBPSError] = useState([]);
const [BBPS, setBBPS] = useState('');
const [leadTagNumber, setLeadTagNumber] = useState([]);
const validateInputs = () => {
if (!Amazon.trim()) {
setAmazonError('Please Fill The Input')
return;
}
if (!AmazonCN.trim()) {
setAmazonCNError('Please Fill The Input')
return;
}
if (!AEPS.trim()) {
setAEPSError('Please Fill The Input')
return;
}
if (!DMT.trim()) {
setDMTError('Please Fill The Input')
return;
}
if (!BBPS.trim()) {
setBBPSError('Please Fill The Input')
return;
}
else
{
//+++++++++++++++++++++++++++++++++=submitting form data to api start+++++++++++++++++++++++++++++++++++
{
const leadTagNumber = props.route.params.leadTagNumber
AsyncStorage.multiGet(["application_id", "created_by",'leadTagNumber']).then(response => {
// console.log(response[0][0]) // Key1
console.log(response[0][1]) // Value1
// console.log(response[1][0]) // Key2
console.log(response[1][1]) // Value2
console.log(leadTagNumber)
fetch('https://xyxtech/Android_API_CI/uploaddata/tbservice_details', {
method: 'POST',
headers: {'Accept': 'application/json, text/plain, */*', "Content-Type": "application/json" },
// We convert the React state to JSON and send it as the POST body
body: JSON.stringify([{ data}])
})
.then((returnValue) => returnValue.json())
.then(function(response) {
console.log(response)
Alert.alert("File uploaded");
return response.json();
});
});
// event.preventDefault();
}
//+++++++++++++++++++++++++++++++++submitting form data to api end++++++++++++++++++++++++++++++++++++++
Alert.alert("success")
return;
//}
}
};
const handleAmazon = (text) => {
setAmazonError('')
setAmazon(text)
}
const handleAmazonCN= (text) => {
setAmazonCNError('')
setAmazonCN(text)
}
const handleAEPS= (text) => {
setAEPSError('')
setAEPS(text)
}
const handleDMT = (text) => {
setDMTError('')
setDMT(text)
}
const handleBBPS = (text) => {
setBBPSError('')
setBBPS(text)
}
return (
<View style={{flex: 1}}>
<ScrollView style={{flex: 1,}} showsVerticalScrollIndicator={false}>
<TextInput
maxLength={30}
placeholder="AEPS (Adhar enabled payment system) *"
style={styles.inputStyle}
onChangeText={(text)=>handleAEPS(text)}
defaultValue={AEPS}
value = {AEPS} />
<Text>{AEPSError}</Text>
</ScrollView>
<Button
style={styles.inputStyleB}
title="Submit"
color="#FF8C00"
onPress={() => validateInputs()}
/>
</View>
)
}
Set new state property to enable/disable button
const [disableButton, setDisableButton] = useState(false);
Now in your button component, add disabled property with disableButton state.
<Button
style={styles.inputStyleB}
title="Submit"
color="#FF8C00"
onPress={() => validateInputs()}
disabled={disableButton}
/>
Disable you button before fetching data
setDisableButton(true) //Add this
const leadTagNumber = props.route.params.leadTagNumber
Incase of fetch error or after fetching is complete, enable button again
setDisabledButton(false)

Duplicate Errors on Formik/Yup Validation

I'm using the following validation schema in Formik:
validationSchema = {
Yup.object({
emails: Yup.array()
.of(Yup.string().email('Please enter valid email addresses only.'))
.min(1, 'At least one email address is required.')
})
}
It works very well, except that, since I'm using a Material UI AutoComplete component, when the user enters multiple invalid email addresses, they get to see the error message once per invalid email address.
Any way around this?
Here's a sandbox link: https://codesandbox.io/s/wild-sea-h2i0m?file=/src/App.tsx
What you want to do then is to make sure you filter out duplicated errors. You should make sure that each error message is unique. I wrote a function that help you do that.
I updated your EmailsField component:
import React from "react";
import Autocomplete from "#material-ui/lab/Autocomplete";
import Chip from "#material-ui/core/Chip";
import CloseIcon from "#material-ui/icons/Close";
import TextField from "#material-ui/core/TextField";
import { FieldProps } from "formik";
const isEmailValid = (email: string) =>
/^[^\s#]+#[^\s#]+\.[^\s#]+$/.test(email);
const EmailsField = ({
field,
form: { errors, touched, setTouched, setFieldValue },
...props
}: FieldProps) => {
console.log('errors', errors)
const name = field.name;
const [value, setValue] = React.useState<string[]>([]);
const [inputValue, setInputValue] = React.useState("");
const handleChange = (event: React.ChangeEvent<{}>, emails: string[]) => {
setTouched({ ...touched, [name]: true });
setValue(emails);
event.persist();
setFieldValue(name, emails);
};
const handleInputChange = (
event: React.ChangeEvent<{}>,
newInputValue: string
) => {
const options = newInputValue.split(/[ ,]+/);
const fieldValue = value
.concat(options)
.map(x => x.trim())
.filter(x => x);
if (options.length > 1) {
handleChange(event, fieldValue);
} else {
setInputValue(newInputValue);
}
};
// 1. This function will help remove duplicated errors
const getEmailErrors = (errors: any) => {
return Array.isArray(errors)
? errors.filter((email: string, i: number, arr: any) => arr.indexOf(email) === i)
: errors;
}
return (
<Autocomplete<string>
multiple
disableClearable={true}
options={[]}
freeSolo
renderTags={(emails, getTagProps) =>
emails.map((email, index) => (
<Chip
deleteIcon={<CloseIcon />}
variant="default"
label={email}
color={isEmailValid(email) ? "primary" : "secondary"}
{...getTagProps({ index })}
/>
))
}
value={value}
inputValue={inputValue}
onChange={handleChange}
onInputChange={handleInputChange}
renderInput={params => (
<TextField
{...params}
name={name}
error={touched[name] && Boolean(errors.emails)}
//---------------------------------------->>>> Call it here
helperText={touched[name] && errors.emails && getEmailErrors(errors.emails as any)}
variant="outlined"
InputProps={{ ...params.InputProps }}
{...props}
/>
)}
/>
);
};
export default EmailsField;

How to use setFieldValue and pass the value as props between components

I'm trying to use ant design forms in my sample registration form, when i'm trying to use setFieldsValue it throws error as "Cannot use setFieldsValue unless getFieldDecorator is used". But I had already used getFieldDecorator in my code.Here is a sample of my code.
handleChange = (e) => {
const fname = e.target.name;
const fvalue = e.target.value;
this.props.setFieldsValue({
fname: fvalue
});
}
render(){
const { getFieldDecorator } = this.props.form
return (
<Row gutter={4}>
<Col className="reg-personal-details-grid-column" span={24}>
<FormItem {...formItemLayout} label="First Name">
{getFieldDecorator("firstName", {
rules: [
{
required: true
}
]
})(
<Input
placeholder="First Name"
required
name="firstName"
onChange={this.handleChange}
/>
)}
</FormItem>
</Col>
</Row>
)
}
fname is not defined in getFieldDecorator.
You should do this:
handleChange = (e) => {
const fname = e.target.name;
const fvalue = e.target.value;
this.props.form.setFieldsValue({
[fname]: fvalue
});
}
You can create your own function to do this:
export const setFieldValue = (
form: FormInstance,
name: NamePath,
value: string
): void => {
if (form && form.getFieldValue(name)) {
const fixname: string[] = [];
if (typeof name == 'object') {
name.forEach((node: string) => {
fixname.push(node);
});
} else {
fixname.push(String(name));
}
let fieldsValue: unknown;
fixname.reverse().forEach((node: string) => {
fieldsValue = {
[String(node)]: fieldsValue != undefined ? fieldsValue : value,
};
});
form.setFieldsValue(fieldsValue);
}
};
and you can use like that
setFieldValue(form, 'phone', '1111111111');
or
setFieldValue(form, ['phones', 'mobile'], '2222222222');
In Antd v4, you only required to call the setFieldsValue in useEffect function.
const [form] = Form.useForm()
useEffect(() => {
//companyInfo -> dynamic obj fetched from API
form.setFieldsValue(companyInfo);
}, [companyInfo, form]);
Then in Form use the form prop as follow:
<Form
//passing form prop
form={form}
labelCol={{ span: 8 }}
wrapperCol={{ span: 14 }}
onFinish={onFinish}
labelAlign="left"
colon={false}
>
you can use it like this
const formRef = useRef(null);
useEffect(() => {
formRef.current?.setFieldsValue({
name: data?.firstName,
});
}, [data]);
return (
<Form ref={formRef}>
<Form.Item name="name">
<Input/>
</Form.Item>