Enhance WizardView component by adding support for controlled current step management and optional sub-step descriptions using Timeline. Introduce new props for sidebar width, button visibility, and step skipping functionality, improving user interaction and flexibility in the wizard flow.
This commit is contained in:
parent
0c6fe5cbac
commit
9442c9105b
@ -9,13 +9,15 @@ import {
|
|||||||
Divider,
|
Divider,
|
||||||
Progress,
|
Progress,
|
||||||
Button,
|
Button,
|
||||||
Dropdown
|
Dropdown,
|
||||||
|
Timeline
|
||||||
} from 'antd'
|
} from 'antd'
|
||||||
import NewObjectButtons from './NewObjectButtons'
|
import NewObjectButtons from './NewObjectButtons'
|
||||||
|
|
||||||
const { Title } = Typography
|
const { Title } = Typography
|
||||||
|
|
||||||
const WizardView = ({
|
const WizardView = ({
|
||||||
|
sizeBarWidth = '160px',
|
||||||
showSteps = true,
|
showSteps = true,
|
||||||
steps,
|
steps,
|
||||||
title = 'Wizard View',
|
title = 'Wizard View',
|
||||||
@ -27,22 +29,76 @@ const WizardView = ({
|
|||||||
progress = 0,
|
progress = 0,
|
||||||
actions = [],
|
actions = [],
|
||||||
sideBarGrow = false,
|
sideBarGrow = false,
|
||||||
disabled = false
|
disabled = false,
|
||||||
|
showButtons = true,
|
||||||
|
showTitle = true,
|
||||||
|
currentStep: controlledCurrentStep,
|
||||||
|
currentSubStep = 0,
|
||||||
|
onStepChange,
|
||||||
|
showSkipButton = false,
|
||||||
|
onSkip = () => {}
|
||||||
}) => {
|
}) => {
|
||||||
const [currentStep, setCurrentStep] = useState(0)
|
const [internalCurrentStep, setInternalCurrentStep] = useState(0)
|
||||||
|
const currentStep = controlledCurrentStep ?? internalCurrentStep
|
||||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
const isMobile = useMediaQuery({ maxWidth: 768 })
|
||||||
|
|
||||||
|
const setCurrentStep = (step) => {
|
||||||
|
if (controlledCurrentStep === undefined) {
|
||||||
|
setInternalCurrentStep(step)
|
||||||
|
}
|
||||||
|
onStepChange?.(step)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex gap='middle' style={{ width: '100%' }}>
|
<Flex gap='middle' style={{ width: '100%' }}>
|
||||||
{!isMobile && showSteps == true ? (
|
{!isMobile && showSteps == true ? (
|
||||||
sideBar != null ? (
|
sideBar != null ? (
|
||||||
sideBar
|
sideBar
|
||||||
) : (
|
) : (
|
||||||
<div style={{ minWidth: sideBarGrow == true ? '100%' : '160px' }}>
|
<div
|
||||||
|
style={{ minWidth: sideBarGrow == true ? '100%' : sizeBarWidth }}
|
||||||
|
>
|
||||||
<Steps
|
<Steps
|
||||||
current={currentStep}
|
current={currentStep}
|
||||||
items={steps.map((step, index) => ({
|
items={steps.map(({ subSteps, ...step }, index) => ({
|
||||||
...step,
|
...step,
|
||||||
|
description: subSteps ? (
|
||||||
|
<Timeline
|
||||||
|
className='subSteps'
|
||||||
|
items={subSteps.map((subStep, subStepIndex) => {
|
||||||
|
const complete =
|
||||||
|
index < currentStep ||
|
||||||
|
(index === currentStep && subStepIndex < currentSubStep)
|
||||||
|
const current =
|
||||||
|
index === currentStep && subStepIndex === currentSubStep
|
||||||
|
|
||||||
|
const disabled = index < currentStep
|
||||||
|
return {
|
||||||
|
...subStep,
|
||||||
|
children: subStep.title,
|
||||||
|
dot: complete ? (
|
||||||
|
<div
|
||||||
|
className={`subSteps-dot ${disabled ? 'subSteps-dot-disabled' : ''}`}
|
||||||
|
>
|
||||||
|
<CheckIcon
|
||||||
|
style={{
|
||||||
|
fontSize: '5px',
|
||||||
|
marginTop: '0px',
|
||||||
|
marginRight: '0px',
|
||||||
|
color: disabled
|
||||||
|
? 'var(--color-primary)'
|
||||||
|
: 'var(--layout-modal-bg)'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : undefined,
|
||||||
|
color: complete ? 'blue' : current ? 'blue' : 'gray'
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
step.description
|
||||||
|
),
|
||||||
icon:
|
icon:
|
||||||
index < currentStep ? (
|
index < currentStep ? (
|
||||||
<div className='ant-steps-item-icon'>
|
<div className='ant-steps-item-icon'>
|
||||||
@ -76,62 +132,83 @@ const WizardView = ({
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Flex vertical gap='middle' style={{ flexGrow: 1, width: '100%' }}>
|
<Flex vertical gap='middle' style={{ flexGrow: 1, width: '100%' }}>
|
||||||
<Title level={2} style={{ margin: '0 0 8px 0', lineHeight: 0.7 }}>
|
{showTitle ? (
|
||||||
{title}
|
<Title level={2} style={{ margin: '0 0 8px 0', lineHeight: 0.7 }}>
|
||||||
</Title>
|
{title}
|
||||||
|
</Title>
|
||||||
|
) : null}
|
||||||
<div style={{ minHeight: '260px', marginBottom: 4, width: '100%' }}>
|
<div style={{ minHeight: '260px', marginBottom: 4, width: '100%' }}>
|
||||||
{steps[currentStep].content}
|
{steps[currentStep].content}
|
||||||
</div>
|
</div>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex gap={'middle'} align='center' justify='end'>
|
{showButtons || progress > 0 || actions.length > 0 ? (
|
||||||
{progress > 0 ? (
|
<Flex
|
||||||
<Progress
|
gap={'middle'}
|
||||||
style={{ maxWidth: '160px' }}
|
align='center'
|
||||||
showInfo={false}
|
justify={showSkipButton ? 'space-between' : 'end'}
|
||||||
percent={progress}
|
>
|
||||||
/>
|
{showSkipButton && showButtons && (
|
||||||
) : null}
|
<Button onClick={onSkip} disabled={disabled}>
|
||||||
{(actions || []).map((action) => {
|
Skip
|
||||||
if (action.steps.includes(steps[currentStep].key)) {
|
</Button>
|
||||||
if (action.children) {
|
)}
|
||||||
return (
|
|
||||||
<Dropdown menu={{ items: action.children }} key={action.key}>
|
<Flex gap={'middle'} align='center' justify='end'>
|
||||||
|
{progress > 0 ? (
|
||||||
|
<Progress
|
||||||
|
style={{ maxWidth: '160px' }}
|
||||||
|
showInfo={false}
|
||||||
|
percent={progress}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
{(actions || []).map((action) => {
|
||||||
|
if (action.steps.includes(steps[currentStep].key)) {
|
||||||
|
if (action.children) {
|
||||||
|
return (
|
||||||
|
<Dropdown
|
||||||
|
menu={{ items: action.children }}
|
||||||
|
key={action.key}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
onClick={action?.onClick}
|
||||||
|
disabled={action?.disabled || disabled}
|
||||||
|
loading={action?.loading || false}
|
||||||
|
>
|
||||||
|
{action.label}
|
||||||
|
</Button>
|
||||||
|
</Dropdown>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return (
|
||||||
<Button
|
<Button
|
||||||
|
key={action.key}
|
||||||
onClick={action?.onClick}
|
onClick={action?.onClick}
|
||||||
disabled={action?.disabled || disabled}
|
disabled={action?.disabled || disabled}
|
||||||
loading={action?.loading || false}
|
loading={action?.loading || false}
|
||||||
>
|
>
|
||||||
{action.label}
|
{action.label}
|
||||||
</Button>
|
</Button>
|
||||||
</Dropdown>
|
)
|
||||||
)
|
}
|
||||||
}
|
return null
|
||||||
return (
|
})}
|
||||||
<Button
|
|
||||||
key={action.key}
|
|
||||||
onClick={action?.onClick}
|
|
||||||
disabled={action?.disabled || disabled}
|
|
||||||
loading={action?.loading || false}
|
|
||||||
>
|
|
||||||
{action.label}
|
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
})}
|
|
||||||
|
|
||||||
<NewObjectButtons
|
{showButtons && (
|
||||||
disabled={disabled}
|
<NewObjectButtons
|
||||||
currentStep={currentStep}
|
disabled={disabled}
|
||||||
totalSteps={steps.length}
|
currentStep={currentStep}
|
||||||
onPrevious={() => setCurrentStep((prev) => prev - 1)}
|
totalSteps={steps.length}
|
||||||
onNext={() => setCurrentStep((prev) => prev + 1)}
|
onPrevious={() => setCurrentStep(currentStep - 1)}
|
||||||
onSubmit={onSubmit}
|
onNext={() => setCurrentStep(currentStep + 1)}
|
||||||
formValid={formValid}
|
onSubmit={onSubmit}
|
||||||
submitLoading={loading}
|
formValid={formValid}
|
||||||
submitText={submitText}
|
submitLoading={loading}
|
||||||
/>
|
submitText={submitText}
|
||||||
</Flex>
|
/>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
) : null}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
@ -149,7 +226,15 @@ WizardView.propTypes = {
|
|||||||
submitText: PropTypes.string,
|
submitText: PropTypes.string,
|
||||||
progress: PropTypes.number,
|
progress: PropTypes.number,
|
||||||
actions: PropTypes.array,
|
actions: PropTypes.array,
|
||||||
sideBarGrow: PropTypes.bool
|
sideBarGrow: PropTypes.bool,
|
||||||
|
showButtons: PropTypes.bool,
|
||||||
|
showTitle: PropTypes.bool,
|
||||||
|
currentStep: PropTypes.number,
|
||||||
|
currentSubStep: PropTypes.number,
|
||||||
|
onStepChange: PropTypes.func,
|
||||||
|
showSkipButton: PropTypes.bool,
|
||||||
|
onSkip: PropTypes.func,
|
||||||
|
sizeBarWidth: PropTypes.string
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WizardView
|
export default WizardView
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user