Reserving seats system in react - node.js

I am trying to make a reserving seats for my airline website. I have done a reserve seats button, when pressed, a page pops up, where it has the array of current available seats and checkboxes besides it in-order to choose your seats. All of these are going fine, but the thing is that when I checkboxes or remove the checkboxes, I need to save the values that I've checked in another array to send them back to the backend and in the backend, I am going to compare it to the previous array and remove the seats that have been chosen.
function Row(props){
const [AvailableFSeats, setfs] = useState();
const [fList,setfList]= useState([]);
const checkf= [];
useEffect(() => {
setfList(props.row.AvailableFSeats);
},[])
const handleChange = (event) => {
setState({
...state,
[event.target.name]: event.target.checked,
});
//checkf should be the array that contains the chosen seats in the current action.
if(event.target.name==="AvailableFSeats"&&event.target.checked===true){
checkf.push(event.target.label);}
}
const {AvailableFFSeats, AvailableEESeats, AvailableBBSeats} = state;
return(
<Box sx={{ display: 'flex' }}>
<FormControl sx={{ m: 3 }} component="fieldset" variant="standard">
<FormLabel component="legend">First Class Seats</FormLabel>
<FormGroup>
{fList.map(AvailableFSeats => (
<FormControlLabel
control={
<Checkbox checked={AvailableFFSeats} onChange={handleChange} name="AvailableFSeats" />
}
label={AvailableFSeats}
/>)
)}
</FormGroup>
</FormControl>
</Box>
)
}

Related

Re-fetching data automatically when Database values changes

Inside my react App, i have a component that shows a list of data fetched from my database.
Now i would like to refresh my component every "X" seconds so if the database values have changed, my component will show also those new values.
Here's my code...
const SingleBet = () => {
const { data } = useGetAllBetsQuery() //REDUX FETCH
return (
<Paper sx={{marginTop:"10px", background:"white"}}>
<Grid container xs={12} sx={{display:"flex", flexDirection:"row", height:"50px"}}>
//ITEMS NO NEEDED
</Grid>
{data.map((data, index) => {
return (
<Paper sx={sxPaperList} key={index}>
<Grid container rowSpacing={2} sx={sxGridContainer}>
<Grid item xs={4} >
{data.ImportoG1 > 0 ? (
<Typography variant="h6" sx={sxTypographyNames}>{data.Giocatore1}
<img src={star} alt="little_star" height="15"/></Typography>
) : (
<Typography variant="h6" sx={sxTypographyNames}>
{data.Giocatore1}
</Typography>
)}
//OTHER THINGS LIKE THIS
</Grid>
</Paper>
)
})}
</Paper>
)
}
How u can see i fetch data from my DATABASE using redux. Now i would like to refresh this component every 5 seconds so that if DATABASE changes, every 5 seconds my component refreshes and show new values
I tried playing with useEffect but i couldnt reach to get any good results. Please help me :D
Here's my useGetAllBetsQuery() code
export const liveApi = createApi({
reducerPath: "liveApi",
baseQuery: fetchBaseQuery({baseUrl: URL}),
endpoints: (builder) => ({
getAllBets: builder.query({
query: () => "live",
})
})
})
export const { useGetAllBetsQuery } = liveApi

Queshtion about removing an item for a map

Im having trouble configuring a remove function for my shopping-list project, the purpose of the project is to make a shopping list with a checkbox, a quantity and an item name, but there's another feature that i can't figure out how to add it, i want to a button
( ), that will remove the selected item, now, the item are mapped, which means they are in lines, if i write ("milk", "2") and then ("milk","3"), it will go line after line, like this:
milk - 2
milk - 3.
now, i want to add a delete button, next to every line that is created, that will be able to delete that line which is connected to him, im guessing i need to define an index, and the map function will do it for me, and it will be easier, but i havent found any explanation about it, so, if you can add to the code a remove button, and explain how did u do it, that would be lovely, thanks in advance guys!
import React, { useState } from 'react';
export const ShoppingListPageContainer = () => {
const [item, setItem] = useState('');
const [quantity, setQuantity] = useState('');
const [list, setList] = useState([]);
const add = () => {
const date = { item, quantity };
if (item || quantity) {
setList((ls) => [...ls, date]);
setItem('');
setQuantity('');
}
};
return (
<div>
<label>
<input
name='item'
value={item}
onChange={(e) => setItem(e.target.value)}
/>
<input
type='number'
name='quantity'
value={quantity}
onChange={(e) => setQuantity(e.target.value)}
/>
<button onClick={add}>add</button>
</label>
{list.map((a) => {
return (
<div>
<il>{a.item}</il>
<il>{' - ' + a.quantity + ' '}</il>
<input type='checkbox' />
<button />
</div>
);
})}
</div>
);
};
Steps:
create function which will accept id as parameter and delete the item in list which matches that id. (Note: id should be uniq).
For example:
const deleteItem = (id) => {
//logic delete by id from list
}
Add this button on map and bind id.
For example:
list.map((a)=><div>
<il>{a.item}</il>
<il>{" - "+ a.quantity + " "}</il>
<button onClick={deleteItem.bind(this, a.id)} />
</div>)
By this way you can delete only one item at a time.
By binding ID to function you will call function with binded id only.
I hope this will help you to progress... Best of luck!
export const ShoppingListPageContainer = () => {
const [item, setItem] = useState("");
const [quantity, setQuantity] = useState("");
const [list, setList] = useState([]);
const handleAddItem = () => {
const date = { item, quantity };
if (item || quantity) {
const newList = [...list, date]
setList(newList);
setItem("");
setQuantity("");
}
};
const handleRemoveItem = (index)=>{
const newList = list.filter((item)=>list.indexOf(item) !==index)
setList(newList)
}
return (
<div>
<label>
<input
name="item"
value={item}
onChange={(e) => setItem(e.target.value)}
/>
<input
type="number"
name="quantity"
value={quantity}
onChange={(e) => setQuantity(e.target.value)}
/>
<button onClick={handleAddItem}>add</button>
</label>
{list.map((a,i) => (
<div>
<il>{a.item}</il>
<il>{` ${a.quantity} `}</il>
<input type="checkbox" />
<button onClick={()=>{handleRemoveItem(i)}} />
</div>
))}
</div>
);
};
This may help you however if it does not please check the implementation of the filter method
https://www.w3schools.com/jsref/jsref_filter.asp

How Can I Test an MUI ToggleButtonGroup with a userEvent?

I am using MUI ToggleButtonGroup component like so:
<ToggleButtonGroup
color="primary"
value={mode}
exclusive
onChange={changeHandler}
fullWidth
className="mt-4"
>
<ToggleButton value="login">Login</ToggleButton>
<ToggleButton value="register">Register</ToggleButton>
</ToggleButtonGroup>
When clicking the 'Register' button, it works fine in the UI. I'd like to get a proper test written with React Testing Library.
Here's what I have:
setup();
heading = screen.getByRole("heading", { level: 2 });
const registerButton = screen.getByRole("button", { name: /register/i });
userEvent.click(registerButton);
expect(heading).toHaveTextContent("Register");
The crux of the issue seems to be that userEvent.click somehow doesn't call the changeHandler. Is there some type of bubbling or something that I need to concern myself with?
Here's a prettyDOM log of the relevant components:
<button
aria-pressed="false"
class="MuiButtonBase-root MuiToggleButton-root MuiToggleButton-fullWidth MuiToggleButton-sizeMedium MuiToggleButton-primary MuiToggleButtonGroup-grouped MuiToggleButtonGroup-groupedHorizontal css-j4p6el-MuiButtonBase-root-MuiToggleButton-root"
tabindex="0"
type="button"
value="register"
>
Register
<span
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
/>
</button> <h2
class="MuiTypography-root MuiTypography-h5 css-ag7rrr-MuiTypography-root"
>
Login
</h2>
Add an id to the component:
<ToggleButton id={${data.value}}> {data.label}
test case:
describe("ToggleButtonGroupComponent onChange Testing", () => {
const onChange = vi.fn();
it("toggle group change value and new value updated and last value no more checked", () => {
const { container } = render(<ToggleButtonGroupComponent {...props} onChange={onChange} />);
// Before change selection
const allValueToggleButton = QueryAttributeById(container, "ssh") as HTMLInputElement;
expect(allValueToggleButton.value).toEqual("ssh");
// Change selection
const withValueToggleButton = QueryAttributeById(container, "http") as HTMLInputElement;
fireEvent.click(withValueToggleButton);
expect(withValueToggleButton.value).toEqual("http");
// Old value is no more checked
expect(allValueToggleButton.value).toEqual("ssh");
});
});

Button press triggers the last button's press

I'm new to react an am trying to create an app to use in my portfolio. Essentially the program is a menu that has access to different menus(json files: texas_pick.js, breakfast.js...), the program is meant to display the menu options in form of buttons, the buttons' details are retrieved from their respective json file. The problem that I am facing is that when making a click on a menu option the data of the last menu item is retrieved. I programmed the backend to only push the item's name and price to the database, and the frontend, to retrieve this data and display it on a table. The data retrieved is only the last button's and not any others. I believe the problem to possibly be within my button code. Any help/tips/recommendations you could give are greatly appreciated.
I clicked every menu item and only the data from the last one was retrieved
import React from 'react'
import {useEffect,useState} from 'react'
import axios from 'axios'
import Texas_Pick from '../../json_files/texas_pick.json'
import './Mid_Container.css'
function Mid_Container() {
const [items, setItems] = useState(Texas_Pick);
const [order, setOrder] = useState({
item: '',
cost: ''
})
const createOrder = () => {
axios
.post("http://localhost:5000/orders", order)
.then(res => {window.location.reload(false)})
.catch(err => console.error(err));
}
const item1 = items[0];
const item2 = items[1];
const item3 = items[2];
const item4 = items[3];
const item5 = items[4];
const item6 = items[5];
return (
<div className="Mid_Container">
<button
style={{backgroundImage: `url(${item1.image})`}}
value={order.item=item1.item,order.cost=item1.price}
onClick={createOrder}
>
<p id="pPrice">${item1.price}</p>
<p id="pItem" >{item1.item}</p>
</button>
<button
style={{backgroundImage: `url(${item2.image})`}}
value={order.item=item2.item,order.cost=item2.price}
onClick={createOrder}
>
<p id="pPrice">${item2.price}</p>
<p id="pItem" >{item2.item}</p>
</button>
<button
style={{backgroundImage: `url(${item3.image})`}}
value={order.item=item3.item,order.cost=item3.price}
onClick={createOrder}
>
<p id="pPrice">${item3.price}</p>
<p id="pItem" >{item3.item}</p>
</button>
<button
style={{backgroundImage: `url(${item4.image})`}}
value={order.item=item4.item,order.cost=item4.price}
onClick={createOrder}
>
<p id="pPrice">${item4.price}</p>
<p id="pItem" >{item4.item}</p>
</button>
</div>
)
}
export default Mid_Container
I think that you should have this approach:
function SomeComponent() {
// Mocking your datas
const [items, setItems] = React.useState([
{
price: "1",
item: "i am the first",
image: "image1.png",
},
{
price: "7",
item: "I am the second",
image: "image2.png",
},
{
price: "3",
item: "i am the third",
image: "image3.png",
},
]);
const [order, setOrder] = React.useState();
const [myResponse, setMyResponse] = React.useState();
const createOrder = (clickedItem) => {
setOrder(clickedItem);
console.log(clickedItem);
// axios
// .post("http://somewhere", clickedItem)
// .then((res) => {
// setMyResponse(res); // or setMyResponse(res.json());
// })
// .catch((err) => console.error(err));
};
console.log('Log selected order in render loop ==> ', order);
console.log('Log response in render loop ==> ', myResponse);
return (
<div>
<div className="Mid_Container">
{items.length && items.map((currItem, index) => {
return (
<button
key={index}
style={{ backgroundImage: `url(${currItem.image})` }}
onClick={() => createOrder(currItem)}
>
<p id="pPrice">${currItem.price}</p>
<p id="pItem">{currItem.item}</p>
</button>
);
})}
</div>
</div>
);
}
Mapping on your items with map function, and pass the current item to your onClickEvent.
I also think you don't need a value attribute on your buttons. It's also not the place to do operations like you do :)
You also don't have to reload the page in the "then" of your promise. React is made to do SPA (single page application), so in the "then", you can put some code like "setResult(myResponse)" to store in you component the new data you got from your API.

Push selected option on click

Im using Node.js, but i really don't know how i can do this guys, pls help
i need push selected option when user click on button, like a cart.
to before submit
const classes = useStyles();
const [codigo, setCodigo] = useState('');
const [nome, setNome] = useState('');
const [descricao, setDescricao] = useState('');
const [preco, setPreco] = useState('');
const [peso, setPeso] = useState('');
const [itemServico, setItemServico] = useState('');
const [servicos, setServicos] =useState([ ]);
useEffect(() =>{
async function loadServicos(){
const response = await api.get("/api/servicos");
console.log(response.data);
setServicos(response.data);
}
loadServicos();
},[])
how can i do this,
<Grid item xs={12} sm={12}>
<FormControl className={classes.formControl}>
<InputLabel id="demo-simple-select-label"></InputLabel>
<Select
native
labelId="demo-simple-select-label"
id="selectServico"
>
{servicos.map((opcao) => (
<option aria-label="None" value={opcao._id}>{opcao.codigo_servico}" - "{opcao.nome_servico}</option>
))}
</Select>
<Button onClick={itemServico.push(document.getElementById("selectServico"))}>Adicionar</Button>
</FormControl>
</Grid>
You need something like this. Please note that I couldn't througly test this as I don't have the full context of your app.
export default function App() {
const [servicos, setServicos] =useState([]);
const [itemServico, setItemServico] = useState([]);
const select = useEffect();
const add = () => {
if(!itemServico.includes(select.current.value))
setItemServico([...itemServico, select.current.value])
}
return (
<div className="App">
<Select
native
labelId="demo-simple-select-label"
id="selectServico"
ref={select}
>
{servicos.map((opcao) => (
<option aria-label="None" value={opcao._id}>{opcao.codigo_servico}" - "{opcao.nome_servico}</option>
))}
</Select>
<Button onClick={add}>Adicionar</Button>
</div>
);
}
We create a reference to the Select element by using the useRef hook. This will allow us to access the Select's value at any time.
We also create a function, add, that adds the selected option's value to the itemServico array. But it only does so if the value being added does not already exists in the array.
Finally, we use the onClick prop of the button to call the add function. This, in a nutshell, is what you would need.

Resources