@homefile/components-v2 2.17.3 → 2.18.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.
- package/dist/components/forms/dynamicForm/fields/uiFields/TileBody.tsx +0 -1
- package/dist/components/homeAssistant/monitorAlerts/BackendAlert.d.ts +1 -1
- package/dist/components/homeAssistant/monitorAlerts/BackendAlert.js +14 -4
- package/dist/components/homeAssistant/monitorAlerts/BackendAlertCard.d.ts +1 -1
- package/dist/components/homeAssistant/monitorAlerts/BackendAlertCard.js +3 -2
- package/dist/components/homeAssistant/monitorAlerts/alertDetails/AlertFields.d.ts +2 -0
- package/dist/components/homeAssistant/monitorAlerts/alertDetails/AlertFields.js +17 -0
- package/dist/components/homeAssistant/monitorAlerts/alertDetails/VideoDetail.d.ts +2 -0
- package/dist/components/homeAssistant/monitorAlerts/alertDetails/VideoDetail.js +5 -0
- package/dist/components/homeAssistant/monitorAlerts/alertDetails/index.d.ts +2 -0
- package/dist/components/homeAssistant/monitorAlerts/alertDetails/index.js +2 -0
- package/dist/helpers/homeAssistant/HomeAssistant.helper.js +5 -5
- package/dist/interfaces/forms/dynamicForm/DynamicForm.interface.d.ts +2 -2
- package/dist/interfaces/headers/TabsHeader.interface.d.ts +3 -4
- package/dist/interfaces/homeAssistant/BackendAlert.interface.d.ts +3 -11
- package/dist/mocks/forms/dynamicForm.mock.d.ts +1 -0
- package/dist/mocks/forms/dynamicForm.mock.js +56 -0
- package/dist/stories/homeAssistant/monitorAlerts/BackendAlert.stories.d.ts +5 -0
- package/dist/stories/homeAssistant/monitorAlerts/BackendAlert.stories.js +14 -0
- package/package.json +1 -1
- package/src/components/forms/dynamicForm/fields/uiFields/TileBody.tsx +0 -1
- package/src/components/homeAssistant/monitorAlerts/BackendAlert.tsx +20 -14
- package/src/components/homeAssistant/monitorAlerts/BackendAlertCard.tsx +5 -5
- package/src/components/homeAssistant/monitorAlerts/alertDetails/AlertFields.tsx +31 -0
- package/src/components/homeAssistant/monitorAlerts/alertDetails/VideoDetail.tsx +20 -0
- package/src/components/homeAssistant/monitorAlerts/alertDetails/index.ts +2 -0
- package/src/helpers/homeAssistant/HomeAssistant.helper.tsx +5 -4
- package/src/interfaces/forms/dynamicForm/DynamicForm.interface.ts +5 -0
- package/src/interfaces/headers/TabsHeader.interface.ts +3 -3
- package/src/interfaces/homeAssistant/BackendAlert.interface.ts +4 -11
- package/src/mocks/forms/dynamicForm.mock.ts +59 -0
- package/src/stories/homeAssistant/monitorAlerts/BackendAlert.stories.tsx +17 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { BackendAlertI } from '../../../interfaces';
|
|
2
|
-
export declare const BackendAlert: ({ category,
|
|
2
|
+
export declare const BackendAlert: ({ category, form }: BackendAlertI) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { BackendAlertCard } from '../..';
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { AlertFields, BackendAlertCard, TabsHeader } from '../..';
|
|
3
3
|
import { getCategoryStyles } from '../../../utils/Alerts.utils';
|
|
4
|
-
|
|
4
|
+
import { Divider } from '@chakra-ui/react';
|
|
5
|
+
export const BackendAlert = ({ category, form }) => {
|
|
6
|
+
var _a, _b, _c, _d, _e;
|
|
5
7
|
const { headerBg, alertIcon, alertIconBg, alertTitle } = getCategoryStyles(category);
|
|
6
|
-
|
|
8
|
+
const alert = form === null || form === void 0 ? void 0 : form.find((item) => item.type === 'alert');
|
|
9
|
+
const tabs = (_b = (_a = alert === null || alert === void 0 ? void 0 : alert.children) === null || _a === void 0 ? void 0 : _a.map((tab) => {
|
|
10
|
+
var _a;
|
|
11
|
+
return ({
|
|
12
|
+
label: tab.name,
|
|
13
|
+
component: _jsx(AlertFields, { fields: (_a = tab.children) !== null && _a !== void 0 ? _a : [] }),
|
|
14
|
+
});
|
|
15
|
+
})) !== null && _b !== void 0 ? _b : [];
|
|
16
|
+
return (_jsxs(BackendAlertCard, { alertBg: headerBg, alertIcon: alertIcon, alertTitle: alertTitle, bg: alertIconBg, icon: (_c = alert === null || alert === void 0 ? void 0 : alert.icon) !== null && _c !== void 0 ? _c : '', title: (_d = alert === null || alert === void 0 ? void 0 : alert.label) !== null && _d !== void 0 ? _d : '', description: (_e = alert === null || alert === void 0 ? void 0 : alert.description) !== null && _e !== void 0 ? _e : '', children: [_jsx(Divider, {}), _jsx(TabsHeader, { tabList: tabs })] }));
|
|
7
17
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { PropsWithChildren } from 'react';
|
|
2
2
|
import { BackendAlertCardI } from '../../../interfaces';
|
|
3
|
-
export declare const BackendAlertCard: ({ alertBg, alertIcon, alertTitle, children, ...props }: PropsWithChildren<BackendAlertCardI>) => import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export declare const BackendAlertCard: ({ alertBg, alertIcon, alertTitle, children, icon, ...props }: PropsWithChildren<BackendAlertCardI>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -14,8 +14,9 @@ import { t } from 'i18next';
|
|
|
14
14
|
import { Box, Button, Collapse, Flex, useDisclosure } from '@chakra-ui/react';
|
|
15
15
|
import { AlertHeader, AlertTemplate, AlertTitle } from '../..';
|
|
16
16
|
import { Warranty } from '../../../assets/images';
|
|
17
|
+
import { fieldIcons } from '../../../helpers';
|
|
17
18
|
export const BackendAlertCard = (_a) => {
|
|
18
|
-
var { alertBg = 'error.2', alertIcon = Warranty, alertTitle = t('homeAssistant.monitorAlerts.protection'), children } = _a, props = __rest(_a, ["alertBg", "alertIcon", "alertTitle", "children"]);
|
|
19
|
+
var { alertBg = 'error.2', alertIcon = Warranty, alertTitle = t('homeAssistant.monitorAlerts.protection'), children, icon = 'warning' } = _a, props = __rest(_a, ["alertBg", "alertIcon", "alertTitle", "children", "icon"]);
|
|
19
20
|
const { isOpen, onToggle } = useDisclosure();
|
|
20
|
-
return (_jsxs(Box, { display: "flex", flexDir: "column", bg: "neutral.white", boxShadow: "lg", borderRadius: "lg", overflow: "hidden", maxW: "420px", children: [_jsx(AlertHeader, { bg: alertBg }), _jsx(AlertTitle, { alertIcon: alertIcon, alertTitle: alertTitle }), _jsx(AlertTemplate, Object.assign({}, props)), _jsx(Collapse, { in: isOpen, animateOpacity: true, children: _jsx(Box, {
|
|
21
|
+
return (_jsxs(Box, { display: "flex", flexDir: "column", bg: "neutral.white", boxShadow: "lg", borderRadius: "lg", overflow: "hidden", maxW: "420px", children: [_jsx(AlertHeader, { bg: alertBg }), _jsx(AlertTitle, { alertIcon: alertIcon, alertTitle: alertTitle }), _jsx(AlertTemplate, Object.assign({}, props, { icon: fieldIcons[icon] })), _jsx(Collapse, { in: isOpen, animateOpacity: true, children: _jsx(Box, { bg: "lightBlue.1", children: children }) }), _jsx(Flex, { py: "base", bg: "lightBlue.1", justify: "flex-end", children: _jsx(Button, { variant: "leftRounded", w: "fit-content", px: "8", fontSize: "sm", fontWeight: "medium", onClick: onToggle, bg: isOpen ? 'blue.8' : 'blue.2', children: t(`homeAssistant.monitorAlerts.${isOpen ? 'collapse' : 'review'}`) }) })] }));
|
|
21
22
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createElement as _createElement } from "react";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Stack, Text } from '@chakra-ui/react';
|
|
4
|
+
import { VideoDetail } from './VideoDetail';
|
|
5
|
+
export const AlertFields = ({ fields }) => {
|
|
6
|
+
return (_jsx(Stack, { spacing: "base", p: "base", children: fields === null || fields === void 0 ? void 0 : fields.map((field) => {
|
|
7
|
+
const { id, type, value } = field;
|
|
8
|
+
switch (type) {
|
|
9
|
+
case 'text':
|
|
10
|
+
return (_jsx(Text, { fontSize: "sm", fontFamily: "secondary", lineHeight: "1.2", whiteSpace: "pre-line", children: String(value) }, id));
|
|
11
|
+
case 'video':
|
|
12
|
+
return _createElement(VideoDetail, Object.assign({}, field, { key: id }));
|
|
13
|
+
default:
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}) }));
|
|
17
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { AspectRatio, Box, Container, Flex, Text } from '@chakra-ui/react';
|
|
3
|
+
export const VideoDetail = ({ name, label, link, description }) => {
|
|
4
|
+
return (_jsx(Container, { p: "base", children: _jsxs(Flex, { gap: "base", children: [_jsx(AspectRatio, { w: "140px", ratio: 16 / 9, children: _jsx("iframe", { title: name, src: link, allowFullScreen: true }) }), _jsxs(Box, { children: [_jsx(Text, { fontWeight: "semibold", children: name }), _jsx(Text, { fontSize: "sm", fontFamily: "secondary", children: `${label} | ${description}` })] })] }) }));
|
|
5
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Fire, House, LargeAppliances, Target, Temperature, Water, } from '../../assets/images';
|
|
1
|
+
import { Fire, GearTime, House, LargeAppliances, Target, Temperature, Water, } from '../../assets/images';
|
|
2
2
|
export const homeAssistantSteps = [
|
|
3
3
|
{
|
|
4
4
|
title: 'Goals',
|
|
@@ -30,24 +30,24 @@ export const CATEGORY_CONFIG = {
|
|
|
30
30
|
label: 'Protection Monitor',
|
|
31
31
|
color: '#DB1DA1',
|
|
32
32
|
accent: '#FDDDF8',
|
|
33
|
-
icon:
|
|
33
|
+
icon: GearTime,
|
|
34
34
|
},
|
|
35
35
|
maintain: {
|
|
36
36
|
label: 'Maintenance Monitor',
|
|
37
37
|
color: '#8CC421',
|
|
38
38
|
accent: '#B9DEF2',
|
|
39
|
-
icon:
|
|
39
|
+
icon: GearTime,
|
|
40
40
|
},
|
|
41
41
|
budget: {
|
|
42
42
|
label: 'Budget Monitor',
|
|
43
43
|
color: '#1D8BDB',
|
|
44
44
|
accent: '#B9DEF2',
|
|
45
|
-
icon:
|
|
45
|
+
icon: GearTime,
|
|
46
46
|
},
|
|
47
47
|
improve: {
|
|
48
48
|
label: 'Improvement Monitor',
|
|
49
49
|
color: '#8516A7',
|
|
50
50
|
accent: '#B9DEF2',
|
|
51
|
-
icon:
|
|
51
|
+
icon: GearTime,
|
|
52
52
|
},
|
|
53
53
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AIGridFieldI, FolderFileI, MenuItemI, PartnerFooterI, TileCtaI } from '../..';
|
|
2
|
-
export type KindTypes = 'ai-image' | 'ai-grid' | 'checkbox' | 'checkbox-agreement' | 'checkbox-group' | 'currency' | 'date' | 'email' | 'file' | 'grid' | 'group' | 'hidden' | 'notes' | 'number' | 'radio' | 'rating' | 'select' | 'string' | 'switch' | 'telephone' | 'text' | 'textarea' | 'default' | UIKindTypes | HomeItemTypes;
|
|
1
|
+
import { AIGridFieldI, AlertFieldType, AlertTabType, FolderFileI, MenuItemI, PartnerFooterI, TileCtaI } from '../..';
|
|
2
|
+
export type KindTypes = 'ai-image' | 'ai-grid' | 'checkbox' | 'checkbox-agreement' | 'checkbox-group' | 'currency' | 'date' | 'email' | 'file' | 'grid' | 'group' | 'hidden' | 'notes' | 'number' | 'radio' | 'rating' | 'select' | 'string' | 'switch' | 'telephone' | 'text' | 'textarea' | 'default' | 'video' | UIKindTypes | HomeItemTypes | AlertTabType | AlertFieldType;
|
|
3
3
|
export type UIKindTypes = 'tile-body' | 'tile-body-logo' | 'tile-body-header' | 'tile-body-section' | 'tile-body-section-grid' | 'tile-body-partner-image' | 'tile-body-description' | 'tile-form' | 'tile-body-action' | 'vertical-icon' | 'primary-cta' | 'secondary-cta';
|
|
4
4
|
export type HomeItemTypes = 'appliances' | 'images' | 'guidelines' | 'item-related' | 'item-icon-btn';
|
|
5
5
|
export type IconTypes = 'barcode' | 'battery' | 'billing' | 'book' | 'book-opened' | 'calc' | 'calendar' | 'check' | 'co2' | 'contact' | 'date' | 'default' | 'detector' | 'electricity' | 'goldbars' | 'heart' | 'image' | 'notes' | 'palette' | 'people' | 'price' | 'rating' | 'receipt' | 'registry' | 'sprinkler' | 'tools' | 'wind' | '68' | 'calendar2' | 'water' | 'calendar-drop' | 'umbrella' | 'heater' | 'roof' | 'foundation' | 'solar-panel' | 'pool' | 'drop' | 'mobile-drop' | 'light' | 'plate' | 'pressure-washer' | 'house' | 'target' | 'title' | 'company' | UIIconTypes;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
interface
|
|
2
|
+
export interface TabI {
|
|
3
3
|
label: string;
|
|
4
4
|
component: ReactNode | null;
|
|
5
5
|
}
|
|
@@ -7,8 +7,7 @@ export interface TabsHeaderI {
|
|
|
7
7
|
defaultIndex?: number;
|
|
8
8
|
onChange?: (index: number) => void;
|
|
9
9
|
rightButton?: ReactNode;
|
|
10
|
-
rightTabList?:
|
|
10
|
+
rightTabList?: TabI[];
|
|
11
11
|
tabIndex?: number;
|
|
12
|
-
tabList:
|
|
12
|
+
tabList: TabI[];
|
|
13
13
|
}
|
|
14
|
-
export {};
|
|
@@ -1,15 +1,7 @@
|
|
|
1
|
+
import { DynamicFormI } from '..';
|
|
1
2
|
export type AlertCategory = 'safeguard' | 'maintain' | 'budget' | 'improve';
|
|
2
3
|
export type AlertTabType = 'details' | 'filter-size' | 'purchase' | 'hire-out';
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
label: string;
|
|
6
|
-
data: T;
|
|
7
|
-
}
|
|
8
|
-
export interface BackendAlertI {
|
|
9
|
-
id: string;
|
|
4
|
+
export type AlertFieldType = 'alert' | 'iconSection' | 'tabList' | 'list';
|
|
5
|
+
export interface BackendAlertI extends DynamicFormI {
|
|
10
6
|
category: AlertCategory;
|
|
11
|
-
icon: string;
|
|
12
|
-
title: string;
|
|
13
|
-
summary: string;
|
|
14
|
-
tabs?: AlertTab[];
|
|
15
7
|
}
|
|
@@ -839,3 +839,59 @@ export const unknownFormMock = {
|
|
|
839
839
|
updatedAt: '2025-04-17T19:26:39.435Z',
|
|
840
840
|
__v: 0,
|
|
841
841
|
};
|
|
842
|
+
export const alertFieldsMock = [
|
|
843
|
+
{
|
|
844
|
+
id: faker.database.mongodbObjectId(),
|
|
845
|
+
name: 'Filter',
|
|
846
|
+
label: 'Time to change your heating & cooling air filter.',
|
|
847
|
+
description: 'Changing your air filter every 30 days ensures efficient system performance and improves indoor air quality by trapping dust and allergens.',
|
|
848
|
+
icon: 'wind',
|
|
849
|
+
value: false,
|
|
850
|
+
type: 'alert',
|
|
851
|
+
children: [
|
|
852
|
+
{
|
|
853
|
+
id: faker.database.mongodbObjectId(),
|
|
854
|
+
name: 'Details',
|
|
855
|
+
label: 'Model or Serial',
|
|
856
|
+
description: faker.lorem.sentence(),
|
|
857
|
+
comments: faker.lorem.sentence(),
|
|
858
|
+
value: '',
|
|
859
|
+
type: 'details',
|
|
860
|
+
visible: true,
|
|
861
|
+
children: [
|
|
862
|
+
{
|
|
863
|
+
id: faker.database.mongodbObjectId(),
|
|
864
|
+
name: '',
|
|
865
|
+
label: '',
|
|
866
|
+
description: '',
|
|
867
|
+
comments: '',
|
|
868
|
+
value: 'Changing your air filter is critical for maintaining your home’s HVAC system efficiency and ensuring good air quality. A clogged filter forces your system to work harder, leading to higher energy bills and potential damage to components. \n\nNeglecting this simple maintenance can result in costly repairs or even a full system replacement, which can run into thousands of dollars. Regularly replacing your air filter not only saves money but also extends the lifespan of your HVAC system, keeping your home comfortable and your expenses in check.',
|
|
869
|
+
type: 'text',
|
|
870
|
+
visible: true,
|
|
871
|
+
},
|
|
872
|
+
{
|
|
873
|
+
id: faker.database.mongodbObjectId(),
|
|
874
|
+
name: 'Where to find and change the Air Filter',
|
|
875
|
+
label: 'Dec 5, 2024',
|
|
876
|
+
description: '1:39',
|
|
877
|
+
comments: '',
|
|
878
|
+
value: '',
|
|
879
|
+
link: 'https://www.youtube.com/embed/qCNIc1y18pA?si=oC1NmAjuh0JZTYcr',
|
|
880
|
+
type: 'video',
|
|
881
|
+
visible: true,
|
|
882
|
+
},
|
|
883
|
+
],
|
|
884
|
+
},
|
|
885
|
+
{
|
|
886
|
+
id: faker.database.mongodbObjectId(),
|
|
887
|
+
name: 'Filter Size',
|
|
888
|
+
label: 'Upload Image',
|
|
889
|
+
description: faker.lorem.sentence(),
|
|
890
|
+
comments: faker.lorem.sentence(),
|
|
891
|
+
value: faker.image.urlPicsumPhotos(),
|
|
892
|
+
type: 'filter-size',
|
|
893
|
+
visible: true,
|
|
894
|
+
},
|
|
895
|
+
],
|
|
896
|
+
},
|
|
897
|
+
];
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Meta } from '@storybook/react';
|
|
2
|
+
import { BackendAlertI } from '../../../interfaces';
|
|
3
|
+
declare const _default: Meta<BackendAlertI>;
|
|
4
|
+
export default _default;
|
|
5
|
+
export declare const BackendAlertComponent: (args: BackendAlertI) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { BackendAlert } from '../../../components';
|
|
3
|
+
import { alertFieldsMock } from '../../../mocks';
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Components/HomeAssistant/MonitorAlerts',
|
|
6
|
+
component: BackendAlert,
|
|
7
|
+
args: {
|
|
8
|
+
category: 'budget',
|
|
9
|
+
form: alertFieldsMock,
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
export const BackendAlertComponent = (args) => {
|
|
13
|
+
return _jsx(BackendAlert, Object.assign({}, args));
|
|
14
|
+
};
|
package/package.json
CHANGED
|
@@ -1,28 +1,34 @@
|
|
|
1
|
-
import { BackendAlertCard } from '@/components'
|
|
2
|
-
import { BackendAlertI } from '@/interfaces'
|
|
1
|
+
import { AlertFields, BackendAlertCard, TabsHeader } from '@/components'
|
|
2
|
+
import { BackendAlertI, TabI } from '@/interfaces'
|
|
3
3
|
import { getCategoryStyles } from '@/utils/Alerts.utils'
|
|
4
|
+
import { Divider } from '@chakra-ui/react'
|
|
4
5
|
|
|
5
|
-
export const BackendAlert = ({
|
|
6
|
-
category,
|
|
7
|
-
icon,
|
|
8
|
-
id,
|
|
9
|
-
title,
|
|
10
|
-
tabs,
|
|
11
|
-
summary,
|
|
12
|
-
}: BackendAlertI) => {
|
|
6
|
+
export const BackendAlert = ({ category, form }: BackendAlertI) => {
|
|
13
7
|
const { headerBg, alertIcon, alertIconBg, alertTitle } =
|
|
14
8
|
getCategoryStyles(category)
|
|
9
|
+
const alert = form?.find((item) => item.type === 'alert')
|
|
10
|
+
|
|
11
|
+
const tabs =
|
|
12
|
+
alert?.children?.map(
|
|
13
|
+
(tab) =>
|
|
14
|
+
({
|
|
15
|
+
label: tab.name,
|
|
16
|
+
component: <AlertFields fields={tab.children ?? []} />,
|
|
17
|
+
} as TabI)
|
|
18
|
+
) ?? []
|
|
19
|
+
|
|
15
20
|
return (
|
|
16
21
|
<BackendAlertCard
|
|
17
22
|
alertBg={headerBg}
|
|
18
23
|
alertIcon={alertIcon}
|
|
19
24
|
alertTitle={alertTitle}
|
|
20
25
|
bg={alertIconBg}
|
|
21
|
-
icon={icon}
|
|
22
|
-
title={
|
|
23
|
-
description={
|
|
26
|
+
icon={alert?.icon ?? ''}
|
|
27
|
+
title={alert?.label ?? ''}
|
|
28
|
+
description={alert?.description ?? ''}
|
|
24
29
|
>
|
|
25
|
-
|
|
30
|
+
<Divider />
|
|
31
|
+
<TabsHeader tabList={tabs} />
|
|
26
32
|
</BackendAlertCard>
|
|
27
33
|
)
|
|
28
34
|
}
|
|
@@ -2,14 +2,16 @@ import { PropsWithChildren } from 'react'
|
|
|
2
2
|
import { t } from 'i18next'
|
|
3
3
|
import { Box, Button, Collapse, Flex, useDisclosure } from '@chakra-ui/react'
|
|
4
4
|
import { AlertHeader, AlertTemplate, AlertTitle } from '@/components'
|
|
5
|
-
import { BackendAlertCardI } from '@/interfaces'
|
|
5
|
+
import { BackendAlertCardI, IconTypes } from '@/interfaces'
|
|
6
6
|
import { Warranty } from '@/assets/images'
|
|
7
|
+
import { fieldIcons } from '@/helpers'
|
|
7
8
|
|
|
8
9
|
export const BackendAlertCard = ({
|
|
9
10
|
alertBg = 'error.2',
|
|
10
11
|
alertIcon = Warranty,
|
|
11
12
|
alertTitle = t('homeAssistant.monitorAlerts.protection'),
|
|
12
13
|
children,
|
|
14
|
+
icon = 'warning',
|
|
13
15
|
...props
|
|
14
16
|
}: PropsWithChildren<BackendAlertCardI>) => {
|
|
15
17
|
const { isOpen, onToggle } = useDisclosure()
|
|
@@ -25,11 +27,9 @@ export const BackendAlertCard = ({
|
|
|
25
27
|
>
|
|
26
28
|
<AlertHeader bg={alertBg} />
|
|
27
29
|
<AlertTitle alertIcon={alertIcon} alertTitle={alertTitle} />
|
|
28
|
-
<AlertTemplate {...props} />
|
|
30
|
+
<AlertTemplate {...props} icon={fieldIcons[icon as IconTypes]} />
|
|
29
31
|
<Collapse in={isOpen} animateOpacity>
|
|
30
|
-
<Box
|
|
31
|
-
{children}
|
|
32
|
-
</Box>
|
|
32
|
+
<Box bg="lightBlue.1">{children}</Box>
|
|
33
33
|
</Collapse>
|
|
34
34
|
<Flex py="base" bg="lightBlue.1" justify="flex-end">
|
|
35
35
|
<Button
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { FieldTypesI } from '@/interfaces'
|
|
2
|
+
import { Box, Stack, Text } from '@chakra-ui/react'
|
|
3
|
+
import { VideoDetail } from './VideoDetail'
|
|
4
|
+
|
|
5
|
+
export const AlertFields = ({ fields }: FieldTypesI) => {
|
|
6
|
+
return (
|
|
7
|
+
<Stack spacing="base" p="base">
|
|
8
|
+
{fields?.map((field) => {
|
|
9
|
+
const { id, type, value } = field
|
|
10
|
+
switch (type) {
|
|
11
|
+
case 'text':
|
|
12
|
+
return (
|
|
13
|
+
<Text
|
|
14
|
+
key={id}
|
|
15
|
+
fontSize="sm"
|
|
16
|
+
fontFamily="secondary"
|
|
17
|
+
lineHeight="1.2"
|
|
18
|
+
whiteSpace="pre-line"
|
|
19
|
+
>
|
|
20
|
+
{String(value)}
|
|
21
|
+
</Text>
|
|
22
|
+
)
|
|
23
|
+
case 'video':
|
|
24
|
+
return <VideoDetail {...field} key={id} />
|
|
25
|
+
default:
|
|
26
|
+
return null
|
|
27
|
+
}
|
|
28
|
+
})}
|
|
29
|
+
</Stack>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ReportI } from '@/interfaces'
|
|
2
|
+
import { AspectRatio, Box, Container, Flex, Text } from '@chakra-ui/react'
|
|
3
|
+
|
|
4
|
+
export const VideoDetail = ({ name, label, link, description }: ReportI) => {
|
|
5
|
+
return (
|
|
6
|
+
<Container p="base">
|
|
7
|
+
<Flex gap="base">
|
|
8
|
+
<AspectRatio w="140px" ratio={16 / 9}>
|
|
9
|
+
<iframe title={name} src={link} allowFullScreen />
|
|
10
|
+
</AspectRatio>
|
|
11
|
+
<Box>
|
|
12
|
+
<Text fontWeight="semibold">{name}</Text>
|
|
13
|
+
<Text fontSize="sm" fontFamily="secondary">
|
|
14
|
+
{`${label} | ${description}`}
|
|
15
|
+
</Text>
|
|
16
|
+
</Box>
|
|
17
|
+
</Flex>
|
|
18
|
+
</Container>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Fire,
|
|
3
|
+
GearTime,
|
|
3
4
|
House,
|
|
4
5
|
LargeAppliances,
|
|
5
6
|
Target,
|
|
@@ -48,24 +49,24 @@ export const CATEGORY_CONFIG: Record<AlertCategory, CategoryConfigI> = {
|
|
|
48
49
|
label: 'Protection Monitor',
|
|
49
50
|
color: '#DB1DA1',
|
|
50
51
|
accent: '#FDDDF8',
|
|
51
|
-
icon:
|
|
52
|
+
icon: GearTime,
|
|
52
53
|
},
|
|
53
54
|
maintain: {
|
|
54
55
|
label: 'Maintenance Monitor',
|
|
55
56
|
color: '#8CC421',
|
|
56
57
|
accent: '#B9DEF2',
|
|
57
|
-
icon:
|
|
58
|
+
icon: GearTime,
|
|
58
59
|
},
|
|
59
60
|
budget: {
|
|
60
61
|
label: 'Budget Monitor',
|
|
61
62
|
color: '#1D8BDB',
|
|
62
63
|
accent: '#B9DEF2',
|
|
63
|
-
icon:
|
|
64
|
+
icon: GearTime,
|
|
64
65
|
},
|
|
65
66
|
improve: {
|
|
66
67
|
label: 'Improvement Monitor',
|
|
67
68
|
color: '#8516A7',
|
|
68
69
|
accent: '#B9DEF2',
|
|
69
|
-
icon:
|
|
70
|
+
icon: GearTime,
|
|
70
71
|
},
|
|
71
72
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AIGridFieldI,
|
|
3
|
+
AlertFieldType,
|
|
4
|
+
AlertTabType,
|
|
3
5
|
FolderFileI,
|
|
4
6
|
MenuItemI,
|
|
5
7
|
PartnerFooterI,
|
|
@@ -30,8 +32,11 @@ export type KindTypes =
|
|
|
30
32
|
| 'text'
|
|
31
33
|
| 'textarea'
|
|
32
34
|
| 'default'
|
|
35
|
+
| 'video'
|
|
33
36
|
| UIKindTypes
|
|
34
37
|
| HomeItemTypes
|
|
38
|
+
| AlertTabType
|
|
39
|
+
| AlertFieldType
|
|
35
40
|
|
|
36
41
|
export type UIKindTypes =
|
|
37
42
|
| 'tile-body'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react'
|
|
2
2
|
|
|
3
|
-
interface
|
|
3
|
+
export interface TabI {
|
|
4
4
|
label: string
|
|
5
5
|
component: ReactNode | null
|
|
6
6
|
}
|
|
@@ -8,7 +8,7 @@ export interface TabsHeaderI {
|
|
|
8
8
|
defaultIndex?: number
|
|
9
9
|
onChange?: (index: number) => void
|
|
10
10
|
rightButton?: ReactNode
|
|
11
|
-
rightTabList?:
|
|
11
|
+
rightTabList?: TabI[]
|
|
12
12
|
tabIndex?: number
|
|
13
|
-
tabList:
|
|
13
|
+
tabList: TabI[]
|
|
14
14
|
}
|
|
@@ -1,18 +1,11 @@
|
|
|
1
|
+
import { DynamicFormI } from '@/interfaces'
|
|
2
|
+
|
|
1
3
|
export type AlertCategory = 'safeguard' | 'maintain' | 'budget' | 'improve'
|
|
2
4
|
|
|
3
5
|
export type AlertTabType = 'details' | 'filter-size' | 'purchase' | 'hire-out'
|
|
4
6
|
|
|
5
|
-
export
|
|
6
|
-
key: AlertTabType
|
|
7
|
-
label: string
|
|
8
|
-
data: T
|
|
9
|
-
}
|
|
7
|
+
export type AlertFieldType = 'alert' | 'iconSection' | 'tabList' | 'list'
|
|
10
8
|
|
|
11
|
-
export interface BackendAlertI {
|
|
12
|
-
id: string
|
|
9
|
+
export interface BackendAlertI extends DynamicFormI {
|
|
13
10
|
category: AlertCategory
|
|
14
|
-
icon: string
|
|
15
|
-
title: string
|
|
16
|
-
summary: string
|
|
17
|
-
tabs?: AlertTab[]
|
|
18
11
|
}
|
|
@@ -853,3 +853,62 @@ export const unknownFormMock: Record<string, any> = {
|
|
|
853
853
|
updatedAt: '2025-04-17T19:26:39.435Z',
|
|
854
854
|
__v: 0,
|
|
855
855
|
}
|
|
856
|
+
|
|
857
|
+
export const alertFieldsMock: ReportI[] = [
|
|
858
|
+
{
|
|
859
|
+
id: faker.database.mongodbObjectId(),
|
|
860
|
+
name: 'Filter',
|
|
861
|
+
label: 'Time to change your heating & cooling air filter.',
|
|
862
|
+
description:
|
|
863
|
+
'Changing your air filter every 30 days ensures efficient system performance and improves indoor air quality by trapping dust and allergens.',
|
|
864
|
+
icon: 'wind',
|
|
865
|
+
value: false,
|
|
866
|
+
type: 'alert',
|
|
867
|
+
children: [
|
|
868
|
+
{
|
|
869
|
+
id: faker.database.mongodbObjectId(),
|
|
870
|
+
name: 'Details',
|
|
871
|
+
label: 'Model or Serial',
|
|
872
|
+
description: faker.lorem.sentence(),
|
|
873
|
+
comments: faker.lorem.sentence(),
|
|
874
|
+
value: '',
|
|
875
|
+
type: 'details',
|
|
876
|
+
visible: true,
|
|
877
|
+
children: [
|
|
878
|
+
{
|
|
879
|
+
id: faker.database.mongodbObjectId(),
|
|
880
|
+
name: '',
|
|
881
|
+
label: '',
|
|
882
|
+
description: '',
|
|
883
|
+
comments: '',
|
|
884
|
+
value:
|
|
885
|
+
'Changing your air filter is critical for maintaining your home’s HVAC system efficiency and ensuring good air quality. A clogged filter forces your system to work harder, leading to higher energy bills and potential damage to components. \n\nNeglecting this simple maintenance can result in costly repairs or even a full system replacement, which can run into thousands of dollars. Regularly replacing your air filter not only saves money but also extends the lifespan of your HVAC system, keeping your home comfortable and your expenses in check.',
|
|
886
|
+
type: 'text',
|
|
887
|
+
visible: true,
|
|
888
|
+
},
|
|
889
|
+
{
|
|
890
|
+
id: faker.database.mongodbObjectId(),
|
|
891
|
+
name: 'Where to find and change the Air Filter',
|
|
892
|
+
label: 'Dec 5, 2024',
|
|
893
|
+
description: '1:39',
|
|
894
|
+
comments: '',
|
|
895
|
+
value: '',
|
|
896
|
+
link: 'https://www.youtube.com/embed/qCNIc1y18pA?si=oC1NmAjuh0JZTYcr',
|
|
897
|
+
type: 'video',
|
|
898
|
+
visible: true,
|
|
899
|
+
},
|
|
900
|
+
],
|
|
901
|
+
},
|
|
902
|
+
{
|
|
903
|
+
id: faker.database.mongodbObjectId(),
|
|
904
|
+
name: 'Filter Size',
|
|
905
|
+
label: 'Upload Image',
|
|
906
|
+
description: faker.lorem.sentence(),
|
|
907
|
+
comments: faker.lorem.sentence(),
|
|
908
|
+
value: faker.image.urlPicsumPhotos(),
|
|
909
|
+
type: 'filter-size',
|
|
910
|
+
visible: true,
|
|
911
|
+
},
|
|
912
|
+
],
|
|
913
|
+
},
|
|
914
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Meta } from '@storybook/react'
|
|
2
|
+
import { BackendAlert } from '@/components'
|
|
3
|
+
import { BackendAlertI } from '@/interfaces'
|
|
4
|
+
import { alertFieldsMock } from '@/mocks'
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: 'Components/HomeAssistant/MonitorAlerts',
|
|
8
|
+
component: BackendAlert,
|
|
9
|
+
args: {
|
|
10
|
+
category: 'budget',
|
|
11
|
+
form: alertFieldsMock,
|
|
12
|
+
},
|
|
13
|
+
} as Meta<BackendAlertI>
|
|
14
|
+
|
|
15
|
+
export const BackendAlertComponent = (args: BackendAlertI) => {
|
|
16
|
+
return <BackendAlert {...args} />
|
|
17
|
+
}
|