Change behavior of Steps React component from Ant Design(https://ant.design/components/steps/) - reactjs

As in the link example, I would like to change the behavior of Steps react component from ANT design to just color and select(highight) only on the step that is click(as oppose to now it colors all the previous steps also)

You have to make use of the status prop in Step.
Documentation
Example in CodeSandbox
Intead of:
<Steps current="2">
<Step title="INSTRUCTIONS" />
<Step title="REGISTRATION" />
<Step title="VERIFICATION" />
</Steps>
use status wait on previous steps:
<Steps current="2">
<Step status="wait" title="INSTRUCTIONS" />
<Step title="REGISTRATION" />
<Step title="VERIFICATION" />
</Steps>

There is a prop available for status in Step component. It overrides highlight by current variable. You can use that.
E.g:
<Steps current={this.state.current} progressDot={customDot}>
<Step
title="Finished"
status={0 < this.state.current ? "wait" : null}
description="You can hover on the dot."
/>
<Step
title="In Progress"
status={1 < this.state.current ? "wait" : null}
description="You can hover on the dot."
/>
<Step
title="Waiting"
status={2 < this.state.current ? "wait" : null}
description="You can hover on the dot."
/>
<Step
title="Start"
status={3 < this.state.current ? "wait" : null}
description="You can hover on the dot."
/>
</Steps>,
);

Related

antd collapse.panel not re rendering

I have this collapse panel in antd.
<Collapse defaultActiveKey={[1]} onChange={onChange}>
<Panel header="Billing Details" key="2" forceRender>
<BillingPanel
invoiceCycleOptions={invoiceCycleOptions}
projectData={projectData}
payModelOptions={payModelOptions}
accTypeOptions={accTypeOptions}
onDateChange={onDateChange}
isEditMode={isEditMode}
isPopulated={isPopulated}
prjStartDate={prjStartDate}
/>
</Panel>
<Panel header="Other Details" key="3" forceRender>
<OtherDetailsPanel
csmOptions={csmOptions}
projectData={projectData}
csm={csm}
onPrimaryCsmSelect={onPrimaryCsmSelect}
accountantOptions={accountantOptions?.map(
(option) => option?.name
)}
isEditMode={isEditMode}
secondaryCsmoptions={secondaryCsmoptions}
setShow={setShow}
setDocument={setDocument}
show={show}
salesPersonOptions={salesPersonOptions}
setIsValidSize={setIsValidSize}
isValidSize={isValidSize}
leadSourceOptions={leadSourceOptions}
marketingChannelOptions={marketingChannelOptions}
activeBillingOptions={activeBillingOptions}
activeBilling={activeBilling}
form={form}
selectedCsm={selectedCsm}
primaryCsm={primaryCsm}
secondaryCsmList={secondaryCsmList}
/>
</Panel>
</Collapse>
when projectData changes, the panel with the header "Other Details" does not re render. I am getting updated projectData in this component but not in the OtherDetailsPanel component. Can anyone help me?

Conditional rendering of parent component in React

I need to return either Porover or Card depending on the condition with the same children content. This can be done by taking the children content into a separate component and returning it like this:
true ? <Popover><ChildrenContent props={props}/></Popover>
: <Card><ChildrenContent props = {props}/></Card>
But it seems to me that this is not the best solution in this case
<Popover dataCy="complexValidation">
<Section marginBottom={3}>
</Section>
<Flex flexDirection="column" gap={3}>
{validations.map((validation) => (
<Flex.Item key={validation.text}>
<Flex alignItems="center">
<Icon name="check_circle" size="large" color={validation.isSuccess ? 'positive' : 'negative'} />
<Flex.Item>
<Typography variant="bodyText2" component="span">
{validation.text}
</Typography>
</Flex.Item>
</Flex>
</Flex.Item>
))}
</Flex>
</Popover>

How to hide multiple fields in react-admin ShowView?

I am trying to hide a set of fields based on the value of another field but the following will not display the conditional fields ever:
export const ServiceShow = (props) => (
<ShowController {...props}>
{controllerProps =>
<ShowView component="div" {...props} {...controllerProps}>
<TabbedShowLayout>
<Tab label="General">
{controllerProps.record && controllerProps.record.maintenance &&
controllerProps.record.maintenance.active &&
<>
<Alert severity="warning">Maintenance period active</Alert>
<DateField label="Maintenance Start" src="maintenance.start" />
<DateField label="Maintenance End" srvc="maintenance.end" />
<TextField label="Maintenance Message" source="maintenance.msg" />
</>
}
</Tab>
</TabbedShowLayout>
</ShowView>
}
</ShowController>
);
The <Alert> is displayed just fine, but the Field components are not. I'm very new to React so probably a simple thing.
Note:If I put a single <TextField> as the conditional output then it will work but anything inside a React.Fragment or <div> for example, it doesn't work.
The reason why Alert shows up and Fields not is because Fields require addtional props passed by react-admin direct parent, in that case, the Tab. <> should pass such props too, but looks like it's not. And thats why a single <TextField> as child renders correctly
You can create a component that pass the props downstream to childs.
export const ServiceShow = (props) => (
<ShowController {...props}>
{controllerProps =>
<ShowView component="div" {...props} {...controllerProps}>
<TabbedShowLayout>
<Tab label="General">
<Maintenance/>
</Tab>
</TabbedShowLayout>
</ShowView>
}
</ShowController>
);
const Maintenance = props => (
{props.record && props.record.maintenance && props.record.maintenance.active &&
<>
<Alert {...props} severity="warning">Maintenance period active</Alert>
<DateField {...props} label="Maintenance Start" src="maintenance.start" />
<DateField {...props} label="Maintenance End" srvc="maintenance.end" />
<TextField {...props}label="Maintenance Message" source="maintenance.msg" />
</>
}
)

How to correctly add the Aside component to create a modal style button on the right side of my show page?

I am building a custom show page for an individual customer. Within this page I need a button that allows me to edit their points value they have. I am wanting to use the aside component that is built in react-admin but I can't seem to get it to work correctly.
I have followed the documentation to add the code for the aside component and I placed my button component within it. However it's not rendering to the page at all. I am receiving a TypeError. 'TypeError: Cannot read roperty "search" of undefined.'
const Aside = (...props) => {
const { customer_id: customer_id_string } = parse(props.location.search);
const customer_id = customer_id_string ? parseInt(customer_id_string, 10) : '';
return (
<div style={{ width: 200, margin: '1em'}}>
<Button
defaultValue={{ customer_id }}
redirect="show"
component={Link}
to={{
pathname: '/points/{{point-id}}/create',
}}
label="Add Points"
>
<Reward>Add Points</Reward>
</Button>
)
</div>
)
};
const CustomerShow = ({ classes, record, ...props }) => (
<Show aside={<Aside />} {...props}>
<TabbedShowLayout>
<Tab label="Customer Basics">
<TextField source="firstName" /><TextField source="lastName" />
<TextField source="email" />
<BooleanField source="active" />
</Tab>
<Tab label="The Rest">
<NumberField label="Points" source="points" />
<NumberField source="usedPoints" />
<NumberField source="expiredPoints" />
<NumberField source="lockedPoints" />
<BooleanField source="agreement1" />
<BooleanField source="agreement2" />
</Tab>
<Tab label="Transactions" resource="transactions" >
<ReferenceManyField
addLabel={false}
reference="transactions"
target="customerId"
pagination={<Pagination />}
perPage={10}
sort={{ field: 'createdAt', order: 'DESC' }}
><Datagrid rowClick="show" >
<DateField source="createdAt"/>
<TextField source="documentNumber"/>
<TextField source="documentType"/>
<NumberField source="grossValue"/>
<NumberField source="pointsEarned"/>
<NumberField source="pointsUsed"/>
</Datagrid>
</ReferenceManyField>
</Tab>
<Tab label="Points" resource="Points" >
<ReferenceManyField
addLabel={false}
reference="points"
target="customerId"
pagination={<Pagination />}
perPage={10}
sort={{ field: 'createdAt', order: 'DESC' }}
><Datagrid rowClick="show" >
<NumberField source="valueLocked" />
<NumberField source="valueUsed" />
<NumberField source="valueRemain" />
<NumberField source="valueExpired" />
<NumberField source="valueEarned" />
</Datagrid>
</ReferenceManyField>
</Tab>
</TabbedShowLayout>
</Show>
);
The expected results are a button on the right side of the page displaying the words "Add Points". The actual results are either a TypeError or the page renders but no button.
I figured out what I was doing wrong. I didn't have one of my sources filled out correctly. It was referencing the wrong source.

Prop to detect if link is active in react

I have a NavLink which have child components
<NavLink
className={StyledAppNavItem}
activeClassName={StyledAppNavItemActive}
to={link.path}
>
<Icon size={28} icon={link.icon} color={isActive?'red':'blue'}/>
<StyledAppNavName>{link.name}</StyledAppNavName>
</NavLink>
Like activeClassName is attached when the link is active, I need to detect if this link is active and send a prop to its child component Icon
Somewhat like <Icon color={linkisActive?'red':'blue'}/>
Unfortunately, there is no way to get isActive from NavLink. You need to create your custom NavLink. Something like this:
function MyNavLink() {
return (
<Route path={link.path} children={({ match }) => (
<Link
className={`${StyledAppNavItem} ${match ? StyledAppNavItemActive : ''}`}
to={link.path}
>
<Icon size={28} icon={link.icon} color={match ? 'red' : 'blue'}/>
<StyledAppNavName>{link.name}</StyledAppNavName>
</Link>
)} />
);
}
Or you can just add Route to your current component:
<NavLink
className={StyledAppNavItem}
activeClassName={StyledAppNavItemActive}
to={link.path}
>
<Route path={link.path} children={({ match }) => (
<Icon size={28} icon={link.icon} color={match?'red':'blue'}/>
)} />
<StyledAppNavName>{link.name}</StyledAppNavName>
</NavLink>

Resources