@homefile/components-v2 2.17.1 → 2.17.3

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 (45) hide show
  1. package/dist/components/homeAssistant/HomeMonitorButton.d.ts +1 -1
  2. package/dist/components/homeAssistant/HomeMonitorButton.js +30 -5
  3. package/dist/components/homeAssistant/HomeMonitorSteps.d.ts +1 -1
  4. package/dist/components/homeAssistant/HomeMonitorSteps.js +8 -4
  5. package/dist/components/homeAssistant/monitorAlerts/AlertHeader.d.ts +3 -1
  6. package/dist/components/homeAssistant/monitorAlerts/AlertHeader.js +3 -3
  7. package/dist/components/homeAssistant/monitorAlerts/BackendAlert.d.ts +2 -0
  8. package/dist/components/homeAssistant/monitorAlerts/BackendAlert.js +7 -0
  9. package/dist/components/homeAssistant/monitorAlerts/BackendAlertCard.d.ts +3 -0
  10. package/dist/components/homeAssistant/monitorAlerts/BackendAlertCard.js +21 -0
  11. package/dist/components/homeAssistant/monitorAlerts/index.d.ts +2 -0
  12. package/dist/components/homeAssistant/monitorAlerts/index.js +2 -0
  13. package/dist/helpers/homeAssistant/HomeAssistant.helper.d.ts +9 -0
  14. package/dist/helpers/homeAssistant/HomeAssistant.helper.js +26 -0
  15. package/dist/interfaces/homeAssistant/BackendAlert.interface.d.ts +15 -0
  16. package/dist/interfaces/homeAssistant/BackendAlert.interface.js +1 -0
  17. package/dist/interfaces/homeAssistant/BackendAlertCard.interface.d.ts +9 -0
  18. package/dist/interfaces/homeAssistant/BackendAlertCard.interface.js +1 -0
  19. package/dist/interfaces/homeAssistant/HomeMonitorSteps.interface.d.ts +8 -1
  20. package/dist/interfaces/homeAssistant/index.d.ts +2 -0
  21. package/dist/interfaces/homeAssistant/index.js +2 -0
  22. package/dist/stories/homeAssistant/HomeMonitorSteps.stories.d.ts +5 -0
  23. package/dist/stories/homeAssistant/HomeMonitorSteps.stories.js +24 -0
  24. package/dist/stories/homeAssistant/monitorAlerts/MonitorAlerts.stories.d.ts +5 -0
  25. package/dist/stories/homeAssistant/monitorAlerts/MonitorAlerts.stories.js +12 -0
  26. package/dist/utils/Alerts.utils.d.ts +7 -0
  27. package/dist/utils/Alerts.utils.js +10 -0
  28. package/package.json +1 -1
  29. package/src/components/homeAssistant/HomeMonitorButton.tsx +56 -14
  30. package/src/components/homeAssistant/HomeMonitorSteps.tsx +14 -4
  31. package/src/components/homeAssistant/monitorAlerts/AlertHeader.tsx +15 -4
  32. package/src/components/homeAssistant/monitorAlerts/BackendAlert.tsx +28 -0
  33. package/src/components/homeAssistant/monitorAlerts/BackendAlertCard.tsx +49 -0
  34. package/src/components/homeAssistant/monitorAlerts/index.ts +2 -0
  35. package/src/helpers/homeAssistant/HomeAssistant.helper.tsx +35 -0
  36. package/src/interfaces/homeAssistant/BackendAlert.interface.ts +18 -0
  37. package/src/interfaces/homeAssistant/BackendAlertCard.interface.ts +9 -0
  38. package/src/interfaces/homeAssistant/HomeMonitorSteps.interface.ts +8 -1
  39. package/src/interfaces/homeAssistant/index.ts +2 -0
  40. package/src/stories/homeAssistant/HomeMonitorSteps.stories.tsx +31 -0
  41. package/src/stories/homeAssistant/monitorAlerts/MonitorAlerts.stories.tsx +15 -0
  42. package/src/utils/Alerts.utils.ts +12 -0
  43. /package/dist/stories/homeAssistant/monitorAlerts/{HomeAssistant.stories.d.ts → BaseAlertCard.stories.d.ts} +0 -0
  44. /package/dist/stories/homeAssistant/monitorAlerts/{HomeAssistant.stories.js → BaseAlertCard.stories.js} +0 -0
  45. /package/src/stories/homeAssistant/monitorAlerts/{HomeAssistant.stories.tsx → BaseAlertCard.stories.tsx} +0 -0
@@ -1,2 +1,2 @@
1
1
  import { HomeMonitorButtonI } from '../../interfaces';
2
- export declare const HomeMonitorButton: ({ currentStep, onStepClick, status, step, }: HomeMonitorButtonI) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const HomeMonitorButton: ({ alertCount, currentStep, onStepClick, status, step, }: HomeMonitorButtonI) => import("react/jsx-runtime").JSX.Element;
@@ -1,26 +1,51 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Center, Image, Stack, Text } from '@chakra-ui/react';
3
3
  import { getIconAltText } from '../../utils';
4
- export const HomeMonitorButton = ({ currentStep, onStepClick, status = 'ok', step, }) => {
4
+ import { keyframes } from '@emotion/react';
5
+ export const HomeMonitorButton = ({ alertCount = 0, currentStep, onStepClick, status = 'ok', step, }) => {
5
6
  const buttonId = `homeMonitorButton-${currentStep}`;
6
7
  const iconAltText = getIconAltText(step.icon);
7
- return (_jsx(Box, { position: "relative", id: buttonId, zIndex: "2", children: _jsxs(Box, { position: "relative", bg: "neutral.white", borderRadius: "lg", boxShadow: "lg", zIndex: "2", children: [_jsx(Box, { bg: status === 'alert' ? 'error.2' : 'green.1', boxSize: "10px", borderRadius: "full", position: "absolute", top: "6px", left: "6px", zIndex: "8" }), _jsxs(Stack, Object.assign({ position: "relative", zIndex: "2", as: "button", spacing: "2", border: "1px solid transparent", align: "center", h: "96px", w: "100%", p: "base" }, setStyles(status), { onClick: () => onStepClick(currentStep), children: [_jsx(Center, { h: "60%", marginTop: "2", children: _jsx(Image, { src: step.icon, alt: iconAltText, w: "auto", h: "28px" }) }), _jsx(Center, { h: "40%", children: _jsx(Text, { fontSize: "xs", textTransform: "uppercase", textAlign: "center", lineHeight: "14px", children: step.title }) })] }))] }) }));
8
+ const alert = status === 'alert';
9
+ const ok = status === 'ok';
10
+ return (_jsx(Box, Object.assign({ position: "relative", id: buttonId, zIndex: "2", boxShadow: "lg" }, setStyles(status), { children: _jsxs(Box, { position: "relative", bg: "neutral.white", borderRadius: "lg", zIndex: "2", children: [_jsx(Box, { bg: alert ? 'error.2' : 'green.1', boxSize: "10px", borderRadius: "full", position: "absolute", top: "6px", left: "6px", zIndex: "8" }), _jsxs(Stack, { position: "relative", zIndex: "2", as: "button", spacing: "2", border: "1px solid transparent", align: "center", h: "96px", w: "100%", p: "base", onClick: () => onStepClick(currentStep), filter: ok ? 'grayscale(1) opacity(0.6)' : '', children: [_jsxs(Center, { h: "60%", marginTop: "2", children: [!alert && (_jsx(Image, { src: step.icon, alt: iconAltText, w: "auto", h: "28px" })), alert && (_jsx(Center, { boxSize: "32px", bg: "error.2", borderRadius: "full", color: "neutral.white", lineHeight: "1", fontWeight: "bold", children: alertCount }))] }), _jsx(Center, { h: "40%", children: _jsx(Text, { fontSize: "xs", textTransform: "uppercase", textAlign: "center", lineHeight: "14px", children: step.title }) })] })] }) })));
8
11
  };
12
+ const alertGradient = keyframes `
13
+ 0% {
14
+ background-position: 0% 50%;
15
+ }
16
+ 100% {
17
+ background-position: 100% 50%;
18
+ }
19
+ `;
9
20
  const setStyles = (status) => {
10
21
  switch (status) {
11
22
  case 'alert':
12
23
  return {
24
+ background: 'white',
13
25
  cursor: 'pointer',
14
- border: '1px solid',
15
- borderColor: 'error.2',
16
26
  transition: 'all 0.3s',
27
+ borderRadius: 'lg',
28
+ border: 'none',
29
+ _before: {
30
+ content: '""',
31
+ position: 'absolute',
32
+ inset: '-2px',
33
+ borderRadius: 'inherit',
34
+ background: 'linear-gradient(270deg,rgb(123, 6, 105),rgb(233, 175, 236), #F544DA)',
35
+ backgroundSize: '400% 400%',
36
+ animation: `${alertGradient} 2s linear infinite`,
37
+ animationDirection: 'alternate',
38
+ zIndex: -1,
39
+ pointerEvents: 'none',
40
+ },
17
41
  _hover: {
18
42
  bg: 'lightGreen.7',
19
43
  },
20
44
  };
21
45
  case 'ok':
22
46
  return {
23
- filter: 'grayscale(1) opacity(0.6)',
47
+ bg: 'neutral.white',
48
+ borderRadius: 'lg',
24
49
  };
25
50
  }
26
51
  };
@@ -1,2 +1,2 @@
1
1
  import { HomeMonitortStepsI } from '../../interfaces';
2
- export declare const HomeMonitorSteps: ({ menuItems, onStepClick, stepsWithAlerts, }: HomeMonitortStepsI) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const HomeMonitorSteps: ({ alerts, menuItems, onStepClick, stepsWithAlerts, }: HomeMonitortStepsI) => import("react/jsx-runtime").JSX.Element;
@@ -4,13 +4,17 @@ import { Box, Flex } from '@chakra-ui/react';
4
4
  import { HomeMonitorButton, IconMenu, MoreHorizontal } from '..';
5
5
  import { homeAssistantSteps } from '../../helpers';
6
6
  import { homeAssistantProxy } from '../../proxies';
7
- export const HomeMonitorSteps = ({ menuItems = [], onStepClick, stepsWithAlerts, }) => {
7
+ export const HomeMonitorSteps = ({ alerts = [], menuItems = [], onStepClick, stepsWithAlerts = [], }) => {
8
8
  const { setSelectedId } = homeAssistantProxy;
9
9
  const isDisabled = menuItems.length === 0;
10
10
  const handleStepClick = (step) => onStepClick(step);
11
- return (_jsx(Flex, { gap: "base", justify: "center", children: homeAssistantSteps.map((step, index) => (_jsx(Box, { position: "relative", flex: "1", children: _jsxs(Fragment, { children: [_jsx(HomeMonitorButton, { currentStep: index + 1, onStepClick: handleStepClick, status: getStatus(index + 1, stepsWithAlerts), step: step }), _jsx(Box, { position: "absolute", top: "-2px", right: "4px", zIndex: "1400", children: _jsx(IconMenu, { zIndex: "2", icon: _jsx(MoreHorizontal, { size: 26 }), itemForm: index + 1, menuItems: menuItems, disabled: isDisabled, onClick: () => setSelectedId(`homeMonitorButton-${index + 1}`) }) })] }) }, step === null || step === void 0 ? void 0 : step.title))) }));
11
+ return (_jsx(Flex, { gap: "base", justify: "center", children: homeAssistantSteps.map((step, index) => {
12
+ var _a;
13
+ return (_jsx(Box, { position: "relative", flex: "1", children: _jsxs(Fragment, { children: [_jsx(HomeMonitorButton, { alertCount: (_a = alerts.find((alert) => alert.step === index + 1)) === null || _a === void 0 ? void 0 : _a.count, currentStep: index + 1, onStepClick: handleStepClick, status: getStatus(index + 1, stepsWithAlerts, alerts), step: step }), _jsx(Box, { position: "absolute", top: "-2px", right: "4px", zIndex: "1400", children: _jsx(IconMenu, { zIndex: "2", icon: _jsx(MoreHorizontal, { size: 26 }), itemForm: index + 1, menuItems: menuItems, disabled: isDisabled, onClick: () => setSelectedId(`homeMonitorButton-${index + 1}`) }) })] }) }, step === null || step === void 0 ? void 0 : step.title));
14
+ }) }));
12
15
  };
13
- const getStatus = (index, stepsWithAlerts) => {
14
- const hasAlert = stepsWithAlerts.includes(index);
16
+ const getStatus = (index, stepsWithAlerts, alerts) => {
17
+ const hasAlert = (stepsWithAlerts === null || stepsWithAlerts === void 0 ? void 0 : stepsWithAlerts.includes(index)) ||
18
+ (alerts === null || alerts === void 0 ? void 0 : alerts.some((alert) => alert.step === index));
15
19
  return hasAlert ? 'alert' : 'ok';
16
20
  };
@@ -1 +1,3 @@
1
- export declare const AlertHeader: () => import("react/jsx-runtime").JSX.Element;
1
+ export declare const AlertHeader: ({ bg }: {
2
+ bg?: string | undefined;
3
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { t } from 'i18next';
3
- import { Flex, Center, Image, Text } from '@chakra-ui/react';
3
+ import { Flex, Center, Image, Text, Box } from '@chakra-ui/react';
4
4
  import { Exclamation } from '../../../assets/images';
5
- export const AlertHeader = () => {
6
- return (_jsx(Flex, { justifyContent: "space-between", px: "base", py: "1", bg: "error.2", borderTopRadius: "lg", align: "center", children: _jsxs(Flex, { align: "center", gap: "2", children: [_jsx(Center, { p: "1", borderRadius: "full", bg: "pink.1", h: "18px", w: "18px", children: _jsx(Image, { src: Exclamation, h: "100%", w: "auto" }) }), _jsx(Text, { color: "white", fontSize: "sm", fontWeight: "medium", textTransform: "uppercase", children: t('homeAssistant.monitorAlerts.homeAction') })] }) }));
5
+ export const AlertHeader = ({ bg = 'error.2' }) => {
6
+ return (_jsx(Flex, { justifyContent: "space-between", px: "base", py: "1", bg: bg, borderTopRadius: "lg", align: "center", children: _jsxs(Flex, { align: "center", gap: "2", children: [_jsxs(Center, { p: "1", position: "relative", h: "18px", w: "18px", children: [_jsx(Box, { borderRadius: "full", bg: "neutral.white", opacity: 0.3, h: "full", w: "full", position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)" }), _jsx(Image, { src: Exclamation, h: "100%", w: "auto" })] }), _jsx(Text, { color: "white", fontSize: "sm", fontWeight: "medium", textTransform: "uppercase", children: t('homeAssistant.monitorAlerts.homeAction') })] }) }));
7
7
  };
@@ -0,0 +1,2 @@
1
+ import { BackendAlertI } from '../../../interfaces';
2
+ export declare const BackendAlert: ({ category, icon, id, title, tabs, summary, }: BackendAlertI) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { BackendAlertCard } from '../..';
3
+ import { getCategoryStyles } from '../../../utils/Alerts.utils';
4
+ export const BackendAlert = ({ category, icon, id, title, tabs, summary, }) => {
5
+ const { headerBg, alertIcon, alertIconBg, alertTitle } = getCategoryStyles(category);
6
+ return (_jsx(BackendAlertCard, { alertBg: headerBg, alertIcon: alertIcon, alertTitle: alertTitle, bg: alertIconBg, icon: icon, title: title, description: summary, children: "content" }));
7
+ };
@@ -0,0 +1,3 @@
1
+ import { PropsWithChildren } from 'react';
2
+ import { BackendAlertCardI } from '../../../interfaces';
3
+ export declare const BackendAlertCard: ({ alertBg, alertIcon, alertTitle, children, ...props }: PropsWithChildren<BackendAlertCardI>) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,21 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { t } from 'i18next';
14
+ import { Box, Button, Collapse, Flex, useDisclosure } from '@chakra-ui/react';
15
+ import { AlertHeader, AlertTemplate, AlertTitle } from '../..';
16
+ import { Warranty } from '../../../assets/images';
17
+ 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
+ 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, { p: "base", 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
+ };
@@ -3,6 +3,8 @@ export * from './AlertHeader';
3
3
  export * from './AlertTemplate';
4
4
  export * from './AlertTitle';
5
5
  export * from './BaseAlertCard';
6
+ export * from './BackendAlert';
7
+ export * from './BackendAlertCard';
6
8
  export * from './WeatherWidget';
7
9
  export * from './HomefileMonitoring';
8
10
  export * from './MonitorAlerts';
@@ -3,6 +3,8 @@ export * from './AlertHeader';
3
3
  export * from './AlertTemplate';
4
4
  export * from './AlertTitle';
5
5
  export * from './BaseAlertCard';
6
+ export * from './BackendAlert';
7
+ export * from './BackendAlertCard';
6
8
  export * from './WeatherWidget';
7
9
  export * from './HomefileMonitoring';
8
10
  export * from './MonitorAlerts';
@@ -1,2 +1,11 @@
1
1
  import { HomeAssistantStepI } from '../../interfaces';
2
+ import { AlertCategory } from '../../interfaces/homeAssistant/BackendAlert.interface';
2
3
  export declare const homeAssistantSteps: Array<HomeAssistantStepI>;
4
+ interface CategoryConfigI {
5
+ label: string;
6
+ icon: string;
7
+ color: string;
8
+ accent: string;
9
+ }
10
+ export declare const CATEGORY_CONFIG: Record<AlertCategory, CategoryConfigI>;
11
+ export {};
@@ -25,3 +25,29 @@ export const homeAssistantSteps = [
25
25
  icon: Water,
26
26
  },
27
27
  ];
28
+ export const CATEGORY_CONFIG = {
29
+ safeguard: {
30
+ label: 'Protection Monitor',
31
+ color: '#DB1DA1',
32
+ accent: '#FDDDF8',
33
+ icon: Fire,
34
+ },
35
+ maintain: {
36
+ label: 'Maintenance Monitor',
37
+ color: '#8CC421',
38
+ accent: '#B9DEF2',
39
+ icon: LargeAppliances,
40
+ },
41
+ budget: {
42
+ label: 'Budget Monitor',
43
+ color: '#1D8BDB',
44
+ accent: '#B9DEF2',
45
+ icon: Target,
46
+ },
47
+ improve: {
48
+ label: 'Improvement Monitor',
49
+ color: '#8516A7',
50
+ accent: '#B9DEF2',
51
+ icon: House,
52
+ },
53
+ };
@@ -0,0 +1,15 @@
1
+ export type AlertCategory = 'safeguard' | 'maintain' | 'budget' | 'improve';
2
+ export type AlertTabType = 'details' | 'filter-size' | 'purchase' | 'hire-out';
3
+ export interface AlertTab<T = unknown> {
4
+ key: AlertTabType;
5
+ label: string;
6
+ data: T;
7
+ }
8
+ export interface BackendAlertI {
9
+ id: string;
10
+ category: AlertCategory;
11
+ icon: string;
12
+ title: string;
13
+ summary: string;
14
+ tabs?: AlertTab[];
15
+ }
@@ -0,0 +1,9 @@
1
+ export interface BackendAlertCardI {
2
+ alertBg?: string;
3
+ alertIcon?: string;
4
+ alertTitle?: string;
5
+ bg?: string;
6
+ icon: string;
7
+ title: string;
8
+ description: string;
9
+ }
@@ -1,12 +1,19 @@
1
1
  import { HomeAssistantStepI, MenuItemI } from '..';
2
+ interface AlertI {
3
+ step: number;
4
+ count: number;
5
+ }
2
6
  export interface HomeMonitortStepsI {
7
+ alerts?: AlertI[];
3
8
  menuItems: MenuItemI[];
4
- stepsWithAlerts: number[];
9
+ stepsWithAlerts?: number[];
5
10
  onStepClick: (step: number) => void;
6
11
  }
7
12
  export interface HomeMonitorButtonI {
13
+ alertCount?: number;
8
14
  currentStep: number;
9
15
  onStepClick: HomeMonitortStepsI['onStepClick'];
10
16
  status: 'alert' | 'ok';
11
17
  step: HomeAssistantStepI;
12
18
  }
19
+ export {};
@@ -1,6 +1,8 @@
1
1
  export * from './ApplianceButton.interface';
2
2
  export * from './ApplianceSteps.interface';
3
+ export * from './BackendAlert.interface';
3
4
  export * from './BaseAlertCard.interface';
5
+ export * from './BackendAlertCard.interface';
4
6
  export * from './HomeAssistantButton.interface';
5
7
  export * from './HomeAssistantPanel.interface';
6
8
  export * from './HomeAssistantStepper.interface';
@@ -1,6 +1,8 @@
1
1
  export * from './ApplianceButton.interface';
2
2
  export * from './ApplianceSteps.interface';
3
+ export * from './BackendAlert.interface';
3
4
  export * from './BaseAlertCard.interface';
5
+ export * from './BackendAlertCard.interface';
4
6
  export * from './HomeAssistantButton.interface';
5
7
  export * from './HomeAssistantPanel.interface';
6
8
  export * from './HomeAssistantStepper.interface';
@@ -0,0 +1,5 @@
1
+ import { Meta } from '@storybook/react';
2
+ import { HomeMonitortStepsI } from '../../interfaces';
3
+ declare const _default: Meta<HomeMonitortStepsI>;
4
+ export default _default;
5
+ export declare const HomeMonitorStepsComponent: (args: HomeMonitortStepsI) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { HomeMonitorSteps } from '../../components';
3
+ import { Box } from '@chakra-ui/react';
4
+ import { action } from '@storybook/addon-actions';
5
+ import { menuMock } from '../../mocks';
6
+ export default {
7
+ title: 'Components/HomeAssistant',
8
+ component: HomeMonitorSteps,
9
+ args: {
10
+ alerts: [
11
+ { step: 2, count: 3 },
12
+ { step: 1, count: 2 },
13
+ { step: 6, count: 2 },
14
+ ],
15
+ menuItems: menuMock,
16
+ onStepClick: action('onStepClick'),
17
+ },
18
+ decorators: [
19
+ (Story) => (_jsx(Box, { p: "base", w: ['full', '800px'], h: "fit-content", children: _jsx(Story, {}) })),
20
+ ],
21
+ };
22
+ export const HomeMonitorStepsComponent = (args) => {
23
+ return _jsx(HomeMonitorSteps, Object.assign({}, args));
24
+ };
@@ -0,0 +1,5 @@
1
+ import { Meta } from '@storybook/react';
2
+ import { MonitorAlertsI } from '../../../interfaces';
3
+ declare const _default: Meta<MonitorAlertsI>;
4
+ export default _default;
5
+ export declare const MonitorAlertsComponent: (args: MonitorAlertsI) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { MonitorAlerts } from '../../../components';
3
+ export default {
4
+ title: 'Components/HomeAssistant/MonitorAlerts',
5
+ component: MonitorAlerts,
6
+ args: {
7
+ alertId: 'change-air-filter',
8
+ },
9
+ };
10
+ export const MonitorAlertsComponent = (args) => {
11
+ return _jsx(MonitorAlerts, Object.assign({}, args));
12
+ };
@@ -0,0 +1,7 @@
1
+ import { AlertCategory } from '../interfaces';
2
+ export declare function getCategoryStyles(cat: AlertCategory): {
3
+ headerBg: string;
4
+ alertTitle: string;
5
+ alertIcon: string;
6
+ alertIconBg: string;
7
+ };
@@ -0,0 +1,10 @@
1
+ import { CATEGORY_CONFIG } from '../helpers';
2
+ export function getCategoryStyles(cat) {
3
+ const cfg = CATEGORY_CONFIG[cat];
4
+ return {
5
+ headerBg: cfg.color,
6
+ alertTitle: cfg.label,
7
+ alertIcon: cfg.icon,
8
+ alertIconBg: cfg.accent,
9
+ };
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@homefile/components-v2",
3
- "version": "2.17.1",
3
+ "version": "2.17.3",
4
4
  "author": "Homefile",
5
5
  "license": "UNLICENSED",
6
6
  "typings": "dist/index.d.ts",
@@ -1,8 +1,10 @@
1
1
  import { Box, Center, Image, Stack, Text } from '@chakra-ui/react'
2
2
  import { HomeMonitorButtonI } from '@/interfaces'
3
3
  import { getIconAltText } from '@/utils'
4
+ import { keyframes } from '@emotion/react'
4
5
 
5
6
  export const HomeMonitorButton = ({
7
+ alertCount = 0,
6
8
  currentStep,
7
9
  onStepClick,
8
10
  status = 'ok',
@@ -10,18 +12,20 @@ export const HomeMonitorButton = ({
10
12
  }: HomeMonitorButtonI) => {
11
13
  const buttonId = `homeMonitorButton-${currentStep}`
12
14
  const iconAltText = getIconAltText(step.icon)
15
+ const alert = status === 'alert'
16
+ const ok = status === 'ok'
13
17
 
14
18
  return (
15
- <Box position="relative" id={buttonId} zIndex="2">
16
- <Box
17
- position="relative"
18
- bg="neutral.white"
19
- borderRadius="lg"
20
- boxShadow="lg"
21
- zIndex="2"
22
- >
19
+ <Box
20
+ position="relative"
21
+ id={buttonId}
22
+ zIndex="2"
23
+ boxShadow="lg"
24
+ {...setStyles(status)}
25
+ >
26
+ <Box position="relative" bg="neutral.white" borderRadius="lg" zIndex="2">
23
27
  <Box
24
- bg={status === 'alert' ? 'error.2' : 'green.1'}
28
+ bg={alert ? 'error.2' : 'green.1'}
25
29
  boxSize="10px"
26
30
  borderRadius="full"
27
31
  position="absolute"
@@ -40,11 +44,25 @@ export const HomeMonitorButton = ({
40
44
  h="96px"
41
45
  w="100%"
42
46
  p="base"
43
- {...setStyles(status)}
44
47
  onClick={() => onStepClick(currentStep)}
48
+ filter={ok ? 'grayscale(1) opacity(0.6)' : ''}
45
49
  >
46
50
  <Center h="60%" marginTop="2">
47
- <Image src={step.icon} alt={iconAltText} w="auto" h="28px" />
51
+ {!alert && (
52
+ <Image src={step.icon} alt={iconAltText} w="auto" h="28px" />
53
+ )}
54
+ {alert && (
55
+ <Center
56
+ boxSize="32px"
57
+ bg="error.2"
58
+ borderRadius="full"
59
+ color="neutral.white"
60
+ lineHeight="1"
61
+ fontWeight="bold"
62
+ >
63
+ {alertCount}
64
+ </Center>
65
+ )}
48
66
  </Center>
49
67
  <Center h="40%">
50
68
  <Text
@@ -62,21 +80,45 @@ export const HomeMonitorButton = ({
62
80
  )
63
81
  }
64
82
 
83
+ const alertGradient = keyframes`
84
+ 0% {
85
+ background-position: 0% 50%;
86
+ }
87
+ 100% {
88
+ background-position: 100% 50%;
89
+ }
90
+ `
91
+
65
92
  const setStyles = (status: HomeMonitorButtonI['status']) => {
66
93
  switch (status) {
67
94
  case 'alert':
68
95
  return {
96
+ background: 'white',
69
97
  cursor: 'pointer',
70
- border: '1px solid',
71
- borderColor: 'error.2',
72
98
  transition: 'all 0.3s',
99
+ borderRadius: 'lg',
100
+ border: 'none',
101
+ _before: {
102
+ content: '""',
103
+ position: 'absolute',
104
+ inset: '-2px',
105
+ borderRadius: 'inherit',
106
+ background:
107
+ 'linear-gradient(270deg,rgb(123, 6, 105),rgb(233, 175, 236), #F544DA)',
108
+ backgroundSize: '400% 400%',
109
+ animation: `${alertGradient} 2s linear infinite`,
110
+ animationDirection: 'alternate',
111
+ zIndex: -1,
112
+ pointerEvents: 'none',
113
+ },
73
114
  _hover: {
74
115
  bg: 'lightGreen.7',
75
116
  },
76
117
  }
77
118
  case 'ok':
78
119
  return {
79
- filter: 'grayscale(1) opacity(0.6)',
120
+ bg: 'neutral.white',
121
+ borderRadius: 'lg',
80
122
  }
81
123
  }
82
124
  }
@@ -6,9 +6,10 @@ import { homeAssistantSteps } from '@/helpers'
6
6
  import { homeAssistantProxy } from '@/proxies'
7
7
 
8
8
  export const HomeMonitorSteps = ({
9
+ alerts = [],
9
10
  menuItems = [],
10
11
  onStepClick,
11
- stepsWithAlerts,
12
+ stepsWithAlerts = [],
12
13
  }: HomeMonitortStepsI) => {
13
14
  const { setSelectedId } = homeAssistantProxy
14
15
 
@@ -21,9 +22,12 @@ export const HomeMonitorSteps = ({
21
22
  <Box key={step?.title} position="relative" flex="1">
22
23
  <Fragment>
23
24
  <HomeMonitorButton
25
+ alertCount={
26
+ alerts.find((alert) => alert.step === index + 1)?.count
27
+ }
24
28
  currentStep={index + 1}
25
29
  onStepClick={handleStepClick}
26
- status={getStatus(index + 1, stepsWithAlerts)}
30
+ status={getStatus(index + 1, stepsWithAlerts, alerts)}
27
31
  step={step}
28
32
  />
29
33
  <Box position="absolute" top="-2px" right="4px" zIndex="1400">
@@ -43,7 +47,13 @@ export const HomeMonitorSteps = ({
43
47
  )
44
48
  }
45
49
 
46
- const getStatus = (index: number, stepsWithAlerts: number[]) => {
47
- const hasAlert = stepsWithAlerts.includes(index)
50
+ const getStatus = (
51
+ index: number,
52
+ stepsWithAlerts: number[],
53
+ alerts: HomeMonitortStepsI['alerts']
54
+ ) => {
55
+ const hasAlert =
56
+ stepsWithAlerts?.includes(index) ||
57
+ alerts?.some((alert) => alert.step === index)
48
58
  return hasAlert ? 'alert' : 'ok'
49
59
  }
@@ -1,19 +1,30 @@
1
1
  import { t } from 'i18next'
2
- import { Flex, Center, Image, Text } from '@chakra-ui/react'
2
+ import { Flex, Center, Image, Text, Box } from '@chakra-ui/react'
3
3
  import { Exclamation } from '@/assets/images'
4
4
 
5
- export const AlertHeader = () => {
5
+ export const AlertHeader = ({ bg = 'error.2' }) => {
6
6
  return (
7
7
  <Flex
8
8
  justifyContent="space-between"
9
9
  px="base"
10
10
  py="1"
11
- bg="error.2"
11
+ bg={bg}
12
12
  borderTopRadius="lg"
13
13
  align="center"
14
14
  >
15
15
  <Flex align="center" gap="2">
16
- <Center p="1" borderRadius="full" bg="pink.1" h="18px" w="18px">
16
+ <Center p="1" position="relative" h="18px" w="18px">
17
+ <Box
18
+ borderRadius="full"
19
+ bg="neutral.white"
20
+ opacity={0.3}
21
+ h="full"
22
+ w="full"
23
+ position="absolute"
24
+ top="50%"
25
+ left="50%"
26
+ transform="translate(-50%, -50%)"
27
+ />
17
28
  <Image src={Exclamation} h="100%" w="auto" />
18
29
  </Center>
19
30
  <Text
@@ -0,0 +1,28 @@
1
+ import { BackendAlertCard } from '@/components'
2
+ import { BackendAlertI } from '@/interfaces'
3
+ import { getCategoryStyles } from '@/utils/Alerts.utils'
4
+
5
+ export const BackendAlert = ({
6
+ category,
7
+ icon,
8
+ id,
9
+ title,
10
+ tabs,
11
+ summary,
12
+ }: BackendAlertI) => {
13
+ const { headerBg, alertIcon, alertIconBg, alertTitle } =
14
+ getCategoryStyles(category)
15
+ return (
16
+ <BackendAlertCard
17
+ alertBg={headerBg}
18
+ alertIcon={alertIcon}
19
+ alertTitle={alertTitle}
20
+ bg={alertIconBg}
21
+ icon={icon}
22
+ title={title}
23
+ description={summary}
24
+ >
25
+ content
26
+ </BackendAlertCard>
27
+ )
28
+ }
@@ -0,0 +1,49 @@
1
+ import { PropsWithChildren } from 'react'
2
+ import { t } from 'i18next'
3
+ import { Box, Button, Collapse, Flex, useDisclosure } from '@chakra-ui/react'
4
+ import { AlertHeader, AlertTemplate, AlertTitle } from '@/components'
5
+ import { BackendAlertCardI } from '@/interfaces'
6
+ import { Warranty } from '@/assets/images'
7
+
8
+ export const BackendAlertCard = ({
9
+ alertBg = 'error.2',
10
+ alertIcon = Warranty,
11
+ alertTitle = t('homeAssistant.monitorAlerts.protection'),
12
+ children,
13
+ ...props
14
+ }: PropsWithChildren<BackendAlertCardI>) => {
15
+ const { isOpen, onToggle } = useDisclosure()
16
+ return (
17
+ <Box
18
+ display="flex"
19
+ flexDir="column"
20
+ bg="neutral.white"
21
+ boxShadow="lg"
22
+ borderRadius="lg"
23
+ overflow="hidden"
24
+ maxW="420px"
25
+ >
26
+ <AlertHeader bg={alertBg} />
27
+ <AlertTitle alertIcon={alertIcon} alertTitle={alertTitle} />
28
+ <AlertTemplate {...props} />
29
+ <Collapse in={isOpen} animateOpacity>
30
+ <Box p="base" bg="lightBlue.1">
31
+ {children}
32
+ </Box>
33
+ </Collapse>
34
+ <Flex py="base" bg="lightBlue.1" justify="flex-end">
35
+ <Button
36
+ variant="leftRounded"
37
+ w="fit-content"
38
+ px="8"
39
+ fontSize="sm"
40
+ fontWeight="medium"
41
+ onClick={onToggle}
42
+ bg={isOpen ? 'blue.8' : 'blue.2'}
43
+ >
44
+ {t(`homeAssistant.monitorAlerts.${isOpen ? 'collapse' : 'review'}`)}
45
+ </Button>
46
+ </Flex>
47
+ </Box>
48
+ )
49
+ }
@@ -3,6 +3,8 @@ export * from './AlertHeader'
3
3
  export * from './AlertTemplate'
4
4
  export * from './AlertTitle'
5
5
  export * from './BaseAlertCard'
6
+ export * from './BackendAlert'
7
+ export * from './BackendAlertCard'
6
8
  export * from './WeatherWidget'
7
9
  export * from './HomefileMonitoring'
8
10
  export * from './MonitorAlerts'
@@ -7,6 +7,7 @@ import {
7
7
  Water,
8
8
  } from '@/assets/images'
9
9
  import { HomeAssistantStepI } from '@/interfaces'
10
+ import { AlertCategory } from '@/interfaces/homeAssistant/BackendAlert.interface'
10
11
 
11
12
  export const homeAssistantSteps: Array<HomeAssistantStepI> = [
12
13
  {
@@ -34,3 +35,37 @@ export const homeAssistantSteps: Array<HomeAssistantStepI> = [
34
35
  icon: Water,
35
36
  },
36
37
  ]
38
+
39
+ interface CategoryConfigI {
40
+ label: string
41
+ icon: string
42
+ color: string
43
+ accent: string
44
+ }
45
+
46
+ export const CATEGORY_CONFIG: Record<AlertCategory, CategoryConfigI> = {
47
+ safeguard: {
48
+ label: 'Protection Monitor',
49
+ color: '#DB1DA1',
50
+ accent: '#FDDDF8',
51
+ icon: Fire,
52
+ },
53
+ maintain: {
54
+ label: 'Maintenance Monitor',
55
+ color: '#8CC421',
56
+ accent: '#B9DEF2',
57
+ icon: LargeAppliances,
58
+ },
59
+ budget: {
60
+ label: 'Budget Monitor',
61
+ color: '#1D8BDB',
62
+ accent: '#B9DEF2',
63
+ icon: Target,
64
+ },
65
+ improve: {
66
+ label: 'Improvement Monitor',
67
+ color: '#8516A7',
68
+ accent: '#B9DEF2',
69
+ icon: House,
70
+ },
71
+ }
@@ -0,0 +1,18 @@
1
+ export type AlertCategory = 'safeguard' | 'maintain' | 'budget' | 'improve'
2
+
3
+ export type AlertTabType = 'details' | 'filter-size' | 'purchase' | 'hire-out'
4
+
5
+ export interface AlertTab<T = unknown> {
6
+ key: AlertTabType
7
+ label: string
8
+ data: T
9
+ }
10
+
11
+ export interface BackendAlertI {
12
+ id: string
13
+ category: AlertCategory
14
+ icon: string
15
+ title: string
16
+ summary: string
17
+ tabs?: AlertTab[]
18
+ }
@@ -0,0 +1,9 @@
1
+ export interface BackendAlertCardI {
2
+ alertBg?: string
3
+ alertIcon?: string
4
+ alertTitle?: string
5
+ bg?: string
6
+ icon: string
7
+ title: string
8
+ description: string
9
+ }
@@ -1,12 +1,19 @@
1
1
  import { HomeAssistantStepI, MenuItemI } from '@/interfaces'
2
2
 
3
+ interface AlertI {
4
+ step: number
5
+ count: number
6
+ }
7
+
3
8
  export interface HomeMonitortStepsI {
9
+ alerts?: AlertI[]
4
10
  menuItems: MenuItemI[]
5
- stepsWithAlerts: number[]
11
+ stepsWithAlerts?: number[]
6
12
  onStepClick: (step: number) => void
7
13
  }
8
14
 
9
15
  export interface HomeMonitorButtonI {
16
+ alertCount?: number
10
17
  currentStep: number
11
18
  onStepClick: HomeMonitortStepsI['onStepClick']
12
19
  status: 'alert' | 'ok'
@@ -1,6 +1,8 @@
1
1
  export * from './ApplianceButton.interface'
2
2
  export * from './ApplianceSteps.interface'
3
+ export * from './BackendAlert.interface'
3
4
  export * from './BaseAlertCard.interface'
5
+ export * from './BackendAlertCard.interface'
4
6
  export * from './HomeAssistantButton.interface'
5
7
  export * from './HomeAssistantPanel.interface'
6
8
  export * from './HomeAssistantStepper.interface'
@@ -0,0 +1,31 @@
1
+ import { Meta } from '@storybook/react'
2
+ import { HomeMonitorSteps } from '@/components'
3
+ import { Box } from '@chakra-ui/react'
4
+ import { action } from '@storybook/addon-actions'
5
+ import { menuMock } from '@/mocks'
6
+ import { HomeMonitortStepsI } from '@/interfaces'
7
+
8
+ export default {
9
+ title: 'Components/HomeAssistant',
10
+ component: HomeMonitorSteps,
11
+ args: {
12
+ alerts: [
13
+ { step: 2, count: 3 },
14
+ { step: 1, count: 2 },
15
+ { step: 6, count: 2 },
16
+ ],
17
+ menuItems: menuMock,
18
+ onStepClick: action('onStepClick'),
19
+ },
20
+ decorators: [
21
+ (Story: any) => (
22
+ <Box p="base" w={['full', '800px']} h="fit-content">
23
+ <Story />
24
+ </Box>
25
+ ),
26
+ ],
27
+ } as Meta<HomeMonitortStepsI>
28
+
29
+ export const HomeMonitorStepsComponent = (args: HomeMonitortStepsI) => {
30
+ return <HomeMonitorSteps {...args} />
31
+ }
@@ -0,0 +1,15 @@
1
+ import { Meta } from '@storybook/react'
2
+ import { MonitorAlerts } from '@/components'
3
+ import { MonitorAlertsI } from '@/interfaces'
4
+
5
+ export default {
6
+ title: 'Components/HomeAssistant/MonitorAlerts',
7
+ component: MonitorAlerts,
8
+ args: {
9
+ alertId: 'change-air-filter',
10
+ },
11
+ } as Meta<MonitorAlertsI>
12
+
13
+ export const MonitorAlertsComponent = (args: MonitorAlertsI) => {
14
+ return <MonitorAlerts {...args} />
15
+ }
@@ -0,0 +1,12 @@
1
+ import { CATEGORY_CONFIG } from '@/helpers'
2
+ import { AlertCategory } from '@/interfaces'
3
+
4
+ export function getCategoryStyles(cat: AlertCategory) {
5
+ const cfg = CATEGORY_CONFIG[cat]
6
+ return {
7
+ headerBg: cfg.color,
8
+ alertTitle: cfg.label,
9
+ alertIcon: cfg.icon,
10
+ alertIconBg: cfg.accent,
11
+ }
12
+ }