@mui/material#Step TypeScript Examples
The following examples show how to use
@mui/material#Step.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: form-stepper.tsx From example with MIT License | 5 votes |
export function FormStepper({ steps, onComplete }: IFormStepperProps) {
const [state, setFormResponse] = useReducer((prevState: any, action: {
type: "next"
response: any
} | {
type: "prev"
}) => {
const state = cloneDeep(prevState)
switch (action.type) {
case "next":
state.responses[state.currentStep] = action.response
state.currentStep = Math.min(state.currentStep + 1, steps.length - 1)
return state
case "prev":
state.currentStep = Math.max(state.currentStep - 1, 0)
return state
}
}, {
currentStep: 0,
responses: []
})
console.log(state)
return (
<>
<Stepper activeStep={state.currentStep}>
{
steps.map((step, index) => {
const last = index === steps.length - 1
const lastCompleted = last && state.currentStep === steps.length - 1
return <Step
key={index}
index={index}
sx={{
".Mui-completed": {
color: lastCompleted ? "green" : "primary"
}
}}
completed={lastCompleted ? true : undefined}
>
<StepLabel>{step.label}</StepLabel>
</Step>
})
}
</Stepper>
<Box sx={{ mt: 4 }}>
{steps[state.currentStep].render(
(formResponse) => {
setFormResponse({ type: "next", response: formResponse })
if (state.currentStep === steps.length - 1) {
onComplete?.(formResponse)
}
},
state.responses[state.currentStep - 1]
)}
</Box>
{
state.currentStep > 0 &&
<Box sx={{ mt: 2 }}>
<Button
startIcon={<Icon icon={faAngleLeft}/>}
color={"inherit"}
variant="text"
onClick={() => setFormResponse({ type: "prev" })}
>
Back
</Button>
</Box>
}
</>
)
}
Example #2
Source File: IrregularityForm.tsx From frontend with MIT License | 4 votes |
export default function IrregularityForm({ campaign, person }: Props) {
const { t } = useTranslation('irregularity')
const classes = useStyles()
const formRef = useRef<FormikProps<IrregularityFormData>>(null)
const [fail, setFail] = useState(false)
const [success, setSuccess] = useState(false)
const [files, setFiles] = useState<File[]>([])
const [activeStep, setActiveStep] = useState<Steps>(Steps.GREETING)
const [failedStep, setFailedStep] = useState<Steps>(Steps.NONE)
const steps: StepType[] = [
{
component: <Greeting />,
},
{
component: <Contacts />,
},
{
component: <Info files={files} setFiles={setFiles} />,
},
]
const isStepFailed = (step: Steps | number): boolean => {
return step === failedStep
}
const mutation = useMutation<
AxiosResponse<IrregularityResponse>,
AxiosError<ApiErrors>,
IrregularityInput
>({
mutationFn: createIrregularity,
})
const fileUploadMutation = useMutation<
AxiosResponse<IrregularityUploadImage[]>,
AxiosError<ApiErrors>,
UploadIrregularityFiles
>({
mutationFn: uploadIrregularityFiles(),
})
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1)
}
const handleSubmit = async (
values: IrregularityFormData,
actions: FormikHelpers<IrregularityFormData>,
) => {
if (isLastStep(activeStep, steps)) {
const errors = await actions.validateForm(values)
const hasErrors = !!Object.keys(errors).length
if (hasErrors) {
setFailedStep(Steps.INFO)
return
}
setActiveStep((prevActiveStep) => prevActiveStep + 1)
setFailedStep(Steps.NONE)
try {
const data: IrregularityInput = {
campaignId: values.info.campaignId,
description: values.info.description,
notifierType: values.info.notifierType,
reason: values.info.reason,
status: values.status,
person: {
firstName: values.person.firstName,
lastName: values.person.lastName,
email: values.person.email,
phone: values.person.phone,
},
}
const response = await mutation.mutateAsync(data)
await fileUploadMutation.mutateAsync({
files,
irregularityId: response.data.id,
})
actions.resetForm()
setSuccess(true)
} catch (error) {
console.error(error)
setFail(true)
if (isAxiosError(error)) {
const { response } = error as AxiosError<ApiErrors>
response?.data.message.map(({ property, constraints }) => {
actions.setFieldError(property, t(matchValidator(constraints)))
})
}
}
return
}
actions.setTouched({})
actions.setSubmitting(false)
initialValues.info.campaignId = campaign.id
initialValues.person.firstName = person?.firstName || ''
initialValues.person.lastName = person?.lastName || ''
initialValues.person.email = person?.email || ''
initialValues.person.phone = person?.phone || ''
await stepsHandler({ actions, activeStep, setActiveStep, setFailedStep })
}
if (success) {
return <Success />
}
if (fail) {
return <Fail setFail={setFail} setActiveStep={setActiveStep} />
}
return (
<>
<GenericForm<IrregularityFormData>
onSubmit={handleSubmit}
initialValues={initialValues}
validationSchema={validationSchema[activeStep]}
innerRef={formRef}>
<Stepper
alternativeLabel
activeStep={activeStep}
className={classes.stepper}
connector={<ColorlibConnector />}>
{steps.map((step, index) => (
<Step key={index}>
<StepLabel error={isStepFailed(index)} StepIconComponent={StepIcon} />
</Step>
))}
</Stepper>
<div className={classes.content}>
<Grid container spacing={5} justifyContent="center" className={classes.instructions}>
<Grid container item xs={12}>
{activeStep < steps.length && steps[activeStep].component}
</Grid>
<Grid container item spacing={3}>
<Actions
activeStep={activeStep}
disableBack={activeStep === 0}
onBack={handleBack}
loading={mutation.isLoading}
campaign={campaign}
nextLabel={isLastStep(activeStep, steps) ? 'cta.submit' : 'cta.next'}
backLabel={isFirstStep(activeStep, steps) ? 'cta.back-to-campaign' : 'cta.back'}
/>
</Grid>
</Grid>
</div>
</GenericForm>
{activeStep === Steps.GREETING && <Remark text={t('steps.greeting.remark')} />}
{activeStep === Steps.CONTACTS && <Remark text={t('steps.contacts.remark')} />}
</>
)
}
Example #3
Source File: FormikStepper.tsx From frontend with MIT License | 4 votes |
export function FormikStepper({ children, ...props }: GenericFormProps<OneTimeDonation>) {
const childrenArray = React.Children.toArray(children) as React.ReactElement<FormikStepProps>[]
const { step, setStep } = useContext(StepsContext)
const router = useRouter()
useEffect(() => {
router.query.success === 'false' || router.query.success === 'true' ? setStep(3) : null
}, [router.query.success])
const currentChild = childrenArray[step]
const { data: currentPerson } = useCurrentPerson()
function isLastStep() {
return step === childrenArray.length - 2
}
function isFirstStep() {
return step === 0
}
function isLogged() {
if (currentPerson === undefined) {
return false
}
if (currentPerson?.status && currentPerson.status !== 'unauthenticated') {
return false
}
return true
}
const { t } = useTranslation('one-time-donation')
return (
<Formik
{...props}
validationSchema={currentChild.props.validationSchema}
onSubmit={async (values, helpers) => {
if (isLastStep()) {
await props.onSubmit(values, helpers)
} else if (isFirstStep() && isLogged()) {
if (values.payment === 'bank') {
router.push({
pathname: router.route,
query: {
slug: router.query.slug,
success: true,
},
})
} else {
setStep((s) => s + 2)
}
} else {
setStep((s) => s + 1)
helpers.setTouched({})
}
}}
validateOnMount
validateOnBlur>
{({ isSubmitting, handleSubmit, isValid }) => (
<Form
onSubmit={handleSubmit}
style={{
maxWidth: '662px',
marginLeft: 'auto',
marginRight: 'auto',
}}
autoComplete="off">
<StyledStepper>
<Stepper alternativeLabel activeStep={step}>
{childrenArray.map((child, index) => (
<Step key={index}>
<StepLabel classes={{ alternativeLabel: classes.stepIcon }}>
{child.props.label}
</StepLabel>
</Step>
))}
</Stepper>
</StyledStepper>
<Box marginY={8}>{currentChild}</Box>
{/* Controls of the form */}
{step === 3 ? null : (
<Grid container rowSpacing={2} columnSpacing={2}>
<Grid item xs={12} md={6}>
<Button
fullWidth
type="button"
variant="text"
disabled={step === 0 || isSubmitting}
color="error"
size="large"
onClick={() => {
if (step === 2 && isLogged()) {
setStep((s) => s - 2)
return
}
setStep((s) => s - 1)
}}>
{t('btns.back')}
</Button>
</Grid>
<Grid item xs={12} md={6}>
<LoadingButton
disabled={!isValid}
fullWidth
type="submit"
variant="contained"
loading={isSubmitting}
color="info"
size="large">
{isSubmitting ? 'Потвърждение' : isLastStep() ? t('btns.end') : t('btns.next')}
</LoadingButton>
</Grid>
</Grid>
)}
</Form>
)}
</Formik>
)
}
Example #4
Source File: SupportForm.tsx From frontend with MIT License | 4 votes |
export default function SupportForm() {
const { t } = useTranslation()
const formRef = useRef<FormikProps<SupportFormData>>(null)
const [activeStep, setActiveStep] = useState<Steps>(Steps.ROLES)
const [failedStep, setFailedStep] = useState<Steps>(Steps.NONE)
const mutation = useMutation<
AxiosResponse<SupportRequestResponse>,
AxiosError<ApiErrors>,
SupportRequestInput
>({
mutationFn: createSupportRequest,
onError: () => AlertStore.show(t('common:alerts.error'), 'error'),
onSuccess: () => AlertStore.show(t('common:alerts.message-sent'), 'success'),
})
const handleBack = () => {
setActiveStep((prevActiveStep) => prevActiveStep - 1)
}
const handleSubmit = async (values: SupportFormData, actions: FormikHelpers<SupportFormData>) => {
if (isLastStep(activeStep, steps)) {
const errors = await actions.validateForm()
const hasErrors = !!Object.keys(errors).length
if (hasErrors) {
setFailedStep(Steps.PERSON)
return
}
setActiveStep((prevActiveStep) => prevActiveStep + 1)
setFailedStep(Steps.NONE)
try {
const { person, ...supportData } = values
await mutation.mutateAsync({ person, supportData })
actions.resetForm()
if (window) {
window.scrollTo({ top: 0, behavior: 'smooth' })
}
} catch (error) {
console.error(error)
if (isAxiosError(error)) {
const { response } = error as AxiosError<ApiErrors>
response?.data.message.map(({ property, constraints }) => {
actions.setFieldError(property, t(matchValidator(constraints)))
})
}
}
return
}
actions.setTouched({})
actions.setSubmitting(false)
switch (activeStep) {
case Steps.ROLES:
{
const errors = await actions.validateForm()
if (errors.roles) {
setFailedStep(Steps.ROLES)
return
}
setActiveStep((prevActiveStep) => prevActiveStep + 1)
setFailedStep(Steps.NONE)
}
break
case Steps.QUESTIONS:
{
const errors = await actions.validateForm()
let hasErrors = false
const questions = Object.entries(values.roles)
.filter(([, value]) => value)
.map(([key]) => key)
Object.keys(errors).forEach((error) => {
if (questions.includes(error)) {
hasErrors = true
}
})
if (hasErrors) {
setFailedStep(Steps.QUESTIONS)
return
}
setActiveStep((prevActiveStep) => prevActiveStep + 1)
setFailedStep(Steps.NONE)
}
break
case Steps.PERSON:
{
const errors = await actions.validateForm()
if (errors.person) {
setFailedStep(Steps.PERSON)
return
}
setActiveStep((prevActiveStep) => prevActiveStep + 1)
setFailedStep(Steps.NONE)
}
break
default:
return 'Unknown step'
}
}
const isStepFailed = (step: Steps | number): boolean => {
return step === failedStep
}
const isLastStep = (activeStep: number, steps: StepType[]): boolean => {
return activeStep === steps.length - 2
}
const isThankYouStep = (activeStep: number, steps: StepType[]): boolean => {
return activeStep === steps.length - 1
}
return (
<GenericForm<SupportFormData>
onSubmit={handleSubmit}
initialValues={initialValues}
validationSchema={validationSchema[activeStep]}
innerRef={formRef}>
<Hidden mdDown>
<Stepper
alternativeLabel
activeStep={activeStep}
connector={<StepConnector sx={{ mt: 1.5 }} />}>
{steps.map((step, index) => (
<Step key={index}>
<StepLabel error={isStepFailed(index)} StepIconComponent={StepIcon}>
{t(step.label)}
</StepLabel>
</Step>
))}
</Stepper>
</Hidden>
{isThankYouStep(activeStep, steps) ? (
steps[activeStep].component
) : (
<Box sx={{ display: 'flex', justifyContent: 'center' }}>
<Grid container justifyContent="center">
<Grid item xs={12} sx={{ mt: 1, mb: 5 }}>
{steps[activeStep].component}
</Grid>
<Grid item xs={12} sx={(theme) => ({ '& button': { minWidth: theme.spacing(12) } })}>
<Actions
disableBack={activeStep === 0}
onBack={handleBack}
loading={mutation.isLoading}
nextLabel={
isLastStep(activeStep, steps) ? 'support:cta.submit' : 'support:cta.next'
}
/>
</Grid>
</Grid>
</Box>
)}
</GenericForm>
)
}