Skip to content

Commit

Permalink
perf: Add new GenericField component
Browse files Browse the repository at this point in the history
  • Loading branch information
acasazza committed May 2, 2022
1 parent a093718 commit 83f9ae6
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 3 deletions.
71 changes: 71 additions & 0 deletions src/components/utils/GenericFieldComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { InitialSkuContext } from '#context/SkuChildrenContext'
import { InitialStockTransferContext } from '#context/StockTransferChildrenContext'
import { LineItem, Sku } from '@commercelayer/sdk'
import Parent from './Parent'
import { InitialLineItemContext } from '#context/LineItemChildrenContext'
import { Context, useContext } from 'react'

export type TResources = {
StockTransfer: LineItem & { resource: 'stock_transfers' }
Sku: Sku & { resource: 'skus' }
LineItem: LineItem & { resource: 'line_items' }
}

export type TResourceKey = {
[K in keyof TResources]: K
}

type ChildrenProps<E extends TResources[keyof TResources]> = Omit<
Props<E>,
'children' | 'attribute'
> & {
element: E[keyof E]
}

type ResourceContext = {
stock_transfers: InitialStockTransferContext
skus: InitialSkuContext
line_items: InitialLineItemContext
}

type GenericContext<K extends keyof ResourceContext> = Context<
ResourceContext[K]
>

type Props<E extends TResources[keyof TResources]> = {
children?: (props: ChildrenProps<E>) => JSX.Element
resource: E['resource']
attribute: keyof E
tagElement: keyof JSX.IntrinsicElements
context: GenericContext<E['resource']>
}

export default function GenericFieldComponent<R extends keyof TResources>(
props: Props<TResources[R]>
) {
const { children, tagElement, attribute, context, ...p } = props
const resourceContext = useContext(context)
let element
for (const key in resourceContext) {
if (Object.prototype.hasOwnProperty.call(resourceContext, key)) {
const dataContext = resourceContext[key] as any
element = dataContext[attribute]
}
}
const Tag = tagElement || 'span'
if (Tag === 'img' && !children) {
const src = element as string
const name = ''
return <img alt={name} src={src} {...(p as JSX.IntrinsicElements['img'])} />
}
const parentProps = {
element,
tagElement,
...p,
}
return children ? (
<Parent {...parentProps}>{children}</Parent>
) : (
<Tag {...p}>{element}</Tag>
)
}
6 changes: 3 additions & 3 deletions src/config/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
import { ErrorPropTypes } from '#typings/errors'
import { BaseInputComponentPropTypes } from '#typings/index'
import { DeliveryLeadTimeField } from '../components/DeliveryLeadTime'
import { StockTransferFieldType } from '#components/StockTransferField'
// import { StockTransferFieldType } from '#components/StockTransferField'
import { PaymentSourceDetailType } from '#components/PaymentSourceDetail'
import { CodeType } from '#reducers/OrderReducer'
import { ShipmentAttribute } from '#components/ShipmentField'
Expand Down Expand Up @@ -970,8 +970,8 @@ const components = {
displayName: 'StockTransferField',
propTypes: {
children: PropTypes.func,
type: PropTypes.oneOf<StockTransferFieldType>(['quantity', 'sku_code'])
.isRequired,
// type: PropTypes.oneOf<StockTransferFieldType>(['quantity', 'sku_code'])
// .isRequired,
},
},
SubmitButton: {
Expand Down
20 changes: 20 additions & 0 deletions src/typings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,23 @@ export type BaseAmountComponent = {
export interface FunctionChildren<P = Record<string, any>> {
(props: P): ReactNode
}

export type ExcludeTag<T extends keyof JSX.IntrinsicElements> = Exclude<
keyof JSX.IntrinsicElements,
T
>

export type ExtractTag<T extends keyof JSX.IntrinsicElements> = Extract<
keyof JSX.IntrinsicElements,
T
>

export type ConditionalElement<E> =
| ({
attribute: Extract<keyof E, 'image_url'>
tagElement: ExtractTag<'img'>
} & JSX.IntrinsicElements['img'])
| ({
attribute: Exclude<keyof E, 'image_url'>
tagElement: ExcludeTag<'img'>
} & JSX.IntrinsicElements[ExcludeTag<'img'>])

0 comments on commit 83f9ae6

Please sign in to comment.