@homefile/components-v2 2.22.2 → 2.23.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.
@@ -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",
@@ -24,7 +24,7 @@ export const DynamicForm = (_a) => {
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,
@@ -83,7 +83,7 @@ export const DynamicForm = (_a) => {
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,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
  };
@@ -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 }), _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.0",
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",
@@ -48,7 +48,7 @@ export const DynamicForm = ({
48
48
  handleFilesUpload,
49
49
  handleRemove,
50
50
  } = useDynamicForm({ fields, onUpload })
51
-
51
+
52
52
  if (searching) {
53
53
  return <SearchItemLoader />
54
54
  }
@@ -70,6 +70,7 @@ export const DynamicForm = ({
70
70
  <>
71
71
  {visibleFields?.map((field) => {
72
72
  const {
73
+ comments,
73
74
  canBeHidden,
74
75
  children,
75
76
  description,
@@ -222,6 +223,7 @@ export const DynamicForm = ({
222
223
  name={name}
223
224
  value={value}
224
225
  description={description}
226
+ comments={comments}
225
227
  />
226
228
  )
227
229
  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
  <>
@@ -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>
@@ -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,156 @@
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 form={receiptFieldsMock} showTitle={false} />
80
+ <Box h="120px" />
81
+ <DrawerFooter>
82
+ <FooterDrawer isOpen variant="footerSquare">
83
+ <FooterButtons
84
+ button1={{
85
+ buttonStyle: 'primaryFooter',
86
+ label: t('buttons.save'),
87
+ onClick: onSave,
88
+ }}
89
+ />
90
+ </FooterDrawer>
91
+ </DrawerFooter>
92
+ </>
93
+ )
94
+ }
95
+
96
+ function StepThree() {
97
+ return (
98
+ <>
99
+ <ReceiptBody>
100
+ <ReceiptDetails
101
+ _id="1"
102
+ cashier="Rochelle"
103
+ itemQuantity={4}
104
+ paymentMethod="Debit"
105
+ purchaseDate={new Date()}
106
+ tax="3.17"
107
+ store="8418"
108
+ storePhone="512.258.7914"
109
+ total="41.65"
110
+ />
111
+
112
+ <TabsHeader
113
+ rightButton={<PdfButton onClick={action('Pdf click')} />}
114
+ tabList={[
115
+ {
116
+ label: 'Items',
117
+ component: (
118
+ <ReceiptItems
119
+ isSelectDisabled={true}
120
+ receipts={receiptList}
121
+ leftOptions={['Project', 'Room', 'Folder']}
122
+ rightOptions={['Kitchen', 'Landscape', 'Bedroom']}
123
+ receiptOptions={['unassigned', 'inventory', 'incidentals']}
124
+ onItemSelectedChange={action('onItemSelectedChange')}
125
+ onLeftSelectChange={action('onLeftSelectChange')}
126
+ onReceiptSelectedChange={action('onReceiptSelectedChange')}
127
+ onRightSelectChange={action('onRightSelectChange')}
128
+ />
129
+ ),
130
+ },
131
+ {
132
+ label: 'Notes',
133
+ component: null,
134
+ },
135
+ ]}
136
+ />
137
+ </ReceiptBody>
138
+ <DrawerFooter>
139
+ <FooterDrawer isOpen variant="footerSquare">
140
+ <FooterButtons
141
+ button1={{
142
+ buttonStyle: 'secondaryFooter',
143
+ label: t('buttons.edit'),
144
+ onClick: action('onEdit'),
145
+ }}
146
+ button2={{
147
+ buttonStyle: 'primaryFooter',
148
+ label: t('buttons.confirm'),
149
+ onClick: action('onConfirm'),
150
+ }}
151
+ />
152
+ </FooterDrawer>
153
+ </DrawerFooter>
154
+ </>
155
+ )
156
+ }