@homefile/components-v2 2.22.2 → 2.23.1

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 (34) hide show
  1. package/dist/assets/locales/en/index.json +1 -0
  2. package/dist/components/dragDrop/DragDropArea.d.ts +1 -1
  3. package/dist/components/dragDrop/DragDropArea.js +2 -2
  4. package/dist/components/forms/dynamicForm/DynamicForm.d.ts +1 -1
  5. package/dist/components/forms/dynamicForm/DynamicForm.js +4 -4
  6. package/dist/components/forms/dynamicForm/SearchItemLoader.d.ts +3 -1
  7. package/dist/components/forms/dynamicForm/SearchItemLoader.js +2 -2
  8. package/dist/components/forms/dynamicForm/fields/CheckboxAgreement.d.ts +1 -1
  9. package/dist/components/forms/dynamicForm/fields/CheckboxAgreement.js +3 -2
  10. package/dist/components/forms/dynamicForm/fields/FileField.d.ts +1 -1
  11. package/dist/components/forms/dynamicForm/fields/FileField.js +2 -2
  12. package/dist/components/headers/TabsHeader.js +1 -1
  13. package/dist/components/receipts/receipt/ReceiptDetails.js +1 -2
  14. package/dist/interfaces/dragDrop/DragDropArea.interface.d.ts +1 -0
  15. package/dist/interfaces/forms/dynamicForm/DynamicForm.interface.d.ts +1 -0
  16. package/dist/interfaces/forms/dynamicForm/fields/FileField.interface.d.ts +1 -0
  17. package/dist/mocks/forms/dynamicForm.mock.d.ts +1 -0
  18. package/dist/mocks/forms/dynamicForm.mock.js +95 -0
  19. package/dist/stories/receipts/receipt/AddReceiptPanel.stories.d.ts +5 -0
  20. package/dist/stories/receipts/receipt/AddReceiptPanel.stories.js +56 -0
  21. package/package.json +1 -1
  22. package/src/assets/locales/en/index.json +1 -0
  23. package/src/components/dragDrop/DragDropArea.tsx +2 -1
  24. package/src/components/forms/dynamicForm/DynamicForm.tsx +7 -2
  25. package/src/components/forms/dynamicForm/SearchItemLoader.tsx +3 -3
  26. package/src/components/forms/dynamicForm/fields/CheckboxAgreement.tsx +4 -2
  27. package/src/components/forms/dynamicForm/fields/FileField.tsx +2 -0
  28. package/src/components/headers/TabsHeader.tsx +1 -1
  29. package/src/components/receipts/receipt/ReceiptDetails.tsx +28 -7
  30. package/src/interfaces/dragDrop/DragDropArea.interface.ts +1 -0
  31. package/src/interfaces/forms/dynamicForm/DynamicForm.interface.ts +1 -0
  32. package/src/interfaces/forms/dynamicForm/fields/FileField.interface.ts +1 -0
  33. package/src/mocks/forms/dynamicForm.mock.ts +97 -0
  34. package/src/stories/receipts/receipt/AddReceiptPanel.stories.tsx +160 -0
@@ -108,6 +108,7 @@
108
108
  "close": "Close",
109
109
  "done": "Done",
110
110
  "delete": "Delete",
111
+ "edit": "Edit",
111
112
  "forward": "Forward",
112
113
  "next": "Next",
113
114
  "previous": "Previous",
@@ -1,2 +1,2 @@
1
1
  import { DragDropAreaI } from '../../interfaces';
2
- export declare const DragDropArea: ({ align, direction, errorMessage, getInputProps, getRootProps, height, message, message2, variant, }: DragDropAreaI) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const DragDropArea: ({ align, direction, errorMessage, getInputProps, getRootProps, height, message, message2, variant, multiple, }: DragDropAreaI) => import("react/jsx-runtime").JSX.Element;
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { t } from 'i18next';
3
3
  import { Container, Flex, Stack, Text } from '@chakra-ui/react';
4
4
  import { Upload } from '..';
5
- export const DragDropArea = ({ align = 'center', direction = 'row', errorMessage, getInputProps, getRootProps, height = '4rem', message = t('dragDrop.message'), message2 = t('dragDrop.message2'), variant = 'dragDropDashed', }) => {
5
+ export const DragDropArea = ({ align = 'center', direction = 'row', errorMessage, getInputProps, getRootProps, height = '4rem', message = t('dragDrop.message'), message2 = t('dragDrop.message2'), variant = 'dragDropDashed', multiple = false, }) => {
6
6
  const hasError = !!errorMessage;
7
- return (_jsxs(Stack, { spacing: "1", children: [_jsxs(Container, Object.assign({ variant: variant, minW: "full", h: height }, getRootProps(), { children: [_jsx("input", Object.assign({}, getInputProps())), _jsx(Flex, { h: height, align: align, justify: "center", p: "base", children: _jsxs(Flex, { align: "center", direction: direction, gap: "2", children: [_jsx(Upload, {}), _jsxs(Flex, { align: "center", gap: "1", children: [message && _jsx(Text, { variant: "dragDrop", children: message }), message2 && _jsx(Text, { variant: "dragDropLink", children: message2 })] })] }) })] })), hasError && _jsx(Text, { variant: "error", children: errorMessage })] }));
7
+ return (_jsxs(Stack, { spacing: "1", children: [_jsxs(Container, Object.assign({ variant: variant, minW: "full", h: height }, getRootProps(), { children: [_jsx("input", Object.assign({}, getInputProps({ multiple }))), _jsx(Flex, { h: height, align: align, justify: "center", p: "base", children: _jsxs(Flex, { align: "center", direction: direction, gap: "2", children: [_jsx(Upload, {}), _jsxs(Flex, { align: "center", gap: "1", children: [message && _jsx(Text, { variant: "dragDrop", children: message }), message2 && _jsx(Text, { variant: "dragDropLink", children: message2 })] })] }) })] })), hasError && _jsx(Text, { variant: "error", children: errorMessage })] }));
8
8
  };
@@ -1,2 +1,2 @@
1
1
  import { DynamicFormI } from '../../../interfaces';
2
- export declare const DynamicForm: ({ callback, displayImages, form: fields, menuItems, onAISend, onRemoveImage, onUpload, searching, showTitle, title, uploadingFieldId, ...props }: DynamicFormI) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const DynamicForm: ({ callback, displayImages, form: fields, menuItems, onAISend, onRemoveImage, onUpload, searching, showTitle, singleFileUpload, title, uploadingFieldId, ...props }: DynamicFormI) => import("react/jsx-runtime").JSX.Element;
@@ -18,13 +18,13 @@ import { HiddenFieldSection, GroupField, TextField, TextAreaField, SelectField,
18
18
  import { useDynamicForm } from '../../../hooks';
19
19
  import { fieldIcons } from '../../../helpers';
20
20
  export const DynamicForm = (_a) => {
21
- var { callback, displayImages, form: fields, menuItems, onAISend, onRemoveImage, onUpload, searching = false, showTitle = true, title, uploadingFieldId } = _a, props = __rest(_a, ["callback", "displayImages", "form", "menuItems", "onAISend", "onRemoveImage", "onUpload", "searching", "showTitle", "title", "uploadingFieldId"]);
21
+ var { callback, displayImages, form: fields, menuItems, onAISend, onRemoveImage, onUpload, searching = false, showTitle = true, singleFileUpload, title, uploadingFieldId } = _a, props = __rest(_a, ["callback", "displayImages", "form", "menuItems", "onAISend", "onRemoveImage", "onUpload", "searching", "showTitle", "singleFileUpload", "title", "uploadingFieldId"]);
22
22
  const { form, visibleFields, hiddenFields, handleAddAll, handleAdd, handleFilesUpload, handleRemove, } = useDynamicForm({ fields, onUpload });
23
23
  if (searching) {
24
24
  return _jsx(SearchItemLoader, {});
25
25
  }
26
26
  return (_jsxs(Stack, { bg: "lightBlue.1", spacing: "0", h: "full", overflowX: "hidden", children: [showTitle && (_jsx(Box, { px: "base", pt: "4", pb: "2", borderBottom: "1px dashed", borderColor: "lightBlue.6", children: _jsx(Text, { fontFamily: "secondary", children: title !== null && title !== void 0 ? title : t('forms.itemDetails') }) })), _jsx(FormProvider, Object.assign({}, form, { children: _jsx(_Fragment, { children: visibleFields === null || visibleFields === void 0 ? void 0 : visibleFields.map((field) => {
27
- const { canBeHidden, children, description, icon, id, name, label, options, type, value, } = field;
27
+ const { comments, canBeHidden, children, description, icon, id, name, label, options, type, value, } = field;
28
28
  const baseProps = {
29
29
  id,
30
30
  value,
@@ -76,14 +76,14 @@ export const DynamicForm = (_a) => {
76
76
  _jsx(SwitchField, Object.assign({}, baseProps, { description: description }))));
77
77
  case 'file':
78
78
  return (_createElement(FieldWithDelete, Object.assign({}, fieldWithDeleteBaseProps, { key: id }),
79
- _jsx(FileField, { icon: baseProps.icon, description: description, onRemove: onRemoveImage, onUpload: (files) => handleFilesUpload({ id, files }), uploading: uploadingFieldId === id, displayImages: displayImages })));
79
+ _jsx(FileField, Object.assign({}, baseProps, { description: description, onRemove: onRemoveImage, onUpload: (files) => handleFilesUpload({ id, files }), uploading: uploadingFieldId === id, displayImages: displayImages, singleFileUpload: singleFileUpload, value: value }))));
80
80
  case 'group':
81
81
  return (_jsx(GroupField, { id: id, fields: children, onRemove: handleRemove, canBeHidden: canBeHidden }, id));
82
82
  case 'checkbox-group':
83
83
  return (_createElement(FieldWithDelete, Object.assign({}, fieldWithDeleteBaseProps, { key: id }),
84
84
  _jsx(CheckboxGroupField, { id: id, description: description, icon: baseProps.icon, children: children }, id)));
85
85
  case 'checkbox-agreement':
86
- return (_jsx(CheckboxAgreement, { id: id, name: name, value: value, description: description }, id));
86
+ return (_jsx(CheckboxAgreement, { id: id, name: name, value: value, description: description, comments: comments }, id));
87
87
  case 'tile-body':
88
88
  return (_createElement(TileBody, Object.assign({}, props, { key: id, callback: callback, fields: children, menuItems: menuItems })));
89
89
  default:
@@ -1 +1,3 @@
1
- export declare const SearchItemLoader: () => import("react/jsx-runtime").JSX.Element;
1
+ export declare const SearchItemLoader: ({ message }: {
2
+ message?: string | undefined;
3
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -3,6 +3,6 @@ import { t } from 'i18next';
3
3
  import { Box, Text, Stack } from '@chakra-ui/react';
4
4
  import { PuffLoader } from 'react-spinners';
5
5
  import { colors } from '../../../theme/colors';
6
- export const SearchItemLoader = () => {
7
- return (_jsxs(Stack, { spacing: "base", align: "center", mt: "50px", children: [_jsx(PuffLoader, { color: colors.blue[1], size: 50 }), _jsx(Box, { w: "40%", children: _jsx(Text, { fontSize: "sm", textAlign: "center", children: t('dynamicForm.searching') }) })] }));
6
+ export const SearchItemLoader = ({ message = t('dynamicForm.searching') }) => {
7
+ return (_jsxs(Stack, { spacing: "base", align: "center", mt: "50px", children: [_jsx(PuffLoader, { color: colors.blue[1], size: 50 }), _jsx(Box, { w: "40%", children: _jsx(Text, { fontSize: "sm", textAlign: "center", whiteSpace: "preserve-breaks", children: message }) })] }));
8
8
  };
@@ -1,2 +1,2 @@
1
1
  import { ReportI } from '../../../../interfaces';
2
- export declare const CheckboxAgreement: ({ description, id, name, value, }: Pick<ReportI, "name" | "id" | "description" | "value">) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const CheckboxAgreement: ({ comments, description, id, name, value, }: Pick<ReportI, "name" | "id" | "description" | "value" | "comments">) => import("react/jsx-runtime").JSX.Element;
@@ -2,9 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
2
2
  import { ChevronRight } from '../../../icons';
3
3
  import { Accordion, AccordionItem, AccordionButton, Flex, Box, AccordionPanel, Checkbox, Text, } from '@chakra-ui/react';
4
4
  import { Controller, useFormContext } from 'react-hook-form';
5
- export const CheckboxAgreement = ({ description, id, name, value, }) => {
5
+ export const CheckboxAgreement = ({ comments, description, id, name, value, }) => {
6
6
  const { control } = useFormContext();
7
- return (_jsx(Accordion, { flex: "1", allowToggle: true, defaultIndex: [0], children: _jsx(AccordionItem, { border: "none", bg: "lightViolet.1", children: ({ isExpanded }) => (_jsxs(_Fragment, { children: [_jsxs(Flex, { p: "base", justify: "space-between", children: [_jsx(Controller, { control: control, name: id, defaultValue: value, render: ({ field: { onChange, value } }) => {
7
+ const collapsed = comments === 'collapsed';
8
+ return (_jsx(Accordion, { flex: "1", allowToggle: true, defaultIndex: collapsed ? [1] : [0], children: _jsx(AccordionItem, { border: "none", bg: "lightViolet.1", children: ({ isExpanded }) => (_jsxs(_Fragment, { children: [_jsxs(Flex, { p: "base", justify: "space-between", children: [_jsx(Controller, { control: control, name: id, defaultValue: value, render: ({ field: { onChange, value } }) => {
8
9
  return (_jsx(Checkbox, { value: String(name), isChecked: Boolean(value), onChange: onChange, children: _jsx(Text, { fontFamily: "secondary", fontWeight: "semibold", fontSize: "sm", color: "violet.1", children: name }) }, id));
9
10
  } }), _jsx(AccordionButton, { w: "fit-content", p: "0", _hover: {
10
11
  bg: 'transparent',
@@ -1,2 +1,2 @@
1
1
  import { FileFieldI } from '../../../../interfaces';
2
- export declare const FileField: ({ description, icon, onRemove, onUpload, uploading, displayImages, }: FileFieldI) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const FileField: ({ description, icon, onRemove, onUpload, uploading, displayImages, singleFileUpload, }: FileFieldI) => import("react/jsx-runtime").JSX.Element;
@@ -3,13 +3,13 @@ import { AspectRatio, Box, Flex, Grid, IconButton, Image, Stack, Text, } from '@
3
3
  import { Close, DragDropArea } from '../../..';
4
4
  import { useFilesUploader } from '../../../../hooks';
5
5
  import { colors } from '../../../../theme/colors';
6
- export const FileField = ({ description, icon, onRemove, onUpload, uploading = false, displayImages = [], }) => {
6
+ export const FileField = ({ description, icon, onRemove, onUpload, uploading = false, displayImages = [], singleFileUpload = false, }) => {
7
7
  const { errorMessage, getInputProps, getRootProps, thumbnails } = useFilesUploader({
8
8
  onUpload,
9
9
  uploading,
10
10
  displayImages,
11
11
  });
12
12
  const isStringArray = Array.isArray(thumbnails) && typeof thumbnails[0] === 'string';
13
- return (_jsxs(Flex, { gap: "base", align: "center", flex: "auto", children: [icon && _jsx(Image, { h: "auto", w: "icon.md", src: icon, marginTop: "2" }), _jsxs(Stack, { spacing: "base", flex: "auto", children: [description && _jsx(Text, { fontFamily: "secondary", children: description }), _jsx(DragDropArea, { errorMessage: errorMessage, getInputProps: getInputProps, getRootProps: getRootProps, height: "85px" }), _jsx(Grid, { gridTemplateColumns: `repeat(auto-fill, minmax(22px, 1fr))`, gap: "base", children: isStringArray &&
13
+ return (_jsxs(Flex, { gap: "base", align: "center", flex: "auto", children: [icon && _jsx(Image, { h: "auto", w: "icon.md", src: icon, marginTop: "2" }), _jsxs(Stack, { spacing: "base", flex: "auto", children: [description && _jsx(Text, { fontFamily: "secondary", children: description }), _jsx(DragDropArea, { errorMessage: errorMessage, getInputProps: getInputProps, getRootProps: getRootProps, height: "85px", multiple: !singleFileUpload }), _jsx(Grid, { gridTemplateColumns: `repeat(auto-fill, minmax(22px, 1fr))`, gap: "base", children: isStringArray &&
14
14
  thumbnails.map((file, index) => (_jsxs(Box, { position: "relative", children: [_jsx(IconButton, { variant: "ghost", "aria-label": "close", maxW: "fit-content", onClick: () => onRemove === null || onRemove === void 0 ? void 0 : onRemove(file), icon: _jsx(Close, { size: 11, stroke: colors.error['2'] }), disabled: uploading, position: "absolute", bg: "neutral.white", p: "0.5", borderRadius: "full", top: "-2", right: "-2", zIndex: "1" }), _jsx(AspectRatio, { maxW: "100%", ratio: 1, children: _jsx(Image, { src: file, objectFit: "cover", alt: `file-${index}` }) })] }, file))) })] })] }));
15
15
  };
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Flex, Tab, TabList, TabPanel, TabPanels, Tabs, } from '@chakra-ui/react';
3
3
  export const TabsHeader = ({ onChange, tabList, tabIndex, defaultIndex, rightButton, rightTabList, }) => {
4
- return (_jsxs(Tabs, { zIndex: "base", variant: "unstyled", onChange: onChange, index: tabIndex, defaultIndex: defaultIndex, h: "100%", children: [_jsx(Box, { bg: "lightBlue.2", children: _jsxs(Flex, { justify: "space-between", children: [_jsx(TabList, { bg: "neutral.white", w: "full", children: tabList === null || tabList === void 0 ? void 0 : tabList.map(({ label }) => (_jsx(CustomTab, { label: label }, label))) }), _jsxs(Flex, { children: [_jsx(TabList, { bg: "neutral.white", w: "full", children: rightTabList === null || rightTabList === void 0 ? void 0 : rightTabList.map(({ label }) => (_jsx(CustomTab, { label: label }, label))) }), rightButton] })] }) }), _jsx(TabPanels, { h: "100%", children: tabList === null || tabList === void 0 ? void 0 : tabList.map(({ label, component }) => (_jsx(TabPanel, { p: "0", h: "100%", children: component }, label))) })] }));
4
+ return (_jsxs(Tabs, { zIndex: "base", variant: "unstyled", onChange: onChange, index: tabIndex, defaultIndex: defaultIndex, h: "100%", children: [_jsx(Box, { bg: "lightBlue.2", children: _jsxs(Flex, { justify: "space-between", children: [_jsx(TabList, { bg: "neutral.white", w: "full", children: tabList === null || tabList === void 0 ? void 0 : tabList.map(({ label }) => (_jsx(CustomTab, { label: label }, label))) }), _jsxs(Flex, { flexShrink: 0, children: [_jsx(TabList, { bg: "neutral.white", w: "full", children: rightTabList === null || rightTabList === void 0 ? void 0 : rightTabList.map(({ label }) => (_jsx(CustomTab, { label: label }, label))) }), rightButton] })] }) }), _jsx(TabPanels, { h: "100%", children: tabList === null || tabList === void 0 ? void 0 : tabList.map(({ label, component }) => (_jsx(TabPanel, { p: "0", h: "100%", children: component }, label))) })] }));
5
5
  };
6
6
  const CustomTab = ({ label = '' }) => {
7
7
  return (_jsx(Tab, { minW: "1rem", px: "base", py: "0", lineHeight: "10", textTransform: "uppercase", fontWeight: "medium", fontSize: "sm", fontFamily: "primary", color: "blue.3", borderBottom: "3px solid transparent", _hover: { cursor: 'pointer' }, _focus: { outline: 'none' }, _selected: {
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { t } from 'i18next';
3
3
  import { Box, Divider, Flex, Image } from '@chakra-ui/react';
4
- import { ReceiptBg } from '../../../assets/images';
5
4
  import { formatDate } from '../../../utils';
6
5
  import { DetailsColumn } from '../..';
7
6
  import { receiptOrigins } from '../../../helpers';
@@ -45,5 +44,5 @@ export const ReceiptDetails = ({ cashier = '', itemQuantity, paymentMethod, purc
45
44
  value: paymentMethod,
46
45
  },
47
46
  ];
48
- return (_jsxs(Box, { boxShadow: "md", minW: "108px", bg: "lightBlue.2", borderBottom: "1px solid", borderColor: "lightBlue.2", children: [_jsx(Box, { bgImg: ReceiptBg, bgRepeat: "repeat-x", w: "100%", h: "10px" }), _jsx(Box, { bg: "neutral.white", px: "2", p: "base", children: _jsxs(Flex, { align: "center", gap: "base", children: [_jsx(Image, { src: storeImage, w: "75px", h: "75px", fit: "cover" }), _jsxs(Flex, { align: "center", gap: "2", flex: "auto", children: [_jsx(DetailsColumn, { details: leftColumn }), _jsx(Divider, { orientation: "vertical", bg: "lightBlue.2", h: "63px", mr: "6" }), _jsx(DetailsColumn, { align: "right", details: rightColumn })] })] }) })] }));
47
+ return (_jsxs(Box, { boxShadow: "md", minW: "108px", bg: "lightBlue.2", borderBottom: "1px solid", borderColor: "lightBlue.2", children: [_jsx(Box, { w: "100%", h: "10px", bg: "lightBlue.2", overflow: "hidden", position: "relative", children: _jsxs("svg", { width: "100%", height: "8", viewBox: "0 0 100 10", preserveAspectRatio: "none", style: { display: 'block', position: 'absolute', bottom: 0, left: 0 }, children: [_jsx("defs", { children: _jsx("pattern", { id: "triangle", width: "4", height: "10", patternUnits: "userSpaceOnUse", children: _jsx("polygon", { points: "0,10 2,0 4,10", fill: "white" }) }) }), _jsx("rect", { width: "100%", height: "10", fill: "url(#triangle)" })] }) }), _jsx(Box, { bg: "neutral.white", px: "2", p: "base", children: _jsxs(Flex, { align: "center", gap: "base", children: [_jsx(Image, { src: storeImage, w: "75px", h: "75px", fit: "cover" }), _jsxs(Flex, { align: "center", gap: "2", flex: "auto", children: [_jsx(DetailsColumn, { details: leftColumn }), _jsx(Divider, { orientation: "vertical", bg: "lightBlue.2", h: "63px", mr: "6" }), _jsx(DetailsColumn, { align: "right", details: rightColumn })] })] }) })] }));
49
48
  };
@@ -9,5 +9,6 @@ export interface DragDropAreaI {
9
9
  height?: number | string;
10
10
  message?: string;
11
11
  message2?: string;
12
+ multiple?: boolean;
12
13
  variant?: 'dragDrop' | 'dragDropDashed';
13
14
  }
@@ -31,6 +31,7 @@ export interface DynamicFormI extends Partial<PartnerFooterI> {
31
31
  onUpload?: (filesByFieldId: Record<string, FolderFileI[] | File[]>) => void;
32
32
  searching?: boolean;
33
33
  showTitle?: boolean;
34
+ singleFileUpload?: boolean;
34
35
  title?: string;
35
36
  uploadingFieldId?: string;
36
37
  }
@@ -4,6 +4,7 @@ export interface FileFieldI extends Pick<ReportI, 'description' | 'icon'> {
4
4
  onUpload?: (files: FolderFileI[]) => void;
5
5
  uploading?: boolean;
6
6
  displayImages?: string[];
7
+ singleFileUpload?: boolean;
7
8
  value?: string;
8
9
  }
9
10
  export interface SingleImageI extends Omit<FileFieldI, 'onUpload'> {
@@ -7,3 +7,4 @@ export declare const unknownFormMock: Record<string, any>;
7
7
  export declare const alertFieldsMock: ReportI[];
8
8
  export declare const alertFieldsMock2: ReportI[];
9
9
  export declare const alertFieldsMock3: ReportI[];
10
+ export declare const receiptFieldsMock: ReportI[];
@@ -1123,3 +1123,98 @@ export const alertFieldsMock3 = [
1123
1123
  type: 'alert',
1124
1124
  },
1125
1125
  ];
1126
+ export const receiptFieldsMock = [
1127
+ {
1128
+ id: faker.database.mongodbObjectId(),
1129
+ name: 'Select to have Homefile use AI & digitize receipt. ',
1130
+ label: 'Find & add information',
1131
+ comments: 'collapsed',
1132
+ description: 'Homefile has an extensive data base of products, but we will also search the web for the most relevant information around products. This includes details like warranty Information, manuals, price, energy info, product ratings, etc. If the item is not in our database, it will populate as soon as we add the info.',
1133
+ value: true,
1134
+ type: 'checkbox-agreement',
1135
+ visible: true,
1136
+ },
1137
+ {
1138
+ id: faker.database.mongodbObjectId(),
1139
+ name: 'Images',
1140
+ description: 'Add picture',
1141
+ comments: '',
1142
+ value: '',
1143
+ type: 'file',
1144
+ canBeHidden: false,
1145
+ },
1146
+ {
1147
+ id: faker.database.mongodbObjectId(),
1148
+ name: 'Receipt',
1149
+ description: faker.lorem.sentence(),
1150
+ comments: faker.lorem.sentence(),
1151
+ value: '',
1152
+ type: 'group',
1153
+ visible: false,
1154
+ icon: 'receipt',
1155
+ children: [
1156
+ {
1157
+ id: faker.database.mongodbObjectId(),
1158
+ name: 'Receipt',
1159
+ label: 'Receipt',
1160
+ description: faker.lorem.sentence(),
1161
+ comments: faker.lorem.sentence(),
1162
+ value: faker.lorem.sentence(),
1163
+ type: 'text',
1164
+ visible: true,
1165
+ icon: 'receipt',
1166
+ },
1167
+ {
1168
+ id: faker.database.mongodbObjectId(),
1169
+ name: 'SKU',
1170
+ label: 'SKU',
1171
+ description: faker.lorem.sentence(),
1172
+ comments: faker.lorem.sentence(),
1173
+ value: faker.lorem.sentence(),
1174
+ type: 'text',
1175
+ visible: true,
1176
+ },
1177
+ {
1178
+ id: faker.database.mongodbObjectId(),
1179
+ name: 'Grid 2',
1180
+ description: faker.lorem.sentence(),
1181
+ comments: faker.lorem.sentence(),
1182
+ value: '',
1183
+ type: 'grid',
1184
+ children: [
1185
+ {
1186
+ id: faker.database.mongodbObjectId(),
1187
+ name: 'Purchase Date',
1188
+ label: 'Purchase Date',
1189
+ description: faker.lorem.sentence(),
1190
+ comments: faker.lorem.sentence(),
1191
+ value: '',
1192
+ type: 'date',
1193
+ visible: true,
1194
+ },
1195
+ {
1196
+ id: faker.database.mongodbObjectId(),
1197
+ name: '$ Amount Paid',
1198
+ label: '$ Amount Paid',
1199
+ description: faker.lorem.sentence(),
1200
+ comments: faker.lorem.sentence(),
1201
+ value: faker.finance.amount({ min: 10, max: 100 }),
1202
+ type: 'currency',
1203
+ visible: true,
1204
+ },
1205
+ ],
1206
+ visible: true,
1207
+ },
1208
+ ],
1209
+ },
1210
+ {
1211
+ id: faker.database.mongodbObjectId(),
1212
+ name: 'Notes',
1213
+ description: faker.lorem.sentence(),
1214
+ comments: faker.lorem.sentence(),
1215
+ value: faker.lorem.text(),
1216
+ type: 'textarea',
1217
+ visible: false,
1218
+ icon: 'notes',
1219
+ },
1220
+ ];
@@ -0,0 +1,5 @@
1
+ import { Meta } from '@storybook/react';
2
+ import { ReceiptContentI } from '../../../interfaces';
3
+ declare const _default: Meta<ReceiptContentI>;
4
+ export default _default;
5
+ export declare const AddReceiptPanel: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,56 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { action } from '@storybook/addon-actions';
3
+ import { RightPanel, ReceiptContent, ReceiptItems, ReceiptDetails, TabsHeader, PdfButton, PanelHeader, DynamicForm, EditItemName, ReceiptBody, SearchItemLoader, FooterButtons, FooterDrawer, } from '../../../components';
4
+ import { receiptList } from '../../../helpers';
5
+ import { Register } from '../../../assets/images';
6
+ import { receiptFieldsMock } from '../../../mocks';
7
+ import { useState } from 'react';
8
+ import { Box, DrawerFooter } from '@chakra-ui/react';
9
+ import { t } from 'i18next';
10
+ export default {
11
+ title: 'Components/Receipts/Receipt',
12
+ component: ReceiptContent,
13
+ };
14
+ export const AddReceiptPanel = () => {
15
+ const [currentStep, setCurrentStep] = useState('1');
16
+ const handleSave = () => {
17
+ setCurrentStep('2');
18
+ setTimeout(() => {
19
+ setCurrentStep('3');
20
+ }, 2000);
21
+ };
22
+ const steps = {
23
+ '1': _jsx(StepOne, { onSave: handleSave }),
24
+ '2': (_jsx(SearchItemLoader, { message: "Digitizing receipt\n One moment please\u2026" })),
25
+ '3': _jsx(StepThree, {}),
26
+ };
27
+ return (_jsx(RightPanel, { isOpen: true, onClose: action('onClose'), children: _jsxs(ReceiptContent, { children: [_jsx(PanelHeader, { handleCloseButton: action('onClose'), title: "Add Receipt", icon: Register }), steps[currentStep]] }) }));
28
+ };
29
+ function StepOne({ onSave }) {
30
+ const [value, setValue] = useState('');
31
+ return (_jsxs(_Fragment, { children: [_jsx(Box, { p: "base", bg: "lightBlue.2", children: _jsx(EditItemName, { isRequired: false, placeholder: "Add receipt name", onChange: (e) => setValue(e.target.value), onSave: onSave, showSaveButton: !!value, value: value }) }), _jsx(DynamicForm, { form: receiptFieldsMock, showTitle: false, singleFileUpload: true }), _jsx(Box, { h: "120px" }), _jsx(DrawerFooter, { children: _jsx(FooterDrawer, { isOpen: true, variant: "footerSquare", children: _jsx(FooterButtons, { button1: {
32
+ buttonStyle: 'primaryFooter',
33
+ label: t('buttons.save'),
34
+ onClick: onSave,
35
+ } }) }) })] }));
36
+ }
37
+ function StepThree() {
38
+ return (_jsxs(_Fragment, { children: [_jsxs(ReceiptBody, { children: [_jsx(ReceiptDetails, { _id: "1", cashier: "Rochelle", itemQuantity: 4, paymentMethod: "Debit", purchaseDate: new Date(), tax: "3.17", store: "8418", storePhone: "512.258.7914", total: "41.65" }), _jsx(TabsHeader, { rightButton: _jsx(PdfButton, { onClick: action('Pdf click') }), tabList: [
39
+ {
40
+ label: 'Items',
41
+ component: (_jsx(ReceiptItems, { isSelectDisabled: true, receipts: receiptList, leftOptions: ['Project', 'Room', 'Folder'], rightOptions: ['Kitchen', 'Landscape', 'Bedroom'], receiptOptions: ['unassigned', 'inventory', 'incidentals'], onItemSelectedChange: action('onItemSelectedChange'), onLeftSelectChange: action('onLeftSelectChange'), onReceiptSelectedChange: action('onReceiptSelectedChange'), onRightSelectChange: action('onRightSelectChange') })),
42
+ },
43
+ {
44
+ label: 'Notes',
45
+ component: null,
46
+ },
47
+ ] })] }), _jsx(DrawerFooter, { children: _jsx(FooterDrawer, { isOpen: true, variant: "footerSquare", children: _jsx(FooterButtons, { button1: {
48
+ buttonStyle: 'secondaryFooter',
49
+ label: t('buttons.edit'),
50
+ onClick: action('onEdit'),
51
+ }, button2: {
52
+ buttonStyle: 'primaryFooter',
53
+ label: t('buttons.confirm'),
54
+ onClick: action('onConfirm'),
55
+ } }) }) })] }));
56
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homefile/components-v2",
3
- "version": "2.22.2",
3
+ "version": "2.23.1",
4
4
  "author": "Homefile",
5
5
  "license": "UNLICENSED",
6
6
  "typings": "dist/index.d.ts",
@@ -108,6 +108,7 @@
108
108
  "close": "Close",
109
109
  "done": "Done",
110
110
  "delete": "Delete",
111
+ "edit": "Edit",
111
112
  "forward": "Forward",
112
113
  "next": "Next",
113
114
  "previous": "Previous",
@@ -13,12 +13,13 @@ export const DragDropArea = ({
13
13
  message = t('dragDrop.message'),
14
14
  message2 = t('dragDrop.message2'),
15
15
  variant = 'dragDropDashed',
16
+ multiple = false,
16
17
  }: DragDropAreaI) => {
17
18
  const hasError = !!errorMessage
18
19
  return (
19
20
  <Stack spacing="1">
20
21
  <Container variant={variant} minW="full" h={height} {...getRootProps()}>
21
- <input {...getInputProps()} />
22
+ <input {...getInputProps({ multiple })} />
22
23
  <Flex h={height} align={align} justify="center" p="base">
23
24
  <Flex align="center" direction={direction} gap="2">
24
25
  <Upload />
@@ -35,6 +35,7 @@ export const DynamicForm = ({
35
35
  onUpload,
36
36
  searching = false,
37
37
  showTitle = true,
38
+ singleFileUpload,
38
39
  title,
39
40
  uploadingFieldId,
40
41
  ...props
@@ -48,7 +49,7 @@ export const DynamicForm = ({
48
49
  handleFilesUpload,
49
50
  handleRemove,
50
51
  } = useDynamicForm({ fields, onUpload })
51
-
52
+
52
53
  if (searching) {
53
54
  return <SearchItemLoader />
54
55
  }
@@ -70,6 +71,7 @@ export const DynamicForm = ({
70
71
  <>
71
72
  {visibleFields?.map((field) => {
72
73
  const {
74
+ comments,
73
75
  canBeHidden,
74
76
  children,
75
77
  description,
@@ -182,12 +184,14 @@ export const DynamicForm = ({
182
184
  return (
183
185
  <FieldWithDelete {...fieldWithDeleteBaseProps} key={id}>
184
186
  <FileField
185
- icon={baseProps.icon}
187
+ {...baseProps}
186
188
  description={description}
187
189
  onRemove={onRemoveImage}
188
190
  onUpload={(files) => handleFilesUpload({ id, files })}
189
191
  uploading={uploadingFieldId === id}
190
192
  displayImages={displayImages}
193
+ singleFileUpload={singleFileUpload}
194
+ value={value as string | undefined}
191
195
  />
192
196
  </FieldWithDelete>
193
197
  )
@@ -222,6 +226,7 @@ export const DynamicForm = ({
222
226
  name={name}
223
227
  value={value}
224
228
  description={description}
229
+ comments={comments}
225
230
  />
226
231
  )
227
232
  case 'tile-body':
@@ -3,13 +3,13 @@ import { Box, Text, Stack } from '@chakra-ui/react'
3
3
  import { PuffLoader } from 'react-spinners'
4
4
  import { colors } from '@/theme/colors'
5
5
 
6
- export const SearchItemLoader = () => {
6
+ export const SearchItemLoader = ({ message = t('dynamicForm.searching') }) => {
7
7
  return (
8
8
  <Stack spacing="base" align="center" mt="50px">
9
9
  <PuffLoader color={colors.blue[1]} size={50} />
10
10
  <Box w="40%">
11
- <Text fontSize="sm" textAlign="center">
12
- {t('dynamicForm.searching')}
11
+ <Text fontSize="sm" textAlign="center" whiteSpace="preserve-breaks">
12
+ {message}
13
13
  </Text>
14
14
  </Box>
15
15
  </Stack>
@@ -13,14 +13,16 @@ import {
13
13
  import { Controller, useFormContext } from 'react-hook-form'
14
14
 
15
15
  export const CheckboxAgreement = ({
16
+ comments,
16
17
  description,
17
18
  id,
18
19
  name,
19
20
  value,
20
- }: Pick<ReportI, 'name' | 'id' | 'description' | 'value'>) => {
21
+ }: Pick<ReportI, 'name' | 'id' | 'description' | 'value' | 'comments'>) => {
21
22
  const { control } = useFormContext()
23
+ const collapsed = comments === 'collapsed'
22
24
  return (
23
- <Accordion flex="1" allowToggle defaultIndex={[0]}>
25
+ <Accordion flex="1" allowToggle defaultIndex={collapsed ? [1] : [0]}>
24
26
  <AccordionItem border="none" bg="lightViolet.1">
25
27
  {({ isExpanded }) => (
26
28
  <>
@@ -21,6 +21,7 @@ export const FileField = ({
21
21
  onUpload,
22
22
  uploading = false,
23
23
  displayImages = [],
24
+ singleFileUpload = false,
24
25
  }: FileFieldI) => {
25
26
  const { errorMessage, getInputProps, getRootProps, thumbnails } =
26
27
  useFilesUploader({
@@ -41,6 +42,7 @@ export const FileField = ({
41
42
  getInputProps={getInputProps}
42
43
  getRootProps={getRootProps}
43
44
  height="85px"
45
+ multiple={!singleFileUpload}
44
46
  />
45
47
  <Grid
46
48
  gridTemplateColumns={`repeat(auto-fill, minmax(22px, 1fr))`}
@@ -33,7 +33,7 @@ export const TabsHeader = ({
33
33
  <CustomTab key={label} label={label} />
34
34
  ))}
35
35
  </TabList>
36
- <Flex>
36
+ <Flex flexShrink={0}>
37
37
  <TabList bg="neutral.white" w="full">
38
38
  {rightTabList?.map(({ label }) => (
39
39
  <CustomTab key={label} label={label} />
@@ -65,18 +65,39 @@ export const ReceiptDetails = ({
65
65
  borderBottom="1px solid"
66
66
  borderColor="lightBlue.2"
67
67
  >
68
- <Box bgImg={ReceiptBg} bgRepeat="repeat-x" w="100%" h="10px" />
68
+ <Box
69
+ w="100%"
70
+ h="10px"
71
+ bg="lightBlue.2"
72
+ overflow="hidden"
73
+ position="relative"
74
+ >
75
+ <svg
76
+ width="100%"
77
+ height="8"
78
+ viewBox="0 0 100 10"
79
+ preserveAspectRatio="none"
80
+ style={{ display: 'block', position: 'absolute', bottom: 0, left: 0 }}
81
+ >
82
+ <defs>
83
+ <pattern
84
+ id="triangle"
85
+ width="4"
86
+ height="10"
87
+ patternUnits="userSpaceOnUse"
88
+ >
89
+ <polygon points="0,10 2,0 4,10" fill="white" />
90
+ </pattern>
91
+ </defs>
92
+ <rect width="100%" height="10" fill="url(#triangle)" />
93
+ </svg>
94
+ </Box>
69
95
  <Box bg="neutral.white" px="2" p="base">
70
96
  <Flex align="center" gap="base">
71
97
  <Image src={storeImage} w="75px" h="75px" fit="cover" />
72
98
  <Flex align="center" gap="2" flex="auto">
73
99
  <DetailsColumn details={leftColumn} />
74
- <Divider
75
- orientation="vertical"
76
- bg="lightBlue.2"
77
- h="63px"
78
- mr="6"
79
- />
100
+ <Divider orientation="vertical" bg="lightBlue.2" h="63px" mr="6" />
80
101
  <DetailsColumn align="right" details={rightColumn} />
81
102
  </Flex>
82
103
  </Flex>
@@ -10,5 +10,6 @@ export interface DragDropAreaI {
10
10
  height?: number | string
11
11
  message?: string
12
12
  message2?: string
13
+ multiple?: boolean
13
14
  variant?: 'dragDrop' | 'dragDropDashed'
14
15
  }
@@ -155,6 +155,7 @@ export interface DynamicFormI extends Partial<PartnerFooterI> {
155
155
  onUpload?: (filesByFieldId: Record<string, FolderFileI[] | File[]>) => void
156
156
  searching?: boolean
157
157
  showTitle?: boolean
158
+ singleFileUpload?: boolean
158
159
  title?: string
159
160
  uploadingFieldId?: string
160
161
  }
@@ -5,6 +5,7 @@ export interface FileFieldI extends Pick<ReportI, 'description' | 'icon'> {
5
5
  onUpload?: (files: FolderFileI[]) => void
6
6
  uploading?: boolean
7
7
  displayImages?: string[]
8
+ singleFileUpload?: boolean
8
9
  value?: string
9
10
  }
10
11
 
@@ -1148,3 +1148,100 @@ export const alertFieldsMock3: ReportI[] = [
1148
1148
  type: 'alert',
1149
1149
  },
1150
1150
  ]
1151
+
1152
+ export const receiptFieldsMock: ReportI[] = [
1153
+ {
1154
+ id: faker.database.mongodbObjectId(),
1155
+ name: 'Select to have Homefile use AI & digitize receipt. ',
1156
+ label: 'Find & add information',
1157
+ comments: 'collapsed',
1158
+ description:
1159
+ 'Homefile has an extensive data base of products, but we will also search the web for the most relevant information around products. This includes details like warranty Information, manuals, price, energy info, product ratings, etc. If the item is not in our database, it will populate as soon as we add the info.',
1160
+ value: true,
1161
+ type: 'checkbox-agreement',
1162
+ visible: true,
1163
+ },
1164
+ {
1165
+ id: faker.database.mongodbObjectId(),
1166
+ name: 'Images',
1167
+ description: 'Add picture',
1168
+ comments: '',
1169
+ value: '',
1170
+ type: 'file',
1171
+ canBeHidden: false,
1172
+ },
1173
+ {
1174
+ id: faker.database.mongodbObjectId(),
1175
+ name: 'Receipt',
1176
+ description: faker.lorem.sentence(),
1177
+ comments: faker.lorem.sentence(),
1178
+ value: '',
1179
+ type: 'group',
1180
+ visible: false,
1181
+ icon: 'receipt',
1182
+ children: [
1183
+ {
1184
+ id: faker.database.mongodbObjectId(),
1185
+ name: 'Receipt',
1186
+ label: 'Receipt',
1187
+ description: faker.lorem.sentence(),
1188
+ comments: faker.lorem.sentence(),
1189
+ value: faker.lorem.sentence(),
1190
+ type: 'text',
1191
+ visible: true,
1192
+ icon: 'receipt',
1193
+ },
1194
+ {
1195
+ id: faker.database.mongodbObjectId(),
1196
+ name: 'SKU',
1197
+ label: 'SKU',
1198
+ description: faker.lorem.sentence(),
1199
+ comments: faker.lorem.sentence(),
1200
+ value: faker.lorem.sentence(),
1201
+ type: 'text',
1202
+ visible: true,
1203
+ },
1204
+ {
1205
+ id: faker.database.mongodbObjectId(),
1206
+ name: 'Grid 2',
1207
+ description: faker.lorem.sentence(),
1208
+ comments: faker.lorem.sentence(),
1209
+ value: '',
1210
+ type: 'grid',
1211
+ children: [
1212
+ {
1213
+ id: faker.database.mongodbObjectId(),
1214
+ name: 'Purchase Date',
1215
+ label: 'Purchase Date',
1216
+ description: faker.lorem.sentence(),
1217
+ comments: faker.lorem.sentence(),
1218
+ value: '',
1219
+ type: 'date',
1220
+ visible: true,
1221
+ },
1222
+ {
1223
+ id: faker.database.mongodbObjectId(),
1224
+ name: '$ Amount Paid',
1225
+ label: '$ Amount Paid',
1226
+ description: faker.lorem.sentence(),
1227
+ comments: faker.lorem.sentence(),
1228
+ value: faker.finance.amount({ min: 10, max: 100 }),
1229
+ type: 'currency',
1230
+ visible: true,
1231
+ },
1232
+ ],
1233
+ visible: true,
1234
+ },
1235
+ ],
1236
+ },
1237
+ {
1238
+ id: faker.database.mongodbObjectId(),
1239
+ name: 'Notes',
1240
+ description: faker.lorem.sentence(),
1241
+ comments: faker.lorem.sentence(),
1242
+ value: faker.lorem.text(),
1243
+ type: 'textarea',
1244
+ visible: false,
1245
+ icon: 'notes',
1246
+ },
1247
+ ]
@@ -0,0 +1,160 @@
1
+ import { Meta } from '@storybook/react'
2
+ import { action } from '@storybook/addon-actions'
3
+ import {
4
+ RightPanel,
5
+ ReceiptContent,
6
+ ReceiptItems,
7
+ ReceiptDetails,
8
+ TabsHeader,
9
+ PdfButton,
10
+ PanelHeader,
11
+ DynamicForm,
12
+ EditItemName,
13
+ ReceiptBody,
14
+ SearchItemLoader,
15
+ FooterButtons,
16
+ FooterDrawer,
17
+ } from '@/components'
18
+ import { receiptList } from '@/helpers'
19
+ import { Register } from '@/assets/images'
20
+ import { ReceiptContentI } from '@/interfaces'
21
+ import { receiptFieldsMock } from '@/mocks'
22
+ import { ReactNode, useState } from 'react'
23
+ import { Box, DrawerBody, DrawerContent, DrawerFooter } from '@chakra-ui/react'
24
+ import { t } from 'i18next'
25
+
26
+ export default {
27
+ title: 'Components/Receipts/Receipt',
28
+ component: ReceiptContent,
29
+ } as Meta<ReceiptContentI>
30
+
31
+ export const AddReceiptPanel = () => {
32
+ const [currentStep, setCurrentStep] = useState('1')
33
+ const handleSave = () => {
34
+ setCurrentStep('2')
35
+ setTimeout(() => {
36
+ setCurrentStep('3')
37
+ }, 2000)
38
+ }
39
+ const steps: Record<string, ReactNode> = {
40
+ '1': <StepOne onSave={handleSave} />,
41
+ '2': (
42
+ <SearchItemLoader
43
+ message="Digitizing receipt
44
+ One moment please…"
45
+ />
46
+ ),
47
+ '3': <StepThree />,
48
+ }
49
+ return (
50
+ <RightPanel isOpen onClose={action('onClose')}>
51
+ <ReceiptContent>
52
+ <PanelHeader
53
+ handleCloseButton={action('onClose')}
54
+ title="Add Receipt"
55
+ icon={Register}
56
+ />
57
+
58
+ {steps[currentStep]}
59
+ </ReceiptContent>
60
+ </RightPanel>
61
+ )
62
+ }
63
+
64
+ function StepOne({ onSave }: { onSave: () => void }) {
65
+ const [value, setValue] = useState('')
66
+ return (
67
+ <>
68
+ <Box p="base" bg="lightBlue.2">
69
+ <EditItemName
70
+ isRequired={false}
71
+ placeholder="Add receipt name"
72
+ onChange={(e) => setValue(e.target.value)}
73
+ onSave={onSave}
74
+ showSaveButton={!!value}
75
+ value={value}
76
+ />
77
+ </Box>
78
+
79
+ <DynamicForm
80
+ form={receiptFieldsMock}
81
+ showTitle={false}
82
+ singleFileUpload
83
+ />
84
+ <Box h="120px" />
85
+ <DrawerFooter>
86
+ <FooterDrawer isOpen variant="footerSquare">
87
+ <FooterButtons
88
+ button1={{
89
+ buttonStyle: 'primaryFooter',
90
+ label: t('buttons.save'),
91
+ onClick: onSave,
92
+ }}
93
+ />
94
+ </FooterDrawer>
95
+ </DrawerFooter>
96
+ </>
97
+ )
98
+ }
99
+
100
+ function StepThree() {
101
+ return (
102
+ <>
103
+ <ReceiptBody>
104
+ <ReceiptDetails
105
+ _id="1"
106
+ cashier="Rochelle"
107
+ itemQuantity={4}
108
+ paymentMethod="Debit"
109
+ purchaseDate={new Date()}
110
+ tax="3.17"
111
+ store="8418"
112
+ storePhone="512.258.7914"
113
+ total="41.65"
114
+ />
115
+
116
+ <TabsHeader
117
+ rightButton={<PdfButton onClick={action('Pdf click')} />}
118
+ tabList={[
119
+ {
120
+ label: 'Items',
121
+ component: (
122
+ <ReceiptItems
123
+ isSelectDisabled={true}
124
+ receipts={receiptList}
125
+ leftOptions={['Project', 'Room', 'Folder']}
126
+ rightOptions={['Kitchen', 'Landscape', 'Bedroom']}
127
+ receiptOptions={['unassigned', 'inventory', 'incidentals']}
128
+ onItemSelectedChange={action('onItemSelectedChange')}
129
+ onLeftSelectChange={action('onLeftSelectChange')}
130
+ onReceiptSelectedChange={action('onReceiptSelectedChange')}
131
+ onRightSelectChange={action('onRightSelectChange')}
132
+ />
133
+ ),
134
+ },
135
+ {
136
+ label: 'Notes',
137
+ component: null,
138
+ },
139
+ ]}
140
+ />
141
+ </ReceiptBody>
142
+ <DrawerFooter>
143
+ <FooterDrawer isOpen variant="footerSquare">
144
+ <FooterButtons
145
+ button1={{
146
+ buttonStyle: 'secondaryFooter',
147
+ label: t('buttons.edit'),
148
+ onClick: action('onEdit'),
149
+ }}
150
+ button2={{
151
+ buttonStyle: 'primaryFooter',
152
+ label: t('buttons.confirm'),
153
+ onClick: action('onConfirm'),
154
+ }}
155
+ />
156
+ </FooterDrawer>
157
+ </DrawerFooter>
158
+ </>
159
+ )
160
+ }