React Form Submission for Firebase Firestore - reactjs

i am trying to pass form data for a recipe project i am doing to a firestore back end.
So far i have:
Successfully added the Firestore back end and tested it works
Created a button on the Firestore Component and passed data to it via props
Created a submit handler and can console log my data, that i ultimately wnat to pass and save in firestore
Problems i think i have:
My AddRecipe component is getting large (maybe thats the nature of
what i am doing but am aware you want to break down into resuable
components where possible) It could be i have got my child / parents
I have maybe got my child / parent model in a muddle
General housekeeping (import effeciency etc)
List item
Firebase Config (with some hard coding i used for testing)
import firebase from 'firebase/compat/app'
import 'firebase/compat/firestore'
import Button from '#mui/material/Button'
import AddRecipe from '../../../pages/recipes/addrecipe'
const WriteRecipe = () => {
const sendData = () => {
console.log(props)
try {
firebase
.firestore()
.collection('recipes')
.doc(props.recipeId)
.set({
arrayData: ['Macaroni Cheese', 2, 'it is delicious',]
})
.then(alert('Data Was successfully sent to Back end'))
}
catch (error) {
console.log(error)
alert(error)
}
}
return (
{/* used to return a button, now null*/ })
}
export default WriteRecipe
import { useState } from 'react'
import Typography from '#mui/material/Typography'
import Grid from '#mui/material/Grid'
import TextField from '#mui/material/TextField'
import makeStyles from '#mui/styles/makeStyles'
import MenuItem from '#mui/material/MenuItem';
import Button from '#mui/material/Button'
import IconButton from '#mui/material/Icon'
import { v4 as uuidv4 } from 'uuid';
import Divider from '#mui/material/Divider';
import AddIcon from '#mui/icons-material/Add';
import RemoveIcon from '#mui/icons-material/Remove';
import WriteRecipe from '../../src/components/firebase/WriteRecipe'
import ReadRecipe from '../../src/components/firebase/ReadRecipe'
import initFirebase from '../../firebase/initFirebase'
initFirebase()
const useStyles = makeStyles({
field: {
marginTop: 10,
marginBottom: 40,
display: 'block'
},
submit: {
martinTop: 10,
marginLeft: 20
},
})
const category = [
{
value: 'Starter',
label: 'Starter',
},
{
value: 'Main',
label: 'Main',
},
{
value: 'Dessert',
label: 'Dessert',
},
];
const serves = [
{
value: 1,
label: '1',
},
{
value: 2,
label: '2',
},
{
value: 3,
label: '3',
},
{
value: 4,
label: '4',
},
{
value: 5,
label: '5',
},
];
const AddRecipe = () => {
const classes = useStyles()
const [inputFields, setInputFields] = useState([
{ id: uuidv4(), firstName: '', lastName: '' },
]);
const handleIngredientChangeInput = (id, event) => {
const newInputFields = inputFields.map(i => {
if (id === i.id) {
i[event.target.name] = event.target.value
}
return i;
})
}
const [title, setTitle] = useState('')
const [Description, setDescription] = useState('')
const [Author, setAuthor] = useState('')
const [Category, setCategory] = useState('')
const [Url, setUrl] = useState('')
const [Serves, setServes] = useState('')
const [Directions, setDirections] = useState('')
const handleAddIngredients = () => {
event.preventDefault()
setInputFields([...inputFields, { id: uuidv4(), firstName: '', lastName: '' }])
}
const handleRemoveIngredients = id => {
event.preventDefault()
const values = [...inputFields];
values.splice(values.findIndex(value => value.id === id), 1);
setInputFields(values);
}
const handleSubmit = (event) => {
event.preventDefault()
if (title && Description && Author && Category && Directions)
console.log(title, Description, Author, Category.at, Url, Serves, Directions)
}
return (
<Grid container direction="column" >
<form noValidate autocomplete="off" onSubmit={handleSubmit}>
<Grid item xs={6} md={12} style={{ marginBottom: "0.5em" }}>
<TextField
onChange={(event) => setTitle(event.target.value)}
sx={{ m: 1, width: '50ch' }}
label="Title"
variant="outlined"
color="secondary"
size="medium"
required>
</TextField>
<TextField
onChange={(event) => setDescription(event.target.value)}
sx={{ m: 1, width: '50ch' }}
label="Description"
variant="outlined"
color="secondary"
size="medium"
required>
</TextField>
<TextField
onChange={(event) => setAuthor(event.target.value)}
sx={{ m: 1, width: '50ch' }}
label="Author"
variant="outlined"
color="secondary"
size="medium"
required></TextField>
</Grid>
<Grid item xs={6} md={6} style={{ marginBottom: "0.5em" }}>
<TextField
onChange={(event) => setCategory(event.target.value)}
sx={{ m: 1, width: '50ch' }}
label="Select Category"
variant="outlined"
color="secondary"
select
size="medium"
required>
{category.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
<TextField
onChange={(event) => setUrl(event.target.value)}
sx={{ m: 1, width: '50ch' }}
label="URL(Where applicable):"
variant="outlined"
color="secondary"
size="medium"
r>
</TextField>
</Grid>
<Grid item xs={6} md={6} style={{ marginBottom: "0.5em" }}>
<TextField
onChange={(event) => setServes(event.target.value)}
sx={{ m: 1, width: '50ch' }}
label="Serves"
variant="outlined"
color="secondary"
select
size="medium"
required>
{serves.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={6} md={6} style={{ marginBottom: "3.0em" }}>
<Divider sx={{ borderBottomWidth: 5, bgcolor: "primary", width: '210ch' }} classes={{ root: classes.dividerColor }}></Divider>
</Grid>
<Grid item xs={12} style={{ marginBottom: "1.5em" }}>
{inputFields.map(inputField => (
<div key={inputField.id}>
<TextField sx={{ marginBottom: '1em', marginRight: '1em' }}
key={inputField.id}
name="ingredients"
label="Ingredients"
variant="outlined"
color="secondary"
/*value={inputField.firstName} -- Important for later perhaps*/
onChange={event => handleIngredientChangeInput(inputField.id, event)}
/>
<TextField sx={{ marginBottom: '1em', marginRight: '1em' }}
key={inputField.id}
name="quantity"
label="Quantity"
variant="outlined"
color="secondary"
/*value={inputField.firstName} -- Important for later perhaps*/
onChange={event => handleIngredientChangeInput(inputField.id, event)}
/>
<IconButton size="large" sx={{ marginTop: '0.5em', marginRight: '1em' }}
type="submit"
colour="secondary"
onClick={handleAddIngredients}>
<AddIcon />
</IconButton>
<IconButton sx={{ marginTop: '0.5em' }}
type="submit"
colour="secondary"
variant="contained" onClick={handleRemoveIngredients}>
<RemoveIcon />
</IconButton>
</div>
))}
</Grid>
<Grid item>
<TextField
onChange={(event) => setDirections(event.target.value)}
label="Directions"
variant="outlined"
color="secondary"
required
multiline
rows={10}
sx={{ width: '150ch' }}
/>
</Grid>
<Grid item>
<Button sx={{ mt: 5, marginBottom: '6em', marginLeft: '30em' }}
type="submit"
colour="secondary"
variant="contained">
Happy Cooking!</Button>
</Grid>
</form>
<ReadRecipe />
</Grid >
)
}
export default AddRecipe
Quite inexperienced (First Project i am doing after courses) so any help would be massively appreciated, banging my head off the wall!

Related

React Hook Form is not submitting

I'm new with react form, I'm using Material UI and Controller Component, and I'm sending a React Hook form request but not getting any response, form's (HTML form tag) onSubmit event is occurring but handleSubmit is not working I have one more form like that it is working perfectly fine but I don't know why it's not working, can anybody please help me with that
import { Button, useTheme, Grid, TextField, Typography } from '#mui/material';
import WSSelectBox from 'components/common/WSSelect';
import React, { FC } from 'react';
import { Controller, FormProvider, useForm } from 'react-hook-form';
import { isMobile } from 'utils/mediaqueries';
import CheckBoxButton from '../CheckBoxButton';
import { formTypes } from './utils';
import { yupResolver } from '#hookform/resolvers/yup';
import * as yup from 'yup';
import { FormPropTypes } from './type';
const schema = yup
.object()
.shape({
name: yup.string().required(),
residentialCountry: yup.number().required(),
initiator: yup.string().required(),
program: yup.string().required(),
list: yup.string().required(),
})
.required();
const Entities: FC<FormPropTypes> = ({
handleClick,
selectedType,
handleSearch,
}) => {
const theme = useTheme();
const methods = useForm({
resolver: yupResolver(schema),
});
const { handleSubmit, control } = methods;
const onSubmit = (data) => {
// Backend is not done yet
console.log('DataData', data);
};
return (
<FormProvider {...methods}>
<form
onSubmit={(e) => {
e.preventDefault();
console.log('skdjskd', 'Line no 44');
handleSubmit(onSubmit);
}}
>
<Grid container spacing={'16px'}>
{formTypes.map((type) => (
<Grid item xs={6} sm={'auto'} md={'auto'} key={type}>
<CheckBoxButton
key={type}
name={'type'}
value={type}
handleClick={handleClick}
active={type == selectedType ? true : false}
/>
</Grid>
))}
</Grid>
<Grid container pt={4} columnSpacing="20px" rowSpacing={'16px'}>
<Grid item xs={12} sm={12} md={6}>
<Controller
name="name"
render={({
// eslint-disable-next-line #typescript-eslint/no-unused-vars
field: { value, ...otherFieldProps },
fieldState,
}) => (
<TextField
fullWidth
id="sanctions-form-name"
label="Name"
variant="outlined"
helperText={
<p
style={{
position: 'relative',
left: -13,
fontSize: 12,
}}
>
Try to enter the full name or part of it. It is possible
to use original language or the Latin alphabet.
</p>
}
required
error={!!fieldState.error}
{...otherFieldProps}
/>
)}
/>
</Grid>
<Grid item xs={12} sm={6} md={3}>
<WSSelectBox
id="sanctions-form-residential-country"
label="Residential country"
name={'residentialCountry'}
data={['Ten', 'Twenty']}
handleSelect={() => {}}
type={'text'}
control={control}
/>
</Grid>
<Grid item xs={12} sm={6} md={3}>
<WSSelectBox
data={['Ten', 'Twenty']}
handleSelect={() => {}}
id="sanctions-form-initiator"
name={'initiator'}
label="Initiator"
type="text"
control={control}
/>
</Grid>
<Grid item xs={12} sm={6} md={6}>
<WSSelectBox
id="sanctions-form-program"
label="Program"
data={['Ten', 'Twenty']}
handleSelect={() => {}}
type="text"
name={'program'}
control={control}
/>
</Grid>
<Grid item xs={12} sm={6} md={6}>
<WSSelectBox
id="sanctions-form-list"
label="List"
data={['Ten', 'Twenty']}
handleSelect={() => {}}
type={'text'}
name={'list'}
control={control}
/>
</Grid>
</Grid>
<Grid
container
pt={{ xs: '20px', md: '30px' }}
rowSpacing="10px"
alignItems="center"
sx={{
[isMobile(theme)]: {
textAlign: 'center',
},
}}
justifyContent="left"
>
<Grid item xs={6} sm={'auto'}>
<Button
variant="contained"
color="primary"
sx={{
minWidth: '200px',
['#media (max-width:460px)']: {
minWidth: '120px',
},
}}
type="submit"
>
Search
</Button>
</Grid>
<Grid item xs={6} sm={'auto'}>
<Button
sx={{
minWidth: '200px',
color: '#3883FA',
['#media (max-width:460px)']: {
minWidth: '120px',
},
}}
type="submit"
>
Reset
</Button>
</Grid>
</Grid>
</form>
<Typography
variant="body2"
sx={{ fontSize: 17, color: '#121E3D', marginTop: '20px' }}
>
Use filters to start your search.
</Typography>
</FormProvider>
);
};
export default Entities;
SELECT BOX
import { TextField, MenuItem, styled, Select } from '#mui/material';
import { Controller, useForm } from 'react-hook-form';
export type SelectBoxProps = {
label: string;
id: string;
data: Array<string>;
handleSelect: VoidFunction;
type: string;
Control: () => {};
};
const SelectBox = styled(TextField)`
& .MuiOutlinedInput-root:focus {
&.Mui-focused fieldset {
border-bottom: none !important;
}
}
`;
const WSSelectBox = ({
label,
id,
data,
handleSelect,
name,
type,
control,
}) => {
return (
<>
<Controller
name={name}
render={({ field }) => (
<SelectBox
defaultValue=""
fullWidth
autoComplete="off"
id={id}
type={type}
label={label}
variant="outlined"
required
select
{...field}
>
{data.map((opt) => (
<MenuItem key={opt} value={opt}>
{opt}
</MenuItem>
))}
</SelectBox>
)}
control={control}
/>
</>
);
};
export default WSSelectBox;

Material ui Component "Select" does not set the chosen item. Selected item doesn't stay selected, and it renders very small

I got a help last week and I have 50% working of Select Component of Material ui V.5.0 and React 18.0. The list of Select is working properly with map function. The thing is that the selected item doesn't show, it doesn't stay selected. Also the size of the Select component is not accepting the width format. I've tried, Box and sx={{}}, and none of them worked. Please all helps will be very appreciated.
// Select is down bellow almost at the end. Above the button.
import React, { useState } from 'react';
import { Container } from '#mui/material';
import { Typography } from '#mui/material';
import { Box } from '#mui/material';
import { TextField } from '#mui/material';
import { makeStyles } from '#mui/styles';
import { Button } from '#mui/material';
import KeyboardArrowRightIcon from '#mui/icons-material/KeyboardArrowRight';
import Grid from '#mui/material/Grid';
// import Controls from '../components/Controls';
import Select from '../components/Select';
const initialValues = {
id: 0,
fullName: '',
address: '',
local: '',
city: '',
CEP: '',
phone: '',
contact: '',
email: '',
numBank: '',
branch: '',
account: '',
balance: '',
date: '',
stateId: '',
}
const useStyles = makeStyles((theme) => {
return{
root: {
display: "flex",
flexwrap: "wrap",
},
textField: {
margimLeft: theme.spacing(1),
margimRight: theme.spacing(1),
width: "25ch",
},
field: {
spacing: 2,
display: "block",
}
}
});
export default function Bancos(){
const classes = useStyles()
const [fullName, setFullName] = useState('');
const [address, setAddress] = useState('');
const [fullNameError, setFullNameError] = useState(false);
const [addressError, setAddressError] = useState(false);
const [numBank, setNumBank] = useState('');
const [branch, setBranch] = useState('');
const [account, setAccount] = useState('');
const [numBankError, setNumBankError] = useState(false);
const [branchError, setBranchError] = useState(false);
const [accountError, setAccountError] = useState(false);
const [ values, setValues ] = useState(initialValues);
const handleInputChange = e => {
const { name, value } = e.target
setValues({
...values,
[name]: value
})
}
const handleSubmit = (e) => {
e.preventDefault()
setFullNameError(false)
setAddressError(false)
if(fullName == ''){
setFullNameError(true)
}
if( address == ''){
setAddressError(true)
}
if ( numBank == ''){
setNumBankError(true)
}
if (branch == ''){
setBranchError(true)
}
if (account == ''){
setAccountError(true)
}
}
return(
<Container>
<form noValidate autoComplete="off" onSubmit={handleSubmit}>
<Typography variant="h6" color="textSecondary" align="center" gutterBottom
className="titleBank">
Cadastro de Bancos
</Typography>
<Grid container spacing={2}>
<Box mt={3} mb={1}> {/* colocar margim top e bottom com box */}
<Grid item xs={6} md={6}>
<TextField label="Nome do Banco" variant="outlined" color="secondary"
sx={{width: "430px", ml: 2}} required className={classes.field} name="fullName"
value={values.fullName} error={ fullNameError }
onChange={ handleInputChange }/>
</Grid></Box>
<Box mt={1}>
<Grid item xs={6} md={10} style={{ display: "flex" }}>
<TextField label="Endereço" variant="outlined" color="secondary"
sx={{width: "650px", mr: 1, ml: 2}} required className={classes.field} name="address"
value={values.address}
onChange={handleInputChange} error={addressError}/>
<TextField label="Bairro" className={classes.textField} name="local"
sx={{width: "350px" }} value={ values.local }
onChange={ handleInputChange } />
</Grid></Box>
<Grid item xs={6} md={10} style={{ display: "flex", margimLeft: 0}}>
<TextField label="Cidade" className={classes.field} name="city"
sx={{width: "320px", mr: 1 }} value={values.city}
onChange={ handleInputChange } />
<TextField label="CEP" className={classes.field} name="CEP"
sx={{width: "180px", mr: 1}} value={ values.CEP }
onChange={ handleInputChange }/>
<TextField label="Contato" className={classes.field} name="contact"
sx={{width: "350px", mr: 1 }} value={ values.contact}
onChange={ handleInputChange } />
</Grid>
<Grid item xs={6} md={10} style={{ display: "flex", margimLeft: 0}}>
<TextField label="Telefone" className={classes.field} name="phone"
sx={{width: "235px", mr: 1 }} value={ values.phone }
onChange={ handleInputChange } />
<TextField label="Celular" className={classes.field} name="phone"
sx={{width: "235px", mr: 1 }} value={ values.phone }
onChange={ handleInputChange } />
<TextField label="E-mail" className={classes.field} name="email"
sx={{width: "350px", mr: 1 }} value={values.email}
onChange={ handleInputChange } />
</Grid><br/>
<Grid item xs={6} md={10} style={{ display: "flex", margimLeft: 0}}>
<Box width="150px">
<Select sx={{width: "150px", mr: 1 }}
name="state"
label="Estado"
value={values.stateId}
onChange={handleInputChange}
options={Select.choices}
fullWidth
/> </Box>
<TextField label="Nº do Banco" className={classes.field} required
sx={{width: "100px", mr: 1 }} name="numBank" value={values.numBank}
onChange={ handleInputChange } error={ numBankError } />
<TextField label="Nº Agência" className={classes.field} name="branch"
sx={{width: "150px", mr: 1 }} value={ values.branch } required
onChange={ handleInputChange } error={ branchError } />
<TextField label="Nº Conta Corrente" className={classes.field} name="account"
sx={{width: "250px", mr: 1 }} value={ values.account } required
onChange={ handleInputChange } error={ accountError } />
<TextField label="Saldo R$" className={classes.field} name="balance"
sx={{width: "180px", mr: 1 }} value={ values.balance }
disabled />
</Grid><br/>
<Grid item xs={6} md={8} style={{ display: "flex" }}>
<Box mt={4}> {/* colocar margim top e bottom com box */}
<Button type="submit" variant="contained" color="primary"
endIcon={<KeyboardArrowRightIcon />}
>
Salvar
</Button>
</Box>
</Grid>
</Grid>
</form>
</Container>
)
}
import React from 'react'
import {FormControl, InputLabel, Select as MuiSelect, MenuItem } from '#mui/material';
// Selection of a State in Brazil
export default function Select(props) {
const choices = () => ([
{ id: '1', title: 'Acre'},
{ id: '2', title: 'Alagoas'},
{ id: '3', title: 'Amazonas' },
{ id: '4', title: 'Amapá' },
{ id: '5', title: 'Bahia' },
{ id: '6', title: 'Distrito Federal'},
{ id: '7', title: 'Espírito Santo' },
{ id: '8', title: 'Mato Grosso do Sul'},
{ id: '9', title: 'Mato Grosso'},
{ id: '10', title: 'Rio de Janeiro'},
{ id: '11', title: 'São Paulo' },
{ id: '12', title: 'Minas Gerais'},
{ id: '13', title: 'Paraná' },
]);
const { name, label, value, onChange } = props;
return (
<FormControl variant="outlined">
<InputLabel>{label}</InputLabel>
<MuiSelect label={label} name={name} value={value} onChange={onChange}>
<MenuItem value="">none</MenuItem>
{
choices().map(
item => (<MenuItem key={item.id} value={item.id}>{item.title}</MenuItem>)
)
}
</MuiSelect>
</FormControl>
)
}
About your question, the Select component width you could add fullWidth for FormControl in your Select component and about the selected item doesn't select problem, I revise your data structure and code and provide all below, you can try it, hope this can help you.
// Select is down below almost at the end. Above the button.
import React, { useState } from 'react';
import { Container } from '#mui/material';
import { Typography } from '#mui/material';
import { Box } from '#mui/material';
import { TextField } from '#mui/material';
import { makeStyles } from '#mui/styles';
import { Button } from '#mui/material';
import KeyboardArrowRightIcon from '#mui/icons-material/KeyboardArrowRight';
import Grid from '#mui/material/Grid';
// import Controls from '../components/Controls';
import Select from '../components/Select';
const initialValues = { id: '', title: ''}
const useStyles = makeStyles((theme) => {
return{
root: {
display: "flex",
flexwrap: "wrap",
},
textField: {
margimLeft: theme.spacing(1),
margimRight: theme.spacing(1),
width: "25ch",
},
field: {
spacing: 2,
display: "block",
}
}
});
export default function Bancos(){
const classes = useStyles()
const [fullName, setFullName] = useState('');
const [address, setAddress] = useState('');
const [fullNameError, setFullNameError] = useState(false);
const [addressError, setAddressError] = useState(false);
const [numBank, setNumBank] = useState('');
const [branch, setBranch] = useState('');
const [account, setAccount] = useState('');
const [numBankError, setNumBankError] = useState(false);
const [branchError, setBranchError] = useState(false);
const [accountError, setAccountError] = useState(false);
const [values, setValues] = useState(initialValues);
const handleInputChange = e => {
const { name, value } = e.target
setValues({id: e.target.value})
}
const handleSubmit = (e) => {
e.preventDefault()
setFullNameError(false)
setAddressError(false)
if(fullName == ''){
setFullNameError(true)
}
if( address == ''){
setAddressError(true)
}
if ( numBank == ''){
setNumBankError(true)
}
if (branch == ''){
setBranchError(true)
}
if (account == ''){
setAccountError(true)
}
}
return(
<Container>
<form noValidate autoComplete="off" onSubmit={handleSubmit}>
<Typography variant="h6" color="textSecondary" align="center" gutterBottom
className="titleBank">
Cadastro de Bancos
</Typography>
<Grid container spacing={2}>
<Box mt={3} mb={1}> {/* colocar margim top e bottom com box */}
<Grid item xs={6} md={6}>
<TextField label="Nome do Banco" variant="outlined" color="secondary"
sx={{width: "430px", ml: 2}} required className={classes.field} name="fullName"
value={values.fullName} error={ fullNameError }
onChange={ handleInputChange }/>
</Grid></Box>
<Box mt={1}>
<Grid item xs={6} md={10} style={{ display: "flex" }}>
<TextField label="Endereço" variant="outlined" color="secondary"
sx={{width: "650px", mr: 1, ml: 2}} required className={classes.field} name="address"
value={values.address}
onChange={handleInputChange} error={addressError}/>
<TextField label="Bairro" className={classes.textField} name="local"
sx={{width: "350px" }} value={ values.local }
onChange={ handleInputChange } />
</Grid></Box>
<Grid item xs={6} md={10} style={{ display: "flex", margimLeft: 0}}>
<TextField label="Cidade" className={classes.field} name="city"
sx={{width: "320px", mr: 1 }} value={values.city}
onChange={ handleInputChange } />
<TextField label="CEP" className={classes.field} name="CEP"
sx={{width: "180px", mr: 1}} value={ values.CEP }
onChange={ handleInputChange }/>
<TextField label="Contato" className={classes.field} name="contact"
sx={{width: "350px", mr: 1 }} value={ values.contact}
onChange={ handleInputChange } />
</Grid>
<Grid item xs={6} md={10} style={{ display: "flex", margimLeft: 0}}>
<TextField label="Telefone" className={classes.field} name="phone"
sx={{width: "235px", mr: 1 }} value={ values.phone }
onChange={ handleInputChange } />
<TextField label="Celular" className={classes.field} name="phone"
sx={{width: "235px", mr: 1 }} value={ values.phone }
onChange={ handleInputChange } />
<TextField label="E-mail" className={classes.field} name="email"
sx={{width: "350px", mr: 1 }} value={values.email}
onChange={ handleInputChange } />
</Grid><br/>
<Grid item xs={6} md={10} style={{ display: "flex", margimLeft: 0}}>
<Box width="150px" sx={{ mr: 1 }}>
<Select
name="state"
label="Estado"
value={values.id}
onChange={handleInputChange}
options={Select.choices}
fullWidth
/> </Box>
<TextField label="Nº do Banco" className={classes.field} required
sx={{width: "100px", mr: 1 }} name="numBank" value={values.numBank}
onChange={ handleInputChange } error={ numBankError } />
<TextField label="Nº Agência" className={classes.field} name="branch"
sx={{width: "150px", mr: 1 }} value={ values.branch } required
onChange={ handleInputChange } error={ branchError } />
<TextField label="Nº Conta Corrente" className={classes.field} name="account"
sx={{width: "250px", mr: 1 }} value={ values.account } required
onChange={ handleInputChange } error={ accountError } />
<TextField label="Saldo R$" className={classes.field} name="balance"
sx={{width: "180px", mr: 1 }} value={ values.balance }
disabled />
</Grid><br/>
<Grid item xs={6} md={8} style={{ display: "flex" }}>
<Box mt={4}> {/* colocar margim top e bottom com box */}
<Button type="submit" variant="contained" color="primary"
endIcon={<Link />}
>
Salvar
</Button>
</Box>
</Grid>
</Grid>
</form>
</Container>
)
}
import React from 'react'
import {FormControl, InputLabel, Select as MuiSelect, MenuItem } from '#mui/material';
// Selection of a State in Brazil
export default function Select(props) {
const choices = () => ([
{ id: '0', title: 'none'},
{ id: '1', title: 'Acre'},
{ id: '2', title: 'Alagoas'},
{ id: '3', title: 'Amazonas' },
{ id: '4', title: 'Amapá' },
{ id: '5', title: 'Bahia' },
{ id: '6', title: 'Distrito Federal'},
{ id: '7', title: 'Espírito Santo' },
{ id: '8', title: 'Mato Grosso do Sul'},
{ id: '9', title: 'Mato Grosso'},
{ id: '10', title: 'Rio de Janeiro'},
{ id: '11', title: 'São Paulo' },
{ id: '12', title: 'Minas Gerais'},
{ id: '13', title: 'Paraná' },
]);
const { name, label, value, onChange } = props;
return (
<FormControl variant="outlined" fullWidth>
<InputLabel>{label}</InputLabel>
<MuiSelect label={label} name={name} value={value} onChange={onChange}>
{
choices().map(
item => (<MenuItem key={item.id} value={item.id}>{item.title}</MenuItem>)
)
}
</MuiSelect>
</FormControl>
)
}
When I run the code I changed, the component working well like this:

AutoComplete: get the id for the user that i was choosen from users list, post request with status 400

I have this project and as it is clear in the postman, I have a request and through the request I must send the invoiceId to the invoice and the user ID must be sent in addition to a message, but the real problem is that I did not know how to get the user ID, the meaning is that when I printed “invoiceID” , "UserID "and "Message", the invoiceID and the message have a value, but UserID is worthless without value "undefined", and the reason is that I have list of the Users, and I must choose one user and then I want to pass this userID for the user that i was choosen and pass it in the "assignToUser" function, and i don't know how to do that.
And in the network I have these errors:
and in Network i have this errors:
enter image description here
how can i solve my problem?
invoiceSlice.js:
import { createSlice, createAsyncThunk } from "#reduxjs/toolkit";
import axios from "axios";
import FuseUtils from "#fuse/utils";
import { getInvoices } from "./invoicesSlice";
export const assignToUser = createAsyncThunk(
"invoicesApp/invoice/assignToUser",
async ({ invoiceId, userId, message }, { dispatch }) => {
console.log("invoiceId, userId, message", invoiceId, userId, message);
const response = await axios
.post(`/invoices/flow/${invoiceId}/approve`, { userId, message })
.catch((error) => {
console.log("error response: ", error);
});
const data = await response.data.data;
console.log("approve invoices: ", data);
dispatch(getInvoices());
return data;
}
);
const invoiceSlice = createSlice({
name: "invoicesApp/invoice",
initialState: null,
reducers: {
resetInvoice: () => null,
newInvoice: {
reducer: (state, action) => action.payload,
prepare: (event) => ({
payload: {
invoice: "",
netAmount: 0,
taxNumber: 0,
grossAmount: 0,
dueDate: "",
issueDate: "",
},
}),
},
},
extraReducers: {
[assignToUser.fulfilled]: (state, action) => action.payload,
},
});
export const { newInvoice, resetInvoice } = invoiceSlice.actions;
export default invoiceSlice.reducer;
approveUser.js:
import { Fragment, useState } from "react";
import { ButtonGroup } from "#material-ui/core";
import React from "react";
import Button from "#material-ui/core/Button";
import Dialog from "#material-ui/core/Dialog";
import DialogActions from "#material-ui/core/DialogActions";
import DialogContent from "#material-ui/core/DialogContent";
import DialogContentText from "#material-ui/core/DialogContentText";
import DialogTitle from "#material-ui/core/DialogTitle";
import useMediaQuery from "#material-ui/core/useMediaQuery";
import { useTheme } from "#material-ui/core/styles";
import { useSnackbar } from "notistack";
import Slide from "#material-ui/core/Slide";
import {
rejectInvoice,
approveInvoice,
assignToUser,
} from "../../store/invoiceSlice";
import { useDispatch, useSelector } from "react-redux";
import TextField from "#mui/material/TextField";
import FlagIcon from "#mui/icons-material/Flag";
import { makeStyles } from "#material-ui/core/styles";
import Autocomplete from "#mui/material/Autocomplete";
import { getUsers } from "../../store/invoiceSlice";
import { useEffect } from "react";
const useStyles = makeStyles((theme) => ({
paper: { padding: "3rem", maxWidth: "990px", minWidth: "300px" },
textStyle: {
paddingLeft: "2rem",
},
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
font: {
fontSize: "5rem",
},
}));
const GroupButttonApproveStatus = (id) => {
const [dialogOpen, setDialogOpen] = useState(false);
const [confirmDialogOpen, setConfirmDialogOpen] = useState(false);
const [assignToUserDialog, setAssignToUserDialog] = useState(false);
const { enqueueSnackbar, closeSnackbar } = useSnackbar();
const dispatch = useDispatch();
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down("sm"));
const AssignToUserFullScreen = useMediaQuery(theme.breakpoints.down("md"));
const classes = useStyles();
const [users, setUsers] = useState([]);
const [message, setMessage] = useState("");
useEffect(() => {
getUsers().then((response) => {
setUsers(response);
});
}, []);
// confirm
console.log("users: ", users);
const handleAssignToUserDialogOpen = () => {
setAssignToUserDialog(true);
};
const handleAssignToUserDialogClose = () => setAssignToUserDialog(false);
// end assign to user
const handleConfirmDialogClose = () => setConfirmDialogOpen(false);
const handleClickConfirmDialogOpen = () => {
setConfirmDialogOpen(true);
};
//end confirm
const handleDialogClose = () => setDialogOpen(false);
const handleClickOpen = () => {
setDialogOpen(true);
};
const handleClose = () => {
setDialogOpen(false);
};
const rejectInvoiceHandleClick = () => {
enqueueSnackbar(
"Invoice rejected successfully",
{ variant: "error" },
{
anchorOrigin: {
vertical: "top",
horizontal: "right",
},
},
{ TransitionComponent: Slide }
);
};
const approveInvoiceHandleClick = () => {
enqueueSnackbar(
"Invoice approved successfully",
{ variant: "success" },
{
anchorOrigin: {
vertical: "top",
horizontal: "right",
},
},
{ TransitionComponent: Slide }
);
};
return (
<Fragment>
<ButtonGroup size="large">
<Button
onClick={(ev) => {
handleClickConfirmDialogOpen();
}}
>
Approve
</Button>
<Button
onClick={(ev) => {
handleClickOpen();
}}
>
Reject
</Button>
<Button
onClick={(ev) => {
handleAssignToUserDialogOpen();
}}
>
Assign to User to approve
</Button>
</ButtonGroup>
{/* reject Dialog */}
<Dialog
classes={{ paper: classes.paper }}
maxWidth="sm"
fullScreen={fullScreen}
open={dialogOpen}
onClose={handleDialogClose}
>
<DialogTitle style={{ fontWeight: "bold" }}>Reject Invoice</DialogTitle>
<DialogContent>
<div
style={{
backgroundColor: "#F8F9FA",
borderRadius: 10,
padding: "3rem",
}}
>
<DialogContentText>
<FlagIcon
style={{ fontSize: 40, color: "#dc3c24", paddingRight: "1rem" }}
/>
Do you really want to reject this invoice ?
</DialogContentText>
<DialogContentText>
<FlagIcon
style={{ fontSize: 40, color: "#F8F9FA", paddingRight: "1rem" }}
/>
Keep in mind that once the invoice is rejected you won’t be able
to proceed with it.
</DialogContentText>
</div>
</DialogContent>
<DialogActions>
<div style={{ paddingRight: "1rem" }}>
<Button
onClick={handleClose}
style={{ color: "#dc3c24", fontWeight: 500 }}
autoFocus
>
Cancel
</Button>
<Button
onClick={(ev) => {
dispatch(rejectInvoice(id?.id));
rejectInvoiceHandleClick(ev);
handleClose();
}}
style={{ color: "#212529", fontWeight: 500 }}
color="primary"
autoFocus
>
Reject Invoice
</Button>
</div>
</DialogActions>
</Dialog>
{/* End reject Dialog */}
{/* Confirm Dialog */}
<Dialog
classes={{ paper: classes.paper }}
maxWidth="sm"
fullScreen={fullScreen}
open={confirmDialogOpen}
onClose={handleConfirmDialogClose}
>
<DialogTitle style={{ fontWeight: "bold" }}>
Approve Invoice
</DialogTitle>
<DialogContent>
<div
style={{
backgroundColor: "#F8F9FA",
borderRadius: 10,
padding: "3rem",
}}
>
<DialogContentText>Almost ready for payment !</DialogContentText>
<DialogContentText>
By confirming you mark this invoice ready for approval.
</DialogContentText>
</div>
</DialogContent>
<DialogActions>
<div style={{ paddingRight: "1rem" }}>
<Button
onClick={handleConfirmDialogClose}
style={{ color: "#dc3c24", fontWeight: 500 }}
autoFocus
>
Cancel
</Button>
<Button
onClick={(ev) => {
dispatch(approveInvoice(id?.id));
approveInvoiceHandleClick(ev);
handleConfirmDialogClose();
}}
style={{ color: "#212529", fontWeight: 500 }}
color="primary"
autoFocus
>
yes, Confirm
</Button>
</div>
</DialogActions>
</Dialog>
{/* End Confirm Dialog */}
{/* assign to user dialog */}
<Dialog
classes={{ paper: classes.paper }}
maxWidth="sm"
fullScreen={AssignToUserFullScreen}
open={assignToUserDialog}
onClose={handleAssignToUserDialogClose}
>
<DialogTitle style={{ fontWeight: "bold", fontSize: "3rem" }}>
Request approval
</DialogTitle>
<div
style={{
backgroundColor: "#F8F9FA",
borderRadius: 10,
padding: "2rem",
paddingLeft: "2rem",
}}
>
<DialogContentText style={{ fontWeight: 600 }}>
{" "}
<FlagIcon
style={{ fontSize: 40, color: "#aacc00", paddingRight: "1rem" }}
/>
Send an invoice approval request to a team member.
</DialogContentText>
<DialogContentText style={{ paddingLeft: 10 }}>
The assigned member will receive a notification asking them to
approve this invoice. Once they accept, payment is on the way!
</DialogContentText>
</div>
<DialogTitle>Assign a member to approve</DialogTitle>
<DialogContent>
<Autocomplete
id="combo-box-demo"
// value={users || ""}
options={users || []}
getOptionLabel={(option) => option.name || ""}
sx={{ width: 860 }}
renderInput={(params) => (
<TextField
{...params}
placeholder="Search Member"
fullWidth
InputProps={{ ...params.InputProps, style: { fontSize: 17 } }}
InputLabelProps={{ style: { fontSize: 17 } }}
/>
)}
/>
</DialogContent>
<DialogContent style={{ marginTop: "15rem" }}>
<form className={classes.root} noValidate autoComplete="off">
<TextField
value={message}
onChange={(e) => setMessage(e.target.value)}
id="outlined-basic"
variant="outlined"
placeholder="Add a message"
fullWidth
size="medium"
InputProps={{ style: { fontSize: 17 } }}
InputLabelProps={{ style: { fontSize: 17 } }}
/>
</form>
</DialogContent>
<DialogActions>
<div style={{ paddingRight: "1rem" }}>
<Button
onClick={handleAssignToUserDialogClose}
style={{ color: "#dc3c24", fontWeight: 500 }}
autoFocus
>
Cancel
</Button>
<Button
onClick={(ev) => {
dispatch(assignToUser(id?.id, users.id, message));
approveInvoiceHandleClick(ev);
handleAssignToUserDialogClose();
}}
style={{ color: "#212529", fontWeight: 500 }}
color="primary"
autoFocus
>
Assign to approve
</Button>
</div>
</DialogActions>
</Dialog>
</Fragment>
);
};
export default GroupButttonApproveStatus;
invoiceDetails.js:
import React from "react";
import { getInvoice } from "../../store/invoiceSlice";
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import Grid from "#material-ui/core/Grid";
import TextField from "#material-ui/core/TextField";
import moment from "moment";
import InputAdornment from "#material-ui/core/InputAdornment";
import TodayIcon from "#material-ui/icons/Today";
import { makeStyles } from "#material-ui/core/styles";
import RejectDialog from "./rejectDialog";
import GroupButton from "./groupButttonReviewStatus";
import GroupButttonReviewStatus from "./groupButttonReviewStatus";
import GroupButttonApproveStatus from "./groupButtonApproveStatus";
import GroupButttonPaymentStatus from "./groupButtonPaymentStatus";
import useMediaQuery from "#material-ui/core/useMediaQuery";
import { useTheme } from "#material-ui/core/styles";
const useStyles = makeStyles((theme) => ({
root: {
"& > *": {
margin: theme.spacing(1),
},
},
input: {
display: "none",
},
button: {
margin: theme.spacing(1),
// padding: theme.spacing(4),
},
}));
const InvoiceDetails = () => {
const classes = useStyles();
const theme = useTheme();
const routeParams = useParams();
const [invoice, setInvoice] = useState([]);
const [open, setOpen] = React.useState(false);
const anchorRef = React.useRef(null);
const [selectedIndex, setSelectedIndex] = React.useState(1);
const breakpoint = useMediaQuery(theme.breakpoints.down("sm"));
// const defaultLayoutPluginInstance = defaultLayoutPlugin();
useEffect(() => {
getInvoice(routeParams).then((response) => {
setInvoice(response);
});
}, []);
const handleClick = () => {
console.info(`You clicked ${options[selectedIndex]}`);
};
const handleMenuItemClick = (event, index) => {
setSelectedIndex(index);
setOpen(false);
};
const handleToggle = () => {
setOpen((prevOpen) => !prevOpen);
};
const handleClose = (event) => {
if (anchorRef.current && anchorRef.current.contains(event.target)) {
return;
}
setOpen(false);
};
console.log("invoice url: ", invoice?.file?.url);
console.log("invoice tara : ", invoice);
const statusGropButton = (status, id) => {
switch (status) {
case "review_pending":
return <GroupButttonReviewStatus id={id} />;
case "approval_pending":
return <GroupButttonApproveStatus id={id} />;
case "payment_pending":
return <GroupButttonPaymentStatus id={id} />;
case "rejected":
return <GroupButton id={id} />;
default:
return;
}
};
return (
<>
<Grid container>
<Grid item xs={7} sm={7}>
{/* pdf viewer */}
<object
// data={invoice?.file?.url}
data="https://documentcloud.adobe.com/view-sdk-demo/PDFs/Bodea%20Brochure.pdf"
type="application/pdf"
width="100%"
height="100%"
>
<p>
Alternative text - include a link{" "}
<a href="https://documentcloud.adobe.com/view-sdk-demo/PDFs/Bodea%20Brochure.pdf">
to the PDF!
</a>
</p>
</object>
</Grid>
<Grid item xs={5} sm={5} style={{ padding: "4rem" }}>
<Grid item>
<h1 style={{ fontWeight: "bold" }}>Invoice Details</h1>
</Grid>
<Grid item style={{ marginTop: "3rem", marginBottom: "2rem" }}>
<Grid item style={{ marginBottom: 10 }}>
<h3>From</h3>
</Grid>
<Grid item>
<h3>{invoice?.submittedBy?.name || ""}</h3>
</Grid>
<Grid item>
<h3>{invoice?.submittedBy?.email || ""}</h3>
</Grid>
</Grid>
<Grid item>
<Grid container item direction={breakpoint ? "row" : "column"}>
<Grid
container
item
xs={3}
sm={3}
direction="row"
justifyContent="flex-start"
alignItems="center"
>
<h3>Invoice ID</h3>
</Grid>
<Grid item xs={12} sm={12}>
<TextField
className="mt-8 mb-16"
id="outlined-size-normal"
value={invoice.id || ""}
variant="outlined"
fullWidth
/>
</Grid>
</Grid>
<Grid container item direction={breakpoint ? "row" : "column"}>
<Grid
container
item
xs={3}
sm={3}
direction="row"
justifyContent="flex-start"
alignItems="center"
>
<h3>Issue Date</h3>
</Grid>
<Grid item xs={12} sm={12}>
<TextField
className="mt-8 mb-16"
id="outlined-size-normal"
value={
moment(moment.utc(invoice.issueDate).toDate())
.local()
.format("YYYY-MM-DD HH:mm:ss") || ""
}
variant="outlined"
InputProps={{
endAdornment: (
<InputAdornment position="start">
<TodayIcon />
</InputAdornment>
),
}}
fullWidth
/>
</Grid>
</Grid>
<Grid container item direction={breakpoint ? "row" : "column"}>
<Grid
container
item
xs={3}
sm={3}
direction="row"
justifyContent="flex-start"
alignItems="center"
>
<h3>Due Date</h3>
</Grid>
<Grid item xs={12} sm={12}>
<TextField
className="mt-8 mb-16"
id="outlined-size-normal"
value={
moment(moment.utc(invoice.dueDate).toDate())
.local()
.format("YYYY-MM-DD HH:mm:ss") || ""
}
variant="outlined"
InputProps={{
endAdornment: (
<InputAdornment position="start">
<TodayIcon />
</InputAdornment>
),
}}
fullWidth
/>
</Grid>
</Grid>
<Grid container item direction={breakpoint ? "row" : "column"}>
<Grid
container
item
xs={3}
sm={3}
direction="row"
justifyContent="flex-start"
alignItems="center"
>
<h3>Net Amount</h3>
</Grid>
<Grid item xs={12} sm={12}>
<TextField
className="mt-8 mb-16"
id="outlined-size-normal"
value={invoice.netAmount || ""}
variant="outlined"
fullWidth
/>
</Grid>
</Grid>
<Grid container item direction={breakpoint ? "row" : "column"}>
<Grid
container
item
xs={3}
sm={3}
direction="row"
justifyContent="flex-start"
alignItems="center"
>
<h3>Tax Number</h3>
</Grid>
<Grid item xs={12} sm={12}>
<TextField
className="mt-8 mb-16"
id="outlined-size-normal"
value={invoice.taxNumber || ""}
variant="outlined"
fullWidth
/>
</Grid>
</Grid>
<Grid container item direction={breakpoint ? "row" : "column"}>
<Grid
container
item
xs={3}
sm={3}
direction="row"
justifyContent="flex-start"
alignItems="center"
>
<h3>Gross Amount</h3>
</Grid>
<Grid item xs={12} sm={12}>
<TextField
className="mt-8 mb-16"
// label="Size"
id="outlined-size-normal"
value={invoice.grossAmount || ""}
variant="outlined"
fullWidth
/>
</Grid>
</Grid>
<Grid
container
direction="row"
justifyContent="center"
alignItems="center"
style={{ marginTop: "3rem" }}
>
<Grid item>{statusGropButton(invoice.status, invoice?.id)}</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
</>
);
};
export default InvoiceDetails;
and this code:
useEffect(() => {
getUsers().then((response) => {
setUsers(response);
});
}, []);
return:
Based on your code I observed this.
You are already passing invoice?.id in statusGropButton(invoice.status, invoice?.id) method.
You are again expecting id from the input as id?.id in assignToUser(id?.id, users.id, message). Why?
Just assuming, because of that the invoiceId is going as undefined. Try by passing just id instead of id?.id while calling the api functions.
You are opening a Dialogue by using assignToUserDialog flag. While submitting the form, you are doing dispatch(assignToUser(id?.id, users.id, message)); in which users is an array. That is the reason you are getting undefined. I would suggest you maintain the specific user information for which the dialogue is opened and send that specifc user.id to the API call.
invoiceId undefined when send request ,you could check assignToUser

Problem autoFocus Autocomplete Material UI

I am not able to focus on the first element of my form which is an Autocomplete component of the Material UI.
When opening the modal, the focus is on the 'unit' element, as shown in the image below:
It dont's work
I want the focus to be on the 'group' element, as shown below:
It work
Here is the Sandbox link:
https://codesandbox.io/s/awesome-bassi-zjp50?file=/src/MyForm.jsx:1422-1431
can anyone help me?
MyForm
import React from "react";
import { Formik, Form, Field } from "formik";
import * as Yup from "yup";
import { Grid } from "#material-ui/core";
import Input from "./components/Input";
import Autocomplete from "./components/Autocomplete";
const initialValues = {
id: 0,
group: {
value: 0,
label: ""
},
name: "",
unit: {
value: 0,
label: ""
}
};
const groupList = [
{
value: "1",
label: "Seeds"
},
{
value: "2",
label: "Fertilizers"
}
];
const unitList = [
{
value: "1",
label: "kg"
},
{
value: "2",
label: "t"
}
];
const validationSchema = Yup.object({
group: Yup.object().shape({
value: Yup.number().required().min(1).nullable()
}),
name: Yup.string().required().max(50),
unit: Yup.object().shape({
value: Yup.number().required().min(1).nullable()
})
});
export default function MyForm() {
function _onSubmit(fields, { props, setErrors, setSubmitting }) {
console.log(fields);
}
return (
<Formik
enableReinitialize={true}
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={_onSubmit}
>
{function Render({ errors, touched, isSubmitting, setFieldValue }) {
return (
<Form id="form">
<Grid container direction="row">
<Grid item xs={12}>
<Field
name="group"
autoFocus
component={Autocomplete}
label="Group"
options={groupList}
disabled={isSubmitting}
textFieldProps={{
fullWidth: true,
margin: "dense",
variant: "outlined"
}}
/>
</Grid>
<Grid item xs={12}>
<Field
name="name"
fullWidth
label="Name"
disabled={isSubmitting}
component={Input}
/>
</Grid>
<Grid item xs={12}>
<Field
name="unit"
component={Autocomplete}
label="Unit"
options={unitList}
disabled={isSubmitting}
textFieldProps={{
fullWidth: true,
margin: "dense",
variant: "outlined"
}}
/>
</Grid>
</Grid>
</Form>
);
}}
</Formik>
);
}
Popup Modal
import React from "react";
import {
Dialog,
DialogTitle,
DialogContent,
makeStyles,
Typography,
Divider,
DialogActions,
Button,
Grid,
Box
} from "#material-ui/core";
const useStyles = makeStyles((theme) => ({
dialogWrapper: {
padding: theme.spacing(2),
position: "absolute",
top: theme.spacing(5)
},
dialogTitle: {
paddingRight: 0
},
button: {
margin: theme.spacing(0.5),
textTransform: "none"
},
buttonsContainer: {
display: "flex",
flex: "0 0 auto",
justifyContent: "flex-end",
width: "100%",
height: "100%"
},
buttons: {
display: "flex"
},
loadingIcon: {
display: "flex",
alignItems: "center",
justifyContent: "center",
marginRight: theme.spacing(1)
}
}));
function Popup(props) {
const classes = useStyles();
const { title, children, openPopup, setOpenPopup, ...rest } = props;
return (
<Dialog
{...rest}
open={openPopup}
maxWidth="sm"
classes={{ paper: classes.dialogWrapper }}
>
<DialogTitle dividers="true" className={classes.dialogTitle}>
<div style={{ display: "flex" }}>
<Typography variant="h4" component="div" style={{ flexGrow: 1 }}>
{title}
</Typography>
</div>
</DialogTitle>
<Divider />
<DialogContent {...rest} direction="row">
{children}
</DialogContent>
<DialogActions {...rest}>
<Grid {...rest} container className={classes.buttonsContainer}>
<Box {...rest} className={classes.buttons}>
<Button
className={classes.button}
variant="contained"
color="primary"
type="submit"
form="form"
{...rest}
>
Save
</Button>
<Button
className={classes.button}
color="default"
fullWidth
onClick={() => {
setOpenPopup(false);
}}
{...rest}
>
Cancel
</Button>
</Box>
</Grid>
</DialogActions>
</Dialog>
);
}
export default Popup;
Autocomplete
import React from "react";
import { FieldProps, getIn } from "formik";
import { TextField, CircularProgress } from "#material-ui/core";
import MuiAutocomplete, {
createFilterOptions
} from "#material-ui/lab/Autocomplete";
const NewAutocomplete: React.FC<
FieldProps & {
label?: string,
options: Array<{ label: string, value: number }>
}
> = ({ textFieldProps, field, form, label, options, isLoading, ...props }) => {
const filterOptions = createFilterOptions({
matchFrom: "start",
limit: 500
});
const errorText =
getIn(form.touched, field.name) && getIn(form.errors, field.name);
const valueInit = [
{
value: 0,
label: ""
}
];
return (
<MuiAutocomplete
{...props}
{...field}
filterOptions={filterOptions}
options={[...valueInit, ...options]}
getOptionLabel={(option) => (option ? option.label : "")}
getOptionSelected={(option, value) => option.value === value?.value}
style={{ width: 300 }}
loading={isLoading}
value={field.value}
onChange={(e, value) => {
form.setFieldValue(field.name, value);
}}
renderInput={(props) => (
<>
<TextField
{...props}
{...textFieldProps}
label={label}
helperText={errorText?.value || errorText}
error={!!errorText}
autoFocus
InputProps={{
...props.InputProps,
endAdornment: (
<React.Fragment>
{isLoading ? (
<CircularProgress color="primary" size={20} />
) : null}
{props.InputProps.endAdornment}
</React.Fragment>
)
}}
/>
</>
)}
/>
);
};
export default NewAutocomplete;
Thanks for your help!
You're actually setting autoFocus to true on TextField by default inside your NewAutocomplete definition (src/components/Autocomplete.jsx:50 in your sandbox).
Once that line removed, you can then add autoFocus: true to textFieldProps value of your first Field in MyForm component.
See codesandbox example

Transfer data to dialog box when clicked

I would like when clicking on my accordion, the data in this line will go into the form of my dialog box. But I am not receiving any data in the form.
Why is the form not receiving the data?
import React, { useEffect, useState } from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import moment from 'moment';
import PerfectScrollbar from 'react-perfect-scrollbar';
import {
Avatar,
Box,
Card,
Accordion,
AccordionSummary,
AccordionDetails,
Grid,
SvgIcon,
InputAdornment,
CardContent,
TextField,
ListItemText,
ListItem,
List,
Checkbox,
Table,
TableBody,
TableCell,
TableHead,
TablePagination,
IconButton,
Typography,
makeStyles,
Button
} from '#material-ui/core';
import ExpandMoreIcon from '#material-ui/icons/ExpandMore';
import getInitials from 'src/utils/getInitials';
import EditProjAdminE from './editProjAdminE';
import AjoutEven from './ajoutEven';
import dataEven from './data';
import SpeedDialTooltipOpen from './speedDialE';
import EditIcon from '#material-ui/icons/Edit';
import AddIcon from '#material-ui/icons/Add';
import { Search as SearchIcon } from 'react-feather';
import { Slide } from 'react-slideshow-image';
import axios from "axios";
import DeleteIcon from '#material-ui/icons/Delete';
const useStyles = makeStyles((theme) => ({
root: {},
absolute: {
position: 'absolute',
bottom: theme.spacing(2),
right: theme.spacing(3),
},
avatar: {
marginRight: theme.spacing(2)
}
}));
const ProjetAdminE = ({ className, dataEleve, ...rest }) => {
const classes = useStyles();
// const [data, setData] = useState(dataEven);
const [filteredEven, setFilteredEven] = useState([]);
const [dataSearch, setDataSearch] = useState([]);
const [loading, setLoading] = useState(false);
const [limit, setLimit] = useState(10);
const [page, setPage] = useState(0);
const [selectedeleveIds, setSelectedeleveIds] = useState([]);
// const dateR = new Date()
// const dateReel = dateR.setDate(dateR.getDate()+1);
const handleLimitChange = (event) => {
setLimit(event.target.value);
};
const handlePageChange = (event, newPage) => {
setPage(newPage);
};
const [search, setSearch] = useState('');
useEffect(() => {
setLoading(true);
axios
.get("http://localhost:8080/employees")
.then((res) => {
setDataSearch(res.data);
setLoading(false);
})
.catch((err) => {
console.log(err);
});
}, []);
const suppression = (id) => {
fetch('http://localhost:8080/evenement/' + id, {
method: 'DELETE',
})
.then(res => res.text())
.then(res => {
// setDataSearch(res.data);
console.log(res)
})
alert(JSON.stringify("événement Numéro " + id + " supprimé"))
}
// const modification =(id) =>{
// fetch('http://localhost:8080/update/' + id, {
// method: 'PUT',
// })
// .then(res => res.text())
// .then(res => console.log(res))
// alert(JSON.stringify("événement Numéro " +id+ " modifié"))
// }
// alert(JSON.stringify(index))
useEffect(() => {
setFilteredEven(
dataSearch.filter((Evenen) =>
Evenen.descrip_evene.toLowerCase().includes(search.toLowerCase())
)
);
}, [search, dataSearch]);
return (
<Card
className={clsx(classes.root, className)}
{...rest}
>
<>
<Box
display="flex"
justifyContent="left"
style={{ height: 30 }}
>
<Typography variant="h3" style={{ margin: 10, color: '#1565C0' }}>
LISTE DES EVENEMENTS
</Typography>
</Box>
<Box mt={3}>
<Card>
<CardContent>
<Box maxWidth={500}>
<TextField
value={search}
onChange={e => {
setSearch(e.target.value);
}}
fullWidth
InputProps={{
startAdornment: (
<InputAdornment position="start">
<SvgIcon
fontSize="small"
color="action"
>
<SearchIcon />
</SvgIcon>
</InputAdornment>
)
}}
placeholder="Recherchez un évenement"
variant="outlined"
/>
</Box>
{/* <Button
color="primary"
variant="contained"
onClick = {alert(JSON.stringify(dateReel))}
>
Rechercher
</Button> */}
</CardContent>
</Card>
</Box>
<Grid>
<Grid spacing={1} md={8} xs={12} style={{ margin: 2 }}>
{filteredEven.map((recherche, index) => (
<Accordion style={{ marginTop: 30 }} >
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
style={{ backgroundColor: '#DADFD9' }}
>
<Grid container spacing={1} md={12} xs={12} style={{ margin: 0 }}>
<Grid item md={2} xs={4}>
{recherche.date_even.slice(0, 10)}
</Grid>
<Grid item md={2} xs={2}>
{recherche.prix_even}
</Grid>
<Grid item md={2} xs={3}>
{recherche.statut}
</Grid>
<Grid item md={3} xs={3}>
{recherche.descrip_evene}
</Grid>
<Grid item md={3} xs={8} style={{ marginTop: -10 }}>
<IconButton>
<EditProjAdminE
dataSearch={dataSearch}
setDataSearch={setDataSearch}
id={recherche.id}
/>
</IconButton>
<IconButton
onClick={async () => {
suppression(recherche.id)
window.location.reload(false)
}}
>
<DeleteIcon fontSize="small" style={{ color: 'black' }} />
</IconButton>
{/* <SpeedDialTooltipOpen/> */}
</Grid>
</Grid>
</AccordionSummary>
<AccordionDetails>
<List>
<ListItem>
<ListItemText primary={
<Typography variant="caption" style={{ fontWeight: 'bold', fontSize: 16 }}>
{recherche.id}
</Typography>
}
secondary="Membre concerné"
/>
</ListItem>
<ListItem>
<ListItemText primary={
<Typography variant="caption" style={{ fontWeight: 'bold', fontSize: 16 }}>
{recherche.lieu}
</Typography>
}
secondary="Lieu"
/>
</ListItem>
<ListItem>
<ListItemText primary={
<Typography variant="caption" style={{ fontWeight: 'bold', fontSize: 16 }}>
{recherche.heure}
</Typography>
}
secondary="Heure"
/>
</ListItem>
</List>
</AccordionDetails>
</Accordion>
))}
</Grid>
</Grid>
<AjoutEven />
</>
</Card>
);
};
// Results.propTypes = {
// className: PropTypes.string,
// dataEleve: PropTypes.array.isRequired
// };
export default ProjetAdminE;
editProjetEven.js
import React, { useState } from 'react';
import clsx from 'clsx';
import PropTypes from 'prop-types';
import moment from 'moment';
import PerfectScrollbar from 'react-perfect-scrollbar';
import { makeStyles, useTheme, withStyles } from '#material-ui/core/styles';
import {
Button,
Grid,
MenuItem,
DialogContent,
DialogActions,
Dialog,
IconButton,
Avatar,
TextField,
DialogTitle,
} from '#material-ui/core';
import getInitials from 'src/utils/getInitials';
import CreateIcon from '#material-ui/icons/Create';
import EditIcon from '#material-ui/icons/Edit';
import DeleteIcon from '#material-ui/icons/Delete';
const useStyles = makeStyles((theme) => ({
root: {
width: 645,
},
item: {
height: 50
},
buttonDial: {
color: "#fff",
},
buttonAnnuler: {
color: "red"
},
buttonSave: {
background: "#558b2f",
color: "#558b2f",
}
}));
export default function EditProjAdminE(setDataSearch,dataSearch,data,setData,id,index) {
const classes = useStyles();
const [open, setOpen] = React.useState(false);
const [opens, setOpens] = React.useState(false);
const handleChange = event => {
const { name, value } = event.target
setDataSearch({ ...dataSearch, [name]: value })
}
// const fullScreen = useMediaQuery(theme.breakpoints.down(645));
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
// const handleInputChange = event => {
// const { name, value } = event.target
// setData({ ...data, [name]: value })
// }
// const item = dataSearch.find(id);
return (
<div>
<div display="flex">
<IconButton onClick={handleClickOpen}>
<EditIcon fontSize="small" alt="modifier" style={{ color: '#205723' }} />
</IconButton>
</div>
<Dialog
fullWidth
// fullScreen
open={open }
onClose={handleClose}
aria-labelledby="responsive-dialog-title"
maxWidth = 'md'
>
{/* { index ==="" ? "aucune information":
<> */}
<DialogTitle id="responsive-dialog-title">Virement</DialogTitle>
<DialogContent >
<Grid container spacing={1}>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="prix_even"
value={dataSearch.prix_even}
// defaultValue={dataSearch.prix_even}
label="Prix"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="heure"
value={dataSearch.heure}
label="Heure"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="lieu"
value={dataSearch.lieu}
label="Lieu"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="date"
name="date_even"
value={dataSearch.date_even}
helperText="Date de l'événement"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="descrip_even"
value={dataSearch.descrip_even}
label="Descr de l'événement"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
<Grid item md={4} xs={12}>
<TextField
fullWidth
margin="dense"
type="text"
name="statut"
value={dataSearch.statut}
label="Statut"
variant="outlined"
onChange={(event) => handleChange(event)}
/>
</Grid>
</Grid>
</DialogContent>
<DialogActions>
<Button
// onClick={alert(JSON.stringify(dataSearch))}
>
Modifier
</Button>
<Button onClick={handleClose} className={classes.buttonAnnuler}>
Fermer
</Button>
</DialogActions>
{/* </>
} */}
</Dialog>
</div>
);
}
on click I pass the index of the object to the array and send it to a new array that I created
<IconButton onClick={async () => {
setData({ ...dataSearch[index] })
handleClickOpen()
}}
>
<EditIcon fontSize="small" alt="modifier" style={{ color: '#205723' }} />
</IconButton>
The handleClickOpen seems to be only opening the dialog box and not invoking setDataSearch({ ...dataSearch, [name]: value }) which seems to be responsible to add values to the dataSearch object that is used in your form fields.
I would personally double check if the EditProjAdminE component is receiving the proper dataSearch and then later call a similar function to handleChange when the open event is triggered.

Resources