form error, 'password is required' response from the backend - reactjs

this is my scheduleForm component
import { LoginOrSchedule } from 'context/isLoginOrIsSquedule/Context';
import React, { useContext, useState } from 'react';
import * as Styled from './styles';
export type ScheduleFormProps = {
errorMessage?: string;
onScheduleSend?: (
name: string,
email: string,
password: string,
age: number,
) => void;
};
export const ScheduleForm = ({
errorMessage,
onScheduleSend,
}: ScheduleFormProps) => {
const [loading, setLoading] = useState(false);
const [form, setForm] = useState({
name: '',
email: '',
password: '',
confirmPass: '',
age: 0,
});
const { dispatch } = useContext(LoginOrSchedule);
const handleSubmitForm = async (e: React.FormEvent) => {
e.preventDefault();
const { age, confirmPass, email, name, password } = form;
if (!age || !confirmPass || !email || !name || !password) {
alert('Um ou mais campos estão em branco');
return;
}
if (confirmPass !== password) {
alert('As senhas não batem');
return;
}
setLoading(true);
if (onScheduleSend) {
await onScheduleSend(name, email, password, age); //<<<sending to backend
}
setLoading(false);
setForm({
name: '',
email: '',
password: '',
confirmPass: '',
age: 0,
});
};
const handleLogin = () => {
dispatch({ type: 'TRIGGER' });
};
return (
<Styled.Wrapper>
<h2>Amostra de formulário de Cadastro</h2>
<Styled.Form onSubmit={handleSubmitForm}>
{!!errorMessage && (
<Styled.ErrorMessage>{errorMessage}</Styled.ErrorMessage>
)}
<Styled.InputWrapper>
<Styled.InputText
id="user-name"
type="text"
name="user-name"
onChange={(e) => {
setForm((f) => {
return { ...f, name: e.target.value };
});
}}
value={form.name}
/>
<Styled.InputLabel htmlFor="user-name">Nome</Styled.InputLabel>
</Styled.InputWrapper>
<Styled.InputWrapper>
<Styled.InputText
id="user-email"
type="email"
name="user-email"
onChange={(e) => {
setForm((f) => {
return { ...f, email: e.target.value };
});
}}
value={form.email}
/>
<Styled.InputLabel htmlFor="user-email">Email</Styled.InputLabel>
</Styled.InputWrapper>
<Styled.InputWrapper>
<Styled.InputText
id="user-age"
type="number"
name="user-age"
onChange={(e) => {
setForm((f) => {
return { ...f, age: Number(e.target.value) };
});
}}
value={form.age === 0 ? '' : form.age}
/>
<Styled.InputLabel htmlFor="user-age">Idade</Styled.InputLabel>
</Styled.InputWrapper>
<Styled.InputWrapper>
<Styled.InputText
id="user-pássword"
type="password"
name="user-password"
onChange={(e) => {
setForm((f) => {
return { ...f, password: e.target.value };
});
}}
value={form.password}
/>
<Styled.InputLabel htmlFor="user-password">Senha</Styled.InputLabel>
</Styled.InputWrapper>
<Styled.InputWrapper>
<Styled.InputText
id="user-confirmPass"
type="password"
name="user-confirmPass"
onChange={(e) => {
setForm((f) => {
return { ...f, confirmPass: e.target.value };
});
}}
value={form.confirmPass}
/>
<Styled.InputLabel htmlFor="user-confirmPass">
Confirme sua senha
</Styled.InputLabel>
</Styled.InputWrapper>
<Styled.newUser onClick={handleLogin}>
Já tem cadastro?? faça o login agora!
</Styled.newUser>
<Styled.SubmitButton
type="submit"
value={loading ? 'Cadastrando...' : 'Cadastrar'}
disabled={loading}
/>
</Styled.Form>
</Styled.Wrapper>
);
};
and this was my function who call back-end
const handleSchedule = async (
name: string,
email: string,
password: string,
age: number,
) => {
const scheduleResponse = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}${process.env.NEXT_PUBLIC_API_REGISTER}`,
{
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
body: JSON.stringify({ name, email, password, age }),
},
);
if (!scheduleResponse.ok) {
const getError = await scheduleResponse.text();
getError.includes('E11000')
? setErrorSchedule('Email já cadastrado')
: setErrorSchedule(getError);
setTimeout(() => {
setErrorSchedule('');
}, 5000);
return;
}
dispatch({ type: 'TRIGGER' });
alert('Cadastrado com sucesso.Por favor, faça o login');
};
but it return to me "password is a required field".
to see if its an back-end error, i create a playground file who do a fetch to the api with the values, and it return a 200
const email = 'emailtest#gmail.com'
const password = 'testpass123'
const age =19
const name= 'testename'
fetch('register',{method:'POST',
headers: {
'Content-Type': 'application/json'
},
body:JSON.stringify({email,password,age,name})
}).then(res=>res.text()).then(text=> console.log(text))
it just happen on the production mode, on localhost work as expect.
someone know what are happening here?

Related

I want to update my quantity at the same time based on quantity update my available quantity and sell quantity

suppose i have quantity, available_qty, and sell_quantity ,I want if my quantity increase my sell_quantity will increase and available_qty decrease ,if my quantity will decrease my sell_quantity will decrease and available_qty will increase..
import React, { useState } from 'react'
import BackButton from '../../components/UI/BackButton'
import Input from '../../components/UI/Input'
import Button from '../../components/UI/Button'
import {
useUpdateOrderMutation,
useGetOrderByIdQuery,
useGetAllProductQuery,
useGetAllOrderQuery,
} from '../../Redux/Services/services'
import { useParams } from 'react-router-dom'
import { useForm, Controller } from 'react-hook-form'
import { useNavigate } from 'react-router-dom'
const UpdateOrder = () => {
const [noData, setNoData] = useState(false)
const {
control,
handleSubmit,
reset,
formState,
setValue,
formState: { errors, isSubmitSuccessful },
} = useForm({
// resolver: yupResolver(createProductSchema),
defaultValues: {
// Category_name: '',
// subCat_name: '',
selling_price: '',
quantity: '',
available_qty: '',
sell_quantity: '',
// unit: '',
total_cost: '',
},
})
React.useEffect(() => {
if (formState.isSubmitSuccessful) {
reset({ quantity: '' })
}
}, [formState, reset])
const params = useParams()
const order_id = params.id
const [updateOrder, responseInfoOrderUpdate] = useUpdateOrderMutation()
const responseInfoOrderById = useGetOrderByIdQuery(order_id)
const responseInfoProduct = useGetAllProductQuery()
const responseInfoAllOrder = useGetAllOrderQuery()
const orderDetails = responseInfoAllOrder.data
if (responseInfoOrderUpdate.isLoading) return <div>Loading....</div>
if (responseInfoOrderUpdate.isError)
return <h1>An error occured {responseInfoOrderUpdate.error.error}</h1>
if (responseInfoOrderById.isLoading) return <div>Loading....</div>
if (responseInfoOrderById.isError)
return <h1>An error occured {responseInfoOrderById.error.error}</h1>
if (responseInfoProduct.isLoading) return <div>Loading....</div>
if (responseInfoProduct.isError)
return <h1>An error occured {responseInfoProduct.error.error}</h1>
// const totalProductQty = responseInfoOrderById.data
// ?.filter((sellQuantity) => sellQuantity.subCat_id === subCat_id)
// .map((additionSell, i) => additionSell.quantity)
// .reduce((qty, purchase) => qty + purchase, 0)
var qty_data = responseInfoOrderById.data?.quantity
var sellingPrice_data = responseInfoOrderById.data?.selling_price
var available_qty = responseInfoOrderById.data?.available_qty
var sell_quantity = responseInfoOrderById.data?.sell_quantity
const totalProductQty =
parseInt(responseInfoOrderById.data?.available_qty) +
parseInt(responseInfoOrderById.data?.sell_quantity)
console.log('totalProductQty', totalProductQty)
console.log('sell_quantity', sell_quantity)
const sell_qty =
parseInt(totalProductQty) -
parseInt(responseInfoOrderById.data?.available_qty)
// const available_qty =
// parseInt(totalProductQty) -
// parseInt(responseInfoOrderById.data?.sell_quantity)
// console.log('sell_qty', sell_qty)
// console.log('available_qty', available_qty)
// const total_sell = parseInt(sellQty) + parseInt(quantity)
const AvailableProduct = parseInt(totalProductQty) - parseInt(qty_data)
const onSubmit = (data) => {
const orderUpdateData = {
id: order_id,
quantity: data.quantity,
available_qty: available_qty,
selling_price: data.selling_price,
total_cost: data.total_cost,
sell_quantity: sell_quantity,
}
updateOrder(orderUpdateData)
console.log(orderUpdateData, 'orderUpdateData')
}
var total_cost = parseInt(sellingPrice_data) * parseInt(qty_data)
console.log('supplier_name', sellingPrice_data, qty_data, total_cost)
setValue('quantity', qty_data)
setValue('selling_price', sellingPrice_data)
setValue('total_cost', total_cost)
setValue('available_qty', available_qty)
setValue('sell_quantity', sell_quantity)
return (
<div className="page__wrapper">
<BackButton />
<div className="place__order__wrapper">
<form onSubmit={handleSubmit(onSubmit)}>
<div className="inputs__cover">
<Controller
control={control}
rules={{
required: true,
}}
render={({ field: { onChange, onBlur, value } }) => (
<Input
label="Selling price"
type="number"
id="selling_price"
readOnly={true}
onChange={onChange}
onBlur={onBlur}
value={value}
/>
)}
name="selling_price"
/>
{errors.selling_price && (
<span className="field_error">This is required.</span>
)}
<Controller
control={control}
rules={{
required: true,
}}
render={({ field: { onChange, onBlur, value } }) => (
<Input
label="Available qty"
type="number"
id="available_qty"
readOnly={true}
onChange={onChange}
onBlur={onBlur}
value={value}
/>
)}
name="available_qty"
/>
{errors.available_qty && (
<span className="field_error">This is required.</span>
)}
<Controller
control={control}
rules={{
required: true,
}}
render={({ field: { onChange, onBlur, value } }) => (
<Input
label="sell Total qty"
type="number"
id="sell_quantity"
readOnly={true}
onChange={onChange}
onBlur={onBlur}
value={value}
/>
)}
name="sell_quantity"
/>
{errors.sell_quantity && (
<span className="field_error">This is required.</span>
)}
<div className="quantity__input">
<Controller
control={control}
rules={{
required: true,
}}
render={({ field: { onChange, onBlur, value } }) => (
<Input
label="Quantity"
type="number"
id="quantity"
onChange={onChange}
onBlur={onBlur}
value={value}
/>
)}
name="quantity"
/>
</div>
<Controller
control={control}
rules={
{
// required: true,
}
}
render={({ field: { onChange, onBlur, value } }) => (
<Input
label="Total cost"
type="number"
id="total_cost"
onChange={onChange}
onBlur={onBlur}
value={noData ? total_cost.toString() : value}
readOnly={true}
/>
)}
name="total_cost"
/>
{errors.total_cost && (
<span className="field_error">This is required.</span>
)}
</div>
<div className="button__wrapper">
<Button className="add__product__button" type="submit">
Add quantity
</Button>
</div>
<div className="button__wrapper">
<Button className="add__product__button" type="submit">
update quantity
</Button>
</div>
</form>
</div>
</div>
)
}
export default UpdateOrder
model is
const mongoose = require("mongoose");
const OrderSchema = new mongoose.Schema(
{
_id: mongoose.Schema.Types.ObjectId, //convert id to normal form
customer_id: {
type: String,
required: true,
lowercase: true,
},
category_id: {
type: String,
required: true,
lowercase: true,
},
subCat_id: {
type: String,
required: true,
lowercase: true,
},
selling_price: {
type: Number,
required: true,
},
quantity: {
type: Number,
required: true,
},
sell_quantity: {
type: Number,
default: 0,
},
available_qty: {
type: Number,
default: 0,
},
unit: {
type: String,
required: true,
enum: {
values: ["kg", "litre", "pcs", "bag"],
message: "unit must be kg/litre/pcs/bag",
},
},
total_cost: {
type: Number,
required: true,
},
},
{ timestamps: true }
);
module.exports = mongoose.model("order", OrderSchema);
query is
const router = require("express").Router();
const { default: mongoose } = require("mongoose");
const Order = require("../models/Order");
//create order
router.post("/order-save", async (req, res) => {
try {
const customer_id = req.body.customer_id;
const category_id = req.body.category_id;
const subCat_id = req.body.subCat_id;
const selling_price = req.body.selling_price;
const quantity = req.body.quantity;
const sell_quantity = req.body.sell_quantity;
const available_qty = req.body.available_qty;
const unit = req.body.unit;
const total_cost = req.body.total_cost;
const oder_data = new Order({
_id: mongoose.Types.ObjectId(),
customer_id: customer_id,
category_id: category_id,
subCat_id: subCat_id,
selling_price: selling_price,
quantity: quantity,
sell_quantity: sell_quantity,
available_qty: available_qty,
unit: unit,
total_cost: total_cost,
});
const orderData = await oder_data.save();
message = "Order Create Successfully..";
return res.status(200).json(orderData);
} catch (err) {
return res.status(200).json(err);
}
});
//get all order
router.get("/get-order", async (req, res) => {
try {
const order = await Order.find();
return res.status(200).json(order);
} catch (err) {
return res.status(200).json(err);
}
});
//get order by id
router.get("/get-order/:id", async (req, res) => {
try {
const orderById = await Order.findById(req.params.id);
return res.status(200).json(orderById);
} catch (error) {
return res.status(500).json(error);
}
});
//get filter customer by id
router.get("/filter-order/:id", async (req, res) => {
try {
const order = await Order.find({ $and: [{ customer_id: req.params.id }] });
return res.status(200).json(order);
} catch (err) {
return res.status(500).json(err);
}
});
//Update Order
router.patch("/update-order/:id", async (req, res) => {
try {
await Order.findByIdAndUpdate(req.params.id, req.body, {
new: true,
});
message = "Order has been updated...";
return res.status(200).json({ message });
} catch (err) {
return res.status(200).json(err);
}
});
module.exports = router;

MERN Authentication: React - Redux - Formik signup/login form does not wait for dispatch return to update and show server error after submit

I have this Formik form for authentication which can switch from login (by default) to signup form using switch button. Using Formik and yup validation schema, the form first check the fields' values on change and before submitting. On submit, I am trying to have another value check from the server side and to show error messages on top of each field (at the same place as the client side error messages provided by Formik and Yup). When the 'submit' button is clicked and in case of a server error after validation, the state of my Redux 'authReducer' is updated with 'errors'' object inside 'data' property. Through local state, then I create a variable 'errorServer' which is an object created to store for each input (as key), the related server error's message (as value). Then, using this object, I'm trying to show the error message(s) on top of field(s) concerned (I tried both Formik methods 'setErrors' and 'setStatus' to do so). But, in the best case, this error message is only appearing after a second click on the 'submit' button and I don't know how to solve this problem... Can anyone provide me some help? Many thanks!
Server side
auth.controller.js
const { findUserPerUsername, findUserPerEmail} = require('../queries/users.queries');
const { createUser } = require('../queries/users.queries');
const { check, validationResult } = require('express-validator');
// Field value validation before signup
exports.validate = (method) => {
switch (method) {
case 'signup': {
return [
check('name')
.exists()
.withMessage('Enter your name.'),
check('username')
.exists()
.withMessage('Enter a username.')
.isAlphanumeric()
.withMessage('Username must contain only letters and numbers.')
.custom(value => {
return findUserPerUsername(value).then(user => {
if (user) {
return Promise.reject('Username already in use.');
}
})
}),
check('email')
.exists()
.withMessage('Enter an email address.')
.isEmail()
.withMessage('A valid email address is required.')
.custom(value => {
return findUserPerEmail(value).then(user => {
if (user) {
return Promise.reject('Email address already in use.');
}
})
}),
check('password')
.exists()
.withMessage('Enter a password.')
.custom(value => {
const pswRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[##$!%*?&-])[A-Za-z\d##$!%*?&-]{8,}$/;
if (pswRegex.test(value) === false) {
return Promise.reject('Password must contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character')
} else {
return Promise.resolve();
}
})
]
}
case 'login': {
return [
check('email')
.exists()
.withMessage('Enter an email address.')
.isEmail()
.withMessage('A valid email address is required'),
check('password')
.exists()
.withMessage('Enter a password.')
.custom(value => {
const pswRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[##$!%*?&-])[A-Za-z\d##$!%*?&-]{8,}$/;
if (pswRegex.test(value) === false) {
return Promise.reject('Password must contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character')
} else {
return Promise.resolve();
}
})
]
}
}
}
exports.signup = async (req, res, next) => {
try {
const body = req.body;
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).send({
success: false,
errors: errors.array()
});
next();
} else {
const user = await createUser(body);
req.login(user);
res.status(200).send({
user: user,
success: true,
message: 'User successfully registered.'
})
next();
}
} catch(e) {
next(e);
}
}
exports.login = async (req, res, next) => {
try {
const errors = validationResult(req);
if (!errors.isEmpty()) {
res.status(400).send({
success: false,
errors: errors.array()
});
next();
} else {
const { email, password } = req.body;
const user = await findUserPerEmail(email);
if (user) {
const match = await user.comparePassword(password);
if (match) {
req.login(user);
res.status(200).send({
user: user,
success: true,
message: 'User successfully logged in.'
});
next();
} else {
res.status(401).send({
success: false,
errors: {
msg: 'Sorry, that password is not right. Please try again or reset your password.',
param: 'password',
location: 'body'
}
});
next();
}
} else {
res.status(401).send({
success: false,
errors: {
msg: 'Sorry, we could not find an account with that email. Please try again or sign up.',
param: 'email',
location: 'body'
}
});
next();
}
}
} catch(e) {
next(e);
}
}
exports.logout = (req, res, next) => {
req.logout();
res.status(200).send({
success: true,
message: "User successfully logged out."
})
next();
}
Client side
auth.config.js
import axios from 'axios';
const API_URL = 'http://localhost:3001/api/auth/'
const signup = ({ name, username, email, password }) => {
return axios.post(API_URL + 'signup', {
name,
username,
email,
password
});
};
const login = ({ email, password }) => {
return axios
.post(API_URL + 'login', {
email,
password
})
.then((res) => {
return res.data;
});
};
const logout = () => {
return axios.get(API_URL + 'logout').then((res) => {
return res.data;
});
};
const getCurrentUser = () => {
/* return JSON.parse(localStorage.getItem('user')); */
}
const AuthConfig = {
signup,
login,
logout,
getCurrentUser
}
export default AuthConfig;
Redux store:
actions.js
import AuthConfig from '../config/auth.config';
export const SIGNUP_SUBMIT = "signup submit";
export const SIGNUP_SUCCESS = "signup success";
export const SIGNUP_ERROR = "signup error";
export const LOGIN_SUBMIT = "login submit";
export const LOGIN_SUCCESS = "login success";
export const LOGIN_ERROR = "login error";
export const LOGOUT = "logout";
export const signup = (name, username, email, password) => (dispatch) => {
return AuthConfig.signup(name, username, email, password).then(
(response) => {
dispatch({
type: SIGNUP_SUCCESS,
payload: response.data
});
},
(error) => {
dispatch({
type: SIGNUP_ERROR,
error: error.response.data
});
}
);
};
export const login = (email, password) => (dispatch) => {
return AuthConfig.login(email, password).then(
(response) => {
dispatch({
type: LOGIN_SUCCESS,
payload: response.data
});
},
(error) => {
dispatch({
type: LOGIN_ERROR,
error: error.response.data
});
}
);
};
export const logout = () => (dispatch) => {
AuthConfig.logout().then(
(response) => {
dispatch({
type: LOGOUT,
payload: response.message
})
}
);
};
reducers.js
import {
SIGNUP_SUBMIT,
SIGNUP_SUCCESS,
SIGNUP_ERROR,
LOGIN_SUBMIT,
LOGIN_SUCCESS,
LOGIN_ERROR,
LOGOUT
} from "./actions";
const initialState = { isLoggedIn: false, data: {} }
export const authReducer = (state = initialState, action) => {
const { type, payload, error } = action;
switch (type) {
case SIGNUP_SUBMIT:
return {
...state,
isLoggedIn: false,
};
case SIGNUP_SUCCESS:
return {
...state,
isLoggedIn: true,
data: payload
};
case SIGNUP_ERROR:
return {
...state,
isLoggedIn: false,
data: error
};
case LOGIN_SUBMIT:
return {
...state,
isLoggedIn: false,
};
case LOGIN_SUCCESS:
return {
...state,
isLoggedIn: true,
data: payload
};
case LOGIN_ERROR:
return {
...state,
isLoggedIn: false,
data: error
};
case LOGOUT:
return {
...state,
isLoggedIn: false,
data: null
};
default: {
return state;
}
}
};
export default authReducer;
Form.js
import React, { useState, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import { Formik, useFormikContext } from 'formik';
import * as Yup from 'yup';
/* import { SignupSchema, LoginSchema /* YupSchema * } from './YupSchema'; */
import Input from './Input';
import { signup, login } from '../../store/actions';
import { Eye, EyeSlash, Lock, MedalStar, Personalcard, Sms, User } from 'iconsax-react';
import './Form.css';
const Logger = () => {
const formik = useFormikContext();
useEffect(() => {
console.group("Formik State");
console.log("status", formik.status);
console.log("values", formik.values);
console.log("errors", formik.errors);
console.log("touched", formik.touched);
console.log("isSubmitting", formik.isSubmitting);
console.log("isValidating", formik.isValidating);
console.log("submitCount", formik.submitCount);
console.groupEnd();
}, [
formik.status,
formik.values,
formik.errors,
formik.touched,
formik.isSubmitting,
formik.isValidating,
formik.submitCount
]);
return null;
};
const ServerValidation = () => {
const { values, /* submitForm, */ } = useFormikContext();
useEffect(() => {
if (values.username === 'JDope99' || values.email === 'jdoe#gmail.com') {
/* submitForm(); */
/* console.log('Username or email already in use.'); */
/* alert(JSON.stringify('Username or email already in use.')); */
}
}, [values]);
return null;
};
const Form = () => {
const authServerErrors = useSelector(state => state.authReducer.data.errors);
console.log(authServerErrors);
const [errorServer, setErrorServer] = useState('');
console.log(errorServer);
const [isSignupForm, setIsSignupForm] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const handleShowPassword = () => setShowPassword(!showPassword);
useEffect(() => {
if (authServerErrors === undefined) {
return
} else {
console.log(authServerErrors);
if (Array.isArray(authServerErrors)) {
let fields = authServerErrors.map(el => el.param);
let msgs = authServerErrors.map(el => el.msg);
if (fields !== [] && msgs !== []) {
let errorObj;
fields.reduce(function(obj, key, index) {
obj[key] = msgs[index]
return errorObj = obj
}, {});
setErrorServer(errorObj);
};
} else {
let field = authServerErrors.param;
let msg = authServerErrors.msg;
let error = {};
error[field] = msg;
setErrorServer(error);
}
}
}, [authServerErrors]);
const switchForm = () => {
setIsSignupForm(!isSignupForm);
setShowPassword(false);
}
const initialValues = {
name: '',
username: '',
email: '',
password: ''
}
const dispatch = useDispatch();
const navigate = useNavigate(); // Will be used to redirect user in case of no server error to /Home
const YupSchema = Yup.object().shape({
name: Yup.string().when('isSignupForm', {
is: true,
then: Yup
.string()
.min(2, 'Too short')
.max(20, 'Too long')
.required('Required'),
otherwise: Yup.string().min(2, 'Too short').max(20, 'Too long')
}),
username: Yup.string().when('isSignupForm', {
is: true,
then: Yup
.string()
.min(2, 'Too short')
.max(20, 'Too long')
.required('Required'),
otherwise: Yup.string().min(2, 'Too short').max(20, 'Too long')
}),
email: Yup
.string()
.email('Valid email required')
.required('Required'),
password: Yup
.string()
.matches(
/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##\$%\^&\*])(?=.{8,})/,
"Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character"
)
.required('Required')
})
return (
<div className="container">
<Formik
initialValues={ initialValues }
validationSchema= { YupSchema }
onSubmit={async (values, actions) => {
try {
if (isSignupForm) {
await dispatch(signup(values));
/* errors.setErrors({
name: errorServer.name,
username: errorServer.username,
email: errorServer.email,
password: errorServer.password
})
console.log(errors); */
} else {
await dispatch(login(values));
}
actions.setStatus({
name: errorServer.name || '',
username: errorServer.username || '',
email: errorServer.email || '',
password: errorServer.password || ''
});
} catch (error) {
console.log(error);
}
}}
>
{({ handleChange, handleBlur, handleReset, handleSubmit, values, errors, status, isValid, dirty }) => (
<form
id="auth-form"
className="d-flex flex-column justify-content-start align-items-start py-3"
onChange={ handleChange }
onBlur={ handleBlur }
onReset={ handleReset }
onSubmit= { handleSubmit }
>
<Logger />
{ isSignupForm ? (
<>
<h2>Sign Up</h2>
<p className="text-lg">Welcome to our website! We hope you will enjoy being part of our community.</p>
<div className="input-box mb-3 w-100">
<Input
label="Name"
type="text"
name="name"
className="form-control"
helpText="Please enter your full name."
icon={<Personalcard size="20" color="#666664" variant="Bold" /* className="input-icon" */ />}
errors={errors.name}
value={values.name}
status={ status !== undefined ? status.name : ''}
/>
</div>
<div className="input-box mb-3 w-100">
<Input
label="Username"
type="text"
name="username"
className="form-control"
helpText="Must contain only letters and numbers"
icon={<User size="20" color="#666664" variant="Bold" /* className="input-icon" */ />}
errors={errors.username}
value={values.username}
status={ status !== undefined ? status.username : ''}
/>
</div>
</>
) : (
<>
<h2>Log In</h2>
<p className="text-lg">We are pleased to have you back.</p>
</>
)}
<div className="input-box mb-3 w-100">
<Input
label="Email"
type="text"
name="email"
className="form-control"
helpText="example#email.com"
icon={<Sms size="20" color="#666664" variant="Bold" /* className="input-icon" */ />}
errors={errors.email}
value={values.email}
status={ status !== undefined ? status.email : ''}
/>
</div>
<div className="input-box mb-3 w-100">
<Input
label="Password"
type={ showPassword ? "text" : "password"}
name="password"
/* className="form-control" */
helpText="Must Contain 8 Characters, One Uppercase, One Lowercase, One Number and One Special Case Character"
icon={<Lock size="20" color="#666664" variant="Bold" /* className="input-icon" */ />}
toggle={ showPassword ? <Eye size="20" color="#000000" className="toggle-icon" onClick={ handleShowPassword } /> : <EyeSlash size="20" color="#000000" className="toggle-icon" onClick={ handleShowPassword } /> }
errors={errors.password}
value={values.password}
status={ status !== undefined ? status.password : ''}
/>
</div>
{ isSignupForm ? (
<div className="mt-1">
<p>By clicking "Sign Up" you agree to our Customer Terms and Privacy Policy.</p>
</div>
) : null}
<div className="d-flex flex-row mt-1">
<button type="submit" className="btn btn-green me-3" disabled={isSignupForm ? !(isValid && dirty) : null }>
{ isSignupForm ? 'Sign Up' : 'Log In' }
</button>
<button type="reset" className="btn btn-outline-black">
Reset
</button>
</div>
<div className="mt-2">
{ isSignupForm ? (
<p>Already have an account? <button type="button" className="link" onClick={() => { switchForm(); handleReset() } }>Log In</button></p>
)
:
(
<p>New to InkIt? <button type="button" className="link" onClick={() => { switchForm(); handleReset() } }>Sign Up</button></p>
)
}
</div>
<ServerValidation />
</form>
)}
</Formik>
</div>
);
};
export default Form;
Input.js
import React, { useState } from 'react';
import { useField } from 'formik';
import { TickSquare } from 'iconsax-react';
const Input = ({ label, helpText, icon, toggle, errors, status, ...props}) => {
const [field, meta, helpers] = useField(props);
console.log({ field, meta, helpers });
// Show inline feedback if EITHER
// - the input is focused AND value is longer than 2 characters
// - or, the has been visited (touched === true)
const [didFocus, setDidFocus] = useState(false);
const handleFocus = () => setDidFocus(true);
const showInputFeedback = (!!didFocus && field.value.trim().length > 2) || meta.touched;
return (
<div className={`form-control px-3 py-2 ${showInputFeedback ? (meta.error ? 'invalid' : 'valid') : ""}`}>
<div className="label-box d-flex flex-row justify-content-between align-items-center">
<label htmlFor={props.name}>{label}</label>
{showInputFeedback ? (
<div className="feedback text-sm">
{ meta.error ? meta.error : status ? status : <TickSquare size="20" color="#06d6a0" variant="Bold" />}
</div>
)
: null}
</div>
<div className="d-flex flex-row flex-nowrap">
<span className="input-icon icon-left">
{icon}
</span>
<input className={ toggle ? "form-control input-password" : "form-control" } autoComplete="off" onFocus={ handleFocus } {...field} {...props} />
{toggle ? (
<span className="input-icon icon-right">
{toggle}
</span>
)
: null
}
</div>
<div className="help-text text-xs">
{helpText}
</div>
</div>
);
}
export default Input;
Chrome console.log:
enter image description here

React Form Validation Issue

i don't know what is wrong with my code , i check the value with console.log and it gets the value normally but when i submit the form it gets back to undefined , and when i try to check the form with if statement if just send the mail with empty values and sometimes it send undefined
const [mails, setMails] = useState({
userFullName: '',
userEmail: '',
userSubject: '',
userMessage: '',
mailFail : false,
});
const [mailStatues, setMailStatues] = useState(false);
const [mailLoader, setMailloader] = useState(false);
const { userFullName, userEmail, userSubject, userMessage, mailFail } = mails;
const handleChange = e => {
setMails({ ...mails, [e.target.name] : e.target.value})
}
function setFail() {
setMails({ mailFail: true })
setTimeout(() => {
setMails({ mailFail: false })
}, 3000);
}
const handleEmail = async (e) => {
e.preventDefault();
console.log(userFullName , userEmail, userSubject, userMessage)
if ( userFullName ) {
setFail()
}
else {
setMailloader(true);
await axios.post('http://localhost:8000/api/form', {
...mails
},
setMails({
userFullName: '',
userEmail: '',
userSubject: '',
userMessage: '',
})
,
setMailloader(false)
,
setMailStatues(true)
)
}
}
here is the form
<form onSubmit={handleEmail}>
<Input id='inputName' type="text" name="userFullName" label="Name" value={userFullName} change={handleChange} />
<Input id='inputEmail' type="email" name="userEmail" label="Email" value={userEmail} change={handleChange}/>
<Input id='inputSubject' type="text" name="userSubject" label="Subject" value={userSubject} change={handleChange}/>
<TextArea id='inputMessage' type="text" name="userMessage" label="Message" value={userMessage} change={handleChange}/>
<BtnAni string="Submit" loading={mailLoader}/>
</form>
Change these lines
setMails({ mailFail: true })
setTimeout(() => {
setMails({ mailFail: false })
}, 3000);
to
setMails(prev => ({ ...prev, mailFail: true }))
setTimeout(() => {
setMails(prev => ({ ...prev, mailFail: false }))
}, 3000);

How can I disable/gray out dropdown selection checkboxes for two records available in setSubmittedNominees state?

How can I disable/gray out dropdown selection checkboxes for two records available in a state setSubmittedNominees in react hooks ? I tried to pass into submittedNominees into selectedValues and disablePreSelectedValues(true) but it doesn't work that way can someone please advise on this ?
codesandbox link:
https://codesandbox.io/s/magical-haslett-s0oeh?file=/src/App.js
import React, { useRef, useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { useForm } from "react-hook-form";
import Axios from "axios";
import { Link, useHistory } from "react-router-dom";
import Multiselect from "multiselect-react-dropdown";
const options = [
{ id: 1, name: "Ath", email: "ath.best#test1.com", access: null },
{ id: 2, name: "Arnolds", email: "arnold#test1.com", access: null },
{ id: 3, name: "Alter", email: "alloop#test1.com", access: null },
{ id: 4, name: "Brandan", email: "brandan#test1.com", access: null },
{ id: 5, name: "Ron", email: "ron#test1.com", access: null },
{ id: 6, name: "Rads", email: "rad#test1.com", access: null },
{ id: 7, name: "Sam", email: "sam#y.com", access: null }
];
const submitted = [
{ id: 4, name: "Brandan", email: "brandan#test1.com", access: null },
{ id: 5, name: "Ron", email: "ron#test1.com", access: null }
];
const Selection= () => {
const [option, setOption] = useState([]);
const [selectedOption, setSelectedOption] = useState([]);
const [nomRegister, setNomRegister] = useState([{}]);
const [helperText, setHelperText] = useState("");
const [userEmail, setUserEmail] = useState("");
const [submittedNominees, setSubmittedNominees] = useState([{}]);
const {
register,
handleSubmit,
watch,
formState: { errors },
reset
} = useForm();
const maxOptions = 3;
const history = useHistory();
useEffect(() => {
const userEmail = localStorage.getItem("loginEmail");
setUserEmail(userEmail);
});
useEffect(() => {
const fetchData = async () => {
try {
const res = await Axios.get(
"http://localhost:8000/service/nomineeslist"
);
//const data1 = res.data;
setOption(options);
console.log("Get the list of nominees :" + JSON.stringify(res.data));
} catch (e) {
console.log(e);
}
};
fetchData();
}, []);
useEffect(() => {
const fetchData = async () => {
try {
// const res = await Axios.get(
// "http://localhost:8000/service/submittednominees"
// );
setSubmittedNominees(submitted);
} catch (e) {
console.log(e);
}
};
fetchData();
}, []);
const handleTypeSelect = (e, i) => {
const copy = [...selectedOption];
copy.push(e[i]);
setSelectedOption(copy);
};
const sendNomination = () => {
console.log("What the Array holds: " + JSON.stringify(nomRegister));
const fetchData = async (nomRegister) => {
try {
const res = await Axios.post(
"http://localhost:8000/service/nominateperson",
{ userEmail },
nomRegister
);
if (res.data) {
console.log("Print data:" + res.data);
const successMessage = res.data.message;
setHelperText(successMessage);
setNomRegister(reset);
}
} catch (e) {
console.log(e);
setNomRegister(reset);
setHelperText(e.message);
}
};
fetchData();
};
options.forEach((option) => {
option.displayValue = option.name + "\t" + option.email;
submittedNominees.forEach((item) => {
let subEmail = item.email; // how can I pass those two email to selectedValues and make it disable ?
});
});
const handleChange = (e, i) => {
const { name, email, value } = e.target;
// immutating state (best practice)
const updateList = nomRegister.map((item) => {
return { ...item };
});
const select_Email = selectedOption.map((item) => {
return item.email;
});
//change the specific array case depends on the id //email:emailList[i],
updateList[i] = {
...updateList[i],
name: name,
email: select_Email[i],
reason: value
};
setNomRegister(updateList);
};
return (
<div className="App">
<h1>Nominate a person</h1>
<div className="nomineeSelectBox">
<div id="dialog2" className="triangle_down1" />
<div className="arrowdown">
<Multiselect
onSelect={(e) => handleTypeSelect(e, selectedOption.length)}
options={selectedOption.length + 1 === maxOptions ? [] : options}
displayValue="displayValue"
selectedValues={subEmail}
showCheckbox={true}
emptyRecordMsg={"Maximum nominees selected !"}
/>
</div>
</div>
<div className="nominationcount"></div>
<form onSubmit={handleSubmit(sendNomination)}>
<div className="nomineesSelectedList">
<h4>Selected Nominees</h4>
{selectedOption.map((x, i) => (
<div key={i}>
<div className="row eachrecord">
<div className="column">
<label className="nomlabel">
{x?.name} <b>>></b>
</label>
</div>
<input
required
type="textarea"
placeholder="Please provide reason for nomination.."
key={i}
id={i}
name={x?.name}
className="nomineechoosed"
onChange={(e) => handleChange(e, i)}
/>
</div>
</div>
))}
<div className="row">
<div className="buttongroup">
<input id="Submit" type="submit" value="Submit" />
<input id="Cancel" type="button" value="Cancel" />
</div>
</div>
</div>
</form>
<span className="nominationValidationText">{helperText}</span>
</div>
);
};
export default Selection;
the issue here is that you are showing your dropdown selection checkboxes by displayValue (displayValue="displayValue") and your submitted array that you you will assign to submittedNominees (setSubmittedNominees(submitted)) does not contain displayValue:
const submitted = [
{ id: 4, name: "Brandan", email: "brandan#test1.com", access: null },
{ id: 5, name: "Ron", email: "ron#test1.com", access: null }
];
Solution::
Make your submitted for example like this:
const submitted = [
{
id: 4,
name: "Brandan",
email: "brandan#test1.com",
access: null,
displayValue: "Brandan brandan#test1.com"
},
{
id: 5,
name: "Ron",
email: "ron#test1.com",
access: null,
displayValue: "Ron ron#test1.com"
}
];
Add selectedValues={submittedNominees} to your Multiselect to find out which values you will disable:
<Multiselect
onSelect={(e) => handleTypeSelect(e, selectedOption.length)}
options={selectedOption.length + 1 === maxOptions ? [] : options}
displayValue="displayValue"
disablePreSelectedValues={true}
selectedValues={submittedNominees}
showCheckbox={true}
emptyRecordMsg={"Maximum nominees selected !"}
/>
Codesandbox link

React-Admin: How to send input values that have been auto filled from an API call?

I have an input 'A' that fetches address data from an API and auto fills inputs 'B' 'C' and 'D' based on that data, but after the inputs have been filled and I try to send that form to my backend, none of those auto filled inputs are sent, just the input 'A' is sent. Furthermore, if i manually edit any of the inputs (remove a char, add a space, change the value) the ones that I edited get sent to my backend.
I'm using a reducer to store the state. The inputs that I'm using are all just normal react-admin TextInput components.
Here's the code:
const AutoFill = () => {
const [searching, setSearching] = useState(false);
const [error, setError] = useState(false);
const [stateData, setStateData] = useReducer(
(state, newState) => ({ ...state, ...newState }),
{
cep: ' - ',
address: '',
number: '',
neighborhood: '',
city: '',
state: '',
}
);
const FormControl = (event) => {
const { name, value } = event.target;
setStateData({ [name]: value });
};
const SearchControl = (event) => {
const { name, value } = event.target;
setStateData({ [name]: value });
if (value && !value.includes('_')) {
setSearching(true);
setStateData({ state: '...' });
setStateData({ city: '...' });
setStateData({ neighborhood: '...' });
setStateData({ address: '...' });
cep(value.replace('-', '')).then(
(result) => {
setSearching(false);
setError(false);
setStateData({ state: result.state });
setStateData({ city: result.city });
setStateData({ neighborhood: result.neighborhood });
setStateData({ address: result.street });
},
() => {
setSearching(false);
setError(true);
setStateData({ state: '' });
setStateData({ city: '' });
setStateData({ neighborhood: '' });
setStateData({ address: '' });
}
);
}
};
return (
<>
<TextInput
source="cep"
error={error}
value={stateData.cep}
onChange={SearchControl}
/>
<TextInput
source="address"
disabled={searching}
value={stateData.address}
onChange={FormControl}
/>
<TextInput
source="number"
disabled={searching}
value={stateData.number}
onChange={FormControl}
/>
<TextInput
source="neighborhood"
disabled={searching}
value={stateData.neighborhood}
onChange={FormControl}
/>
<TextInput
source="state"
disabled={searching}
value={stateData.state}
onChange={FormControl}
/>
<TextInput
source="city"
disabled={searching}
value={stateData.city}
onChange={FormControl}
/>
</>
);
};
export const Create = (props) => {
return (
<Create {...props}>
<SimpleForm>
<NumberInput label="Value" source="price" />
<AutoFill />
<RichTextInput label="Description" source="description" />
</SimpleForm>
</Create>
);
};
You're going to need to use React Final Form's FormState and Form solutions. Will use snippets of my code for example.
1) Grab the form values
const formState = useFormState();
const form = useForm();
const {
asset_system_parent_id: majorSystem,
classification,
} = formState.values;
2) Setup useEffect that will observe changes to a form field:
useEffect(() => {
const setFluidEnd = async () => {
DO SOMETHING!!!!!
};
if ('Fluid End Maintenance' === classification) {
setFluidEnd();
}
}, [classification, form, notify]);
3) Use form.change (+ form.batch if you need to update multiple inputs)
useEffect(() => {
const setFluidEnd = async () => {
await requestGetList('asset-systems', 'id', 'ASC', 500, {
description: 'Fluid End',
relationship: 'parent',
})
.then(res => {
form.change('asset_system_parent_id', res.data[0].id);
})
.catch(error => {
notify(`System Assets not found`, 'warning');
});
};
if ('Fluid End Maintenance' === classification) {
setFluidEnd();
}
}, [classification, form, notify]);
You can read more about the api here: https://final-form.org/docs/final-form/types/FormApi
Please use this code.
-index.js file
import axios from "axios";
export const setInputValue = (data) => {
return axios.get(`https://www.example.com/profile`)
.then((response) => {
return response.data;
});
};
-component.js
return setInputValue(value).then(() => {
this.setState(() => ({
loading: false
}));
});
...
render(){
return (
...
<input type="text" onClick={e => this.onClick(e)} value={this.state.value}/>
..
)}
...
react-admin.php
...
public function setInputValue(value)
{
try {
$user->set(value);
return response()->json(["result" => "successfully!"]);
} catch (\Exception $e) {
return getErrorResponse($e);
}
}

Resources