@homefile/components-v2 2.24.25 → 2.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/components/forms/Collapsible.d.ts +1 -1
  2. package/dist/components/forms/Collapsible.js +3 -3
  3. package/dist/components/forms/readOnly/ReadOnlyDynamicForm.js +4 -2
  4. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyAppliances.js +16 -15
  5. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyAppliances.tsx +40 -35
  6. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyCollapsible.d.ts +2 -0
  7. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyCollapsible.js +19 -0
  8. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyCollapsible.tsx +34 -0
  9. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyGuidelines.js +1 -1
  10. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyGuidelines.tsx +2 -2
  11. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyHomeItemText.js +1 -1
  12. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyHomeItemText.tsx +1 -1
  13. package/dist/components/forms/readOnly/fields/homeItem/index.d.ts +1 -0
  14. package/dist/components/forms/readOnly/fields/homeItem/index.js +1 -0
  15. package/dist/components/forms/readOnly/fields/homeItem/index.ts +1 -0
  16. package/dist/components/headers/CollapsibleHeader.js +1 -1
  17. package/dist/helpers/receipts/Receipts.helper.js +6 -5
  18. package/dist/interfaces/forms/Collapsible.interface.d.ts +2 -1
  19. package/dist/interfaces/forms/dynamicForm/DynamicForm.interface.d.ts +1 -1
  20. package/dist/interfaces/forms/readOnly/homeItem/ReadOnlyAppliances.interface.d.ts +1 -1
  21. package/dist/mocks/forms/dynamicForm.mock.js +36 -16
  22. package/dist/stories/forms/readOnly/ReadOnlyDynamicForm.stories.d.ts +1 -0
  23. package/dist/stories/forms/readOnly/ReadOnlyDynamicForm.stories.js +5 -1
  24. package/dist/stories/receipts/receipt/ReceiptDetails.stories.d.ts +1 -0
  25. package/dist/stories/receipts/receipt/ReceiptDetails.stories.js +1 -0
  26. package/package.json +1 -1
  27. package/src/components/forms/Collapsible.tsx +3 -2
  28. package/src/components/forms/readOnly/ReadOnlyDynamicForm.tsx +4 -1
  29. package/src/components/forms/readOnly/fields/homeItem/ReadOnlyAppliances.tsx +40 -35
  30. package/src/components/forms/readOnly/fields/homeItem/ReadOnlyCollapsible.tsx +34 -0
  31. package/src/components/forms/readOnly/fields/homeItem/ReadOnlyGuidelines.tsx +2 -2
  32. package/src/components/forms/readOnly/fields/homeItem/ReadOnlyHomeItemText.tsx +1 -1
  33. package/src/components/forms/readOnly/fields/homeItem/index.ts +1 -0
  34. package/src/components/headers/CollapsibleHeader.tsx +1 -1
  35. package/src/helpers/receipts/Receipts.helper.ts +7 -5
  36. package/src/interfaces/forms/Collapsible.interface.ts +2 -1
  37. package/src/interfaces/forms/dynamicForm/DynamicForm.interface.ts +1 -0
  38. package/src/interfaces/forms/readOnly/homeItem/ReadOnlyAppliances.interface.ts +1 -1
  39. package/src/mocks/forms/dynamicForm.mock.ts +36 -16
  40. package/src/stories/forms/readOnly/ReadOnlyDynamicForm.stories.tsx +13 -1
  41. package/src/stories/receipts/receipt/ReceiptDetails.stories.tsx +1 -0
@@ -1,3 +1,3 @@
1
1
  import { PropsWithChildren } from 'react';
2
2
  import { CollapsibleI } from '../../interfaces';
3
- export declare const Collapsible: ({ children, icon, title, }: PropsWithChildren<CollapsibleI>) => import("react/jsx-runtime").JSX.Element;
3
+ export declare const Collapsible: ({ children, icon, title, showShadow, }: PropsWithChildren<CollapsibleI>) => import("react/jsx-runtime").JSX.Element;
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Accordion, AccordionButton, AccordionItem, AccordionPanel, Box, Flex, } from '@chakra-ui/react';
3
3
  import { ChevronRight, CollapsibleHeader } from '..';
4
- export const Collapsible = ({ children, icon, title, }) => {
5
- return (_jsx(Accordion, { flex: "1", allowMultiple: true, boxShadow: "md", children: _jsx(AccordionItem, { border: "none", children: ({ isExpanded }) => (_jsxs(_Fragment, { children: [_jsx(AccordionButton, { w: "100%", p: "base", bg: "neutral.white", transition: "all .2s ease-in-out", borderBottom: "1px solid", borderColor: isExpanded ? 'lightBlue.2' : 'transparent', _hover: {
6
- boxShadow: 'lg',
4
+ export const Collapsible = ({ children, icon, title, showShadow = true, }) => {
5
+ return (_jsx(Accordion, { flex: "1", allowMultiple: true, boxShadow: showShadow ? 'md' : 'none', children: _jsx(AccordionItem, { border: "none", children: ({ isExpanded }) => (_jsxs(_Fragment, { children: [_jsx(AccordionButton, { w: "100%", p: "base", bg: "neutral.white", transition: "all .2s ease-in-out", borderBottom: "1px solid", borderColor: isExpanded ? 'lightBlue.2' : 'transparent', _hover: {
6
+ boxShadow: showShadow ? 'lg' : 'none',
7
7
  }, _focus: {
8
8
  outline: 'none',
9
9
  }, children: _jsxs(Flex, { align: "center", justify: "space-between", flex: "1", children: [_jsx(CollapsibleHeader, { icon: icon, title: title }), _jsx(Box, { rounded: "full", border: "1px solid", padding: "1", borderColor: "blue.3", transition: "all .2s ease-in-out", transform: isExpanded ? 'rotate(-90deg)' : 'rotate(0)', children: _jsx(ChevronRight, {}) })] }) }), _jsx(AccordionPanel, { p: "base", bg: "neutral.white", children: children })] })) }) }));
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { createElement as _createElement } from "react";
3
3
  import { Box } from '@chakra-ui/react';
4
- import { ReadOnlyAppliances, ReadOnlyDate, ReadOnlyGrid, ReadOnlyGroup, ReadOnlyInput, ReadOnlyNotes, ReadOnlyRating, ReadOnlyTextArea, } from '../..';
4
+ import { ReadOnlyAppliances, ReadOnlyCollapsible, ReadOnlyDate, ReadOnlyGrid, ReadOnlyGroup, ReadOnlyInput, ReadOnlyNotes, ReadOnlyRating, ReadOnlyTextArea, } from '../..';
5
5
  import { fieldIcons } from '../../../helpers';
6
- export const ReadOnlyDynamicForm = ({ form: fields, onClick, onEdit = () => { }, }) => {
6
+ export const ReadOnlyDynamicForm = ({ form: fields, onClick, onEdit, }) => {
7
7
  return (_jsx(Box, { bg: "lightBlue.1", overflow: "scroll", children: fields === null || fields === void 0 ? void 0 : fields.map((field) => {
8
8
  const { children = [], icon, id, name, type, value } = field;
9
9
  const baseProps = {
@@ -33,6 +33,8 @@ export const ReadOnlyDynamicForm = ({ form: fields, onClick, onEdit = () => { },
33
33
  return _jsx(ReadOnlyGroup, { children: children }, id);
34
34
  case 'appliances':
35
35
  return _createElement(ReadOnlyAppliances, Object.assign({}, field, { key: id, onEdit: onEdit }));
36
+ case 'collapsible':
37
+ return _createElement(ReadOnlyCollapsible, Object.assign({}, field, { key: id }));
36
38
  case 'notes':
37
39
  return _createElement(ReadOnlyNotes, Object.assign({}, field, { key: id }));
38
40
  default:
@@ -5,19 +5,20 @@ import { colors } from '../../../../../theme/colors';
5
5
  export const ReadOnlyAppliances = ({ description, id, name, children, onEdit, value, }) => {
6
6
  const rating = children === null || children === void 0 ? void 0 : children.find(({ type }) => type === 'rating');
7
7
  const images = children === null || children === void 0 ? void 0 : children.find(({ type }) => type === 'images');
8
- return (_jsxs(Stack, { spacing: "base", p: "base", bg: "neutral.white", mt: "2px", children: [_jsxs(Flex, { justify: "space-between", children: [_jsx(Text, { fontSize: "xs", textTransform: "uppercase", children: name }), _jsx(IconButton, { "aria-label": "Edit appliance", variant: "ghost", w: "fit-content", icon: _jsx(Edit, { size: 18, stroke: colors.blue[3] }), onClick: () => onEdit(id) })] }), _jsxs(Flex, { gap: "base", children: [_jsx(ReadOnlyHomeItemImages, Object.assign({}, images)), _jsxs(Stack, { spacing: "4", flex: "1", children: [_jsx(ReadOnlyHomeItemRating, Object.assign({}, rating)), _jsxs(Stack, { spacing: "base", children: [_jsx(Text, { fontSize: "22px", fontWeight: "semibold", children: value }), _jsx(Text, { fontFamily: "secondary", fontSize: "sm", children: description })] }), _jsx(Box, { flex: "1", borderBottom: "1px dashed", borderColor: "lightBlue.6", h: "1px" }), _jsx(Box, { children: children === null || children === void 0 ? void 0 : children.map(({ id, name, value, type }) => {
9
- const baseProps = {
10
- key: `${id}-${name}-${value}-${type}`,
11
- id,
12
- value,
13
- type,
14
- name,
15
- };
16
- switch (type) {
17
- case 'text':
18
- return _jsx(ReadOnlyHomeItemText, Object.assign({}, baseProps));
19
- default:
20
- return null;
21
- }
22
- }) })] })] })] }));
8
+ return (_jsxs(Stack, { spacing: "base", p: "base", bg: "neutral.white", mt: "2px", children: [name ||
9
+ (onEdit && (_jsxs(Flex, { justify: "space-between", children: [_jsx(Text, { fontSize: "xs", textTransform: "uppercase", children: name }), onEdit && (_jsx(IconButton, { "aria-label": "Edit appliance", variant: "ghost", w: "fit-content", icon: _jsx(Edit, { size: 18, stroke: colors.blue[3] }), onClick: () => onEdit(id) }))] }))), _jsxs(Flex, { gap: "base", children: [_jsx(ReadOnlyHomeItemImages, Object.assign({}, images)), _jsxs(Stack, { spacing: "4", flex: "1", children: [_jsx(ReadOnlyHomeItemRating, Object.assign({}, rating)), _jsxs(Stack, { spacing: "base", children: [_jsx(Text, { fontSize: "22px", fontWeight: "semibold", children: value }), _jsx(Box, { children: children === null || children === void 0 ? void 0 : children.map(({ id, name, value, type }) => {
10
+ const baseProps = {
11
+ key: `${id}-${name}-${value}-${type}`,
12
+ id,
13
+ value,
14
+ type,
15
+ name,
16
+ };
17
+ switch (type) {
18
+ case 'text':
19
+ return _jsx(ReadOnlyHomeItemText, Object.assign({}, baseProps));
20
+ default:
21
+ return null;
22
+ }
23
+ }) }), _jsx(Box, { flex: "1", borderBottom: "1px dashed", borderColor: "lightBlue.6", h: "1px" }), _jsx(Text, { fontFamily: "secondary", fontSize: "sm", children: description })] })] })] })] }));
23
24
  };
@@ -20,18 +20,23 @@ export const ReadOnlyAppliances = ({
20
20
  const images = children?.find(({ type }) => type === 'images')
21
21
  return (
22
22
  <Stack spacing="base" p="base" bg="neutral.white" mt="2px">
23
- <Flex justify="space-between">
24
- <Text fontSize="xs" textTransform="uppercase">
25
- {name}
26
- </Text>
27
- <IconButton
28
- aria-label="Edit appliance"
29
- variant="ghost"
30
- w="fit-content"
31
- icon={<Edit size={18} stroke={colors.blue[3]} />}
32
- onClick={() => onEdit(id)}
33
- />
34
- </Flex>
23
+ {name ||
24
+ (onEdit && (
25
+ <Flex justify="space-between">
26
+ <Text fontSize="xs" textTransform="uppercase">
27
+ {name}
28
+ </Text>
29
+ {onEdit && (
30
+ <IconButton
31
+ aria-label="Edit appliance"
32
+ variant="ghost"
33
+ w="fit-content"
34
+ icon={<Edit size={18} stroke={colors.blue[3]} />}
35
+ onClick={() => onEdit(id)}
36
+ />
37
+ )}
38
+ </Flex>
39
+ ))}
35
40
  <Flex gap="base">
36
41
  <ReadOnlyHomeItemImages {...images} />
37
42
  <Stack spacing="4" flex="1">
@@ -40,33 +45,33 @@ export const ReadOnlyAppliances = ({
40
45
  <Text fontSize="22px" fontWeight="semibold">
41
46
  {value}
42
47
  </Text>
48
+ <Box>
49
+ {children?.map(({ id, name, value, type }) => {
50
+ const baseProps = {
51
+ key: `${id}-${name}-${value}-${type}`,
52
+ id,
53
+ value,
54
+ type,
55
+ name,
56
+ }
57
+ switch (type) {
58
+ case 'text':
59
+ return <ReadOnlyHomeItemText {...baseProps} />
60
+ default:
61
+ return null
62
+ }
63
+ })}
64
+ </Box>
65
+ <Box
66
+ flex="1"
67
+ borderBottom="1px dashed"
68
+ borderColor="lightBlue.6"
69
+ h="1px"
70
+ />
43
71
  <Text fontFamily="secondary" fontSize="sm">
44
72
  {description}
45
73
  </Text>
46
74
  </Stack>
47
- <Box
48
- flex="1"
49
- borderBottom="1px dashed"
50
- borderColor="lightBlue.6"
51
- h="1px"
52
- />
53
- <Box>
54
- {children?.map(({ id, name, value, type }) => {
55
- const baseProps = {
56
- key: `${id}-${name}-${value}-${type}`,
57
- id,
58
- value,
59
- type,
60
- name,
61
- }
62
- switch (type) {
63
- case 'text':
64
- return <ReadOnlyHomeItemText {...baseProps} />
65
- default:
66
- return null
67
- }
68
- })}
69
- </Box>
70
75
  </Stack>
71
76
  </Flex>
72
77
  </Stack>
@@ -0,0 +1,2 @@
1
+ import { ReportI } from '../../../../../interfaces';
2
+ export declare const ReadOnlyCollapsible: ({ children, }: Pick<ReportI, "children">) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Stack } from '@chakra-ui/react';
3
+ import { Collapsible, ReadOnlyTextArea } from '../../../..';
4
+ export const ReadOnlyCollapsible = ({ children, }) => {
5
+ return (_jsx(Stack, { bg: "lightBlue.2", spacing: "2px", children: children === null || children === void 0 ? void 0 : children.map(({ id, name = '', value, type }) => {
6
+ const baseProps = {
7
+ id,
8
+ value,
9
+ type,
10
+ name,
11
+ };
12
+ switch (type) {
13
+ case 'text':
14
+ return (_jsx(Collapsible, { title: name, showShadow: false, children: _jsx(ReadOnlyTextArea, Object.assign({}, baseProps)) }, `${id}-${name}-${value}-${type}`));
15
+ default:
16
+ return null;
17
+ }
18
+ }) }));
19
+ };
@@ -0,0 +1,34 @@
1
+ import { Stack } from '@chakra-ui/react'
2
+ import { Collapsible, ReadOnlyTextArea } from '@/components'
3
+ import { ReportI } from '@/interfaces'
4
+
5
+ export const ReadOnlyCollapsible = ({
6
+ children,
7
+ }: Pick<ReportI, 'children'>) => {
8
+ return (
9
+ <Stack bg="lightBlue.2" spacing="2px">
10
+ {children?.map(({ id, name = '', value, type }) => {
11
+ const baseProps = {
12
+ id,
13
+ value,
14
+ type,
15
+ name,
16
+ }
17
+ switch (type) {
18
+ case 'text':
19
+ return (
20
+ <Collapsible
21
+ title={name}
22
+ showShadow={false}
23
+ key={`${id}-${name}-${value}-${type}`}
24
+ >
25
+ <ReadOnlyTextArea {...baseProps} />
26
+ </Collapsible>
27
+ )
28
+ default:
29
+ return null
30
+ }
31
+ })}
32
+ </Stack>
33
+ )
34
+ }
@@ -3,7 +3,7 @@ import { Text, Stack, Grid } from '@chakra-ui/react';
3
3
  import { HiddenField } from '../../../..';
4
4
  import { fieldIcons } from '../../../../../helpers';
5
5
  export const ReadOnlyGuidelines = ({ name, children, onClick, }) => {
6
- return (_jsxs(Stack, { spacing: "base", children: [_jsx(Text, { fontSize: "xs", textTransform: "uppercase", children: name }), _jsx(Grid, { templateColumns: "repeat(2, minmax(80px, 1fr))", gap: "base", children: children === null || children === void 0 ? void 0 : children.map((child) => {
6
+ return (_jsxs(Stack, { spacing: "base", flex: "1", width: "100%", children: [_jsx(Text, { fontSize: "xs", textTransform: "uppercase", children: name }), _jsx(Grid, { templateColumns: "repeat(auto-fit, minmax(0, 75px))", gap: "base", children: children === null || children === void 0 ? void 0 : children.map((child) => {
7
7
  const { id, icon, value } = child;
8
8
  const btnIcon = icon ? fieldIcons[icon] : '';
9
9
  return (_jsx(HiddenField, { id: id, icon: btnIcon, name: value, onClick: () => onClick === null || onClick === void 0 ? void 0 : onClick(id) }, id));
@@ -9,11 +9,11 @@ export const ReadOnlyGuidelines = ({
9
9
  onClick,
10
10
  }: ReadOnlyGuidelinesI) => {
11
11
  return (
12
- <Stack spacing="base">
12
+ <Stack spacing="base" flex="1" width="100%">
13
13
  <Text fontSize="xs" textTransform="uppercase">
14
14
  {name}
15
15
  </Text>
16
- <Grid templateColumns="repeat(2, minmax(80px, 1fr))" gap="base">
16
+ <Grid templateColumns="repeat(auto-fit, minmax(0, 75px))" gap="base">
17
17
  {children?.map((child) => {
18
18
  const { id, icon, value } = child
19
19
  const btnIcon = icon ? fieldIcons[icon] : ''
@@ -3,7 +3,7 @@ import { Box, Flex, Text } from '@chakra-ui/react';
3
3
  export const ReadOnlyHomeItemText = ({ name, value }) => {
4
4
  if (!name)
5
5
  return null;
6
- return (_jsxs(Flex, { gap: "base", children: [_jsx(Box, { w: "20%", children: _jsx(CustomText, { children: `${name}:` }) }), _jsx(CustomText, { children: String(value) })] }));
6
+ return (_jsxs(Flex, { gap: "base", children: [_jsx(Box, { w: "30%", children: _jsx(CustomText, { children: `${name}:` }) }), _jsx(CustomText, { children: String(value) })] }));
7
7
  };
8
8
  const CustomText = ({ children = '' }) => {
9
9
  return (_jsx(Text, { fontSize: "sm", fontFamily: "secondary", children: children }));
@@ -5,7 +5,7 @@ export const ReadOnlyHomeItemText = ({ name, value }: Partial<ReportI>) => {
5
5
  if (!name) return null
6
6
  return (
7
7
  <Flex gap="base">
8
- <Box w="20%">
8
+ <Box w="30%">
9
9
  <CustomText>{`${name}:`}</CustomText>
10
10
  </Box>
11
11
  <CustomText>{String(value)}</CustomText>
@@ -1,4 +1,5 @@
1
1
  export * from './ReadOnlyAppliances';
2
+ export * from './ReadOnlyCollapsible';
2
3
  export * from './ReadOnlyGuidelines';
3
4
  export * from './ReadOnlyHomeItemImages';
4
5
  export * from './ReadOnlyHomeItemRating';
@@ -1,4 +1,5 @@
1
1
  export * from './ReadOnlyAppliances';
2
+ export * from './ReadOnlyCollapsible';
2
3
  export * from './ReadOnlyGuidelines';
3
4
  export * from './ReadOnlyHomeItemImages';
4
5
  export * from './ReadOnlyHomeItemRating';
@@ -1,4 +1,5 @@
1
1
  export * from './ReadOnlyAppliances'
2
+ export * from './ReadOnlyCollapsible'
2
3
  export * from './ReadOnlyGuidelines'
3
4
  export * from './ReadOnlyHomeItemImages'
4
5
  export * from './ReadOnlyHomeItemRating'
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Flex, Image, Text } from '@chakra-ui/react';
3
3
  export const CollapsibleHeader = ({ icon, title, }) => {
4
- return (_jsxs(Flex, { align: "center", gap: "base", children: [_jsx(Image, { h: "auto", w: "icon.md", src: icon }), _jsx(Text, { fontSize: "sm", textTransform: "uppercase", children: title })] }));
4
+ return (_jsxs(Flex, { align: "center", gap: "base", children: [icon && _jsx(Image, { h: "auto", w: "icon.md", src: icon }), _jsx(Text, { fontSize: "sm", textTransform: "uppercase", children: title })] }));
5
5
  };
@@ -1,16 +1,17 @@
1
1
  import { HomeDepot, Lowes, Walmart, DefaultReceipt } from '../../assets/images';
2
2
  export const receiptOrigins = {
3
- homeDepot: HomeDepot,
4
- HomeDepot: HomeDepot,
3
+ homedepot: HomeDepot,
5
4
  lowes: Lowes,
6
- Lowes: Lowes,
7
5
  walmart: Walmart,
8
- Walmart: Walmart,
9
6
  "": DefaultReceipt
10
7
  };
8
+ function normalize(input) {
9
+ return input.trim().toLowerCase().replace(/['\s]+/g, '');
10
+ }
11
11
  export const getReceiptOrigin = (key) => {
12
12
  var _a;
13
- return (_a = receiptOrigins[key]) !== null && _a !== void 0 ? _a : DefaultReceipt;
13
+ const normalizedKey = normalize(key);
14
+ return (_a = receiptOrigins[normalizedKey]) !== null && _a !== void 0 ? _a : DefaultReceipt;
14
15
  };
15
16
  export const receipts = [
16
17
  {
@@ -1,4 +1,5 @@
1
1
  export interface CollapsibleI {
2
- icon: string;
2
+ icon?: string;
3
3
  title: string;
4
+ showShadow?: boolean;
4
5
  }
@@ -1,5 +1,5 @@
1
1
  import { AIGridFieldI, AlertFieldType, AlertTabType, FolderFileI, MenuItemI, PartnerFooterI, TileCtaI } from '../..';
2
- export type KindTypes = 'ai-image' | 'ai-grid' | 'checkbox' | 'checkbox-agreement' | 'checkbox-group' | 'currency' | 'date' | 'email' | 'file' | 'grid' | 'group' | 'hidden' | 'notes' | 'number' | 'radio' | 'rating' | 'select' | 'string' | 'switch' | 'telephone' | 'text' | 'textarea' | 'default' | 'video' | UIKindTypes | HomeItemTypes | AlertTabType | AlertFieldType;
2
+ export type KindTypes = 'ai-image' | 'ai-grid' | 'checkbox' | 'checkbox-agreement' | 'checkbox-group' | 'collapsible' | 'currency' | 'date' | 'email' | 'file' | 'grid' | 'group' | 'hidden' | 'notes' | 'number' | 'radio' | 'rating' | 'select' | 'string' | 'switch' | 'telephone' | 'text' | 'textarea' | 'default' | 'video' | UIKindTypes | HomeItemTypes | AlertTabType | AlertFieldType;
3
3
  export type UIKindTypes = 'tile-body' | 'tile-body-logo' | 'tile-body-header' | 'tile-body-section' | 'tile-body-section-grid' | 'tile-body-partner-image' | 'tile-body-description' | 'tile-form' | 'tile-body-action' | 'vertical-icon' | 'primary-cta' | 'secondary-cta';
4
4
  export type HomeItemTypes = 'appliances' | 'images' | 'guidelines' | 'item-related' | 'item-icon-btn';
5
5
  export type IconTypes = 'barcode' | 'battery' | 'billing' | 'book' | 'book-opened' | 'calc' | 'calendar' | 'check' | 'co2' | 'contact' | 'date' | 'default' | 'detector' | 'electricity' | 'fire' | 'goldbars' | 'heart' | 'image' | 'life-preserver' | 'notes' | 'palette' | 'plant' | 'people' | 'price' | 'rating' | 'receipt' | 'registry' | 'sprinkler' | 'tools' | 'wind' | '68' | 'calendar2' | 'water' | 'calendar-drop' | 'umbrella' | 'heater' | 'roof' | 'foundation' | 'solar-panel' | 'pool' | 'drop' | 'mobile-drop' | 'light' | 'plate' | 'pressure-washer' | 'house' | 'target' | 'title' | 'company' | 'wallet' | UIIconTypes;
@@ -1,4 +1,4 @@
1
1
  import { ReportI } from '../../..';
2
2
  export interface ReadOnlyAppliancesI extends ReportI {
3
- onEdit: (id: string) => void;
3
+ onEdit?: (id: string) => void;
4
4
  }
@@ -673,7 +673,7 @@ export const tileUIMock = [
673
673
  export const viewingHomeItemMock = [
674
674
  {
675
675
  id: faker.database.mongodbObjectId(),
676
- name: 'Appliances',
676
+ name: '',
677
677
  description: 'KitchenAid Counter-depth 20-cu ft French Door Refrigerator with Ice Maker and Water dispenser (Stainless Steel) ENERGY STAR',
678
678
  comments: faker.lorem.sentence(),
679
679
  value: 'Refrigerator',
@@ -687,21 +687,13 @@ export const viewingHomeItemMock = [
687
687
  description: '',
688
688
  comments: '',
689
689
  value: [
690
- faker.image.urlLoremFlickr(),
691
- faker.image.urlLoremFlickr(),
692
- faker.image.urlLoremFlickr(),
693
- faker.image.urlLoremFlickr(),
690
+ faker.image.urlPicsumPhotos(),
691
+ faker.image.urlPicsumPhotos(),
692
+ faker.image.urlPicsumPhotos(),
693
+ faker.image.urlPicsumPhotos(),
694
694
  ],
695
695
  type: 'images',
696
696
  },
697
- {
698
- id: faker.database.mongodbObjectId(),
699
- name: '',
700
- description: '',
701
- comments: '',
702
- value: 4,
703
- type: 'rating',
704
- },
705
697
  {
706
698
  id: faker.database.mongodbObjectId(),
707
699
  name: 'Brand',
@@ -772,13 +764,41 @@ export const viewingHomeItemMock = [
772
764
  },
773
765
  {
774
766
  id: faker.database.mongodbObjectId(),
775
- name: 'Notes',
767
+ name: 'Collapsible',
776
768
  description: '',
777
769
  comments: faker.lorem.sentence(),
778
770
  value: faker.lorem.paragraphs(),
779
- type: 'notes',
771
+ type: 'collapsible',
780
772
  visible: true,
781
- options: [],
773
+ children: [
774
+ {
775
+ id: faker.database.mongodbObjectId(),
776
+ name: 'Care Instructions',
777
+ description: faker.lorem.sentence(),
778
+ comments: faker.lorem.sentence(),
779
+ value: faker.lorem.paragraphs(),
780
+ type: 'text',
781
+ visible: true,
782
+ },
783
+ {
784
+ id: faker.database.mongodbObjectId(),
785
+ name: 'OVERVIEW',
786
+ description: faker.lorem.sentence(),
787
+ comments: faker.lorem.sentence(),
788
+ value: faker.lorem.paragraphs(),
789
+ type: 'text',
790
+ visible: true,
791
+ },
792
+ {
793
+ id: faker.database.mongodbObjectId(),
794
+ name: 'Dimensions',
795
+ description: faker.lorem.sentence(),
796
+ comments: faker.lorem.sentence(),
797
+ value: faker.lorem.paragraphs(),
798
+ type: 'text',
799
+ visible: true,
800
+ },
801
+ ],
782
802
  },
783
803
  ];
784
804
  export const unknownFormMock = {
@@ -3,3 +3,4 @@ import { DynamicFormI } from '../../../interfaces';
3
3
  declare const _default: Meta;
4
4
  export default _default;
5
5
  export declare const ReadOnlyDynamicFormComponent: (args: DynamicFormI) => import("react/jsx-runtime").JSX.Element;
6
+ export declare const ReadOnlyAddItem: (args: DynamicFormI) => import("react/jsx-runtime").JSX.Element;
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Box } from '@chakra-ui/react';
3
+ import { action } from '@storybook/addon-actions';
3
4
  import { ReadOnlyDynamicForm } from '../../../components';
4
- import { unknownFormMock } from '../../../mocks';
5
+ import { unknownFormMock, viewingHomeItemMock } from '../../../mocks';
5
6
  import { mapApiObjectToFormFields } from '../../../utils';
6
7
  export default {
7
8
  title: 'Components/Forms/ReadOnlyDynamicForm',
@@ -13,3 +14,6 @@ export const ReadOnlyDynamicFormComponent = (args) => {
13
14
  });
14
15
  return (_jsx(Box, { p: "base", bg: "neutral.white", w: ['full', '500px'], children: _jsx(ReadOnlyDynamicForm, { form: unknownForm }) }));
15
16
  };
17
+ export const ReadOnlyAddItem = (args) => {
18
+ return (_jsx(Box, { p: "base", bg: "#EFECF7", w: ['full', '433px'], children: _jsx(ReadOnlyDynamicForm, { form: viewingHomeItemMock, onClick: action('onClick') }) }));
19
+ };
@@ -13,6 +13,7 @@ export declare const ReceiptDetailsComponent: {
13
13
  store: string;
14
14
  storePhone: string;
15
15
  name: string;
16
+ origin: string;
16
17
  total: string;
17
18
  onEdit: import("@storybook/addon-actions").HandlerFunction;
18
19
  onFileClick: () => void;
@@ -18,6 +18,7 @@ ReceiptDetailsComponent.args = {
18
18
  store: '8418',
19
19
  storePhone: '1234567890',
20
20
  name: 'Home Depot',
21
+ origin: "Home Depot",
21
22
  total: '41.65',
22
23
  onEdit: action('onEdit'),
23
24
  onFileClick: () => { }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homefile/components-v2",
3
- "version": "2.24.25",
3
+ "version": "2.25.0",
4
4
  "author": "Homefile",
5
5
  "license": "UNLICENSED",
6
6
  "typings": "dist/index.d.ts",
@@ -14,9 +14,10 @@ export const Collapsible = ({
14
14
  children,
15
15
  icon,
16
16
  title,
17
+ showShadow = true,
17
18
  }: PropsWithChildren<CollapsibleI>) => {
18
19
  return (
19
- <Accordion flex="1" allowMultiple boxShadow="md">
20
+ <Accordion flex="1" allowMultiple boxShadow={showShadow ? 'md' : 'none'}>
20
21
  <AccordionItem border="none">
21
22
  {({ isExpanded }) => (
22
23
  <>
@@ -28,7 +29,7 @@ export const Collapsible = ({
28
29
  borderBottom="1px solid"
29
30
  borderColor={isExpanded ? 'lightBlue.2' : 'transparent'}
30
31
  _hover={{
31
- boxShadow: 'lg',
32
+ boxShadow: showShadow ? 'lg' : 'none',
32
33
  }}
33
34
  _focus={{
34
35
  outline: 'none',
@@ -2,6 +2,7 @@ import { Box } from '@chakra-ui/react'
2
2
  import { ReadOnlyDynamicFormI, IconTypes } from '@/interfaces'
3
3
  import {
4
4
  ReadOnlyAppliances,
5
+ ReadOnlyCollapsible,
5
6
  ReadOnlyDate,
6
7
  ReadOnlyGrid,
7
8
  ReadOnlyGroup,
@@ -15,7 +16,7 @@ import { fieldIcons } from '@/helpers'
15
16
  export const ReadOnlyDynamicForm = ({
16
17
  form: fields,
17
18
  onClick,
18
- onEdit = () => {},
19
+ onEdit,
19
20
  }: ReadOnlyDynamicFormI) => {
20
21
  return (
21
22
  <Box bg="lightBlue.1" overflow="scroll">
@@ -74,6 +75,8 @@ export const ReadOnlyDynamicForm = ({
74
75
  return <ReadOnlyGroup key={id}>{children}</ReadOnlyGroup>
75
76
  case 'appliances':
76
77
  return <ReadOnlyAppliances {...field} key={id} onEdit={onEdit} />
78
+ case 'collapsible':
79
+ return <ReadOnlyCollapsible {...field} key={id} />
77
80
  case 'notes':
78
81
  return <ReadOnlyNotes {...field} key={id} />
79
82
  default:
@@ -20,18 +20,23 @@ export const ReadOnlyAppliances = ({
20
20
  const images = children?.find(({ type }) => type === 'images')
21
21
  return (
22
22
  <Stack spacing="base" p="base" bg="neutral.white" mt="2px">
23
- <Flex justify="space-between">
24
- <Text fontSize="xs" textTransform="uppercase">
25
- {name}
26
- </Text>
27
- <IconButton
28
- aria-label="Edit appliance"
29
- variant="ghost"
30
- w="fit-content"
31
- icon={<Edit size={18} stroke={colors.blue[3]} />}
32
- onClick={() => onEdit(id)}
33
- />
34
- </Flex>
23
+ {name ||
24
+ (onEdit && (
25
+ <Flex justify="space-between">
26
+ <Text fontSize="xs" textTransform="uppercase">
27
+ {name}
28
+ </Text>
29
+ {onEdit && (
30
+ <IconButton
31
+ aria-label="Edit appliance"
32
+ variant="ghost"
33
+ w="fit-content"
34
+ icon={<Edit size={18} stroke={colors.blue[3]} />}
35
+ onClick={() => onEdit(id)}
36
+ />
37
+ )}
38
+ </Flex>
39
+ ))}
35
40
  <Flex gap="base">
36
41
  <ReadOnlyHomeItemImages {...images} />
37
42
  <Stack spacing="4" flex="1">
@@ -40,33 +45,33 @@ export const ReadOnlyAppliances = ({
40
45
  <Text fontSize="22px" fontWeight="semibold">
41
46
  {value}
42
47
  </Text>
48
+ <Box>
49
+ {children?.map(({ id, name, value, type }) => {
50
+ const baseProps = {
51
+ key: `${id}-${name}-${value}-${type}`,
52
+ id,
53
+ value,
54
+ type,
55
+ name,
56
+ }
57
+ switch (type) {
58
+ case 'text':
59
+ return <ReadOnlyHomeItemText {...baseProps} />
60
+ default:
61
+ return null
62
+ }
63
+ })}
64
+ </Box>
65
+ <Box
66
+ flex="1"
67
+ borderBottom="1px dashed"
68
+ borderColor="lightBlue.6"
69
+ h="1px"
70
+ />
43
71
  <Text fontFamily="secondary" fontSize="sm">
44
72
  {description}
45
73
  </Text>
46
74
  </Stack>
47
- <Box
48
- flex="1"
49
- borderBottom="1px dashed"
50
- borderColor="lightBlue.6"
51
- h="1px"
52
- />
53
- <Box>
54
- {children?.map(({ id, name, value, type }) => {
55
- const baseProps = {
56
- key: `${id}-${name}-${value}-${type}`,
57
- id,
58
- value,
59
- type,
60
- name,
61
- }
62
- switch (type) {
63
- case 'text':
64
- return <ReadOnlyHomeItemText {...baseProps} />
65
- default:
66
- return null
67
- }
68
- })}
69
- </Box>
70
75
  </Stack>
71
76
  </Flex>
72
77
  </Stack>
@@ -0,0 +1,34 @@
1
+ import { Stack } from '@chakra-ui/react'
2
+ import { Collapsible, ReadOnlyTextArea } from '@/components'
3
+ import { ReportI } from '@/interfaces'
4
+
5
+ export const ReadOnlyCollapsible = ({
6
+ children,
7
+ }: Pick<ReportI, 'children'>) => {
8
+ return (
9
+ <Stack bg="lightBlue.2" spacing="2px">
10
+ {children?.map(({ id, name = '', value, type }) => {
11
+ const baseProps = {
12
+ id,
13
+ value,
14
+ type,
15
+ name,
16
+ }
17
+ switch (type) {
18
+ case 'text':
19
+ return (
20
+ <Collapsible
21
+ title={name}
22
+ showShadow={false}
23
+ key={`${id}-${name}-${value}-${type}`}
24
+ >
25
+ <ReadOnlyTextArea {...baseProps} />
26
+ </Collapsible>
27
+ )
28
+ default:
29
+ return null
30
+ }
31
+ })}
32
+ </Stack>
33
+ )
34
+ }
@@ -9,11 +9,11 @@ export const ReadOnlyGuidelines = ({
9
9
  onClick,
10
10
  }: ReadOnlyGuidelinesI) => {
11
11
  return (
12
- <Stack spacing="base">
12
+ <Stack spacing="base" flex="1" width="100%">
13
13
  <Text fontSize="xs" textTransform="uppercase">
14
14
  {name}
15
15
  </Text>
16
- <Grid templateColumns="repeat(2, minmax(80px, 1fr))" gap="base">
16
+ <Grid templateColumns="repeat(auto-fit, minmax(0, 75px))" gap="base">
17
17
  {children?.map((child) => {
18
18
  const { id, icon, value } = child
19
19
  const btnIcon = icon ? fieldIcons[icon] : ''
@@ -5,7 +5,7 @@ export const ReadOnlyHomeItemText = ({ name, value }: Partial<ReportI>) => {
5
5
  if (!name) return null
6
6
  return (
7
7
  <Flex gap="base">
8
- <Box w="20%">
8
+ <Box w="30%">
9
9
  <CustomText>{`${name}:`}</CustomText>
10
10
  </Box>
11
11
  <CustomText>{String(value)}</CustomText>
@@ -1,4 +1,5 @@
1
1
  export * from './ReadOnlyAppliances'
2
+ export * from './ReadOnlyCollapsible'
2
3
  export * from './ReadOnlyGuidelines'
3
4
  export * from './ReadOnlyHomeItemImages'
4
5
  export * from './ReadOnlyHomeItemRating'
@@ -7,7 +7,7 @@ export const CollapsibleHeader = ({
7
7
  }: Pick<CollapsibleI, 'icon' | 'title'>) => {
8
8
  return (
9
9
  <Flex align="center" gap="base">
10
- <Image h="auto" w="icon.md" src={icon} />
10
+ {icon && <Image h="auto" w="icon.md" src={icon} />}
11
11
  <Text fontSize="sm" textTransform="uppercase">
12
12
  {title}
13
13
  </Text>
@@ -2,17 +2,19 @@ import { ReceiptCardItemI } from '@/interfaces'
2
2
  import { HomeDepot, Lowes, Walmart, DefaultReceipt } from '@/assets/images'
3
3
 
4
4
  export const receiptOrigins: Record<string, string> = {
5
- homeDepot: HomeDepot,
6
- HomeDepot: HomeDepot,
5
+ homedepot: HomeDepot,
7
6
  lowes: Lowes,
8
- Lowes: Lowes,
9
7
  walmart: Walmart,
10
- Walmart: Walmart,
11
8
  "" : DefaultReceipt
12
9
  }
13
10
 
11
+ function normalize(input: string) {
12
+ return input.trim().toLowerCase().replace(/['\s]+/g, '');
13
+ }
14
+
14
15
  export const getReceiptOrigin = (key: string): string => {
15
- return receiptOrigins[key] ?? DefaultReceipt;
16
+ const normalizedKey = normalize(key)
17
+ return receiptOrigins[normalizedKey] ?? DefaultReceipt;
16
18
  };
17
19
 
18
20
  export const receipts: ReceiptCardItemI[] = [
@@ -1,4 +1,5 @@
1
1
  export interface CollapsibleI {
2
- icon: string
2
+ icon?: string
3
3
  title: string
4
+ showShadow?: boolean
4
5
  }
@@ -14,6 +14,7 @@ export type KindTypes =
14
14
  | 'checkbox'
15
15
  | 'checkbox-agreement'
16
16
  | 'checkbox-group'
17
+ | 'collapsible'
17
18
  | 'currency'
18
19
  | 'date'
19
20
  | 'email'
@@ -1,5 +1,5 @@
1
1
  import { ReportI } from '@/interfaces'
2
2
 
3
3
  export interface ReadOnlyAppliancesI extends ReportI {
4
- onEdit: (id: string) => void
4
+ onEdit?: (id: string) => void
5
5
  }
@@ -681,7 +681,7 @@ export const tileUIMock: ReportI[] = [
681
681
  export const viewingHomeItemMock: ReportI[] = [
682
682
  {
683
683
  id: faker.database.mongodbObjectId(),
684
- name: 'Appliances',
684
+ name: '',
685
685
  description:
686
686
  'KitchenAid Counter-depth 20-cu ft French Door Refrigerator with Ice Maker and Water dispenser (Stainless Steel) ENERGY STAR',
687
687
  comments: faker.lorem.sentence(),
@@ -696,21 +696,13 @@ export const viewingHomeItemMock: ReportI[] = [
696
696
  description: '',
697
697
  comments: '',
698
698
  value: [
699
- faker.image.urlLoremFlickr(),
700
- faker.image.urlLoremFlickr(),
701
- faker.image.urlLoremFlickr(),
702
- faker.image.urlLoremFlickr(),
699
+ faker.image.urlPicsumPhotos(),
700
+ faker.image.urlPicsumPhotos(),
701
+ faker.image.urlPicsumPhotos(),
702
+ faker.image.urlPicsumPhotos(),
703
703
  ],
704
704
  type: 'images',
705
705
  },
706
- {
707
- id: faker.database.mongodbObjectId(),
708
- name: '',
709
- description: '',
710
- comments: '',
711
- value: 4,
712
- type: 'rating',
713
- },
714
706
  {
715
707
  id: faker.database.mongodbObjectId(),
716
708
  name: 'Brand',
@@ -781,13 +773,41 @@ export const viewingHomeItemMock: ReportI[] = [
781
773
  },
782
774
  {
783
775
  id: faker.database.mongodbObjectId(),
784
- name: 'Notes',
776
+ name: 'Collapsible',
785
777
  description: '',
786
778
  comments: faker.lorem.sentence(),
787
779
  value: faker.lorem.paragraphs(),
788
- type: 'notes',
780
+ type: 'collapsible',
789
781
  visible: true,
790
- options: [],
782
+ children: [
783
+ {
784
+ id: faker.database.mongodbObjectId(),
785
+ name: 'Care Instructions',
786
+ description: faker.lorem.sentence(),
787
+ comments: faker.lorem.sentence(),
788
+ value: faker.lorem.paragraphs(),
789
+ type: 'text',
790
+ visible: true,
791
+ },
792
+ {
793
+ id: faker.database.mongodbObjectId(),
794
+ name: 'OVERVIEW',
795
+ description: faker.lorem.sentence(),
796
+ comments: faker.lorem.sentence(),
797
+ value: faker.lorem.paragraphs(),
798
+ type: 'text',
799
+ visible: true,
800
+ },
801
+ {
802
+ id: faker.database.mongodbObjectId(),
803
+ name: 'Dimensions',
804
+ description: faker.lorem.sentence(),
805
+ comments: faker.lorem.sentence(),
806
+ value: faker.lorem.paragraphs(),
807
+ type: 'text',
808
+ visible: true,
809
+ },
810
+ ],
791
811
  },
792
812
  ]
793
813
 
@@ -1,7 +1,8 @@
1
1
  import { Meta } from '@storybook/react'
2
2
  import { Box } from '@chakra-ui/react'
3
+ import { action } from '@storybook/addon-actions'
3
4
  import { ReadOnlyDynamicForm } from '@/components'
4
- import { unknownFormMock } from '@/mocks'
5
+ import { unknownFormMock, viewingHomeItemMock } from '@/mocks'
5
6
  import { DynamicFormI } from '@/interfaces'
6
7
  import { mapApiObjectToFormFields } from '@/utils'
7
8
 
@@ -20,3 +21,14 @@ export const ReadOnlyDynamicFormComponent = (args: DynamicFormI) => {
20
21
  </Box>
21
22
  )
22
23
  }
24
+
25
+ export const ReadOnlyAddItem = (args: DynamicFormI) => {
26
+ return (
27
+ <Box p="base" bg="#EFECF7" w={['full', '433px']}>
28
+ <ReadOnlyDynamicForm
29
+ form={viewingHomeItemMock}
30
+ onClick={action('onClick')}
31
+ />
32
+ </Box>
33
+ )
34
+ }
@@ -26,6 +26,7 @@ ReceiptDetailsComponent.args = {
26
26
  store: '8418',
27
27
  storePhone: '1234567890',
28
28
  name: 'Home Depot',
29
+ origin: "Home Depot",
29
30
  total: '41.65',
30
31
  onEdit: action('onEdit'),
31
32
  onFileClick: () => {}