@razorpay/blade
Version:
The Design System that powers Razorpay
320 lines (278 loc) • 7.79 kB
Markdown
### 2. Custom Component Definitions
#### EntityItemRow Component
```jsx
import { Component } from 'react';
import { connect } from 'react-redux';
class EntityItemRow extends Component {
render() {
const {
id,
luminateRowId,
activeEntityId,
activeSecEntityId,
rowClasses = '',
onRowClick,
item,
isDisabled,
} = this.props;
const receiverType = item?.receiver_type || '';
const sourceChannel = item?.source_channel || '';
return (
<tr
onClick={() => {
onRowClick?.({
id,
rowData: { receiverType, sourceChannel },
});
}}
className={`${luminateRowId === id ? 'luminate' : ''}${
activeEntityId === id || activeSecEntityId === id ? ' active' : ''
}${rowClasses ?? ''}${isDisabled?.(item) ? ' disabled' : ''}`}
data-testid={`entity-item-row-${id}`}
>
{this.props.children}
</tr>
);
}
}
const mapStateToProps = (state) => {
return state.app;
};
export default connect(mapStateToProps, null)(EntityItemRow);
```
#### TableBody Component
```jsx
import React from 'react';
import TableLoader from 'common/ui/TableLoader';
import EmptyTableRow from 'common/ui/EmptyTableRow';
export default (props) => {
let tableRowComponent;
const {
isLoading,
emptyTableRow,
emptyTableMsg,
colSpan,
rows,
children,
SpinnerComponent,
} = props;
if (isLoading) {
tableRowComponent = SpinnerComponent || <TableLoader colSpan={colSpan} />;
} else if (!rows.length) {
tableRowComponent = emptyTableRow || (
<EmptyTableRow colSpan={colSpan} message={emptyTableMsg} />
);
}
return (
<tbody>
{tableRowComponent
? typeof tableRowComponent === 'function'
? tableRowComponent(colSpan)
: tableRowComponent
: children}
</tbody>
);
};
```
#### ShowWhen Component
```jsx
export const ShowWhen = (props) => {
const i18 = useI18Service();
// creating an abstraction of just consuming splitz experiment, rest service should not be accessed via RouteGuard
const { abExperiments } = useSplitzService();
const { loader, children, session, ...rest } = props;
const showWhenUtilResult = validateUtil(
{
options: rest,
session,
},
{
i18,
splitz: { abExperiments },
},
);
if (showWhenUtilResult === TAGS_API_NOT_RESOLVED_YET) {
return loader || <Loader />;
} else if (showWhenUtilResult) {
return children;
}
return null;
};
```
### 3. Migration Example
#### Original Custom Implimentation Code
```jsx
import Text from '@razorpay/blade-old/src/atoms/Text';
import View from '@razorpay/blade-old/src/atoms/View';
import Flex from '@razorpay/blade-old/src/atoms/Flex';
import Icon from '@razorpay/blade-old/src/atoms/Icon';
import TableBody from 'common/ui/TableBody';
import MobileListView from 'common/ui/MobileListView';
import { amount, createdAt } from 'common/ui/item/pair';
import EntityItemRow from 'merchant/containers/EntityItemRow';
import { isMobileDevice } from 'merchant/components/Home/data';
import {
customer,
invoiceId,
invoiveStatus,
paymentLink,
paymentLinkId,
receiptNumber,
referenceId,
} from 'merchant/views/Invoices/Invoices/item';
import { shareURL } from 'merchant/views/Invoices/Invoices/helpers';
const PaymentLinkMobileTableListView = (items) => {
const { item, onShareLinkSuccess = () => {} } = items;
return (
<EntityItemRow id={item?.id}>
<td>
{paymentLinkId.value(item)}
{item?.customer_details && customer.value(item)}
{item?.short_url && (
<View
className="link-container"
data-tip="Copied"
onClick={() => {
onShareLinkSuccess();
shareURL(item.short_url, item?.id);
}}
>
<Flex alignItems="center">
<Text size="small">
<div className="share-payment-link">
<Icon name="share" size="small" />
</div>
Share payment link
</Text>
</Flex>
</View>
)}
</td>
<td>{amount.value(item)}</td>
<td>{invoiveStatus.value(item)}</td>
</EntityItemRow>
);
};
const InvoiceListItem = (props) => {
const { invoice, columns } = props;
return (
<EntityItemRow id={invoice.id}>
{columns.map(({ title, value }) => (
<td key={title}>{value(invoice)}</td>
))}
</EntityItemRow>
);
};
export default (props) => {
const {
type,
invoices,
isLoading,
onCopy = () => {},
EmptyList,
isPaymentlinksV2Enabled,
} = props;
const isPaymentLinksType = type === 'link';
const label = isPaymentLinksType ? paymentLinkId : invoiceId;
const listStyle = isPaymentLinksType ? 'Payment-link-list' : 'Invoice-list';
const receipt = isPaymentlinksV2Enabled ? referenceId : receiptNumber;
const columns = [label, createdAt, amount, receipt, customer, paymentLink(onCopy), invoiveStatus];
return isMobileDevice() && isPaymentLinksType ? (
<MobileListView
headers={['Payment Link Id', 'Amount', 'Status']}
TableListItem={PaymentLinkMobileTableListView}
tableWrapperClass={listStyle}
items={invoices}
{...props}
/>
) : (
<div className="table-responsive">
<table className="table table-hover">
<thead>
<tr>
{columns.map(({ title }) => (
<th key={title}>{title}</th>
))}
</tr>
</thead>
<TableBody isLoading={isLoading} colSpan={8} rows={invoices} emptyTableRow={EmptyList}>
{invoices.map((invoice) => (
<InvoiceListItem key={invoice.id} invoice={invoice} columns={columns} />
))}
</TableBody>
</table>
</div>
);
};
```
#### Expected Code after Migration
```jsx
import {
Table,
TableHeader,
TableHeaderRow,
TableHeaderCell,
TableBody,
TableRow,
TableCell,
} from '@razorpay/blade/components';
import { amount, createdAt } from 'common/ui/item/pair';
import {
customer,
invoiceId,
invoiveStatus,
paymentLink,
paymentLinkId,
receiptNumber,
referenceId,
} from 'merchant/views/Invoices/Invoices/item';
import { shareURL } from 'merchant/views/Invoices/Invoices/helpers';
const InvoiceListItem = (props) => {
const { invoice, columns } = props;
return (
<TableRow item={invoice}>
{columns.map(({ title, value }) => (
<TableCell key={title}>{value(invoice)}</TableCell>
))}
</TableRow>
);
};
export default (props) => {
const {
type,
invoices,
isLoading,
onCopy = () => {},
EmptyList,
isPaymentlinksV2Enabled,
} = props;
const isPaymentLinksType = type === 'link';
const label = isPaymentLinksType ? paymentLinkId : invoiceId;
const receipt = isPaymentlinksV2Enabled ? referenceId : receiptNumber;
const columns = [label, createdAt, amount, receipt, customer, paymentLink(onCopy), invoiveStatus];
return (
<Table data={{ nodes: invoices }} isLoading={isLoading}>
{(tableData) => (
<>
<TableHeader>
<TableHeaderRow>
{columns.map(({ title }) => (
<TableHeaderCell key={title}>{title}</TableHeaderCell>
))}
</TableHeaderRow>
</TableHeader>
<TableBody>
{tableData.length <= 0 ? (
<EmptyList />
) : (
tableData.map((invoice) => (
<InvoiceListItem key={invoice.id} invoice={invoice} columns={columns} />
))
)}
</TableBody>
</>
)}
</Table>
);
};
```