How to Implement a search function in reactJS using MaterialUI - html

I try to develop a pokedex using the pokeapi. For now it works fine, the pokemon are fetched correctly and are displayed in a container. Now i want to implement a function to search and filter the pokemon. Therefore i used MaterialUI to put a searchBar on top of the App.
The fetched pokemon are given from App.js to my Component PokemonList which maps the data. My idea is now to filter the pokemonData before it is given to PokemonList to map only the pokemon i am looking for. But here i am stuck. I have no idea how to connect the search function with my pokemonData Hook from App.js . Can you help me?
This is my searchBar Component:
const SearchAppBar = () => {
const [search, setSearch] = useState("");
console.log(search)
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static" sx={{ bgcolor: "black"}}>
<Toolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="open drawer"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<Typography
variant="h6"
noWrap
component="div"
sx={{ flexGrow: 1, display: { xs: 'none', sm: 'block' } }}
>
<img src={logo} alt="logo" width="150" height="auto" />
</Typography>
<Search>
<SearchIconWrapper>
<SearchIcon />
</SearchIconWrapper>
<StyledInputBase
onChange={(e) => setSearch(e.target.value)}
id = 'searchbox'
placeholder="Search for Pokémon..."
inputProps={{'aria-label': 'search'}}
/>
</Search>
</Toolbar>
</AppBar>
</Box>
);
}
export default SearchAppBar;

you should save the entered value from input into a state and filter your data based on that state

Related

Close Button on Modal disappear in real iphone

The Close Button still appear when I test responsive in Chrome but it disappear in real iphone.
When click into image, the image gallery will appear but in iphone, it just have previous button and next button, the close button is disappear.
Here're my code:
import React, { useState } from "react";
import {
Box,
HStack,
IconButton,
Image,
Modal,
ModalContent,
ModalOverlay,
Spacer,
Text,
VStack,
} from "#chakra-ui/react";
import ArrowLeftIcon16x8 from "../../icons/ArrowLeftIcon16x8";
import ArrowRightIcon16x8 from "../../icons/ArrowRightIcon16x8";
import { CloseIcon } from "#chakra-ui/icons";
const ImageGalleryModal = ({
isOpen,
onClose,
currentImage,
listingImages,
}) => {
const [showCurrentImage, setShowCurrentImage] = useState(currentImage);
return (
<Modal
blockScrollOnMount={true}
isOpen={isOpen}
onClose={onClose}
isCentered
size={"full"}
>
<ModalOverlay />
<ModalContent minWidth={"100%"} height={"100vh"} position={"relative"}>
<Image
top={"0"}
width={"full"}
height={"100vh"}
alt={"img_rent"}
src={listingImages[showCurrentImage]?.url}
objectFit={"cover"}
position={"absolute"}
zIndex={100}
/>
<VStack w={"100vw"} h={"100vh"} alignItems={"flex-end"} spacing={0}>
<Box
top={{ base: "16px", lg: "24px" }}
right={{ base: "16px", lg: "24px" }}
borderRadius={"8px"}
position={"absolute"}
zIndex={1000}
>
<IconButton
onClick={onClose}
width={"32px"}
height={"32px"}
borderRadius={"8px"}
bgColor={"rgba(255, 255, 255, 0.3)"}
icon={<CloseIcon />}
aria-label={"Close Image Gallery"}
/>
</Box>
<HStack
position={"absolute"}
zIndex={999}
width={"full"}
height={"full"}
>
<HStack
paddingLeft={{ base: "16px", lg: "24px" }}
height={"full"}
alignItems={"center"}
>
<IconButton
onClick={() =>
setShowCurrentImage(
showCurrentImage > 0
? showCurrentImage - 1
: listingImages?.length - 1
)
}
width={"32px"}
height={"32px"}
borderRadius={"8px"}
bgColor={"rgba(255, 255, 255, 0.3)"}
icon={<ArrowLeftIcon16x8 />}
aria-label={"previous image"}
/>
</HStack>
<Spacer />
<HStack
paddingBottom={{ base: "12px", lg: "16px" }}
height={"full"}
alignItems={"flex-end"}
>
<Text
width={{ base: "56px", lg: "64px" }}
height={{ base: "24px", lg: "34px" }}
fontWeight={500}
fontSize={{ base: "12px", lg: "16px" }}
color={"black.500"}
bgColor={"rgba(255, 255, 255, 0.3)"}
borderRadius={"8px"}
padding={{ base: "4px 18px", lg: "5px 18px" }}
>
{`${listingImages?.length > 0 ? showCurrentImage + 1 : 0}/${
listingImages?.length
}`}
</Text>
</HStack>
<Spacer />
<HStack
paddingRight={{ base: "16px", lg: "24px" }}
height={"full"}
alignItems={"center"}
>
<IconButton
onClick={() =>
setShowCurrentImage(
showCurrentImage < listingImages?.length - 1
? showCurrentImage + 1
: 0
)
}
width={"32px"}
height={"32px"}
borderRadius={"8px"}
bgColor={"rgba(255, 255, 255, 0.3)"}
icon={<ArrowRightIcon16x8 />}
aria-label={"next image"}
/>
</HStack>
</HStack>
</VStack>
</ModalContent>
</Modal>
);
};
export default ImageGalleryModal;
I tried to make zIndex of close button to higher than another buttons but it not working.
The button is visible if you see it closely (See the blue mark on the picture at the top right corner). Just apply some top margin to the close button in a media query. Or if it uses "position: absolute" increase the top value.
(

Access Object Properties in React

In my react app, I have an array of objects in a file(users.js) and I have another file(contacts.jsx). I am putting the material ui card in contacts.jsx file and in that card I want to access properties of object.
I have tried to access it by using dot(.) operator but I am getting undefined in console.log. What mistake am I doing and How can I access properties like avatar, email, first_name etc.?
users.js
const users = [{
id: 1,
email: "george.bluth#reqres.in",
first_name: "George",
last_name: "Bluth",
avatar: "https://reqres.in/img/faces/1-image.jpg"
},
{
id: 2,
email: "janet.weaver#reqres.in",
first_name: "Janet",
last_name: "Weaver",
avatar: "https://reqres.in/img/faces/2-image.jpg"
}]
export default users;
contacts.jsx
import React from "react";
import FilterListIcon from '#mui/icons-material/FilterList';
import { Button, Card, CardActions, CardContent, CardMedia, Typography } from "#mui/material";
import users from "../constants/users";
const Contacts = () => {
return (
<div className="parentDiv">
{
console.log(users.email,'email') // Result: undefined 'email'
}
<div className="header">
<h1>Robo Space</h1>
<input className="searchFilter" type='text' placeholder="Search here" />
<span className="filterIcon"><FilterListIcon /></span>
</div>
<div className="body">
<Card sx={{ maxWidth: 345 }}>
<CardMedia
component="img"
height="140"
img={users.avatar}
alt="robo img"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="div">
{users.first_name}
</Typography>
<Typography variant="body2" color="text.secondary">
{users.last_name}
</Typography>
</CardContent>
<CardActions>
<Button size="small">Show More</Button>
</CardActions>
</Card>
</div>
</div>
)
}
export default Contacts;
To access single properties you can use the dot operator like users[0].email, to access the properties dynamically you can use .map() like that:
import React from "react";
import FilterListIcon from '#mui/icons-material/FilterList';
import { Button, Card, CardActions, CardContent, CardMedia, Typography } from "#mui/material";
import users from "./users";
const Contacts = () => {
return (
<div className="parentDiv">
{
console.log(users[0].email,'email') // Result: undefined 'email'
}
<div className="header">
<h1>Robo Space</h1>
<input className="searchFilter" type='text' placeholder="Search here" />
<span className="filterIcon"><FilterListIcon /></span>
</div>
<div className="body">
{users.map((user)=>{
return (
<Card sx={{ maxWidth: 345 }}>
<CardMedia
component="img"
height="140"
src={user.avatar}
alt="robo img"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="div">
{user.first_name}
</Typography>
<Typography variant="body2" color="text.secondary">
{user.last_name}
</Typography>
</CardContent>
<CardActions>
<Button size="small">Show More</Button>
</CardActions>
</Card>
)
})}
</div>
</div>
)
}
export default Contacts;
Here is a Sandbox in case you need it.

Mui DatePicker change date format

I am trying to customise the mui DatePicker. I want the date format to be as follows: Day, DD Month.
example: Monday, 10 September
here is my code:
<LocalizationProvider dateAdapter={AdapterDateFns} locale={frLocale}>
<Stack spacing={3}>
<ThemeProvider theme={calendarTheme}>
<DatePicker
disabled={false}
//the current format
inputFormat="MM/dd/yyyy"
leftArrowButtonText={t("notification.previous_month")}
rightArrowButtonText={t("notification.next_month")}
minDate={today}
InputProps={{
classes: {
notchedOutline: classes.noBorder,
root: classes.reverse,
},
}}
components={{
OpenPickerIcon: Table,
SwitchViewIcon: ArrowDown,
}}
value={value}
onChange={handlechange}
renderInput={(params: any) => (
<TextField
style={{
color: "red",
}}
{...params}
/>
)}
/>
</ThemeProvider>
</Stack>
</LocalizationProvider>
You need to use fromat like format="EEEE, MM MMMM":
<DesktopDatePicker
label="Date desktop"
inputFormat="EEEE, MM MMMM"
openTo={"day"}
value={value}
onChange={handleChange}
renderInput={(params) => <TextField {...params} />}
/>

onClick not propagated

I'm having troubles with creating a simple gallery allowing to print pictures. I constructed the interface. When I click on the print button, I'm not able to propagate event to a function. Funny enough, it always works for just a couple of items in the gallery so that console logs foo. Could you please point me where is the problem? I am using material-ui, tileData is a json with image url etc...
Many thanks!
class Galery extends React.Component {
state = {
tileData: tileData
};
printThis = tile => {
console.log("printing tile... " + tile.target.value);
};
render() {
const classes = this.props;
return (
<div className={classes.root}>
<ButtonAppBar />
<div style={{ marginBottom: 20 }} />
<Grid container spacing={8}>
<Grid item xs={10}>
<GridList
cellHeight={250}
cellWidth={250}
cols={5}
spacing={4}
className={classes.gridList}
>
{tileData.map(tile => (
<GridListTile key={tile.img}>
<img src={tile.img} alt={tile.title} />
<GridListTileBar
title={tile.title}
subtitle={<span>by: {tile.author}</span>}
actionIcon={
<IconButton
className={classes.icon}
value="foo"
onClick={this.printThis}
>
<i className="material-icons md-24 md-light">print</i>
</IconButton>
}
secondActionIcon={
<IconButton className={classes.icon}>
<i className="material-icons md-24 md-light">delete</i>
</IconButton>
}
/>
</GridListTile>
))}
</GridList>
</Grid>
<Grid item xs={2}>
<div className={classes.stats}>
<StatsTable />
</div>
</Grid>
</Grid>
</div>
);
}
}
It works for me to access the object id through event.currentTarget as per github answer here https://github.com/mui-org/material-ui/issues/7974#issuecomment-329250974
`
So my implementation is:
printThis = (event) => {
console.log('printing tile... '+ event.currentTarget.id);
};
<IconButton className={classes.icon} id = {tile.img} onClick={this.printThis}>
<i className="material-icons md-24 md-light" >
print
</i>
</IconButton>

How to make a react component that is a table with different sized columns and rows

I'm trying to make this into a react component so I can use it in my website:
I don't know how to go about making this or, if any libraries are involved, I don't know which ones.
it looks like this component will take a few properties:
const CardsDisplay = ({numCards}) => { /* ... */ }
const AvatarDisplay = ({imageUrl, numCards, name, score, popupMenu }) =>
<div style={{textAlign: 'center'}}>
<div style={{display: 'flex', justifyContent: 'space-between'}}>
<img src={imageUrl} />
<CardsDisplay numCards={numCards} />
</div>
{name}
<br />
{score.toLocaleString()}
<popupMenu style={{float: 'right'}} />
</div>