material-ui horizontally align two cards below first card - reactjs

How can I align Graph Two and Graph three horizontally below Graph One ?
In other words I want to leave Graph One card how it is but move Graph two so it is on the same level and Graph three and they are horizontally aligned with one another below Graph One
This is what I have so far
import React from "react";
import Grid from "#mui/material/Grid";
import Container from "#mui/material/Container";
import Box from "#mui/material/Box";
import Typography from "#mui/material/Typography";
import Card from "#mui/material/Card";
import CardActions from "#mui/material/CardActions";
import CardContent from "#mui/material/CardContent";
import Button from "#mui/material/Button";
import Paper from "#mui/material/Paper";
const styles = {
card: {
minWidth: 275,
display: "inline-block"
}
};
const YourCardOne = () => {
return (
<Card variant="outlined" style={{ height: "200%" }}>
<CardContent>
<Typography color="textSecondary" gutterBottom>
Graph One
</Typography>
<Typography variant="h5" component="h2">
Sarah Doria
</Typography>
<Typography color="textSecondary">Position</Typography>
<Typography variant="body2" component="p">
Company
<br />
{'"a benevolent smile"'}
</Typography>
</CardContent>
<CardActions></CardActions>
</Card>
);
};
const YourCardTwo = () => {
return (
<Card variant="outlined" style={{ height: "100%" }}>
<CardContent>
<Typography color="textSecondary" gutterBottom>
Graph Two
</Typography>
<Typography variant="h5" component="h2">
Sarah Doria
</Typography>
<Typography color="textSecondary">Position</Typography>
<Typography variant="body2" component="p">
Company
<br />
{'"a benevolent smile"'}
</Typography>
</CardContent>
<CardActions></CardActions>
</Card>
);
};
const YourCardThree = () => {
return (
<Card variant="outlined" style={{ height: "100%" }}>
<CardContent>
<Typography color="textSecondary" gutterBottom>
Graph Three
</Typography>
<Typography variant="h5" component="h2">
Sarah Doria
</Typography>
<Typography color="textSecondary">Position</Typography>
<Typography variant="body2" component="p">
Company
<br />
{'"a benevolent smile"'}
</Typography>
</CardContent>
<CardActions></CardActions>
</Card>
);
};
export default function GraphBackDrop() {
return (
<div>
<Container>
<Grid
container
spacing={3}
direction="row"
justify="center"
alignItems="stretch"
>
<Grid item xs={48}>
<Grid container spacing={25}>
<Grid item xs={12}>
<YourCardOne />
</Grid>
<Grid item xs={20} >
<YourCardTwo />
</Grid>
</Grid>
</Grid>
<Grid item xs={20}>
<YourCardThree />
</Grid>
</Grid>
</Container>
</div>
);
}

You can update your GraphBackDrop component to this:
export default function GraphBackDrop() {
return (
<Container>
<Grid
container
spacing={3}
justifyContent="center"
alignItems="stretch"
>
<Grid item xs={12}>
<YourCardOne />
</Grid>
<Grid item xs={12} sm={6}>
<YourCardTwo />
</Grid>
<Grid item xs={12} sm={6}>
<YourCardThree />
</Grid>
</Grid>
</Container>
);
}
Note: xs, sm, md, lg & xl are identified as breakpoints. It sets the number of columns the grid item uses. It can't be greater than the total number of columns of the container (12 by default).
If you want to learn more about MUI Grid component, refer to this official documentation.

Related

Box component inserting text to 'start' and 'end'

I am using material UI components and I'm trying to make a card component. I want my text will be in the same row inbox component("phase" and "2" have to be in the same row). However, I couldn't do it. Here is my code;
<Card className={classes.rootMultiple} variant='outlined'>
<CardContent>
<Box>
<Box justifyContent={'start'}>
<Typography
variant='h5'
component='h2'
className={classes.titleMultiple}
>
phase
</Typography>
</Box>
<Box display='flex' justifyContent={'end'}>
<Typography
variant='h7'
component='h2'
className={classes.descriptionMultiple}
>
2
</Typography>
</Box>
</Box>
</CardContent>
</Card>;
Try to specify the display and flexDirection attributes in the parent's Box.
Then use the flex attribute on the children's `Box:
<Card className={classes.rootMultiple} variant='outlined'>
<CardContent>
<Box sx={{
display: 'flex',
flexDirection: 'row',
}}>
<Box flex={1}>
<Typography
variant='h5'
component='h2'
className={classes.titleMultiple}
>
phase
</Typography>
</Box>
<Box flex={0}>
<Typography
variant='h7'
component='h2'
className={classes.descriptionMultiple}
>
2
</Typography>
</Box>
</Box>
</CardContent>
</Card>
You can just write a Grid (that uses flex) with justify-content: space-between.
<Card className={classes.rootMultiple} variant='outlined'>
<CardContent>
<Grid container justifyContent="space-between">
<Grid item>
<Typography
variant='h5'
component='h2'
className={classes.titleMultiple}
>
phase
</Typography>
</Grid>
<Grid item>
<Typography
variant='h7'
component='h2'
className={classes.descriptionMultiple}
>
2
</Typography>
</Grid>
</Grid>
</CardContent>
</Card>
No need to make other components; less is better. Of course you can use Box with flex style, but Grid does it for you.
Note that h7 isn't a valid value for variant inside Typography.
EDIT: I wrote space-between only because your example prints the texts in the margins, but of corse you can use what you want: they will be always in same row.

Getting “Cannot call a class as a function” in my React Project :throw new TypeError("Cannot call a class as a function");

I'm making COVID-19 tracker project and I got this error and I'm stuck, not sure where its coming from.
import { Card, CardContent, Typography, Grid } from '#material-ui/core';
import CountUp from 'react-countup';
import cx from 'react-countup';
import styles from './Cards.module.css';
const CardComponent = ({ className, cardTitle, value, lastUpdate, cardSubtitle }) => (
<Grid item xs={12} md={3} component={Card} className={cx(styles.card, className)}>
<CardContent>
<Typography color="textSecondary" gutterBottom>
{cardTitle}
</Typography>
<Typography variant="h5" component="h2">
<CountUp start={0} end={value} duration={2.75} separator="," />
</Typography>
<Typography color="textSecondary">
{new Date(lastUpdate).toDateString()}
</Typography>
<Typography variant="body2" component="p">
{cardSubtitle}
</Typography>
</CardContent>
</Grid>
);
const Info = ({ data: { confirmed, recovered, deaths, lastUpdate } }) => {
if (!confirmed) {
return 'Loading...';
}
return (
<div className={styles.container}>
<Typography gutterBottom variant="h4" component="h2">Global</Typography>
<Grid container spacing={3} justify="center">
<CardComponent
className={styles.infected}
cardTitle="Infected"
value={confirmed.value}
lastUpdate={lastUpdate}
cardSubtitle="Number of active cases from COVID-19."
/>
<CardComponent
className={styles.recovered}
cardTitle="Recovered"
value={recovered.value}
lastUpdate={lastUpdate}
cardSubtitle="Number of recoveries from COVID-19."
/>
<CardComponent
className={styles.deaths}
cardTitle="Deaths"
value={deaths.value}
lastUpdate={lastUpdate}
cardSubtitle="Number of deaths caused by COVID-19."
/>
</Grid>
</div>
);
};
export default Info;```
You are not returning a JSX element in your component but a simple string.
if (!confirmed) {
return 'Loading...';
}

How to save values from api as a number REACT js

This is the api I am using https://covid19.mathdro.id/api
I need to take the {recovered.value} and divide it by {confirmed.value} and then multiply the result by 100 to get the recovery percentage.
But these values are coming as string and not number//
this is the file
import React from "react";
import { Card, CardContent, Typography, Grid } from "#material-ui/core";
import CountUp from "react-countup";
import cx from "classnames";
import styles from "./Cards.module.css";
const Info = ({ data: { confirmed, recovered, deaths, lastUpdate } }) => {
if (!confirmed) {
return "Loading...";
}
return (
<div className={styles.container}>
<Grid container spacing={3} justify="center">
<Grid
item
xs={12}
md={3}
component={Card}
className={cx(styles.card, styles.infected)}
>
<CardContent>
<Typography color="textSecondary" gutterBottom>
Infected
</Typography>
<Typography variant="h5" component="h2">
<CountUp
start={0}
end={confirmed.value}
duration={2.75}
separator=","
/>
<div>
{recovered.value}/{confirmed.value}
</div>
</Typography>
<Typography color="textSecondary">
{new Date(lastUpdate).toDateString()}
</Typography>
<Typography variant="body2" component="p">
Number of active cases of COVID-19.
</Typography>
</CardContent>
</Grid>
<Grid
item
xs={12}
md={3}
component={Card}
className={cx(styles.card, styles.recovered)}
>
<CardContent>
<Typography color="textSecondary" gutterBottom>
Recovered
</Typography>
<Typography variant="h5" component="h2">
<CountUp
start={0}
end={recovered.value}
duration={2.75}
separator=","
/>
</Typography>
<Typography color="textSecondary">
{new Date(lastUpdate).toDateString()}
</Typography>
<Typography variant="body2" component="p">
Number of recoveries from COVID-19.
</Typography>
</CardContent>
</Grid>
<Grid
item
xs={12}
md={3}
component={Card}
className={cx(styles.card, styles.deaths)}
>
<CardContent>
<Typography color="textSecondary" gutterBottom>
Deaths
</Typography>
<Typography variant="h5" component="h2">
<CountUp
start={0}
end={deaths.value}
duration={2.75}
separator=","
/>
</Typography>
<Typography color="textSecondary">
{new Date(lastUpdate).toDateString()}
</Typography>
<Typography variant="body2" component="p">
Number of deaths caused by COVID-19.
</Typography>
</CardContent>
</Grid>
</Grid>
</div>
);
};
export default Info;
and I have tried parseInt, in this part of code,for confirmed, but it does not woke
const Info = ({ data: { parseInt(confirmed), recovered, deaths,
lastUpdate } }) => {
if (!confirmed) {
return "Loading...";
}
....
this is my app.js
import React from "react";
import { Cards, CountryPicker, Chart } from "./components";
import { fetchData } from "./api/";
import styles from "./App.module.css";
class App extends React.Component {
state = {
data: {},
country: "",
};
componentWillUpdate() {
console.log("hello");
}
async componentDidMount() {
const data = await fetchData();
this.setState({ data });
console.log("data");
}
handleCountryChange = async (country) => {
const data = await fetchData(country);
this.setState({ data, country: country });
console.log("data");
};
render() {
const { data, country } = this.state;
return (
<div className={styles.container}>
<Cards data={data} />
<CountryPicker handleCountryChange={this.handleCountryChange} />
<Chart data={data} country={country} />
</div>
);
}
}
export default App;
You have bug on your code. I tried to fixed it and able to run it. Please check the update code here:
import React from "react";
import {Card, CardContent, Typography, Grid} from "#material-ui/core";
import CountUp from "react-countup";
import cx from "classnames";
import {makeStyles, useTheme} from '#material-ui/core/styles';
const useStyles = makeStyles(theme => ({
container: {},
infected: {},
recovered: {},
deaths: {}
}));
const Info = ({data: {confirmed, recovered, deaths, lastUpdate}}) => {
const styles = useStyles();
return (
<div className={styles.container}>
<Grid container spacing={3} justify="center">
<Grid
item
xs={12}
md={3}
component={Card}
className={cx(styles.card, styles.infected)}
>
<CardContent>
<Typography color="textSecondary" gutterBottom>
Infected
</Typography>
<Typography variant="h5" component="h2">
<CountUp
start={0}
end={confirmed.value}
duration={2.75}
separator=","
/>
<div>
{recovered.value}/{confirmed.value}
</div>
</Typography>
<Typography color="textSecondary">
{new Date(lastUpdate).toDateString()}
</Typography>
<Typography variant="body2" component="p">
Number of active cases of COVID-19.
</Typography>
</CardContent>
</Grid>
<Grid
item
xs={12}
md={3}
component={Card}
className={cx(styles.card, styles.recovered)}
>
<CardContent>
<Typography color="textSecondary" gutterBottom>
Recovered
</Typography>
<Typography variant="h5" component="h2">
<CountUp
start={0}
end={recovered.value}
duration={2.75}
separator=","
/>
</Typography>
<Typography color="textSecondary">
{new Date(lastUpdate).toDateString()}
</Typography>
<Typography variant="body2" component="p">
Number of recoveries from COVID-19.
</Typography>
</CardContent>
</Grid>
<Grid
item
xs={12}
md={3}
component={Card}
className={cx(styles.card, styles.deaths)}
>
<CardContent>
<Typography color="textSecondary" gutterBottom>
Deaths
</Typography>
<Typography variant="h5" component="h2">
<CountUp
start={0}
end={deaths.value}
duration={2.75}
separator=","
/>
</Typography>
<Typography color="textSecondary">
{new Date(lastUpdate).toDateString()}
</Typography>
<Typography variant="body2" component="p">
Number of deaths caused by COVID-19.
</Typography>
</CardContent>
</Grid>
</Grid>
</div>
);
};
export default Info;
You should should use Info Component in your app component like below:
import React from 'react';
import Info from "./Info";
class App extends React.Component {
render() {
let data = {
confirmed: {value: 245550},
recovered: {value: 4555},
deaths: {value: 4534},
lastUpdate: Date.now()
};
return (
<Info data={data}/>
)
}
}
export default App;

How to map two different data values from api in react js

I am following https://github.com/adrianhajdin/project_corona_tracker
https://www.youtube.com/watch?v=khJlrj3Y6Ls
So in this project the following api is used-
https://covid19.mathdro.id/api/daily
here I am getting covid cases values for each day. I need to display the number of cases that increased from yesterday to today
so I am trying to get values of current date confirmed cases(total cases)- yesterday's date confirmed cases
this is my card.jsx file:
import React from "react";
import { Card, CardContent, Typography, Grid } from "#material-ui/core";
import CountUp from "react-countup";
import cx from "classnames";
import styles from "./Cards.module.css";
const Info = ({ data: { confirmed, recovered, deaths, lastUpdate } }) => {
if (!confirmed) {
return "Loading...";
}
return (
<div className={styles.container}>
<Grid container spacing={3} justify="center">
<Grid
item
xs={12}
md={3}
component={Card}
className={cx(styles.card, styles.infected)}
>
<CardContent>
<Typography color="textSecondary" gutterBottom>
Infected
</Typography>
<Typography variant="h5" component="h2">
<div>
---------------> total cases-yesterday's cases
</div>
<CountUp
start={0}
end={confirmed.value}
duration={2.75}
separator=","
/>
</Typography>
<Typography color="textSecondary">
{new Date(lastUpdate).toDateString()}
</Typography>
<Typography variant="body2" component="p">
Number of active cases of COVID-19.
</Typography>
</CardContent>
</Grid>
<Grid
item
xs={12}
md={3}
component={Card}
className={cx(styles.card, styles.recovered)}
>
<CardContent>
<Typography color="textSecondary" gutterBottom>
Recovered
</Typography>
<Typography variant="h5" component="h2">
<div>
{(
(Number(recovered.value) / Number(confirmed.value)) *
100
).toFixed(2)}{" "}
%
</div>
<CountUp
start={0}
end={recovered.value}
duration={2.75}
separator=","
/>
</Typography>
<Typography color="textSecondary">
{new Date(lastUpdate).toDateString()}
</Typography>
<Typography variant="body2" component="p">
Number of recoveries from COVID-19.
</Typography>
</CardContent>
</Grid>
<Grid
item
xs={12}
md={3}
component={Card}
className={cx(styles.card, styles.deaths)}
>
<CardContent>
<Typography color="textSecondary" gutterBottom>
Deaths
</Typography>
<Typography variant="h5" component="h2">
<div>
{(
(Number(deaths.value) / Number(confirmed.value)) *
100
).toFixed(2)}{" "}
%
</div>
<CountUp
start={0}
end={deaths.value}
duration={2.75}
separator=","
/>
</Typography>
<Typography color="textSecondary">
{new Date(lastUpdate).toDateString()}
</Typography>
<Typography variant="body2" component="p">
Number of deaths caused by COVID-19.
</Typography>
</CardContent>
</Grid>
</Grid>
</div>
);
};
export default Info;
Here's one way to extract that data:
fetch('https://covid19.mathdro.id/api/daily', {
method: 'GET'
}).then(res => res.json()).then(d => {
let todayData = d[d.length - 1];
let yesterdayData = d[d.length - 2];
console.log({
todayData
});
console.log({
yesterdayData
});
// minus total confirmed today - yesterday
const todayTotalDiff = todayData.totalConfirmed - yesterdayData.totalConfirmed;
console.log(`minus total confirmed today - yesterday = ${todayTotalDiff}`);
});

How to put different content for each cards

I am using material ui album template for my react app
I want to put different image and different text for each cards for this when I remove this array it create the problems in responsiveness of the cards
I tried to put separte grid for each cards but thats some how solve the issue but that responsiveness of the template does not remain same
here is my demo code
https://codesandbox.io/s/material-demo-pz8df
Make sure you're updating the right cards array. Use an array of objects as well, where each object has a key for an image-link and one for the description. In the .map() we'll use these values to render the content. Here's a working sandbox: https://codesandbox.io/s/material-demo-3v44c
The responsiveness will work like expected.
Working code:
import React from "react";
import AppBar from "#material-ui/core/AppBar";
import Button from "#material-ui/core/Button";
import CameraIcon from "#material-ui/icons/PhotoCamera";
import Card from "#material-ui/core/Card";
import CardActions from "#material-ui/core/CardActions";
import CardContent from "#material-ui/core/CardContent";
import CardMedia from "#material-ui/core/CardMedia";
import CssBaseline from "#material-ui/core/CssBaseline";
import Grid from "#material-ui/core/Grid";
import Toolbar from "#material-ui/core/Toolbar";
import Typography from "#material-ui/core/Typography";
import { makeStyles } from "#material-ui/core/styles";
import Container from "#material-ui/core/Container";
import Link from "#material-ui/core/Link";
function MadeWithLove() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{"Built with love by the "}
<Link color="inherit" href="https://material-ui.com/">
Material-UI
</Link>
{" team."}
</Typography>
);
}
const useStyles = makeStyles(theme => ({
icon: {
marginRight: theme.spacing(2)
},
heroContent: {
backgroundColor: theme.palette.background.paper,
padding: theme.spacing(8, 0, 6)
},
heroButtons: {
marginTop: theme.spacing(4)
},
cardGrid: {
paddingTop: theme.spacing(8),
paddingBottom: theme.spacing(8)
},
card: {
height: "100%",
display: "flex",
flexDirection: "column"
},
cardMedia: {
paddingTop: "56.25%" // 16:9
},
cardContent: {
flexGrow: 1
},
footer: {
backgroundColor: theme.palette.background.paper,
padding: theme.spacing(6)
}
}));
const cards = [
{
img:
"https://images.unsplash.com/photo-1564135624576-c5c88640f235?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3300&q=80",
desc: "Campsite"
},
{
img:
"https://images.unsplash.com/photo-1564198879220-63f2734f7cec?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2072&q=80",
desc: "Space"
}
];
export default function Album() {
const classes = useStyles();
return (
<React.Fragment>
<CssBaseline />
<AppBar position="relative">
<Toolbar>
<CameraIcon className={classes.icon} />
<Typography variant="h6" color="inherit" noWrap>
Album layout
</Typography>
</Toolbar>
</AppBar>
<main>
{/* Hero unit */}
<div className={classes.heroContent}>
<Container maxWidth="sm">
<Typography
component="h1"
variant="h2"
align="center"
color="textPrimary"
gutterBottom
>
Album layout
</Typography>
<Typography
variant="h5"
align="center"
color="textSecondary"
paragraph
>
Something short and leading about the collection below—its
contents, the creator, etc. Make it short and sweet, but not too
short so folks don&apos;t simply skip over it entirely.
</Typography>
<div className={classes.heroButtons}>
<Grid container spacing={2} justify="center">
<Grid item>
<Button variant="contained" color="primary">
Main call to action
</Button>
</Grid>
<Grid item>
<Button variant="outlined" color="primary">
Secondary action
</Button>
</Grid>
</Grid>
</div>
</Container>
</div>
<Container className={classes.cardGrid} maxWidth="md">
{/* End hero unit */}
<Grid container spacing={4}>
{cards.map(card => (
<Grid item key={card} xs={12} sm={6} md={4}>
<Card className={classes.card}>
<CardMedia
className={classes.cardMedia}
image={card.img}
title="Image title"
/>
<CardContent className={classes.cardContent}>
<Typography gutterBottom variant="h5" component="h2">
Heading
</Typography>
<Typography>{card.desc}</Typography>
</CardContent>
<CardActions>
<Button size="small" color="primary">
View
</Button>
<Button size="small" color="primary">
Edit
</Button>
</CardActions>
</Card>
</Grid>
))}
</Grid>
</Container>
</main>
{/* Footer */}
<footer className={classes.footer}>
<Typography variant="h6" align="center" gutterBottom>
Footer
</Typography>
<Typography
variant="subtitle1"
align="center"
color="textSecondary"
component="p"
>
Something here to give the footer a purpose!
</Typography>
<MadeWithLove />
</footer>
{/* End footer */}
</React.Fragment>
);
}

Resources