@homefile/components-v2 2.59.1 → 2.60.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 (171) hide show
  1. package/dist/assets/locales/en/index.json +5 -2
  2. package/dist/components/folderPanel/displayFiles/GridFile.js +9 -1
  3. package/dist/components/folderPanel/displayFiles/ListFile.js +9 -1
  4. package/dist/components/forms/dynamicForm/DynamicForm.js +1 -1
  5. package/dist/components/forms/dynamicForm/HiddenField.js +2 -2
  6. package/dist/components/forms/dynamicForm/fields/HomeInitialSetup.js +3 -1
  7. package/dist/components/forms/readOnly/ReadOnlyDynamicForm.js +10 -2
  8. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyAppliances.js +21 -22
  9. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyGuidelines.js +6 -3
  10. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyHistory.d.ts +2 -0
  11. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyHistory.js +35 -0
  12. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyItemRelated.js +8 -3
  13. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyOverview.d.ts +2 -0
  14. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyOverview.js +16 -0
  15. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyPurchaseDetails.d.ts +2 -0
  16. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyPurchaseDetails.js +30 -0
  17. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyWarrantyBanner.d.ts +2 -0
  18. package/dist/components/forms/readOnly/fields/homeItem/ReadOnlyWarrantyBanner.js +42 -0
  19. package/dist/components/forms/readOnly/fields/homeItem/index.d.ts +4 -0
  20. package/dist/components/forms/readOnly/fields/homeItem/index.js +4 -0
  21. package/dist/components/headers/TabsHeader.js +1 -1
  22. package/dist/components/history/AddDocuments.d.ts +7 -0
  23. package/dist/components/history/AddDocuments.js +8 -0
  24. package/dist/components/history/DatePennant.d.ts +7 -0
  25. package/dist/components/history/DatePennant.js +6 -0
  26. package/dist/components/history/HistoryCard.d.ts +19 -0
  27. package/dist/components/history/HistoryCard.js +13 -0
  28. package/dist/components/history/index.d.ts +3 -0
  29. package/dist/components/history/index.js +3 -0
  30. package/dist/components/homeBoard/AddToHomefile.js +1 -1
  31. package/dist/components/homeBoard/HomeCard.js +1 -1
  32. package/dist/components/homeItems/ViewingHomeItemBody.d.ts +2 -0
  33. package/dist/components/homeItems/ViewingHomeItemBody.js +41 -0
  34. package/dist/components/homeItems/ViewingHomeItemPanel.js +17 -19
  35. package/dist/components/homeItems/index.d.ts +1 -0
  36. package/dist/components/homeItems/index.js +1 -0
  37. package/dist/components/homi/HomiPresence.d.ts +2 -0
  38. package/dist/components/homi/HomiPresence.js +31 -0
  39. package/dist/components/homi/HomiVoice.d.ts +2 -0
  40. package/dist/components/homi/HomiVoice.js +6 -0
  41. package/dist/components/homi/ProgressBar.d.ts +2 -0
  42. package/dist/components/homi/ProgressBar.js +9 -0
  43. package/dist/components/homi/RevealValueCard.d.ts +2 -0
  44. package/dist/components/homi/RevealValueCard.js +23 -0
  45. package/dist/components/homi/StaggerReveal.d.ts +2 -0
  46. package/dist/components/homi/StaggerReveal.js +29 -0
  47. package/dist/components/homi/index.d.ts +5 -0
  48. package/dist/components/homi/index.js +5 -0
  49. package/dist/components/inboxTile/InboxForwardBanner.js +1 -1
  50. package/dist/components/index.d.ts +2 -0
  51. package/dist/components/index.js +2 -0
  52. package/dist/components/inputs/InlineEditField.d.ts +2 -0
  53. package/dist/components/inputs/InlineEditField.js +15 -0
  54. package/dist/components/inputs/RadioCard.d.ts +3 -1
  55. package/dist/components/inputs/RadioCard.js +3 -3
  56. package/dist/components/inputs/TextInput.d.ts +1 -1
  57. package/dist/components/inputs/TextInput.js +11 -4
  58. package/dist/components/inputs/index.d.ts +1 -0
  59. package/dist/components/inputs/index.js +1 -0
  60. package/dist/components/myHomes/HomeDetailsContent.js +1 -1
  61. package/dist/components/myHomes/IncludePublicRecords.d.ts +13 -1
  62. package/dist/components/myHomes/IncludePublicRecords.js +16 -6
  63. package/dist/components/myHomes/edithome/EditHomeDetails.js +12 -3
  64. package/dist/components/myHomes/steps/NewHomeDetails.d.ts +1 -1
  65. package/dist/components/myHomes/steps/NewHomeDetails.js +3 -3
  66. package/dist/components/myProfile/MyProfileBody.d.ts +1 -1
  67. package/dist/components/myProfile/MyProfileBody.js +2 -2
  68. package/dist/components/myProfile/details/HomiSms.d.ts +1 -1
  69. package/dist/components/myProfile/details/HomiSms.js +53 -23
  70. package/dist/components/myProfile/details/TwoFactorSetting.js +2 -1
  71. package/dist/components/propertyTiles/propertyTaxes/PropertyTaxes.js +1 -1
  72. package/dist/components/propertyTiles/trendingValue/TrendingValue.js +1 -1
  73. package/dist/components/rooms/RoomHeader.d.ts +1 -1
  74. package/dist/components/rooms/RoomHeader.js +3 -3
  75. package/dist/components/wizard/ControlledWizard.d.ts +1 -1
  76. package/dist/components/wizard/ControlledWizard.js +42 -3
  77. package/dist/components/wizard/WizardInitialOptions.js +3 -3
  78. package/dist/components/wizard/WizardSelectCard.d.ts +14 -0
  79. package/dist/components/wizard/WizardSelectCard.js +32 -0
  80. package/dist/components/wizard/WizardStepPrompt.d.ts +11 -0
  81. package/dist/components/wizard/WizardStepPrompt.js +20 -0
  82. package/dist/components/wizard/WizardSuccessHeader.d.ts +1 -1
  83. package/dist/components/wizard/WizardSuccessHeader.js +2 -2
  84. package/dist/components/wizard/index.d.ts +2 -0
  85. package/dist/components/wizard/index.js +2 -0
  86. package/dist/helpers/forms/dynamicForm.helper.js +4 -0
  87. package/dist/hooks/folderPanel/useDisplayFiles.js +11 -2
  88. package/dist/hooks/forms/useAddressStored.js +8 -2
  89. package/dist/hooks/index.d.ts +2 -0
  90. package/dist/hooks/index.js +2 -0
  91. package/dist/hooks/motion/index.d.ts +2 -0
  92. package/dist/hooks/motion/index.js +2 -0
  93. package/dist/hooks/motion/useCountUp.d.ts +10 -0
  94. package/dist/hooks/motion/useCountUp.js +39 -0
  95. package/dist/hooks/motion/usePrefersReducedMotion.d.ts +14 -0
  96. package/dist/hooks/motion/usePrefersReducedMotion.js +15 -0
  97. package/dist/hooks/rooms/useRoomHeader.d.ts +4 -1
  98. package/dist/hooks/rooms/useRoomHeader.js +9 -1
  99. package/dist/hooks/useDirtySave.d.ts +14 -0
  100. package/dist/hooks/useDirtySave.js +33 -0
  101. package/dist/index.d.ts +3 -3
  102. package/dist/index.js +3 -3
  103. package/dist/interfaces/forms/dynamicForm/DynamicForm.interface.d.ts +7 -3
  104. package/dist/interfaces/forms/readOnly/homeItem/ReadOnlyOverview.interface.d.ts +2 -0
  105. package/dist/interfaces/forms/readOnly/homeItem/ReadOnlyOverview.interface.js +1 -0
  106. package/dist/interfaces/forms/readOnly/homeItem/ReadOnlyPurchaseDetails.interface.d.ts +5 -0
  107. package/dist/interfaces/forms/readOnly/homeItem/ReadOnlyPurchaseDetails.interface.js +1 -0
  108. package/dist/interfaces/forms/readOnly/homeItem/ReadOnlyWarrantyBanner.interface.d.ts +27 -0
  109. package/dist/interfaces/forms/readOnly/homeItem/ReadOnlyWarrantyBanner.interface.js +1 -0
  110. package/dist/interfaces/forms/readOnly/homeItem/index.d.ts +3 -0
  111. package/dist/interfaces/forms/readOnly/homeItem/index.js +3 -0
  112. package/dist/interfaces/homeItems/ViewingHomeItemPanel.interface.d.ts +1 -0
  113. package/dist/interfaces/homi/HomiPresence.interface.d.ts +9 -0
  114. package/dist/interfaces/homi/HomiPresence.interface.js +1 -0
  115. package/dist/interfaces/homi/ProgressBar.interface.d.ts +8 -0
  116. package/dist/interfaces/homi/ProgressBar.interface.js +1 -0
  117. package/dist/interfaces/homi/RevealValueCard.interface.d.ts +16 -0
  118. package/dist/interfaces/homi/RevealValueCard.interface.js +1 -0
  119. package/dist/interfaces/homi/StaggerReveal.interface.d.ts +9 -0
  120. package/dist/interfaces/homi/StaggerReveal.interface.js +1 -0
  121. package/dist/interfaces/homi/index.d.ts +4 -0
  122. package/dist/interfaces/homi/index.js +4 -0
  123. package/dist/interfaces/index.d.ts +1 -0
  124. package/dist/interfaces/index.js +1 -0
  125. package/dist/interfaces/inputs/InlineEditField.interface.d.ts +7 -0
  126. package/dist/interfaces/inputs/InlineEditField.interface.js +1 -0
  127. package/dist/interfaces/inputs/Input.interface.d.ts +6 -1
  128. package/dist/interfaces/inputs/index.d.ts +1 -0
  129. package/dist/interfaces/inputs/index.js +1 -0
  130. package/dist/interfaces/myHomes/AddHomeContent.interface.d.ts +3 -0
  131. package/dist/interfaces/myProfile/MyProfileBody.interface.d.ts +1 -0
  132. package/dist/interfaces/myProfile/details/HomiSms.interface.d.ts +11 -2
  133. package/dist/interfaces/rooms/RoomHeader.interface.d.ts +5 -0
  134. package/dist/interfaces/wizard/ControlledWizard.interface.d.ts +6 -0
  135. package/dist/interfaces/wizard/WizardStepPrompt.interface.d.ts +9 -0
  136. package/dist/interfaces/wizard/WizardStepPrompt.interface.js +1 -0
  137. package/dist/interfaces/wizard/index.d.ts +1 -0
  138. package/dist/interfaces/wizard/index.js +1 -0
  139. package/dist/stories/forms/readOnly/ReadOnlyAppliances.stories.d.ts +4 -0
  140. package/dist/stories/forms/readOnly/ReadOnlyAppliances.stories.js +33 -0
  141. package/dist/stories/forms/readOnly/ReadOnlyWarrantyBanner.stories.d.ts +4 -0
  142. package/dist/stories/forms/readOnly/ReadOnlyWarrantyBanner.stories.js +10 -0
  143. package/dist/stories/homeItems/ReadOnlyHistory.stories.d.ts +4 -0
  144. package/dist/stories/homeItems/ReadOnlyHistory.stories.js +46 -0
  145. package/dist/stories/homeItems/ReadOnlyOverview.stories.d.ts +5 -0
  146. package/dist/stories/homeItems/ReadOnlyOverview.stories.js +69 -0
  147. package/dist/stories/homeItems/ViewingHomeItemPanel.stories.d.ts +4 -0
  148. package/dist/stories/homeItems/ViewingHomeItemPanel.stories.js +204 -0
  149. package/dist/stories/homi/HomiPresence.stories.d.ts +18 -0
  150. package/dist/stories/homi/HomiPresence.stories.js +11 -0
  151. package/dist/stories/homi/HomiVoice.stories.d.ts +4 -0
  152. package/dist/stories/homi/HomiVoice.stories.js +8 -0
  153. package/dist/stories/homi/ProgressBar.stories.d.ts +10 -0
  154. package/dist/stories/homi/ProgressBar.stories.js +9 -0
  155. package/dist/stories/homi/RevealValueCard.stories.d.ts +19 -0
  156. package/dist/stories/homi/RevealValueCard.stories.js +22 -0
  157. package/dist/stories/homi/StaggerReveal.stories.d.ts +5 -0
  158. package/dist/stories/homi/StaggerReveal.stories.js +8 -0
  159. package/dist/stories/inputs/InlineEditField.stories.d.ts +10 -0
  160. package/dist/stories/inputs/InlineEditField.stories.js +11 -0
  161. package/dist/stories/myProfile/MyProfilePanel.stories.js +1 -1
  162. package/dist/stories/myProfile/details/HomiSms.stories.d.ts +3 -2
  163. package/dist/stories/myProfile/details/HomiSms.stories.js +3 -2
  164. package/dist/stories/wizard/ControlledWizard.stories.d.ts +9 -0
  165. package/dist/stories/wizard/ControlledWizard.stories.js +41 -60
  166. package/dist/theme/index.d.ts +3 -0
  167. package/dist/theme/index.js +7 -4
  168. package/dist/utils/Formaters.utils.d.ts +2 -0
  169. package/dist/utils/Formaters.utils.js +14 -0
  170. package/dist/utils/Weather.utils.js +11 -4
  171. package/package.json +1 -1
@@ -546,7 +546,7 @@
546
546
  "title": "You are viewing "
547
547
  },
548
548
  "details": {
549
- "header": "Homefile Summary",
549
+ "header": "Edit Home",
550
550
  "tabs": {
551
551
  "tab1": "Details",
552
552
  "tab2": "Projects",
@@ -558,6 +558,7 @@
558
558
  "title": "Let’s add your first home."
559
559
  },
560
560
  "form": {
561
+ "editHomeName": "Home Name",
561
562
  "externalLink": "Add optional external link",
562
563
  "homeName": "Name your home",
563
564
  "name": "Name or Project Number",
@@ -626,6 +627,7 @@
626
627
  "2FactorSubtitle": "Select how you would like to receive your 2FA codes. These codes keep your account secure.",
627
628
  "2FactorTitle": "2 Factor Authentication (2FA)",
628
629
  "homiSmsAlt": "Homi SMS",
630
+ "homiSmsConsent": "SMS messaging consent & terms",
629
631
  "homiSmsSubtitle": "Enable SMS messaging to interact with Homi without a mobile app. Text images, documents, and information directly into Homefile so Homi can capture and organize it for you automatically.",
630
632
  "homiSmsTitle": "Enable Homi SMS Messaging"
631
633
  },
@@ -1062,7 +1064,8 @@
1062
1064
  "title": "Reset your Password"
1063
1065
  },
1064
1066
  "roomHeader": {
1065
- "roomValue": "Est room value",
1067
+ "estValue": "Est. value",
1068
+ "roomValue": "Room value",
1066
1069
  "saveBtn": "Save"
1067
1070
  },
1068
1071
  "rooms": {
@@ -14,15 +14,23 @@ import { Button, Image, Text, Box, WrapItem, Stack } from '@chakra-ui/react';
14
14
  import { IconMenuWithMove, MoreHorizontal } from '../../../components';
15
15
  import { DocIcon } from '../../../assets/images';
16
16
  import { fileTypes, getFileExtension } from '../../../helpers';
17
+ import { useDisplayFiles } from '../../../hooks';
17
18
  export const GridFile = (_a) => {
18
19
  var { menu = [], onClick, onMove } = _a, props = __rest(_a, ["menu", "onClick", "onMove"]);
19
20
  const { _id, title, updatedAt, files = [], receipt, report } = props;
20
21
  const fileExtension = getFileExtension(files, !!receipt);
22
+ // Real image thumbnail (empty string for non-images); falls back to the icon.
23
+ const { imageUrl } = useDisplayFiles({ files, title });
24
+ const typeIcon = report && report.length > 0 && !receipt
25
+ ? DocIcon
26
+ : fileTypes[fileExtension] || DocIcon;
21
27
  const itemForm = {
22
28
  _id,
23
29
  name: title || '',
24
30
  updatedAt,
25
31
  icon: fileTypes[fileExtension] || DocIcon,
26
32
  };
27
- return (_jsxs(WrapItem, { maxW: "7rem", position: "relative", children: [_jsx(Box, { position: "absolute", top: "0", right: "1", zIndex: "docked", children: _jsx(IconMenuWithMove, { disabled: menu.length < 1 ? true : false, icon: _jsx(MoreHorizontal, { size: 28 }), itemForm: itemForm, menuItems: menu, onMove: () => onMove(itemForm) }) }), _jsx(Button, { variant: "folder", px: "base", pb: "base", pt: "6", onClick: () => onClick(props), children: _jsxs(Stack, { spacing: "1", align: "center", children: [_jsx(Image, { src: (report && report.length > 0 && !receipt) ? DocIcon : fileTypes[fileExtension] || DocIcon, w: "46px", h: "49px", alt: fileExtension, transition: "all 0.2s ease-in-out" }), _jsxs(Box, { children: [_jsx(Text, { isTruncated: true, maxWidth: "5rem", fontSize: "sm", children: title }), _jsx(Text, { variant: "date", children: updatedAt })] })] }) })] }));
33
+ return (_jsxs(WrapItem, { maxW: "7rem", position: "relative", children: [_jsx(Box, { position: "absolute", top: "0", right: "1", zIndex: "docked", children: _jsx(IconMenuWithMove, { disabled: menu.length < 1 ? true : false, icon: _jsx(MoreHorizontal, { size: 28 }), itemForm: itemForm, menuItems: menu, onMove: () => onMove(itemForm) }) }), _jsx(Button, { variant: "folder", px: "base", pb: "base", pt: "6", onClick: () => onClick(props), children: _jsxs(Stack, { spacing: "1", align: "center", children: [_jsx(Image, Object.assign({ src: imageUrl || typeIcon, fallbackSrc: typeIcon }, (imageUrl
34
+ ? { boxSize: '72px', objectFit: 'cover', borderRadius: 'base' }
35
+ : { w: '46px', h: '49px' }), { alt: fileExtension, transition: "all 0.2s ease-in-out" })), _jsxs(Box, { children: [_jsx(Text, { isTruncated: true, maxWidth: "5rem", fontSize: "sm", children: title }), _jsx(Text, { variant: "date", children: updatedAt })] })] }) })] }));
28
36
  };
@@ -14,15 +14,23 @@ import { Image, Text, Box, Flex } from '@chakra-ui/react';
14
14
  import { IconMenuWithMove, MoreHorizontal } from '../../../components';
15
15
  import { DocIcon } from '../../../assets/images';
16
16
  import { fileTypes, getFileExtension } from '../../../helpers';
17
+ import { useDisplayFiles } from '../../../hooks';
17
18
  export const ListFile = (_a) => {
18
19
  var { menu = [], onClick, onMove } = _a, props = __rest(_a, ["menu", "onClick", "onMove"]);
19
20
  const { _id, title, updatedAt, files = [], receipt, report } = props;
20
21
  const fileExtension = getFileExtension(files, !!receipt);
22
+ // Real image thumbnail (empty string for non-images); falls back to the icon.
23
+ const { imageUrl } = useDisplayFiles({ files, title });
24
+ const typeIcon = report && report.length > 0 && !receipt
25
+ ? DocIcon
26
+ : fileTypes[fileExtension] || DocIcon;
21
27
  const itemForm = {
22
28
  _id,
23
29
  name: title || '',
24
30
  updatedAt,
25
31
  icon: fileTypes[fileExtension] || DocIcon,
26
32
  };
27
- return (_jsx(Box, { bg: "neutral.white", w: "100%", transition: "all 0.2s ease-in-out", _hover: { bg: 'lightGreen.1' }, children: _jsxs(Flex, { children: [_jsxs(Flex, { gap: "base", p: "base", as: "button", flex: "1", onClick: () => onClick(props), children: [_jsx(Image, { src: (report && report.length > 0 && !receipt) ? DocIcon : fileTypes[fileExtension] || DocIcon, minW: "32px", h: "auto", alt: fileExtension, transition: "all 0.2s ease-in-out" }), _jsxs(Box, { mt: "-1", children: [_jsx(Text, { variant: "date", textTransform: "uppercase", textAlign: "left", children: fileExtension === '' ? 'Doc' : fileExtension }), _jsx(Text, { textOverflow: "ellipsis", noOfLines: 1, fontSize: "sm", textAlign: "left", children: title })] })] }), _jsxs(Flex, { align: "center", gap: "2", h: "fit-content", p: "1", pr: "base", children: [_jsx(Text, { variant: "date", w: "fit-content", children: updatedAt }), _jsx(IconMenuWithMove, { disabled: menu.length < 1 ? true : false, icon: _jsx(MoreHorizontal, { size: 28 }), itemForm: itemForm, menuItems: menu, onMove: () => onMove(itemForm) })] })] }) }));
33
+ return (_jsx(Box, { bg: "neutral.white", w: "100%", transition: "all 0.2s ease-in-out", _hover: { bg: 'lightGreen.1' }, children: _jsxs(Flex, { children: [_jsxs(Flex, { gap: "base", p: "base", as: "button", flex: "1", onClick: () => onClick(props), children: [_jsx(Image, Object.assign({ src: imageUrl || typeIcon, fallbackSrc: typeIcon }, (imageUrl
34
+ ? { boxSize: '40px', objectFit: 'cover', borderRadius: 'base' }
35
+ : { minW: '32px', h: 'auto' }), { alt: fileExtension, transition: "all 0.2s ease-in-out" })), _jsxs(Box, { mt: "-1", children: [_jsx(Text, { variant: "date", textTransform: "uppercase", textAlign: "left", children: fileExtension === '' ? 'Doc' : fileExtension }), _jsx(Text, { textOverflow: "ellipsis", noOfLines: 1, fontSize: "sm", textAlign: "left", children: title })] })] }), _jsxs(Flex, { align: "center", gap: "2", h: "fit-content", p: "1", pr: "base", children: [_jsx(Text, { variant: "date", w: "fit-content", children: updatedAt }), _jsx(IconMenuWithMove, { disabled: menu.length < 1 ? true : false, icon: _jsx(MoreHorizontal, { size: 28 }), itemForm: itemForm, menuItems: menu, onMove: () => onMove(itemForm) })] })] }) }));
28
36
  };
@@ -23,7 +23,7 @@ export const DynamicForm = (_a) => {
23
23
  if (searching) {
24
24
  return _jsx(SearchItemLoader, {});
25
25
  }
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) => {
26
+ return (_jsxs(Stack, { bg: props.style === 'wizard' ? 'transparent' : 'lightBlue.1', spacing: "0", h: "full", overflowX: props.style === 'wizard' ? 'visible' : '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
27
  const { comments, canBeHidden, children, description, icon, id, name, label, options, type, value, } = field;
28
28
  const baseProps = {
29
29
  id,
@@ -4,7 +4,7 @@ import { Plus } from '../../../components';
4
4
  import { colors } from '../../../theme/colors';
5
5
  export const HiddenField = ({ disabled, h = '80px', icon, id, isActive, name, onClick, showPlusIcon = false, }) => {
6
6
  const handleClick = () => onClick(id);
7
- return (_jsxs(Box, { position: "relative", children: [_jsxs(Center, { as: "button", disabled: disabled, bg: "neutral.white", borderRadius: "4px", w: "100%", h: h, boxShadow: "md", flexDirection: "column", onClick: handleClick, gap: "1", transition: "all .2s ease-in-out", border: "1px solid", borderColor: isActive ? 'blue.1' : 'transparent', _hover: {
7
+ return (_jsxs(Box, { position: "relative", children: [_jsxs(Center, { as: "button", disabled: disabled, bg: "neutral.white", borderRadius: "4px", w: "100%", h: h, boxShadow: "md", flexDirection: "column", onClick: handleClick, gap: "1", py: "2", px: "1", transition: "all .2s ease-in-out", border: "1px solid", borderColor: isActive ? 'blue.1' : 'transparent', _hover: {
8
8
  borderColor: 'blue.1',
9
9
  }, _disabled: {
10
10
  opacity: 0.5,
@@ -13,5 +13,5 @@ export const HiddenField = ({ disabled, h = '80px', icon, id, isActive, name, on
13
13
  },
14
14
  }, _active: {
15
15
  boxShadow: 'md',
16
- }, children: [_jsx(Image, { h: "22px", w: "auto", maxW: "28px", src: icon }), _jsx(Text, { textTransform: "uppercase", fontSize: "xs", noOfLines: 2, overflow: "hidden", lineHeight: "1", width: "100%", children: name })] }), showPlusIcon && (_jsx(Box, { position: "absolute", top: "1", left: "1", children: _jsx(Plus, { size: 14, stroke: colors.blue[3] }) }))] }));
16
+ }, children: [_jsx(Center, { flex: "1", children: _jsx(Image, { h: "28px", w: "auto", maxW: "36px", src: icon }) }), _jsx(Text, { fontFamily: "primary", color: "gray.3", textTransform: "uppercase", fontSize: "12px", noOfLines: 2, overflow: "hidden", lineHeight: "1", width: "100%", children: name })] }), showPlusIcon && (_jsx(Box, { position: "absolute", top: "1", left: "1", children: _jsx(Plus, { size: 14, stroke: colors.blue[3] }) }))] }));
17
17
  };
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Stack } from '@chakra-ui/react';
3
- import { WizardTextBody, WizardInitialOptions, WizardStepOptions, } from '../../../../components';
3
+ import { WizardTextBody, WizardInitialOptions, WizardStepOptions, WizardSelectCard, } from '../../../../components';
4
4
  export const HomeInitialSetup = ({ fields, callback, style }) => {
5
5
  // const isWizard = style === 'wizard'
6
6
  return (_jsx(Stack, { bg: "neutral.white", spacing: { base: '6', md: '0' }, children: fields === null || fields === void 0 ? void 0 : fields.map(({ children = [], id, label = '', type, value, description }) => {
@@ -11,6 +11,8 @@ export const HomeInitialSetup = ({ fields, callback, style }) => {
11
11
  return (_jsx(WizardInitialOptions, { form: children, title: String(value), callback: callback, style: style }, id));
12
12
  case 'home-wizard-step-options':
13
13
  return (_jsx(WizardStepOptions, { form: children, title: String(value), callback: callback, style: style }, id));
14
+ case 'home-wizard-select-card':
15
+ return (_jsx(WizardSelectCard, { form: children, title: String(value), callback: callback, style: style }, id));
14
16
  default:
15
17
  return null;
16
18
  }
@@ -1,7 +1,7 @@
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, ReadOnlyCollapsible, ReadOnlyDate, ReadOnlyGrid, ReadOnlyGroup, ReadOnlyInput, ReadOnlyNotes, ReadOnlyRating, ReadOnlyTextArea, } from '../../../components';
4
+ import { ReadOnlyAppliances, ReadOnlyCollapsible, ReadOnlyDate, ReadOnlyGrid, ReadOnlyGroup, ReadOnlyInput, ReadOnlyHistory, ReadOnlyNotes, ReadOnlyOverview, ReadOnlyPurchaseDetails, ReadOnlyRating, ReadOnlyTextArea, ReadOnlyWarrantyBanner, } from '../../../components';
5
5
  import { fieldIcons } from '../../../helpers';
6
6
  /**
7
7
  * Coerce a field value into something safe to render. A malformed value that
@@ -51,7 +51,7 @@ export const ReadOnlyDynamicForm = ({ form: fields, onClick, onEdit, }) => {
51
51
  case 'textarea':
52
52
  return (_createElement(ReadOnlyTextArea, Object.assign({}, baseProps, { key: `${id}-${name}-${value}-${type}` })));
53
53
  case 'grid':
54
- return (_jsx(ReadOnlyGrid, { onClick: onClick, children: children }, id));
54
+ return (_jsx(ReadOnlyGrid, { onClick: onClick, borderBottom: "none", children: children }, id));
55
55
  case 'group':
56
56
  return _jsx(ReadOnlyGroup, { children: children }, id);
57
57
  case 'appliances':
@@ -60,6 +60,14 @@ export const ReadOnlyDynamicForm = ({ form: fields, onClick, onEdit, }) => {
60
60
  return _createElement(ReadOnlyCollapsible, Object.assign({}, field, { key: id }));
61
61
  case 'notes':
62
62
  return _createElement(ReadOnlyNotes, Object.assign({}, field, { key: id }));
63
+ case 'warranty':
64
+ return _createElement(ReadOnlyWarrantyBanner, Object.assign({}, field, { key: id }));
65
+ case 'purchase':
66
+ return (_createElement(ReadOnlyPurchaseDetails, Object.assign({}, field, { key: id, onClick: onClick })));
67
+ case 'overview':
68
+ return _createElement(ReadOnlyOverview, Object.assign({}, field, { key: id }));
69
+ case 'history':
70
+ return _createElement(ReadOnlyHistory, Object.assign({}, field, { key: id }));
63
71
  default:
64
72
  return null;
65
73
  }
@@ -1,24 +1,23 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Text, Flex, Stack, IconButton, Box } from '@chakra-ui/react';
3
- import { ReadOnlyHomeItemRating, Edit, ReadOnlyHomeItemImages, ReadOnlyHomeItemText, } from '../../../../../components';
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { Text, Flex, Stack, IconButton, Box, Image, SimpleGrid } from '@chakra-ui/react';
4
+ import { Edit } from '../../../../../components';
4
5
  import { colors } from '../../../../../theme/colors';
5
- export const ReadOnlyAppliances = ({ description, id, name, children, onEdit, value, }) => {
6
- const rating = children === null || children === void 0 ? void 0 : children.find(({ type }) => type === 'rating');
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: [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 })] })] })] })] }));
6
+ import { formatCurrency } from '../../../../../utils';
7
+ // Dashed rule between sections (XD: light gray dashed).
8
+ const DashedRule = () => (_jsx(Box, { borderBottom: "1px dashed", borderColor: "lightGray.2" }));
9
+ // Brand / Model# / Serial# row label #6C7679, value #464646 (XD).
10
+ const DetailRow = ({ label, value }) => (_jsxs(Flex, { children: [_jsx(Text, { w: "35%", fontFamily: "secondary", fontSize: "14px", lineHeight: "18px", color: "#6C7679", children: label }), _jsx(Text, { fontFamily: "secondary", fontSize: "14px", lineHeight: "18px", color: "gray.3", children: value != null ? String(value) : '' })] }));
11
+ // Retail Price / Est Replacement Cost — label left #6C7679, value right #464646.
12
+ const ValueRow = ({ label, value, bold, }) => (_jsxs(Flex, { justify: "space-between", children: [_jsx(Text, { fontFamily: "secondary", fontSize: "16px", lineHeight: "20px", color: "#6C7679", children: label }), _jsx(Text, { fontFamily: "secondary", fontSize: "16px", lineHeight: "20px", color: "gray.3", fontWeight: bold ? 'bold' : 'normal', children: value != null && value !== ''
13
+ ? formatCurrency({ value: value })
14
+ : '' })] }));
15
+ export const ReadOnlyAppliances = ({ description, id, name, children = [], onEdit, value, }) => {
16
+ var _a;
17
+ const imageField = children.find(({ type }) => type === 'images');
18
+ const images = (_a = imageField === null || imageField === void 0 ? void 0 : imageField.value) !== null && _a !== void 0 ? _a : [];
19
+ const [mainImage, setMainImage] = useState(images[0]);
20
+ const detailFields = children.filter(({ type }) => type === 'text');
21
+ const valueFields = children.filter(({ type }) => type === 'currency');
22
+ return (_jsxs(Stack, { spacing: "base", p: "base", bg: "neutral.white", mt: "2px", children: [(name || onEdit) && (_jsxs(Flex, { justify: "space-between", align: "center", w: "full", children: [_jsx(Text, { fontFamily: "primary", fontSize: "12px", letterSpacing: "0", color: "#525458", textTransform: "uppercase", children: name }), onEdit && (_jsx(IconButton, { "aria-label": "Edit appliance", variant: "ghost", w: "fit-content", minW: "auto", h: "auto", p: "0", flexShrink: 0, icon: _jsx(Edit, { size: 18, stroke: colors.blue[3] }), onClick: () => onEdit(id) }))] })), _jsxs(Flex, { gap: "base", align: "stretch", children: [_jsxs(Flex, { direction: "column", gap: "base", flexShrink: 0, w: "174px", children: [_jsx(Image, { src: mainImage, alt: "home item", boxSize: "174px", objectFit: "cover" }), images.length > 0 && (_jsx(SimpleGrid, { columns: 4, spacing: "2", children: images.map((image) => (_jsx(Box, { as: "button", backgroundImage: image, backgroundSize: "cover", backgroundPosition: "center", boxSize: "34px", onClick: () => setMainImage(image) }, image))) }))] }), _jsxs(Stack, { flex: "1", spacing: "base", children: [_jsxs(Stack, { spacing: "13px", children: [_jsx(Text, { fontFamily: "primary", fontWeight: "600", fontSize: "22px", lineHeight: "15px", letterSpacing: "0", color: "gray.3", children: value }), _jsx(Text, { fontFamily: "secondary", fontSize: "14px", lineHeight: "15px", color: "gray.3", children: description })] }), _jsx(DashedRule, {}), detailFields.length > 0 && (_jsx(Stack, { spacing: "0", children: detailFields.map((field) => (_jsx(DetailRow, { label: field.name ? `${field.name}:` : undefined, value: field.value }, `${field.id}-${field.name}`))) })), valueFields.length > 0 && (_jsxs(_Fragment, { children: [_jsx(DashedRule, {}), _jsx(Stack, { spacing: "0", children: valueFields.map((field, i) => (_jsx(ValueRow, { label: field.name, value: field.value, bold: i === valueFields.length - 1 }, `${field.id}-${field.name}`))) })] }))] })] })] }));
24
23
  };
@@ -1,11 +1,14 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Text, Stack, Grid } from '@chakra-ui/react';
2
+ import { Text, Stack, Box, Flex } from '@chakra-ui/react';
3
3
  import { HiddenField } from '../../../../../components';
4
4
  import { fieldIcons } from '../../../../../helpers';
5
+ // Care & Guidelines column: hugs its content (content-width) so the Parts
6
+ // column can fill the remaining width to the right of the 13px separator.
7
+ // Tiles are fixed 75px squares (HiddenField's own `h` prop — not modified).
5
8
  export const ReadOnlyGuidelines = ({ name, children, onClick, }) => {
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) => {
9
+ return (_jsxs(Stack, { spacing: "base", width: "fit-content", flexShrink: 0, children: [_jsx(Text, { fontFamily: "primary", fontSize: "12px", color: "gray.3", textTransform: "uppercase", children: name }), _jsx(Flex, { flexWrap: "wrap", gap: "base", children: children === null || children === void 0 ? void 0 : children.map((child) => {
7
10
  const { id, icon, value } = child;
8
11
  const btnIcon = icon ? fieldIcons[icon] : '';
9
- return (_jsx(HiddenField, { id: id, icon: btnIcon, name: value, onClick: () => onClick === null || onClick === void 0 ? void 0 : onClick(id) }, id));
12
+ return (_jsx(Box, { w: "75px", children: _jsx(HiddenField, { id: id, h: "75px", icon: btnIcon, name: value, onClick: () => onClick === null || onClick === void 0 ? void 0 : onClick(id) }) }, id));
10
13
  }) })] }));
11
14
  };
@@ -0,0 +1,2 @@
1
+ import { ReportI } from '../../../../../interfaces';
2
+ export declare const ReadOnlyHistory: ({ name, value, label, accentColor, children, }: ReportI) => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Flex, Stack, Text } from '@chakra-ui/react';
3
+ import { DatePennant, HistoryCard } from '../../../../../components';
4
+ import { fieldIcons } from '../../../../../helpers';
5
+ import { formatCurrency } from '../../../../../utils';
6
+ // label (left #6C7679) + value (right #464646) — Brand / Model# rows (XD "Card").
7
+ const Row = ({ label, value }) => (_jsxs(Flex, { gap: "base", children: [_jsx(Text, { minW: "70px", fontFamily: "secondary", fontSize: "14px", lineHeight: "20px", color: "#6C7679", children: label }), _jsx(Text, { fontFamily: "secondary", fontSize: "14px", lineHeight: "20px", color: "gray.3", children: value != null ? String(value) : '' })] }));
8
+ // A single history event on the timeline: a date pennant (color per event type)
9
+ // joined by a node to the core HistoryCard. `label` = the pennant date,
10
+ // `accentColor` = the pennant color. Body is derived from children: an optional
11
+ // bold heading (value, e.g. a service company), Brand/Model-style rows for named
12
+ // text, plain lines for unnamed (address), a currency child as the attachment,
13
+ // an images child as the logo.
14
+ export const ReadOnlyHistory = ({ name, value, label, accentColor, children = [], }) => {
15
+ var _a;
16
+ const image = (_a = children.find(({ type }) => type === 'images')) === null || _a === void 0 ? void 0 : _a.value;
17
+ const attach = children.find(({ type }) => type === 'currency');
18
+ const textFields = children.filter(({ type }) => type === 'text');
19
+ const heading = value != null && value !== '' ? String(value) : '';
20
+ const color = accentColor || '#1E6388';
21
+ // Honesty: nothing credible to show → render nothing.
22
+ if (!name && !heading && textFields.length === 0 && !attach)
23
+ return null;
24
+ const attachment = attach
25
+ ? {
26
+ // Data-driven file-type icon (e.g. 'pdf'); none if unspecified.
27
+ icon: attach.icon ? fieldIcons[attach.icon] : undefined,
28
+ label: attach.name,
29
+ amount: attach.value != null && attach.value !== ''
30
+ ? formatCurrency({ value: attach.value })
31
+ : undefined,
32
+ }
33
+ : undefined;
34
+ return (_jsx(Box, { pl: "base", pr: "base", pt: "base", _last: { pb: 'base' }, children: _jsxs(Flex, { align: "flex-start", children: [_jsxs(Flex, { align: "center", pt: "12px", flexShrink: 0, children: [_jsx(DatePennant, { date: label, color: color }), _jsx(Box, { boxSize: "10px", borderRadius: "full", bg: "neutral.white", border: "2px solid", borderColor: color, ml: "0", zIndex: 2 })] }), _jsx(Box, { flex: "1", ml: "6px", children: _jsx(HistoryCard, { title: name, image: image, imagePosition: heading ? 'right' : 'left', attachment: attachment, children: _jsxs(Stack, { spacing: "0", children: [heading && (_jsx(Text, { fontFamily: "secondary", fontWeight: "bold", fontSize: "16px", lineHeight: "22px", color: "gray.3", children: heading })), textFields.map((field) => field.name ? (_jsx(Row, { label: `${field.name}:`, value: field.value }, field.id)) : (_jsx(Text, { fontFamily: "secondary", fontSize: "14px", lineHeight: "18px", color: "#3E4045", children: field.value != null ? String(field.value) : '' }, field.id)))] }) }) })] }) }));
35
+ };
@@ -1,11 +1,16 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Text, Stack, Grid, Box } from '@chakra-ui/react';
2
+ import { Text, Stack, Grid, Box, Flex, Link } from '@chakra-ui/react';
3
3
  import { HiddenField } from '../../../../../components';
4
4
  import { fieldIcons } from '../../../../../helpers';
5
+ // Parts & Accessories column: fills the width to the right of the separator
6
+ // (flex="1"), so "View All" sits at the right edge. The 13px on the LEFT of the
7
+ // separator is the parent Flex `gap="base"` (=13px); the 13px on the RIGHT is
8
+ // this box's `pl="13px"`. Tiles are fixed 75px squares, three across, wrapping
9
+ // in threes. Icons are data-driven (each part's `icon` → the appliance icon).
5
10
  export const ReadOnlyItemRelated = ({ name, children, onClick, }) => {
6
- return (_jsx(Box, { borderLeft: "1px solid", borderColor: "lightBlue.6", pl: "4", marginInlineStart: "auto", children: _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) => {
11
+ return (_jsx(Box, { flex: "1", borderLeft: "1px solid", borderColor: "lightBlue.5", pl: "13px", children: _jsxs(Stack, { spacing: "base", children: [_jsxs(Flex, { justify: "space-between", align: "center", gap: "base", children: [_jsx(Text, { fontFamily: "primary", fontSize: "12px", color: "gray.3", textTransform: "uppercase", children: name }), _jsx(Link, { fontFamily: "secondary", fontSize: "14px", fontWeight: "normal", color: "#2487C5", flexShrink: 0, onClick: () => onClick === null || onClick === void 0 ? void 0 : onClick('view-all'), children: "View All" })] }), _jsx(Grid, { templateColumns: "repeat(4, 75px)", gap: "base", children: children === null || children === void 0 ? void 0 : children.map((child) => {
7
12
  const { id, icon, value } = child;
8
13
  const btnIcon = icon ? fieldIcons[icon] : '';
9
- return (_jsx(HiddenField, { id: id, icon: btnIcon, name: value, onClick: () => onClick === null || onClick === void 0 ? void 0 : onClick(id) }, id));
14
+ return (_jsx(HiddenField, { id: id, h: "75px", icon: btnIcon, name: value, onClick: () => onClick === null || onClick === void 0 ? void 0 : onClick(id) }, id));
10
15
  }) })] }) }));
11
16
  };
@@ -0,0 +1,2 @@
1
+ import { ReadOnlyOverviewI } from '../../../../../interfaces';
2
+ export declare const ReadOnlyOverview: ({ name, children }: ReadOnlyOverviewI) => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Accordion, AccordionButton, AccordionItem, AccordionPanel, Box, Flex, ListItem, Text, UnorderedList, } from '@chakra-ui/react';
3
+ import { ChevronRight } from '../../../../../components';
4
+ // A Specs collapsible section — XD assembled Specs artboard. Exact spec:
5
+ // white card, 3px radius, shadow rgba(0,0,0,.16) 0 3px 6px; header padded
6
+ // 13px (top/sides) and 6.5px (bottom); title Poppins Regular 12px #525458
7
+ // uppercase + a blue circle chevron; body = bulleted list (Assistant 12px
8
+ // #464646). Built directly on Accordion (the shared Collapsible can't express
9
+ // this padding/radius/shadow).
10
+ export const ReadOnlyOverview = ({ name = '', children = [] }) => {
11
+ const bullets = children.filter((c) => c.value != null && c.value !== '');
12
+ // Honesty: no bullets → render nothing (never fabricate specs).
13
+ if (bullets.length === 0)
14
+ return null;
15
+ return (_jsx(Accordion, { allowToggle: true, bg: "neutral.white", borderRadius: "3px", boxShadow: "0 3px 6px rgba(0, 0, 0, 0.16)", children: _jsx(AccordionItem, { border: "none", children: ({ isExpanded }) => (_jsxs(_Fragment, { children: [_jsx(AccordionButton, { p: "base", _hover: { bg: 'transparent' }, _focus: { outline: 'none' }, children: _jsxs(Flex, { flex: "1", align: "center", justify: "space-between", children: [_jsx(Text, { fontFamily: "primary", fontSize: "14px", color: "#525458", textTransform: "uppercase", children: name }), _jsx(Box, { rounded: "full", border: "1px solid", borderColor: "blue.3", padding: "1", transition: "all .2s ease-in-out", transform: isExpanded ? 'rotate(-90deg)' : 'rotate(0)', children: _jsx(ChevronRight, {}) })] }) }), _jsx(AccordionPanel, { px: "13px", pb: "13px", pt: "0", children: _jsx(UnorderedList, { spacing: "base", m: "0", pl: "1.1em", children: bullets.map((bullet) => (_jsx(ListItem, { fontFamily: "secondary", fontSize: "14px", lineHeight: "1.4", color: "gray.3", children: String(bullet.value) }, bullet.id))) }) })] })) }) }));
16
+ };
@@ -0,0 +1,2 @@
1
+ import { ReadOnlyPurchaseDetailsI } from '../../../../../interfaces';
2
+ export declare const ReadOnlyPurchaseDetails: ({ id, name, link, children, onClick, }: ReadOnlyPurchaseDetailsI) => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Text, Flex, Stack, Box, Image, Link } from '@chakra-ui/react';
3
+ import { formatCurrency } from '../../../../../utils';
4
+ // Purchase Details block — XD "Purchase Details" (500×178). Retailer logo
5
+ // (128px square) + retailer name, then a purchase column (Purchased / Payment)
6
+ // and, past a vertical dashed divider, a totals column (Price / Tax / Total).
7
+ // Fonts/colors from the XD character styles:
8
+ // header "PURCHASE DETAILS" Poppins Regular 12px #464646 uppercase
9
+ // "View Receipt" Assistant Regular 14px #2488C6
10
+ // retailer label Assistant Regular 14px #6C7679
11
+ // retailer name Poppins SemiBold 18px #464646
12
+ // row label Assistant Regular 14px #6C7679
13
+ // row value Assistant Regular 14px #464646 (Total: Bold)
14
+ // label (left, #6C7679) + value (right, #464646). `bold` for the Total value.
15
+ const Row = ({ label, value, bold, }) => (_jsxs(Flex, { justify: "space-between", gap: "base", children: [_jsx(Text, { fontFamily: "secondary", fontSize: "14px", lineHeight: "20px", color: "#6C7679", children: label }), _jsx(Text, { fontFamily: "secondary", fontSize: "14px", lineHeight: "20px", color: "gray.3", fontWeight: bold ? 'bold' : 'normal', children: value != null ? String(value) : '' })] }));
16
+ export const ReadOnlyPurchaseDetails = ({ id, name, link, children = [], onClick, }) => {
17
+ var _a, _b;
18
+ const logo = (_a = children.find(({ type }) => type === 'images')) === null || _a === void 0 ? void 0 : _a.value;
19
+ const retailer = children.find((c) => c.name === 'Retailer');
20
+ const detailFields = children.filter(({ type, name: n }) => (type === 'text' || type === 'date') && n !== 'Retailer');
21
+ const valueFields = children.filter(({ type }) => type === 'currency');
22
+ // Honesty: nothing credible to show → render nothing (never fabricate).
23
+ if (!retailer && !logo && valueFields.length === 0)
24
+ return null;
25
+ return (_jsxs(Stack, { spacing: "base", p: "base", bg: "neutral.white", mt: "2px", children: [_jsxs(Flex, { justify: "space-between", align: "center", w: "full", children: [_jsx(Text, { fontFamily: "primary", fontSize: "12px", letterSpacing: "0", color: "gray.3", textTransform: "uppercase", children: name }), link && (_jsx(Link, { fontFamily: "secondary", fontSize: "14px", fontWeight: "normal", color: "#2488C6", onClick: () => onClick === null || onClick === void 0 ? void 0 : onClick(id), children: "View Receipt" }))] }), _jsxs(Flex, { gap: "base", align: "stretch", children: [logo && (_jsx(Image, { src: logo, alt: (retailer === null || retailer === void 0 ? void 0 : retailer.value) || 'retailer', boxSize: "128px", objectFit: "contain", flexShrink: 0 })), _jsxs(Stack, { flex: "1", spacing: "13px", children: [retailer && (_jsx(Text, { fontFamily: "primary", fontWeight: "600", fontSize: "22px", lineHeight: "26px", letterSpacing: "0", color: "gray.3", mt: "30px", children: String((_b = retailer.value) !== null && _b !== void 0 ? _b : '') })), _jsxs(Flex, { gap: "base", align: "flex-start", children: [detailFields.length > 0 && (_jsx(Stack, { flex: "1", spacing: "0", children: detailFields.map((field) => (_jsx(Row, { label: field.name ? `${field.name}:` : undefined, value: field.value }, `${field.id}-${field.name}`))) })), valueFields.length > 0 && (_jsx(Box, { borderLeft: "1px dashed", borderColor: "lightGray.2", pl: "base", w: "170px", flexShrink: 0, children: _jsx(Stack, { spacing: "0", children: valueFields.map((field, i) => (_jsx(Row, { label: field.name ? `${field.name}:` : undefined, value: field.value != null && field.value !== ''
26
+ ? formatCurrency({
27
+ value: field.value,
28
+ })
29
+ : '', bold: i === valueFields.length - 1 }, `${field.id}-${field.name}`))) }) }))] })] })] })] }));
30
+ };
@@ -0,0 +1,2 @@
1
+ import { ReadOnlyWarrantyBannerI } from '../../../../../interfaces';
2
+ export declare const ReadOnlyWarrantyBanner: ({ icon, value, state, link, }: ReadOnlyWarrantyBannerI) => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Flex, Image, Link, Text } from '@chakra-ui/react';
3
+ import { fieldIcons } from '../../../../../helpers';
4
+ /**
5
+ * Warranty-status banner. Built to the EXACT CSS from the "Read Only Item" XD
6
+ * (dev/spec mode), under-warranty artboard:
7
+ * container: height 76px, background #F2F9F2, no border, no radius
8
+ * badge circle: 45×45, #E0EBE0, full radius, 10px from the left / centered
9
+ * umbrella: 27×29
10
+ * text: Poppins Regular 16px/20px, letter-spacing 0, #464646, left
11
+ *
12
+ * Only the under-warranty state is designed in the XD. `expired` and `recall`
13
+ * palettes below are PROVISIONAL placeholders (awaiting their own artboards) —
14
+ * flagged so they get exact CSS before shipping, not invented values.
15
+ *
16
+ * HONESTY: `recall` must ONLY be used with REAL recall data (#357) — the banner
17
+ * renders nothing when `value` is empty and never fabricates an alert.
18
+ */
19
+ // Per-state visuals. `icon` is a `fieldIcons` key and is the SINGLE swap point
20
+ // for each state's glyph — drop the new expired/recall icons in here (one line
21
+ // each) once their assets are registered in `fieldIcons`. Colors reuse existing
22
+ // design-system variants (no new colors): under-warranty = exact XD; expired =
23
+ // neutral gray family; recall = the app's alert color (`error`, same variant as
24
+ // AlertBanner / CreditCardError). Exact XD for expired/recall is still TBD.
25
+ const STATE = {
26
+ underWarranty: { bg: '#F2F9F2', badge: '#E0EBE0', icon: 'warranty' },
27
+ expired: { bg: 'lightGray.1', badge: 'lightGray.2', icon: 'warranty' }, // TODO: swap to the expired icon
28
+ recall: { bg: 'error.1', badge: 'error.2', icon: 'warranty' }, // TODO: swap to the recall icon
29
+ };
30
+ export const ReadOnlyWarrantyBanner = ({ icon, value, state = 'underWarranty', link, }) => {
31
+ var _a;
32
+ // No data → render nothing. Never fabricate a status (critical for recall).
33
+ if (!value)
34
+ return null;
35
+ const s = (_a = STATE[state]) !== null && _a !== void 0 ? _a : STATE.underWarranty;
36
+ // Field-provided icon overrides; otherwise the state's own (swappable) icon.
37
+ const iconKey = icon !== null && icon !== void 0 ? icon : s.icon;
38
+ const bannerIcon = iconKey ? fieldIcons[iconKey] : '';
39
+ return (_jsxs(Flex, { align: "center", gap: "10px", minH: "76px", pl: "10px", pr: "base", bg: s.bg, mt: "2px", children: [_jsx(Flex, { align: "center", justify: "center", flexShrink: 0, boxSize: "45px", borderRadius: "full", bg: s.badge, children: state === 'recall' ? (
40
+ // Extra-bold Poppins "!" sized to the internal icon (~29px).
41
+ _jsx(Text, { fontFamily: "primary", fontWeight: "extrabold", fontSize: "29px", lineHeight: "1", color: "neutral.white", children: "!" })) : (bannerIcon && (_jsx(Image, { src: bannerIcon, alt: "warranty status", w: "27px", h: "29px", objectFit: "contain" }))) }), link ? (_jsx(Link, { href: link, isExternal: true, fontFamily: "primary", fontSize: "16px", lineHeight: "20px", letterSpacing: "0", color: "gray.3", sx: { textWrap: 'balance' }, children: String(value) })) : (_jsx(Text, { fontFamily: "primary", fontSize: "16px", lineHeight: "20px", letterSpacing: "0", color: "gray.3", sx: { textWrap: 'balance' }, children: String(value) }))] }));
42
+ };
@@ -4,4 +4,8 @@ export * from './ReadOnlyGuidelines';
4
4
  export * from './ReadOnlyHomeItemImages';
5
5
  export * from './ReadOnlyHomeItemRating';
6
6
  export * from './ReadOnlyHomeItemText';
7
+ export * from './ReadOnlyHistory';
7
8
  export * from './ReadOnlyItemRelated';
9
+ export * from './ReadOnlyOverview';
10
+ export * from './ReadOnlyPurchaseDetails';
11
+ export * from './ReadOnlyWarrantyBanner';
@@ -4,4 +4,8 @@ export * from './ReadOnlyGuidelines';
4
4
  export * from './ReadOnlyHomeItemImages';
5
5
  export * from './ReadOnlyHomeItemRating';
6
6
  export * from './ReadOnlyHomeItemText';
7
+ export * from './ReadOnlyHistory';
7
8
  export * from './ReadOnlyItemRelated';
9
+ export * from './ReadOnlyOverview';
10
+ export * from './ReadOnlyPurchaseDetails';
11
+ export * from './ReadOnlyWarrantyBanner';
@@ -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, { 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))) })] }));
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 ? tabList : []), ...(rightTabList !== null && rightTabList !== void 0 ? rightTabList : [])].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: "normal", fontSize: "sm", fontFamily: "primary", color: "blue.2", borderBottom: "3px solid transparent", _hover: { cursor: 'pointer' }, _focus: { outline: 'none' }, _selected: {
@@ -0,0 +1,7 @@
1
+ export interface AddDocumentsI {
2
+ title?: string;
3
+ message?: string;
4
+ /** "browse" affordance — the consumer wires the real file picker/dropzone. */
5
+ onBrowse?: () => void;
6
+ }
7
+ export declare const AddDocuments: ({ title, message, onBrowse, }: AddDocumentsI) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Flex, Link, Stack, Text } from '@chakra-ui/react';
3
+ import { Upload } from '../../components';
4
+ // Add-documents zone atop the History tab — XD "Assembled – 1".
5
+ // Section sits on the dark rail color (#E9EDEF); inside, a 72px dashed drop
6
+ // area (bg rgba(219,236,246,.6), 1px dashed #707070, radius 4px). The message
7
+ // is Assistant 16px #606060; "browse" is a Poppins Medium 16px #2487C5 link.
8
+ export const AddDocuments = ({ title = 'Add Notes, Documents and Service Records', message = 'Drag and drop media here or', onBrowse, }) => (_jsxs(Stack, { spacing: "base", p: "base", bg: "#E9EDEF", children: [_jsx(Text, { fontFamily: "secondary", fontSize: "16px", color: "#606060", children: title }), _jsxs(Flex, { h: "72px", align: "center", justify: "center", gap: "2", bg: "rgba(219, 236, 246, 0.6)", border: "1px dashed", borderColor: "rgba(112, 112, 112, 0.45)", borderRadius: "4px", children: [_jsx(Upload, {}), _jsx(Text, { fontFamily: "secondary", fontSize: "16px", color: "#606060", children: message }), _jsx(Link, { fontFamily: "secondary", fontSize: "16px", color: "#2487C5", onClick: onBrowse, children: "browse" })] })] }));
@@ -0,0 +1,7 @@
1
+ export interface DatePennantI {
2
+ /** Display date, e.g. "01 23 2017". */
3
+ date?: string;
4
+ /** Pennant fill — data-driven per event type (a legend maps color→type). */
5
+ color?: string;
6
+ }
7
+ export declare const DatePennant: ({ date, color }: DatePennantI) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Flex, Text } from '@chakra-ui/react';
3
+ // Date pennant — XD "Assembled – 1" timeline tag: a right-pointing flag
4
+ // (113×47, default #1E6388) with the event date in white Poppins Medium 16px.
5
+ // The fill color varies per event type (see the timeline legend, TODO).
6
+ export const DatePennant = ({ date, color = '#1E6388' }) => (_jsx(Flex, { w: "113px", h: "47px", bg: color, align: "center", pl: "base", flexShrink: 0, sx: { clipPath: 'polygon(0 0, 79% 0, 100% 50%, 79% 100%, 0 100%)' }, children: _jsx(Text, { fontFamily: "primary", fontWeight: "500", fontSize: "16px", lineHeight: "1", color: "neutral.white", whiteSpace: "nowrap", children: date }) }));
@@ -0,0 +1,19 @@
1
+ import { ReactNode } from 'react';
2
+ export interface HistoryCardI {
3
+ /** Event title, e.g. "Added Refrigerator" / "Service Record" (rendered uppercase). */
4
+ title?: string;
5
+ /** Image/logo URL (48px square). */
6
+ image?: string;
7
+ /** Which side the image sits on. 'right' (e.g. a service-company logo) keeps
8
+ * the text left-justified and lets the logo grow. Default 'left'. */
9
+ imagePosition?: 'left' | 'right';
10
+ /** Optional attachment row below a divider: file icon + label + amount. */
11
+ attachment?: {
12
+ icon?: string;
13
+ label?: string;
14
+ amount?: string;
15
+ };
16
+ /** Body content (the part that varies between derivatives). */
17
+ children?: ReactNode;
18
+ }
19
+ export declare const HistoryCard: ({ title, image, imagePosition, attachment, children, }: HistoryCardI) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Box, Flex, Image, Stack, Text } from '@chakra-ui/react';
3
+ // Core History card TEMPLATE — the shared shell every history event derives
4
+ // from (XD "Card" 344×154 and "Card 2" 344×197). Structure:
5
+ // header (event title, Poppins 12px #3E4045 uppercase)
6
+ // body (left image/logo 48px + a content slot — varies per derivative)
7
+ // divider + attachment row (file icon + name Assistant 16px #3E4045 +
8
+ // amount Assistant Bold 16px #464646), only when `attachment` is set.
9
+ // Presentational and slot-based so new event types compose it via `children`.
10
+ export const HistoryCard = ({ title, image, imagePosition = 'left', attachment, children, }) => (_jsx(Box, { bg: "neutral.white", borderRadius: "4px", boxShadow: "0 2px 10px rgba(0, 0, 0, 0.08)", p: "base", children: _jsxs(Stack, { spacing: "base", children: [title && (_jsx(Text, { fontFamily: "primary", fontSize: "12px", letterSpacing: "0", color: "#3E4045", textTransform: "uppercase", children: title })), _jsxs(Flex, { gap: "base", align: "flex-start", direction: imagePosition === 'right' ? 'row-reverse' : 'row', children: [image &&
11
+ (imagePosition === 'right' ? (
12
+ // Right-side logo: a larger area, kept uncropped.
13
+ _jsx(Image, { src: image, alt: title || 'history', h: "90px", maxW: "150px", w: "auto", objectFit: "contain", flexShrink: 0 })) : (_jsx(Image, { src: image, alt: title || 'history', boxSize: "48px", objectFit: "cover", flexShrink: 0 }))), _jsx(Box, { flex: "1", children: children })] }), attachment && (_jsxs(_Fragment, { children: [_jsx(Box, { borderTop: "1px solid", borderColor: "lightGray.2" }), _jsxs(Flex, { justify: "space-between", align: "center", gap: "base", children: [_jsxs(Flex, { gap: "2", align: "center", children: [attachment.icon && (_jsx(Image, { src: attachment.icon, alt: "", boxSize: "24px", objectFit: "contain" })), _jsx(Text, { fontFamily: "secondary", fontSize: "16px", color: "#3E4045", children: attachment.label })] }), attachment.amount != null && (_jsx(Text, { fontFamily: "secondary", fontWeight: "bold", fontSize: "16px", color: "gray.3", children: attachment.amount }))] })] }))] }) }));
@@ -0,0 +1,3 @@
1
+ export * from './AddDocuments';
2
+ export * from './DatePennant';
3
+ export * from './HistoryCard';
@@ -0,0 +1,3 @@
1
+ export * from './AddDocuments';
2
+ export * from './DatePennant';
3
+ export * from './HistoryCard';
@@ -5,6 +5,6 @@ import { ContainerHeader, HiddenField, TileTooltip } from '../../components';
5
5
  import { GreenCirclePlus } from '../../assets/images';
6
6
  export const AddToHomefile = ({ documentList, headerList, isDisabled = false, showHelp }) => {
7
7
  return (_jsx(TileTooltip, { label: "addToHomefile", children: _jsxs(Container, { variant: "launchpad", h: "full", minW: ['full', '20rem'], bg: "lightViolet.1", children: [_jsx(ContainerHeader, { title: t('addToHomefile.title'), titleIcon: GreenCirclePlus, menuItems: headerList, fontWeight: 'normal', showHelp: showHelp }), _jsx(Grid, { templateColumns: "repeat(auto-fill, minmax(70px, 1fr))", gap: "base", p: "base", children: documentList.map((item) => {
8
- return (_jsx(HiddenField, { h: "58px", id: item.label, name: item.label, icon: item.icon, disabled: isDisabled, onClick: item.onClick, showPlusIcon: true }, item.label));
8
+ return (_jsx(HiddenField, { h: "68px", id: item.label, name: item.label, icon: item.icon, disabled: isDisabled, onClick: item.onClick, showPlusIcon: true }, item.label));
9
9
  }) })] }) }));
10
10
  };
@@ -29,5 +29,5 @@ export const HomeCard = (_a) => {
29
29
  };
30
30
  const { imageUrl } = useHomeCard(image);
31
31
  const hasImage = Boolean(imageUrl);
32
- return (_jsx(TileTooltip, { label: "homeCard", children: _jsxs(Stack, { spacing: "base", bg: "white", children: [_jsxs(Center, { pos: "relative", h: "12rem", bg: "lightBlue.2", overflow: "hidden", children: [loading && (_jsx(Center, { h: "8rem", children: _jsx(BeatLoader, { color: "gray", size: 8 }) })), !loading && (_jsxs(_Fragment, { children: [editImage && (_jsx(EditFileUploader, { handleInputChange: addImage, "aria-label": t('ariaLabels.edit'), position: "absolute", right: "2", top: "1" })), _jsx(Image, { src: (hasImage && imageUrl) || randomImages(0), alt: `${name} ${t('images.altImage')}`, w: "full", objectFit: "cover" })] }))] }), !isEditMode && (_jsx(HomeCardReadOnly, Object.assign({ addImage: addImage, name: name, externalLink: externalLink, edit: edit }, props, address))), isEditMode && (_jsx(EditHomeDetails, { address: address, externalLink: externalLink, name: name, setIsDirty: setIsDirty }))] }) }));
32
+ return (_jsx(TileTooltip, { label: "homeCard", children: _jsxs(Stack, { spacing: "base", bg: "white", children: [_jsxs(Center, { pos: "relative", w: "full", aspectRatio: "16 / 9", bg: "lightBlue.2", overflow: "hidden", children: [loading && (_jsx(Center, { h: "8rem", children: _jsx(BeatLoader, { color: "gray", size: 8 }) })), !loading && (_jsxs(_Fragment, { children: [editImage && (_jsx(EditFileUploader, { handleInputChange: addImage, "aria-label": t('ariaLabels.edit'), position: "absolute", right: "2", top: "1" })), _jsx(Image, { src: (hasImage && imageUrl) || randomImages(0), alt: `${name} ${t('images.altImage')}`, w: "full", h: "full", objectFit: "cover" })] }))] }), !isEditMode && (_jsx(HomeCardReadOnly, Object.assign({ addImage: addImage, name: name, externalLink: externalLink, edit: edit }, props, address))), isEditMode && (_jsx(EditHomeDetails, { address: address, externalLink: externalLink, name: name, setIsDirty: setIsDirty }))] }) }));
33
33
  };
@@ -0,0 +1,2 @@
1
+ import { ViewingHomeItemBodyI } from '../../interfaces';
2
+ export declare const ViewingHomeItemBody: ({ form, onClick, onEdit, }: ViewingHomeItemBodyI) => import("react/jsx-runtime").JSX.Element;