diff --git a/services/frontend/src/components/Record.tsx b/services/frontend/src/components/Record.tsx index b273fe7..058ef80 100644 --- a/services/frontend/src/components/Record.tsx +++ b/services/frontend/src/components/Record.tsx @@ -1,25 +1,38 @@ -import { Fragment, FunctionComponent, ReactElement, useCallback } from "react"; +import { + Fragment, + FunctionComponent, + ReactElement, + useCallback, + useMemo +} from "react"; import { styled } from "@mui/joy"; import IconButton from "@mui/joy/IconButton"; import { MinusSmIcon } from "@heroicons/react/solid"; import TextField from "./global/FormElements/TextField"; import Toggle from "./global/FormElements/Toggle"; +import Records, { IRecordsProps } from "./Records"; export interface IFieldType { name: string; - placeholder: string; + placeholder?: string; required?: boolean; - type: "text" | "toggle"; - options?: { - text: string; - value: string; - }[]; + type: "text" | "toggle" | "records"; + options?: + | { + text: string; + value: string; + }[] + | IRecordsProps; } export interface IRecordProps { fields: IFieldType[]; index: number; onRemove: (index: number) => void; + direction?: "column" | "row"; + renderLayout?: (elements: ReactElement[]) => ReactElement; + renderField?: (element: ReactElement, field: IFieldType) => ReactElement; + renderRemove?: (element: ReactElement) => ReactElement; } const Root = styled("div")` @@ -28,6 +41,8 @@ const Root = styled("div")` justify-content: flex-start; align-items: flex-start; column-gap: ${({ theme }) => theme.spacing(2)}; + width: 100%; + @media (max-width: 768px) { column-gap: ${({ theme }) => theme.spacing(1)}; } @@ -38,37 +53,74 @@ const RemoveButton = styled(IconButton)``; const Record: FunctionComponent = ( props: IRecordProps ): ReactElement => { - const { fields, index, onRemove } = props; + const { fields, index, onRemove, renderLayout, renderField, renderRemove } = + props; const handleRemove = useCallback(() => { onRemove(index); }, [index, onRemove]); + const renderLayoutWrapper = useMemo( + () => renderLayout || ((elements: ReactElement[]) => <>{elements}), + [renderLayout] + ); + + const renderFieldWrapper = useMemo( + () => renderField || ((element: ReactElement) => element), + [renderField] + ); + + const renderRemoveWrapper = useMemo( + () => renderRemove || ((element: ReactElement) => element), + [renderRemove] + ); + return ( - {fields.map(({ type, name, placeholder, required, options }) => ( - - {type === "text" && ( - - )} - {type === "toggle" && ( - - )} - - ))} - - - + {renderLayoutWrapper( + fields.map((field) => ( + + {renderFieldWrapper( + <> + {field.type === "text" && ( + + )} + {field.type === "toggle" && ( + + )} + {field.type === "records" && ( + + )} + , + field + )} + + )) + )} + {renderRemoveWrapper( + + + + )} ); };