Overriding MUI Stepper - reactjs

I need to change a Mui Stepper ( which the code works perfetly )
but what I need is a bit different ,
Instead of having this :
I want to get the text under the icon and instead of having a line between tow steps I prefer to have a '<'
Here is the code :
import Box from '#mui/material/Box';
import Stepper from '#mui/material/Stepper';
import Step from '#mui/material/Step';
import StepButton from '#mui/material/StepButton';
import Button from '#mui/material/Button';
import Typography from '#mui/material/Typography';
const steps = ['Select campaign settings', 'Create an ad group', 'Create an ad'];
export default function HorizontalNonLinearStepper() {
const [activeStep, setActiveStep] = React.useState(0);
const [completed, setCompleted] = React.useState<{
[k: number]: boolean;
}>({});
const totalSteps = () => {
return steps.length;
};
const completedSteps = () => {
return Object.keys(completed).length;
};
const isLastStep = () => {
return activeStep === totalSteps() - 1;
};
const allStepsCompleted = () => {
return completedSteps() === totalSteps();
};
const handleNext = () => {
const newActiveStep =
isLastStep() && !allStepsCompleted()
? // It's the last step, but not all steps have been completed,
// find the first step that has been completed
steps.findIndex((step, i) => !(i in completed))
: activeStep + 1;
setActiveStep(newActiveStep);
};
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};
const handleStep = (step: number) => () => {
setActiveStep(step);
};
const handleComplete = () => {
const newCompleted = completed;
newCompleted[activeStep] = true;
setCompleted(newCompleted);
handleNext();
};
const handleReset = () => {
setActiveStep(0);
setCompleted({});
};
return (
<Box sx={{ width: '100%' }}>
<Stepper nonLinear activeStep={activeStep}>
{steps.map((label, index) => (
<Step key={label} completed={completed[index]}>
<StepButton color="inherit" onClick={handleStep(index)}>
{label}
</StepButton>
</Step>
))}
</Stepper>
<div>
{allStepsCompleted() ? (
<React.Fragment>
<Typography sx={{ mt: 2, mb: 1 }}>
All steps completed - you&apos;re finished
</Typography>
<Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}>
<Box sx={{ flex: '1 1 auto' }} />
<Button onClick={handleReset}>Reset</Button>
</Box>
</React.Fragment>
) : (
<React.Fragment>
<Typography sx={{ mt: 2, mb: 1 }}>Step {activeStep + 1}</Typography>
<Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}>
<Button
color="inherit"
disabled={activeStep === 0}
onClick={handleBack}
sx={{ mr: 1 }}
>
Back
</Button>
<Box sx={{ flex: '1 1 auto' }} />
<Button onClick={handleNext} sx={{ mr: 1 }}>
Next
</Button>
{activeStep !== steps.length &&
(completed[activeStep] ? (
<Typography variant="caption" sx={{ display: 'inline-block' }}>
Step {activeStep + 1} already completed
</Typography>
) : (
<Button onClick={handleComplete}>
{completedSteps() === totalSteps() - 1
? 'Finish'
: 'Complete Step'}
</Button>
))}
</Box>
</React.Fragment>
)}
</div>
</Box>
);
}
Is there a way to override the MUI Stepper styles ?
Thank you in advance

Okay so basically it was 2 steps. The first one was to make the labels appear below the icons which was relatively easy.
I had to add alternativeLabel as a prop to the <Stepper />.
The next step was to remove the lines and replace them with < which wasn't straightforward. I did that by styling the .MuiStepConnector class, replacing its content and removing the border.
<Stepper
nonLinear
alternativeLabel
activeStep={activeStep}
sx={{
".MuiStepConnector-root": {
top: 0
},
".MuiStepConnector-root span": {
borderColor: "transparent"
},
".MuiStepConnector-root span::before": {
display: "flex",
justifyContent: "center",
content: '"<"'
}
}}
>
This is the result:

Related

MUI React How to properly make a language dropdown

I'm new to react with Typescript & MUI.
I'm working on a project that was originally built by someone else.
I need to modify an existing code and turn it into a <Autocomplete /> dropdownlist
Can someone please help with this?
I'm not really sure how to do this and I have been working on this for hours.
So basiclly the code below is working fine, I just need to make some changes to wrap the Language list in a dropdown list.
Currently it is working more like a dropdown menu.
const { borderRadius, locale, onChangeLocale } = useConfig();
const theme = useTheme();
const matchesXs = useMediaQuery(theme.breakpoints.down('md'));
const [open, setOpen] = useState(false);
const anchorRef = useRef<any>(null);
const [language, setLanguage] = useState<string>(locale);
const handleListItemClick = (
event:
| React.MouseEvent<HTMLAnchorElement>
| React.MouseEvent<HTMLDivElement, MouseEvent>
| undefined,
lng: string
) => {
setLanguage(lng);
onChangeLocale(lng);
setOpen(false);
};
const handleToggle = () => {
setOpen(prevOpen => !prevOpen);
};
const handleClose = (event: MouseEvent | TouchEvent) => {
if (anchorRef.current && anchorRef.current.contains(event.target)) {
return;
}
setOpen(false);
};
const prevOpen = useRef(open);
useEffect(() => {
if (prevOpen.current === true && open === false) {
anchorRef.current.focus();
}
prevOpen.current = open;
}, [open]);
useEffect(() => {
setLanguage(locale);
}, [locale]);
return (
<>
<Box
sx={{
ml: 3,
mr: 2,
[theme.breakpoints.down('md')]: {
ml: 1,
},
}}
>
<Avatar
variant="rounded"
sx={{
...theme.typography.commonAvatar,
...theme.typography.mediumAvatar,
border: '1px solid',
borderColor: 'rgba(255,255,255, 0)',
background: 'rgba(255,255,255, 0)',
color: theme.palette.primary.dark,
transition: 'all .2s ease-in-out',
'&[aria-controls="menu-list-grow"],&:hover': {
color: theme.palette.primary.main,
},
}}
ref={anchorRef}
aria-controls={open ? 'menu-list-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
color="inherit"
>
{language !== 'en' && (
<Typography
variant="h2"
color="inherit"
sx={{ textTransform: 'uppercase', fontWeight: '500' }}
>
{language}
</Typography>
)}
{language === 'en' && (
<TranslateTwoToneIcon sx={{ fontSize: '2.2rem' }} />
)}
</Avatar>
</Box>
<Popper
placement={matchesXs ? 'bottom-start' : 'bottom'}
open={open}
anchorEl={anchorRef.current}
role={undefined}
transition
disablePortal
popperOptions={{
modifiers: [
{
name: 'offset',
options: {
offset: [matchesXs ? 0 : 0, 20],
},
},
],
}}
>
{({ TransitionProps }) => (
<ClickAwayListener onClickAway={handleClose}>
<Transitions
position={matchesXs ? 'top-left' : 'top'}
in={open}
{...TransitionProps}
>
<Paper elevation={16}>
{open && (
<List
component="nav"
sx={{
width: '100%',
minWidth: 200,
maxWidth: 280,
bgcolor: theme.palette.background.paper,
borderRadius: `${borderRadius}px`,
[theme.breakpoints.down('md')]: {
maxWidth: 250,
},
}}
>
<ListItemButton
selected={language === 'en'}
onClick={event => handleListItemClick(event, 'en')}
>
<ListItemText
primary={
<Grid container>
<Typography color="textPrimary">English</Typography>
<Typography
variant="caption"
color="textSecondary"
sx={{ ml: '8px' }}
>
(UK)
</Typography>
</Grid>
}
/>
</ListItemButton>
<ListItemButton
selected={language === 'sv'}
onClick={event => handleListItemClick(event, 'sv')}
>
<ListItemText
primary={
<Grid container>
<Typography color="textPrimary">Svenska</Typography>
<Typography
variant="caption"
color="textSecondary"
sx={{ ml: '8px' }}
>
(SE)
</Typography>
</Grid>
}
/>
</ListItemButton>
</List>
)}
</Paper>
</Transitions>
</ClickAwayListener>
)}
</Popper>
</>
);
};
export default LocalizationSection;```

Get All TextField values from loop in Next.js when I press Submit button

first of all look at these below screenshots:
There are two tasks which I want to achieve:
There are two questions shown on the page using the array map method, by default I'm showing only one question, and when I press the next part button the second question will appear with the same question and a TextField (multiline). Now I've implemented a word counter in TextField but when I type something in 1st question the counter works properly. But when I go to the next question the here counter shows the previous question's word counter value, I want them to separately work for both questions.
When I click on the next part and again when I click on the previous part then the values from TextField are removed automatically. I want the values there if I navigate to the previous and next part questions. Also, I want to get both TextField values for a form submission when I press the Submit Test button.
Below are my codes for this page. I'm using Next.js and MUI
import { Grid, Typography, Box, NoSsr, TextField } from '#mui/material';
import PersonIcon from '#mui/icons-material/Person';
import Timer from '../../../components/timer';
import Button from '#mui/material/Button';
import { useState } from 'react';
import ArrowForwardIosIcon from '#mui/icons-material/ArrowForwardIos';
import { Scrollbars } from 'react-custom-scrollbars';
import AppBar from '#mui/material/AppBar';
import Toolbar from '#mui/material/Toolbar';
import ArrowBackIosIcon from '#mui/icons-material/ArrowBackIos';
import axios from '../../../lib/axios';
import { decode } from 'html-entities';
import { blueGrey } from '#mui/material/colors';
export default function Writing({ questions }) {
const [show, setShow] = useState(false);
const [show1, setShow1] = useState(true);
const [showQuestionCounter, setShowQuestionCounter] = useState(0);
const [wordsCount, setWordsCount] = useState(0);
return (
<>
<Box sx={{ flexGrow: 1 }}>
<AppBar position="fixed" style={{ background: blueGrey[900] }}>
<Toolbar>
<Grid container spacing={2} alignItems="center">
<Grid item xs={4} display="flex" alignItems="center">
<PersonIcon
sx={{ background: '#f2f2f2', borderRadius: '50px' }}
/>
<Typography variant="h6" color="#f2f2f2" ml={1}>
xxxxx xxxxx-1234
</Typography>
</Grid>
<Grid item xs={4} container justifyContent="center">
<Timer timeValue={2400} />
</Grid>
<Grid item xs={4} container justifyContent={'right'}>
<Button
variant="contained"
style={{ background: 'white', color: 'black' }}
size="small">
Settings
</Button>
<Button
variant="contained"
style={{
background: 'white',
color: 'black',
margin: '0px 10px',
}}
size="small">
Hide
</Button>
<Button
variant="contained"
style={{ background: 'white', color: 'black' }}
size="small">
Help
</Button>
</Grid>
</Grid>
</Toolbar>
</AppBar>
</Box>
<Box
sx={{
background: blueGrey[50],
height: '100%',
width: '100%',
position: 'absolute',
}}
pt={{ xs: 13, sm: 11, md: 10, lg: 11, xl: 11 }}>
{questions.map((question, index) =>
index === showQuestionCounter ? (
<Box
key={question.id}
px={3}
sx={{ background: '#f2f2f2', pb: 4 }}
position={{
xs: 'sticky',
sm: 'sticky',
lg: 'initial',
md: 'initial',
xl: 'initial',
}}>
<Box
style={{ background: '#f7fcff', borderRadius: '4px' }}
py={1}
px={2}>
<Box>
<Typography variant="h6" component="h6" ml={1}>
Part {question.id}
</Typography>
<Typography variant="subtitle2" component="div" ml={1} mt={1}>
<NoSsr>
<div
dangerouslySetInnerHTML={{
__html: decode(question.questions[0].question, {
level: 'html5',
}),
}}></div>
</NoSsr>
</Typography>
</Box>
</Box>
<Box
style={{
background: '#f7fcff',
borderRadius: '4px',
marginBottom: '75px',
}}
pt={1}
px={3}
mt={{ xs: 2, sm: 2, md: 2, lg: 0, xl: 3 }}>
<Grid container spacing={2}>
<Grid item xs={12} sm={12} lg={6} md={6} xl={6}>
<Box
py={{ lg: 1, md: 1, xl: 1 }}
style={{ height: '50vh' }}>
<Scrollbars universal>
<Typography
variant="body1"
component="div"
style={{ textAlign: 'justify' }}
mr={2}>
<NoSsr>
<div
dangerouslySetInnerHTML={{
__html: decode(question.question_text, {
level: 'html5',
}),
}}></div>
</NoSsr>
</Typography>
</Scrollbars>
</Box>
</Grid>
<Grid
item
xs={12}
sm={12}
lg={6}
md={6}
xl={6}
mt={{ md: 4, lg: 4, xl: 4 }}>
<TextField
id={`${question.id}`}
label="Type your answer here"
multiline
name={`answer_${question.id}`}
rows={12}
variant="outlined"
fullWidth
helperText={`Words Count: ${wordsCount}`}
onChange={(e) => {
setWordsCount(
e.target.value.trim().split(/\s+/).length
);
}}
/>
</Grid>
</Grid>
</Box>
</Box>
) : null
)}
<Box sx={{ position: 'fixed', width: '100%', left: 0, bottom: 0 }}>
<Grid
container
style={{ background: blueGrey[300], display: 'flex' }}
py={2}
px={3}>
<Grid
item
xs={3}
sm={3}
lg={6}
md={6}
xl={6}
container
justifyContent={'start'}>
<Button
variant="contained"
style={{ background: 'white', color: 'black' }}
size="small">
Save Draft
</Button>
</Grid>
<Grid
item
xs={9}
sm={9}
lg={6}
md={6}
xl={6}
container
justifyContent={'end'}>
<Button
variant="contained"
size="small"
style={{
background: 'white',
color: 'black',
visibility: show1 ? 'visible' : 'hidden',
}}
endIcon={<ArrowForwardIosIcon />}
onClick={() => {
setShow((prev) => !prev);
setShowQuestionCounter(showQuestionCounter + 1);
setShow1((s) => !s);
}}>
Next Part
</Button>
{show && (
<>
<Box>
<Button
variant="contained"
style={{
background: 'white',
color: 'black',
margin: '0 10px',
visibility: show ? 'visible' : 'hidden',
}}
startIcon={<ArrowBackIosIcon />}
size="small"
onClick={() => {
setShow1((s) => !s);
setShowQuestionCounter(showQuestionCounter - 1);
setShow((prev) => !prev);
}}>
previous Part
</Button>
<Button variant="contained" color="success">
Submit Test
</Button>
</Box>
</>
)}
</Grid>
</Grid>
</Box>
</Box>
</>
);
}
export async function getServerSideProps(context) {
const { id } = context.query;
const token = context.req.cookies.token;
if (!token) {
context.res.writeHead(302, {
Location: '/',
});
context.res.end();
}
const res = await axios.get(`test/${id}/questions`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
if (res.data.success) {
return {
props: {
questions: res.data.data.questions,
},
};
}
}
The wordsCount state is shared between both questions, which means that when you go to the next question the state remains unchanged and shows the wordsCount from the first question. To solve it, each question needs to have it's own state which you can do by creating a Question component and mapping over it:
export default function Question({ question }) {
const [wordsCount, setWordsCount] = useState(0)
return (
<Box
// ...
>
{/* ... */}
<TextField
// ...
helperText={`${wordsCount} words`}
onChange={(e) => {
setWordsCount(e.target.value.trim().split(/\s+/).length)
}}
/>
{/* ... */}
</Box>
)
}
Then map over it:
{questions.map((question, index) =>
index === showQuestionCounter ? (
<Question key={question.id} question={question} />
) : null
)}
Currently, the value of TextField gets reset you the component is unmounted (i.e. when you go to the next question). You need to make the TextField component a controlled component, meaning that you store the value of the field in useState. And if you need to submit the value of TextField later, then you probably need to store the values in the parent component:
export default function Writing({ questions }) {
// ...
const [answers, setAnswers] = useState([])
function handleChange(id, answer) {
// copy the current answers
let newAnswers = [...answers]
// find the index of the id of the answer in the current answers
const index = newAnswers.findIndex((item) => item.id === id)
// if the answer does exist, replace the previous answer with the new one, else add the new answer
if (index) {
newAnswers[index] = { id, answer }
setAnswers(newAnswers)
} else {
setAnswers([...answers, { id, answer }])
}
}
return (
<>
{/* ... */}
{questions.map((question, index) =>
index === showQuestionCounter ? (
<Question
key={question.id}
question={question}
value={answers.find((item) => item.id === question.id)?.answer || ''}
handleChange={handleChange}
/>
) : null
)}
</>
}
In the Question component, add the handler.
export default function Question({ question, value, handleInputChange }) {
const [wordsCount, setWordsCount] = useState(0)
return (
<Box>
{/* ... */}
<TextField
helperText={`${wordsCount} words`}
value={value}
onChange={(e) => {
handleInputChange(question.id, e.target.value)
setWordsCount(e.target.value.trim().split(/\s+/).length)
}}
/>
{/* ... */}
</Box>
)
}
In the parent component (Writing) you should be able to use the values for form submission.

Automatically Changing State on a React App

I'm looking to change the way I manage state in my app.
Currently, I am using a mapped component which when selected, will set the index of the card and then use this index to colour the component background blue.
This is great! And it works, however to change from e.g card 1 to 2, I need to tap on card 1 again to set index to 0, then select card 2. I do not know how to change the function so if selected outside the container, set index =0, then set index=1, per a conventional app.
I am managing as such:
const [isSelected, setIsSelected] = useState("");
function handleParamChange(e) {
e.preventDefault();
const param = e.target.name //name may be desc
const value = e.target.value
setParams(prevParams => {
return { ...prevParams, [param]: value}
})
}
With a mapped component of:
{
jobs.length > 0 &&
jobs.map(
(job, index) =>
<JobCard
key={job.id}
job={job}
index={index + 1}
isSelected={isSelected}
setIsSelected={setIsSelected}
/>)
}
const JobCard = ({ setIsSelected, isSelected, index, job }) => {
const [open, setOpen] = useState(false)
const [isActive, setIsActive] = useState(false);
console.log(isSelected)
return (
<CardContainer>
{/* BELOW WORKING */}
{/* <CardPrimary onClick={() => setIsSelected(true)} className={isSelected ? "css-class-to-highlight-div" : undefined}> */}
<CardPrimary
onClick={() => {
if (!isSelected) {
setIsSelected(index);
setIsActive(true);
} else if (isSelected === index) {
setIsSelected("");
setIsActive(false);
}
}}
style={{
backgroundColor: isActive ? "#0062ff" : "inherit",
display: "flex",
height: "90%",
width: "95%",
borderRadius: "10px",
justifyContent: "center",
flexDirection: "column",
boxShadow: "0px 4px 10px rgba(0, 0, 0, 0.25)"
}}
>
<CardHeader>
<CardHeaderTopRow>
<Typography variant = "cardheader1" color={isActive ? "white" : "inherit"}>
{job.title}
</Typography>
<HeartDiv>
<IconButton color={open ? "error" : "buttoncol"} sx={{ boxShadow: 3}} fontSize ="2px" size="small"
onClick={()=> setOpen(prevOpen => !prevOpen)}>
<FavoriteIcon fontSize="inherit"
/>
</IconButton>
</HeartDiv>
</CardHeaderTopRow>
<Typography variant = "subtitle4" color={isActive ? "#d6d6d6" : "text.secondary"}>
{job.company.display_name}
</Typography>
</CardHeader>
</CardContainer>
)
}
export default JobCard
This all works.
And I have no issues, I just want to improve it. So How would you implement react hooks and a ref to automatically assign the state and change the isSelected index based on clicks?
If i understand correct, you only want one card to be selected and also the isActive inside the JobCard should be in sync with the isSelected you pass.
If so, you only need one state variable and to be safe, it should really be the job.id and not the index.
So, instead of const [isSelected, setIsSelected] = useState(""); you should rename it to something like const [selectedJob, setSelectedJob] = useState();
and also handle the toggle click here
const toggleJob = useCallback((jobId)=>{
setSelectedJob( (currentJobId) => currentJobId === jobId ? null : jobId );
},[]);
Then
{
jobs.length > 0 &&
jobs.map(
(job, index) =>
<JobCard
key={job.id}
job={job}
isSelected={job.id === selectedJob}
toggleJob={toggleJob}
/>)
}
and finally
const JobCard = ({ toggleJob, isSelected, job }) => {
const [open, setOpen] = useState(false)
const handleCardClick = useCallback(()=>{
toggleJob(job.id);
},[toggleJob, job])
return (
<CardContainer>
<CardPrimary
onClick={handleCardClick}
style={{
backgroundColor: isSelected ? "#0062ff" : "inherit",
display: "flex",
height: "90%",
width: "95%",
borderRadius: "10px",
justifyContent: "center",
flexDirection: "column",
boxShadow: "0px 4px 10px rgba(0, 0, 0, 0.25)"
}}
>
<CardHeader>
<CardHeaderTopRow>
<Typography variant = "cardheader1" color={isSelected ? "white" : "inherit"}>
{job.title}
</Typography>
<HeartDiv>
<IconButton color={open ? "error" : "buttoncol"} sx={{ boxShadow: 3}} fontSize ="2px" size="small"
onClick={()=> setOpen(prevOpen => !prevOpen)}>
<FavoriteIcon fontSize="inherit"
/>
</IconButton>
</HeartDiv>
</CardHeaderTopRow>
<Typography variant = "subtitle4" color={isSelected ? "#d6d6d6" : "text.secondary"}>
{job.company.display_name}
</Typography>
</CardHeader>
</CardContainer>
)
}
export default JobCard

alternativeLabel in Stepper component using material UI

I'm learning Material UI. I am struggling with one problem.
I am using Stepper component and for mobile devices I want add props alternativeLabel which will make the labels will be under the circle.
I got lost. Could someone show me how to achieve it ?
Thank you for any help ! ❤️
export default function ProgressBarStepper({ step }) {
const classes = useStyles();
const [activeStep, setActiveStep] = React.useState(step);
const [skipped, setSkipped] = React.useState(new Set());
const isStepSkipped = (step) => {
return skipped.has(step);
};
// how to have alternativeLabel only for mobile ??
//connector={false}
return (
<Box sx={{ width: "100%" }}>
<Stepper activeStep={activeStep} connector={<QontoConnector />} >
{steps.map((label, index) => {
const stepProps = {};
const labelProps = {};
if (isStepSkipped(index)) {
stepProps.completed = false;
}
return (
<Step
sx={{
"& .MuiStepLabel-root .Mui-completed": {
fontWeight: "700",
},
}}
key={label}
{...stepProps}
>
<StepLabel
className={classes.boolspac}
sx={{ fontWeight: "700", padding: "0" }}
{...labelProps}
>
{label}
</StepLabel>
</Step>
);
})}
</Stepper>
</Box>
);
}

How to submit and validate a form from outside component ReactJS

I have a multi-step component on which I would like to have a form in one of the steps, so when the user tries to go to the next step I could validate the input and submit the form. So far I have this code, but I haven't figured how to validate and submit the code from the outside button.
I would appreciate your help.
import CostumForm from './NannySignupComponents/InformacionPersonal';
const steps = ['Shipping address', 'Payment details', 'Review your order'];
const theme = createTheme();
export default function Checkout() {
function getStepContent(step) {
switch (step) {
case 0:
return (
<CostumForm/>
);
case 1:
return ;
case 2:
return ;
default:
throw new Error('Unknown step');
}
}
const [activeStep, setActiveStep] = useState(0);
const handleNext = () => {
setActiveStep(activeStep + 1);
this.setState({submitFromOutside: true})
};
const handleBack = () => {
setActiveStep(activeStep - 1);
};
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<AppBar
position="absolute"
color="default"
elevation={0}
sx={{
position: 'relative',
borderBottom: (t) => `1px solid ${t.palette.divider}`,
}}
>
<Toolbar>
<Typography variant="h6" color="inherit" noWrap>
Company name
</Typography>
</Toolbar>
</AppBar>
<Container component="main" maxWidth="sm" sx={{ mb: 4 }} >
<Paper variant="outlined" sx={{ my: { xs: 3, md: 6 }, p: { xs: 2, md: 3 } }}>
<Typography component="h1" variant="h4" align="center">
Checkout
</Typography>
<Stepper activeStep={activeStep} sx={{ pt: 3, pb: 5 }}>
{steps.map((label) => (
<Step key={label}>
<StepLabel>{label}</StepLabel>
</Step>
))}
</Stepper>
<React.Fragment>
{activeStep === steps.length ? (
<React.Fragment>
<Typography variant="h5" gutterBottom>
Thank you for your order.
</Typography>
<Typography variant="subtitle1">
Your order number is #2001539. We have emailed your order
confirmation, and will send you an update when your order has
shipped.
</Typography>
</React.Fragment>
) : (
<React.Fragment>
{getStepContent(activeStep)}
<Box sx={{ display: 'flex', justifyContent: 'flex-end' }}>
{activeStep !== 0 && (
<Button onClick={handleBack} sx={{ mt: 3, ml: 1 }} >
Back
</Button>
)}
<Button
variant="contained"
onClick={handleNext}
sx={{ mt: 3, ml: 1 }}
>
{activeStep === steps.length - 1 ? 'Place order' : 'Next'}
</Button>
</Box>
</React.Fragment>
)}
</React.Fragment>
</Paper>
</Container>
</ThemeProvider>
);
}

Resources