From 14432c665becac514cd2ad66223e330bbe1c953e Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Wed, 21 Jun 2023 14:29:03 +0100 Subject: [PATCH] Re-usable expandable row component --- src/components/Form/Row.tsx | 114 ++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 src/components/Form/Row.tsx diff --git a/src/components/Form/Row.tsx b/src/components/Form/Row.tsx new file mode 100644 index 0000000..043f173 --- /dev/null +++ b/src/components/Form/Row.tsx @@ -0,0 +1,114 @@ +import styled from 'styled-components'; +import colors from 'styles/colors'; + +interface RowProps { + lbl: string, + val: string, + key?: string, + rowList?: RowProps[], +} + +const StyledRow = styled.div` + display: flex; + justify-content: space-between; + padding: 0.25rem; + &:not(:last-child) { border-bottom: 1px solid ${colors.primary}; } + span.lbl { font-weight: bold; } + span.val { + max-width: 200px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } +`; + +const StyledExpandableRow = styled(StyledRow).attrs({ + as: "summary" +})``; + +const Details = styled.details` + transition: all 0.2s ease-in-out; + summary { + padding-left: 1rem; + } + summary:before { + content: "►"; + position: absolute; + margin-left: -1rem; + color: ${colors.primary}; + cursor: pointer; + } + &[open] summary:before { + content: "▼"; + } +`; + +const SubRowList = styled.ul` + margin: 0; + padding: 0.25rem; + background: ${colors.primaryTransparent}; +`; + +const SubRow = styled(StyledRow).attrs({ + as: "li" +})` + border-bottom: 1px dashed ${colors.primaryTransparent} !important; +`; + +const formatDate = (dateString: string): string => { + return new Intl.DateTimeFormat('en-GB', { + day: 'numeric', month: 'long', year: 'numeric' + }).format(new Date(dateString)); +} + +const formatValue = (value: any): string => { + const isValidDate = (date: any) => date instanceof Date && !isNaN(date as any as number); + if (isValidDate(new Date(value))) return formatDate(value); + if (typeof value === 'object') return JSON.stringify(value); + if (typeof value === 'boolean') return value ? '✅' : '❌'; + return value; +}; + +const copyToClipboard = (text: string) => { + navigator.clipboard.writeText(text); +} + +export const ExpandableRow = (props: RowProps) => { + const { lbl, val, rowList } = props; + return ( +
+ + {lbl} + {val} + + { rowList && + + { rowList?.map((row: RowProps, index: number) => { + return ( + + {row.lbl} + copyToClipboard(row.val)}> + {formatValue(row.val)} + + + ) + })} + + } +
+ ); +}; + +const Row = (props: RowProps) => { + const { lbl, val, key } = props; + return ( + + {lbl} + copyToClipboard(val)}> + {formatValue(val)} + + + ); +}; + +export default Row;