blixify-ui-web-mcp 0.1.3 → 0.1.19

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 (168) hide show
  1. package/lib/components/action/button/README.md +12 -11
  2. package/lib/components/action/button/button.stories.tsx +38 -27
  3. package/lib/components/action/buttonGroup/buttonGroup.stories.tsx +82 -16
  4. package/lib/components/action/iconButton/README.md +1 -0
  5. package/lib/components/action/iconButton/iconButton.stories.tsx +6 -12
  6. package/lib/components/action/radioList/radioList.stories.tsx +10 -16
  7. package/lib/components/action/slider/slider.stories.tsx +9 -15
  8. package/lib/components/action/textButton/textButton.stories.tsx +6 -12
  9. package/lib/components/action/toggle/toggle.stories.tsx +6 -12
  10. package/lib/components/advanced/collapse/collapse.stories.tsx +240 -24
  11. package/lib/components/advanced/infoWindow/infoWindow.stories.tsx +10 -16
  12. package/lib/components/advanced/popUp/README.md +33 -7
  13. package/lib/components/advanced/popUp/popUp.stories.tsx +9 -15
  14. package/lib/components/auth/bareSignIn/bareSignIn.stories.tsx +36 -16
  15. package/lib/components/auth/bareSignUp/bareSignUp.stories.tsx +7 -13
  16. package/lib/components/auth/signIn/signIn.stories.tsx +4 -10
  17. package/lib/components/auth/signUp/signUp.stories.tsx +4 -10
  18. package/lib/components/chart/areaChart/areaChart.stories.tsx +12 -18
  19. package/lib/components/chart/barChart/barChart.stories.tsx +12 -18
  20. package/lib/components/chart/boxPlotChart/boxPlotChart.stories.tsx +11 -17
  21. package/lib/components/chart/bubbleChart/bubbleChart.stories.tsx +11 -17
  22. package/lib/components/chart/card/card.stories.tsx +172 -38
  23. package/lib/components/chart/ganttChart/ganttChart.stories.tsx +10 -16
  24. package/lib/components/chart/heatmapChart/heatmapChart.stories.tsx +11 -17
  25. package/lib/components/chart/lineChart/lineChart.stories.tsx +8 -14
  26. package/lib/components/chart/pieChart/pieChart.stories.tsx +11 -17
  27. package/lib/components/chart/polarAreaChart/polarAreaChart.stories.tsx +11 -17
  28. package/lib/components/chart/radarChart/radarChart.stories.tsx +6 -12
  29. package/lib/components/chart/radialBar/radialChart.stories.tsx +4 -10
  30. package/lib/components/chart/rangeBarChart/rangeBarChart.stories.tsx +8 -14
  31. package/lib/components/chart/statsCard/statsCard.stories.tsx +12 -18
  32. package/lib/components/chart/treemapChart/treemapChart.stories.tsx +11 -17
  33. package/lib/components/chat/chatAnchor/README.md +7 -0
  34. package/lib/components/chat/chatAnchor/chatAnchor.stories.tsx +15 -21
  35. package/lib/components/chat/chatBase/README.md +103 -22
  36. package/lib/components/chat/chatBase/chatBase.stories.tsx +657 -57
  37. package/lib/components/chat/chatDashboard/README.md +17 -15
  38. package/lib/components/chat/chatDashboard/chatDashboard.stories.tsx +358 -46
  39. package/lib/components/data/dataGraph/dataGraph.stories.tsx +8 -14
  40. package/lib/components/data/dataReference/dataReference.stories.tsx +9 -15
  41. package/lib/components/data/dataTemplate/README.md +443 -129
  42. package/lib/components/data/dataTemplate/dataModule.stories.tsx +10 -15
  43. package/lib/components/data/dataTemplate/dataTemplate.stories.tsx +20 -34
  44. package/lib/components/data/dataWrapper/README.md +207 -84
  45. package/lib/components/data/dataWrapper/dataWrapper.consumer.stories.tsx +2125 -0
  46. package/lib/components/data/dataWrapper/dataWrapper.edit.stories.tsx +607 -0
  47. package/lib/components/data/dataWrapper/dataWrapper.utils.stories.tsx +576 -0
  48. package/lib/components/data/dataWrapper/dataWrapper.view.stories.tsx +1273 -0
  49. package/lib/components/data/flexFilter/flexFilter.stories.tsx +171 -0
  50. package/lib/components/data/queryForm/queryForm.stories.tsx +6 -12
  51. package/lib/components/data/readQuery/readQuery.stories.tsx +6 -11
  52. package/lib/components/data/readQueryHoc/readQueryHoc.stories.tsx +6 -12
  53. package/lib/components/data/writeQuery/README.md +21 -10
  54. package/lib/components/data/writeQuery/writeQuery.stories.tsx +6 -10
  55. package/lib/components/design/actionSection/actionSection.stories.tsx +10 -14
  56. package/lib/components/design/banner/banner.stories.tsx +6 -12
  57. package/lib/components/design/bannerAction/bannerAction.stories.tsx +100 -21
  58. package/lib/components/design/blogSection/blogSection.stories.tsx +6 -12
  59. package/lib/components/design/carouselSection/carouselSection.stories.tsx +6 -12
  60. package/lib/components/design/designList/designList.stories.tsx +6 -12
  61. package/lib/components/design/faq/faq.stories.tsx +53 -31
  62. package/lib/components/design/fileGrid/fileGrid.stories.tsx +10 -16
  63. package/lib/components/design/fileViewer/fileViewer.stories.tsx +6 -12
  64. package/lib/components/design/footerSection/footerSection.stories.tsx +6 -12
  65. package/lib/components/design/googleReview/googleReview.stories.tsx +6 -12
  66. package/lib/components/design/heroSection/heroSection.stories.tsx +10 -16
  67. package/lib/components/design/iconList/iconList.stories.tsx +6 -12
  68. package/lib/components/design/imageGallery/imageGallery.stories.tsx +6 -12
  69. package/lib/components/design/imageZoom/imageZoom.stories.tsx +6 -12
  70. package/lib/components/design/leftContent/leftContent.stories.tsx +6 -12
  71. package/lib/components/design/logoCloud/logoCloud.stories.tsx +6 -12
  72. package/lib/components/design/onboarding/onboarding.stories.tsx +8 -14
  73. package/lib/components/design/pricing/pricing.stories.tsx +6 -12
  74. package/lib/components/design/rightContent/rightContent.stories.tsx +6 -12
  75. package/lib/components/design/sectionList/sectionList.stories.tsx +6 -12
  76. package/lib/components/design/teams/teams.stories.tsx +6 -12
  77. package/lib/components/display/alert/alert.stories.tsx +8 -14
  78. package/lib/components/display/calendar/README.md +49 -0
  79. package/lib/components/display/calendar/calendar.stories.tsx +78 -35
  80. package/lib/components/display/clipboard/clipboard.stories.tsx +6 -12
  81. package/lib/components/display/detailList/detailList.stories.tsx +172 -48
  82. package/lib/components/display/drawer/README.md +44 -11
  83. package/lib/components/display/drawer/drawer.stories.tsx +71 -16
  84. package/lib/components/display/emptyState/emptyState.stories.tsx +47 -15
  85. package/lib/components/display/feeds/feeds.stories.tsx +6 -12
  86. package/lib/components/display/flexTable/README.md +11 -7
  87. package/lib/components/display/flexTable/flexTable.stories.tsx +318 -20
  88. package/lib/components/display/grid/README.md +29 -30
  89. package/lib/components/display/grid/grid.stories.tsx +16 -23
  90. package/lib/components/display/kanban/kanban.stories.tsx +17 -23
  91. package/lib/components/display/list/README.md +30 -29
  92. package/lib/components/display/list/list.stories.tsx +11 -17
  93. package/lib/components/display/loading/loading.stories.tsx +7 -12
  94. package/lib/components/display/mapView/mapView.stories.tsx +9 -15
  95. package/lib/components/display/modal/modal.stories.tsx +6 -13
  96. package/lib/components/display/newCalendar/README.md +163 -0
  97. package/lib/components/display/newCalendar/newCalendar.stories.tsx +292 -0
  98. package/lib/components/display/newFeeds/README.md +53 -0
  99. package/lib/components/display/newFeeds/newFeeds.stories.tsx +104 -0
  100. package/lib/components/display/newKanban/README.md +25 -0
  101. package/lib/components/display/newKanban/newKanban.stories.tsx +131 -0
  102. package/lib/components/display/newList/README.md +30 -0
  103. package/lib/components/display/newList/newList.stories.tsx +231 -0
  104. package/lib/components/display/newPagination/README.md +15 -0
  105. package/lib/components/display/newTable/README.md +121 -0
  106. package/lib/components/display/newTable/newTable.stories.tsx +551 -0
  107. package/lib/components/display/notification/notification.stories.tsx +6 -12
  108. package/lib/components/display/progress/progress.stories.tsx +7 -12
  109. package/lib/components/display/stepper/README.md +4 -0
  110. package/lib/components/display/stepper/stepper.stories.tsx +70 -23
  111. package/lib/components/display/table/README.md +38 -37
  112. package/lib/components/display/table/table.stories.tsx +34 -36
  113. package/lib/components/display/tag/tag.stories.tsx +34 -40
  114. package/lib/components/input/address/address.stories.tsx +12 -18
  115. package/lib/components/input/canvas/canvas.stories.tsx +12 -18
  116. package/lib/components/input/checkbox/checkbox.stories.tsx +7 -13
  117. package/lib/components/input/datePicker/datePicker.stories.tsx +41 -11
  118. package/lib/components/input/form/form.stories.tsx +11 -17
  119. package/lib/components/input/markdown/README.md +80 -2
  120. package/lib/components/input/markdown/markdown.stories.tsx +83 -32
  121. package/lib/components/input/monthYearPicker/monthYearPicker.stories.tsx +52 -24
  122. package/lib/components/input/netPromoterScore/netPromoterScore.stories.tsx +6 -12
  123. package/lib/components/input/rating/rating.stories.tsx +6 -12
  124. package/lib/components/input/select/README.md +31 -29
  125. package/lib/components/input/select/select.stories.tsx +33 -39
  126. package/lib/components/input/signature/signature.stories.tsx +12 -18
  127. package/lib/components/input/textArea/textArea.stories.tsx +6 -12
  128. package/lib/components/input/textInput/textinput.stories.tsx +14 -20
  129. package/lib/components/input/uploadInput/uploadInput.stories.tsx +143 -19
  130. package/lib/components/navigation/bars/README.md +27 -0
  131. package/lib/components/navigation/bars/bars.stories.tsx +56 -19
  132. package/lib/components/navigation/bottomTab/bottomTab.stories.tsx +7 -12
  133. package/lib/components/navigation/breadcrumb/breadcrumb.stories.tsx +8 -14
  134. package/lib/components/navigation/header/header.stories.tsx +33 -21
  135. package/lib/components/navigation/leftNav/leftNav.stories.tsx +10 -16
  136. package/lib/components/navigation/tabs/tabs.stories.tsx +10 -16
  137. package/lib/components/structure/column/column.stories.tsx +10 -15
  138. package/lib/components/structure/container/container.stories.tsx +8 -13
  139. package/lib/components/structure/link/link.stories.tsx +11 -17
  140. package/lib/components/structure/text/text.stories.tsx +12 -17
  141. package/lib/components/template/authPage/authPage.stories.tsx +6 -5
  142. package/lib/components/template/calendarView/calendarView.stories.tsx +726 -0
  143. package/lib/components/template/chatDashboard/chatDashboard.stories.tsx +497 -0
  144. package/lib/components/template/landingPage/landingPage.stories.tsx +10 -7
  145. package/lib/components/template/mapLayout/mapLayout.stories.tsx +519 -0
  146. package/lib/components/template/productListing/productListing.stories.tsx +7 -13
  147. package/lib/components/template/productOverview/productOverview.stories.tsx +5 -11
  148. package/lib/components/template/shoppingCart/shoppingCart.stories.tsx +6 -12
  149. package/lib/components/template/userHomePage/userHomePage.stories.tsx +384 -524
  150. package/lib/components/template/userRankingDashboard/userRankingDashboard.stories.tsx +145 -75
  151. package/lib/mcp/tools/componentsRoot.d.ts +2 -0
  152. package/lib/mcp/tools/componentsRoot.d.ts.map +1 -0
  153. package/lib/mcp/tools/componentsRoot.js +59 -0
  154. package/lib/mcp/tools/componentsRoot.js.map +1 -0
  155. package/lib/mcp/tools/getBackendComponent.d.ts.map +1 -1
  156. package/lib/mcp/tools/getBackendComponent.js +2 -5
  157. package/lib/mcp/tools/getBackendComponent.js.map +1 -1
  158. package/lib/mcp/tools/getComponent.d.ts.map +1 -1
  159. package/lib/mcp/tools/getComponent.js +2 -5
  160. package/lib/mcp/tools/getComponent.js.map +1 -1
  161. package/lib/mcp/tools/listComponents.d.ts.map +1 -1
  162. package/lib/mcp/tools/listComponents.js +15 -10
  163. package/lib/mcp/tools/listComponents.js.map +1 -1
  164. package/lib/mcp/tools/suggestTemplate.d.ts.map +1 -1
  165. package/lib/mcp/tools/suggestTemplate.js +107 -21
  166. package/lib/mcp/tools/suggestTemplate.js.map +1 -1
  167. package/package.json +1 -1
  168. package/lib/components/data/dataWrapper/dataWrapper.stories.tsx +0 -831
@@ -1,605 +1,465 @@
1
- import { storiesOf } from "@storybook/react";
1
+ import { Disclosure, Menu, Popover, Transition } from "@headlessui/react";
2
+ import {
3
+ ArrowDownTrayIcon,
4
+ ArrowPathIcon,
5
+ ArrowTrendingUpIcon,
6
+ BellIcon,
7
+ CheckCircleIcon,
8
+ FireIcon,
9
+ PlusIcon,
10
+ SparklesIcon,
11
+ } from "@heroicons/react/24/outline";
12
+ import {
13
+ ChartBarIcon,
14
+ HomeIcon,
15
+ ListBulletIcon,
16
+ UserIcon,
17
+ } from "@heroicons/react/24/solid";
2
18
  import React, { useState } from "react";
3
19
  import { Button } from "../../action/button";
4
- import { ActionSection } from "../../design/actionSection";
5
- import { FAQContent } from "../../design/faq";
6
- import { FooterSection } from "../../design/footerSection";
7
- import { GoogleReview } from "../../design/googleReview";
8
- import { IconList } from "../../design/iconList";
9
- import { Grid, GridClass } from "../../display/grid";
10
- import { Modal } from "../../display/modal";
11
- import { Select } from "../../input/select";
12
- import { TextInput } from "../../input/textInput";
20
+ import { ButtonGroup } from "../../action/buttonGroup";
21
+ import { AreaChart } from "../../chart/areaChart";
22
+ import { Card } from "../../chart/card";
23
+ import { Collapse } from "../../advanced/collapse";
13
24
  import { Container } from "../../structure/container";
25
+ import { FooterSection } from "../../design/footerSection";
26
+ import { BottomTab } from "../../navigation/bottomTab";
14
27
  import { Header } from "../../navigation/header";
15
- import "../../../index.css";
16
- import { Disclosure, Menu, Popover, Transition } from "@headlessui/react";
17
- // eslint-disable-next-line @typescript-eslint/no-var-requires
18
- const Logo = require("../../../assets/logo.png");
28
+ import { NewList, NewListItem } from "../../display/newList";
29
+ import { Progress } from "../../display/progress";
19
30
 
20
- const stories = storiesOf("Template", module);
31
+ const meta = { title: "Template/App Home Page" };
32
+ export default meta;
21
33
 
22
- const QUAL_ITEMS = [
23
- {
24
- title: "Own a Property",
25
- desc: "Perfect, that means our service is a great fit.",
26
- icon: (
27
- <svg
28
- className="w-6 h-6"
29
- fill="none"
30
- viewBox="0 0 24 24"
31
- stroke="currentColor"
32
- >
33
- <path
34
- strokeLinecap="round"
35
- strokeLinejoin="round"
36
- strokeWidth={2}
37
- d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
38
- />
39
- </svg>
40
- ),
41
- },
42
- {
43
- title: "Monthly Electricity Bill Over RM 200",
44
- desc: "The higher your bill, the more you stand to save with solar.",
45
- icon: (
46
- <svg
47
- className="w-6 h-6"
48
- fill="none"
49
- viewBox="0 0 24 24"
50
- stroke="currentColor"
51
- >
52
- <path
53
- strokeLinecap="round"
54
- strokeLinejoin="round"
55
- strokeWidth={2}
56
- d="M13 10V3L4 14h7v7l9-11h-7z"
57
- />
58
- </svg>
59
- ),
60
- },
34
+
35
+ const Logo = new URL("../../../assets/logo.png", import.meta.url).href;
36
+
37
+ // ─── Sample data (domain-neutral) ───────────────────────────────────────────
38
+
39
+ const TODAY = new Date();
40
+ const fmtDate = TODAY.toLocaleDateString(undefined, {
41
+ weekday: "long",
42
+ day: "numeric",
43
+ month: "long",
44
+ });
45
+
46
+ const NAVIGATION = [
47
+ { name: "Home", href: "#" },
48
+ { name: "Activity", href: "#" },
49
+ { name: "Insights", href: "#" },
50
+ { name: "Settings", href: "#" },
61
51
  ];
62
52
 
63
- const USE_CASE_ITEMS = [
64
- {
65
- id: "user-1",
66
- percentage: "90%",
67
- imageSrc:
68
- "https://images.unsplash.com/photo-1494790108377-be9c29b29330?auto=format&fit=facearea&facepad=2&w=400&h=300&q=80",
69
- name: "Sarah Lim",
70
- location: "Petaling Jaya, Selangor",
71
- totalSaving: "RM 450/mo",
72
- monthlySaving: "RM 45/mo",
73
- videoUrl: "",
74
- },
53
+ const USER_NAV = [
54
+ { name: "Your profile", action: () => {} },
55
+ { name: "Sign out", action: () => {} },
56
+ ];
57
+
58
+ const USER = {
59
+ name: "Louis Ong",
60
+ email: "louis@blixify.co",
61
+ image: Logo,
62
+ };
63
+
64
+ // INFO: BottomTab uses solid heroicons + href links. Mirrors the desktop
65
+ // Header nav so mobile users get the same surface in thumb-reach.
66
+ const BOTTOM_TABS = [
67
+ { icon: HomeIcon, title: "Home", href: "#" },
68
+ { icon: ChartBarIcon, title: "Insights", href: "#" },
69
+ { icon: ListBulletIcon, title: "Activity", href: "#" },
70
+ { icon: UserIcon, title: "Profile", href: "#" },
71
+ ];
72
+
73
+ // INFO: FooterSection expects FooterList[] with title + subList. Mirrors
74
+ // the header nav so signed-in users get the same surface in both places.
75
+ const FOOTER_LIST = [
75
76
  {
76
- id: "user-2",
77
- percentage: "50%",
78
- imageSrc:
79
- "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?auto=format&fit=facearea&facepad=2&w=400&h=300&q=80",
80
- name: "Ahmad Razif",
81
- location: "Johor Bahru, Johor",
82
- totalSaving: "RM 320/mo",
83
- monthlySaving: "RM 160/mo",
84
- videoUrl: "",
77
+ title: "Navigate",
78
+ subList: NAVIGATION.map((n) => ({ name: n.name, link: n.href })),
85
79
  },
86
80
  {
87
- id: "user-3",
88
- percentage: "60%",
89
- imageSrc:
90
- "https://images.unsplash.com/photo-1550525811-e5869dd03032?auto=format&fit=facearea&facepad=2&w=400&h=300&q=80",
91
- name: "Priya Nair",
92
- location: "George Town, Penang",
93
- totalSaving: "RM 380/mo",
94
- monthlySaving: "RM 152/mo",
95
- videoUrl: "",
81
+ title: "Account",
82
+ subList: [
83
+ { name: "Profile", link: "#" },
84
+ { name: "Sign out", link: "#" },
85
+ ],
96
86
  },
97
87
  ];
98
88
 
99
- const WHY_ITEMS = [
100
- {
101
- image:
102
- "https://images.unsplash.com/photo-1519244703995-f4e0f30006d5?auto=format&fit=crop&w=128&h=128&q=80",
103
- title: "Lorem ipsum dolor sit amet.",
104
- desc: "Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.",
105
- },
89
+ const QUICK_ACTIONS = [
90
+ { id: "add", label: "Add entry", icon: PlusIcon },
91
+ { id: "new", label: "New record", icon: SparklesIcon },
92
+ { id: "sync", label: "Sync", icon: ArrowPathIcon },
93
+ { id: "export", label: "Export", icon: ArrowDownTrayIcon },
94
+ ];
95
+
96
+ const KPI_TILES = [
106
97
  {
107
- image:
108
- "https://images.unsplash.com/photo-1517841905240-472988babdf9?auto=format&fit=crop&w=128&h=128&q=80",
109
- title: "Consectetur adipiscing elit.",
110
- desc: "Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua ut enim ad minim veniam.",
98
+ title: "Streak",
99
+ count: 12,
100
+ unit: "days",
101
+ description: "Best: 24 days",
102
+ trend: "On track",
103
+ icon: FireIcon,
111
104
  },
112
105
  {
113
- image:
114
- "https://images.unsplash.com/photo-1505840717430-882ce147ef2d?auto=format&fit=crop&w=128&h=128&q=80",
115
- title: "Ut enim ad minim veniam.",
116
- desc: "Quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat duis aute.",
106
+ title: "This Week",
107
+ count: 547,
108
+ unit: "pts",
109
+ description: "Mon — Sun",
110
+ trend: "+18% MoM",
111
+ icon: SparklesIcon,
117
112
  },
118
113
  ];
119
114
 
120
- const HOW_IT_WORKS_STEPS = [
115
+ // INFO: 7-day trend for the area chart — 1 series, last 7 days
116
+ const TREND_CATEGORIES = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
117
+ const TREND_SERIES = [
118
+ { name: "Score", data: [62, 71, 65, 78, 74, 82, 82] },
119
+ ];
120
+
121
+ // INFO: progress bars are visualisations (chart-adjacent), so they keep
122
+ // distinct fill colours — but the palette is intentionally cohesive
123
+ // (primary -> teal -> indigo) rather than the previous primary/emerald/amber
124
+ // rainbow.
125
+ const PROGRESS_BARS = [
121
126
  {
122
- title: "Step 1: Get a Free Quote",
123
- description:
124
- "Fill in your details and we'll prepare a custom proposal for you.",
125
- icon: (
126
- <svg
127
- className="w-6 h-6"
128
- fill="none"
129
- viewBox="0 0 24 24"
130
- stroke="currentColor"
131
- >
132
- <path
133
- strokeLinecap="round"
134
- strokeLinejoin="round"
135
- strokeWidth={2}
136
- d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
137
- />
138
- </svg>
139
- ),
127
+ id: "p1",
128
+ label: "Goal A",
129
+ current: 6,
130
+ target: 8,
131
+ unit: "hrs",
132
+ fill: "bg-gradient-to-r from-primary-500 to-primary-400",
140
133
  },
141
134
  {
142
- title: "Step 2: Professional Installation",
143
- description: "Our certified team handles your request quickly and cleanly.",
144
- icon: (
145
- <svg
146
- className="w-6 h-6"
147
- fill="none"
148
- viewBox="0 0 24 24"
149
- stroke="currentColor"
150
- >
151
- <path
152
- strokeLinecap="round"
153
- strokeLinejoin="round"
154
- strokeWidth={2}
155
- d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"
156
- />
157
- </svg>
158
- ),
135
+ id: "p2",
136
+ label: "Goal B",
137
+ current: 1850,
138
+ target: 2200,
139
+ unit: "kcal",
140
+ fill: "bg-gradient-to-r from-teal-500 to-teal-400",
159
141
  },
160
142
  {
161
- title: "Step 3: Start Saving",
162
- description: "Track your progress and savings directly in the app.",
163
- icon: (
164
- <svg
165
- className="w-6 h-6"
166
- fill="none"
167
- viewBox="0 0 24 24"
168
- stroke="currentColor"
169
- >
170
- <path
171
- strokeLinecap="round"
172
- strokeLinejoin="round"
173
- strokeWidth={2}
174
- d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
175
- />
176
- </svg>
177
- ),
143
+ id: "p3",
144
+ label: "Goal C",
145
+ current: 7200,
146
+ target: 10000,
147
+ unit: "steps",
148
+ fill: "bg-gradient-to-r from-indigo-500 to-indigo-400",
178
149
  },
179
150
  ];
180
151
 
181
- const FAQ_LIST = [
152
+ // INFO: recent activity uses emoji as the avatar — replaces the previous
153
+ // icon-with-coloured-background pattern. Emoji adds personality without the
154
+ // visual noise of multiple coloured circles competing for attention.
155
+ const RECENT_ITEMS: NewListItem[] = [
182
156
  {
183
- question: "How does the system work?",
184
- answer:
185
- "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
157
+ id: "r1",
158
+ title: "Activity logged",
159
+ description: "Recorded 45 mins · 320 kcal",
160
+ icon: <span className="text-2xl">🏃</span>,
161
+ date: new Date(TODAY.getTime() - 1000 * 60 * 45),
186
162
  },
187
163
  {
188
- question: "What is the payback period?",
189
- answer:
190
- "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
164
+ id: "r2",
165
+ title: "Reminder dismissed",
166
+ description: "Daily check-in completed",
167
+ icon: <span className="text-2xl">🔔</span>,
168
+ date: new Date(TODAY.getTime() - 1000 * 60 * 60 * 2),
191
169
  },
192
170
  {
193
- question: "How much do I need to invest?",
194
- answer:
195
- "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
171
+ id: "r3",
172
+ title: "Entry created",
173
+ description: "Manual entry · 240 kcal",
174
+ icon: <span className="text-2xl">📝</span>,
175
+ date: new Date(TODAY.getTime() - 1000 * 60 * 60 * 4),
196
176
  },
197
177
  {
198
- question: "By how much will my costs be reduced?",
199
- answer:
200
- "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
178
+ id: "r4",
179
+ title: "Sync completed",
180
+ description: "12 new items synced",
181
+ icon: <span className="text-2xl">🔄</span>,
182
+ date: new Date(TODAY.getTime() - 1000 * 60 * 60 * 6),
201
183
  },
202
184
  ];
203
185
 
204
- const PRODUCT_CARDS: GridClass[] = [
186
+ const REMINDER_ITEMS: NewListItem[] = [
205
187
  {
206
- id: "product-a",
207
- title: "Solar PV System",
208
- description: "Generate your own clean electricity",
188
+ id: "rm1",
189
+ title: "Weekly review",
190
+ description: "Schedule pending — Sun 9:00 AM",
191
+ icon: <span className="text-2xl">⏰</span>,
209
192
  },
210
193
  {
211
- id: "product-b",
212
- title: "Solar + Battery Storage",
213
- description: "Generate and store energy for round-the-clock savings",
194
+ id: "rm2",
195
+ title: "Profile incomplete",
196
+ description: "Add your preferences to personalise recommendations",
197
+ icon: <span className="text-2xl">👤</span>,
214
198
  },
215
199
  ];
216
200
 
217
- const PRODUCT_GRID_ITEMS: { [id: string]: React.ReactElement } = {
218
- "product-a": (
219
- <div className="flex flex-col rounded-xl overflow-hidden shadow-md bg-white">
220
- <img
221
- src="https://images.unsplash.com/photo-1508514177221-188b1cf16e9d?auto=format&fit=crop&w=600&h=300&q=80"
222
- alt="Product A"
223
- className="h-48 w-full object-cover"
224
- />
225
- <div className="p-6 flex flex-col gap-y-2">
226
- <p className="text-lg font-semibold text-gray-900">Solar PV System</p>
227
- <p className="text-sm text-gray-500">Model: Jinko Tiger Neo 580W</p>
228
- <p className="text-sm text-gray-500">System Size: 8 kWp · 14 panels</p>
229
- <p className="text-2xl font-bold text-primary-600 mt-2">
230
- Save RM 280/mo
231
- </p>
232
- <span className="inline-block mt-1 px-3 py-1 bg-primary-100 text-primary-700 text-xs font-semibold rounded-full w-fit">
233
- ~70% savings
234
- </span>
201
+ // ─── Inline sub-components ──────────────────────────────────────────────────
202
+
203
+ // INFO: HeroCard keeps the primary->violet gradient — one decorative moment
204
+ // at the top sets the tone, but everything below it standardises on
205
+ // `primary` so the eye isn't pulled in 5 directions. Headers / heroes are
206
+ // not interactive UI; the rule "interactive = primary only" still holds.
207
+ const HeroCard = ({ name, streak }: { name: string; streak: number }) => (
208
+ <div className="relative mt-4 overflow-hidden rounded-2xl bg-gradient-to-br from-primary-500 via-primary-400 to-violet-500 p-5 text-white shadow-lg md:p-6">
209
+ <div className="pointer-events-none absolute -right-10 -top-10 h-40 w-40 rounded-full bg-white/10 blur-2xl" />
210
+ <div className="pointer-events-none absolute -bottom-12 -left-8 h-32 w-32 rounded-full bg-white/10 blur-2xl" />
211
+ <div className="relative">
212
+ <p className="text-xs font-medium uppercase tracking-wide text-white/80">
213
+ {fmtDate}
214
+ </p>
215
+ <h1 className="mt-1 text-2xl font-bold md:text-3xl">
216
+ Good morning, {name} 👋
217
+ </h1>
218
+ <div className="mt-3 inline-flex items-center gap-1.5 rounded-full bg-white/20 px-3 py-1 text-xs font-semibold backdrop-blur">
219
+ <FireIcon className="h-3.5 w-3.5 text-white" />
220
+ <span>{streak} day streak — keep it going!</span>
235
221
  </div>
236
222
  </div>
237
- ),
238
- "product-b": (
239
- <div className="flex flex-col rounded-xl overflow-hidden shadow-md bg-white">
240
- <img
241
- src="https://images.unsplash.com/photo-1466611653911-95081537e5b7?auto=format&fit=crop&w=600&h=300&q=80"
242
- alt="Product B"
243
- className="h-48 w-full object-cover"
244
- />
245
- <div className="p-6 flex flex-col gap-y-2">
246
- <p className="text-lg font-semibold text-gray-900">
247
- Solar + Battery Storage
248
- </p>
249
- <p className="text-sm text-gray-500">
250
- Model: Jinko Tiger Neo 580W + Growatt 10kWh
251
- </p>
252
- <p className="text-sm text-gray-500">System Size: 10 kWp · 18 panels</p>
253
- <p className="text-2xl font-bold text-primary-600 mt-2">
254
- Save RM 380/mo
223
+ </div>
224
+ );
225
+
226
+ const ProgressBar = ({
227
+ label,
228
+ current,
229
+ target,
230
+ unit,
231
+ fill,
232
+ }: {
233
+ label: string;
234
+ current: number;
235
+ target: number;
236
+ unit: string;
237
+ fill: string;
238
+ }) => {
239
+ const pct = Math.min(100, Math.round((current / target) * 100));
240
+ const isComplete = pct >= 100;
241
+ return (
242
+ <div>
243
+ <div className="mb-1.5 flex items-baseline justify-between">
244
+ <div className="flex items-center gap-2">
245
+ <p className="text-sm font-medium text-gray-800">{label}</p>
246
+ {isComplete && (
247
+ <span className="inline-flex items-center gap-1 rounded-full bg-primary-100 px-2 py-0.5 text-[10px] font-bold uppercase text-primary-700">
248
+ <CheckCircleIcon className="h-3 w-3" />
249
+ Done
250
+ </span>
251
+ )}
252
+ </div>
253
+ <p className="text-xs text-gray-500">
254
+ <span className="font-semibold text-gray-900">{current}</span>
255
+ {" / "}
256
+ {target} {unit}
255
257
  </p>
256
- <span className="inline-block mt-1 px-3 py-1 bg-primary-100 text-primary-700 text-xs font-semibold rounded-full w-fit">
257
- ~90% savings
258
- </span>
258
+ </div>
259
+ <div className="h-2.5 w-full overflow-hidden rounded-full bg-gray-100">
260
+ <div
261
+ className={`h-full rounded-full transition-all ${fill}`}
262
+ style={{ width: `${pct}%` }}
263
+ />
259
264
  </div>
260
265
  </div>
261
- ),
266
+ );
262
267
  };
263
268
 
264
- stories.add("User Home Page", () => {
265
- const [videoModal, setVideoModal] = useState(false);
266
- const [videoUrl, setVideoUrl] = useState("");
267
-
268
- const gridItems: GridClass[] = USE_CASE_ITEMS.map((item) => ({
269
- id: item.id,
270
- title: item.name,
271
- description: item.location,
272
- imageUrl: item.imageSrc,
273
- extra: item,
274
- }));
275
-
276
- const customGridItems: { [id: string]: React.ReactElement } = {};
277
- USE_CASE_ITEMS.forEach((item) => {
278
- customGridItems[item.id] = (
279
- <div className="w-72 h-full flex flex-col rounded-3xl shadow-lg overflow-hidden lg:w-full hover:shadow-xl">
280
- <img
281
- src={item.imageSrc}
282
- alt={item.name}
283
- className="h-48 object-cover rounded-t-3xl"
284
- />
285
- <div className="-mt-6 p-6 bg-primary-900 text-white">
286
- <h1 className="text-5xl font-bold">{item.percentage}</h1>
287
- <p>reduction in bill</p>
288
- <p className="text-primary-300 text-xl font-semibold">
289
- From {item.totalSaving} to {item.monthlySaving}
290
- </p>
291
- <div className="mt-8 flex justify-between items-center">
292
- <div className="text-sm text-gray-300">
293
- <p>{item.name}</p>
294
- <p>{item.location}</p>
295
- </div>
296
- {item.videoUrl && (
297
- <button
298
- onClick={() => {
299
- setVideoUrl(item.videoUrl!);
300
- setVideoModal(true);
301
- }}
302
- className="text-primary-300 hover:text-white"
303
- >
304
- <svg
305
- className="w-8 h-8"
306
- fill="currentColor"
307
- viewBox="0 0 24 24"
308
- >
309
- <path d="M8 5v14l11-7z" />
310
- </svg>
311
- </button>
312
- )}
313
- </div>
314
- </div>
315
- </div>
316
- );
317
- });
269
+ const TrendChip = ({ text }: { text: string }) => (
270
+ <div className="inline-flex items-center gap-1 text-xs font-medium text-primary-600">
271
+ <ArrowTrendingUpIcon className="h-3.5 w-3.5" />
272
+ <span>{text}</span>
273
+ </div>
274
+ );
275
+
276
+ // ─── Story ─────────────────────────────────────────────────────────────────
277
+
278
+ export const AppHomePage = () => {
279
+ const [activeAction, setActiveAction] = useState<string | null>(null);
318
280
 
319
281
  return (
320
- <div className="bg-white">
282
+ <div className="min-h-screen bg-gray-50">
283
+ {/* HEADER — sticky top nav with logo, links, avatar */}
321
284
  <Header
322
285
  defaultNav="/"
323
- page="Headphones"
286
+ page="Home"
324
287
  logo={Logo}
325
- navigation={[
326
- { name: "Home", href: "#" },
327
- { name: "Products", href: "#" },
328
- { name: "Calculator", href: "#" },
329
- { name: "About Us", href: "#" },
330
- ]}
288
+ navigation={NAVIGATION}
289
+ userNavigation={USER_NAV}
290
+ user={USER}
331
291
  lib={{ Disclosure, Menu, Transition, Popover }}
332
292
  />
333
- <div
334
- className="relative h-screen bg-cover bg-top"
335
- style={{
336
- backgroundImage:
337
- "url(https://images.unsplash.com/photo-1508514177221-188b1cf16e9d?auto=format&fit=crop&w=1920&q=80)",
338
- }}
339
- >
340
- <div className="absolute inset-0 bg-black/40 z-0" />
341
- <div className="relative z-10 h-full flex flex-col items-center justify-center text-center px-4">
342
- <p className="mb-4 text-xl font-medium text-primary-200 sm:text-2xl md:text-3xl">
343
- Malaysia's Leading Solar Energy Provider
344
- </p>
345
- <h1 className="text-3xl font-bold text-white mb-8 max-w-3xl md:text-5xl">
346
- Cut Your Electricity Bill by Up to 90%
347
- </h1>
348
- <div className="mb-6 text-lg text-gray-200 max-w-xl">
349
- {[
350
- "How much can I save by switching to solar?",
351
- "What is the payback period for solar panels?",
352
- "How do I get started with solar installation?",
353
- ].map((q, i) => (
354
- <p key={i} className="mb-1 italic">
355
- "{q}"
356
- </p>
357
- ))}
293
+
294
+ <Container bgColor="bg-gray-50" className="pb-28">
295
+ <HeroCard name="Louis" streak={12} />
296
+
297
+ {/* Quick actions — selectable pill group via ButtonGroup */}
298
+ <ButtonGroup
299
+ containerClassName="mt-4"
300
+ variant="pill"
301
+ selectedId={activeAction}
302
+ onClick={(id) => setActiveAction(id)}
303
+ selection={QUICK_ACTIONS.map((a) => {
304
+ const Icon = a.icon;
305
+ const isActive = activeAction === a.id;
306
+ return {
307
+ id: a.id,
308
+ name: a.label,
309
+ icon: (
310
+ <Icon
311
+ className={`h-4 w-4 ${
312
+ isActive ? "text-white" : "text-primary-600"
313
+ }`}
314
+ />
315
+ ),
316
+ };
317
+ })}
318
+ />
319
+
320
+ {/* Score + KPI tiles — mobile: Score spans both columns then
321
+ Streak + This Week share a row. Desktop (md+): all three sit
322
+ in a single 3-col row so the score tile no longer floats in
323
+ ~1200px of empty space. */}
324
+ <div className="mt-4 grid grid-cols-2 gap-3 md:grid-cols-3">
325
+ <div className="col-span-2 rounded-2xl border border-gray-200 bg-white p-4 shadow-sm md:col-span-1">
326
+ <div className="flex items-baseline justify-between">
327
+ <p className="text-sm font-medium text-gray-500">Today's Score</p>
328
+ <TrendChip text="+5 vs yesterday" />
329
+ </div>
330
+ <div className="mt-1 flex items-baseline gap-1">
331
+ <p className="text-4xl font-bold text-gray-900">82</p>
332
+ <p className="text-lg font-medium text-gray-400">/100</p>
333
+ </div>
334
+ <div className="mt-3">
335
+ <Progress percentage={82} />
336
+ </div>
358
337
  </div>
359
- <Button text="GET STARTED" type="normal" onClick={() => {}} />
338
+ {KPI_TILES.map((kpi) => {
339
+ const Icon = kpi.icon;
340
+ return (
341
+ <Card
342
+ key={kpi.title}
343
+ size="compact"
344
+ icon={<Icon className="h-4 w-4 text-primary-600" />}
345
+ iconBgColor="bg-primary-100"
346
+ title={kpi.title}
347
+ count={kpi.count}
348
+ unit={kpi.unit}
349
+ description={kpi.description}
350
+ subContent={<TrendChip text={kpi.trend} />}
351
+ />
352
+ );
353
+ })}
360
354
  </div>
361
- </div>
362
355
 
363
- <div id="use-case-section">
364
- <Modal
365
- open={videoModal}
366
- renderContent={() => (
367
- <iframe
368
- width="100%"
369
- height="500"
370
- src={videoUrl}
371
- title="Video"
372
- allowFullScreen
356
+ {/* TREND CHART — single focal data viz, compact at ~200px */}
357
+ <div className="mt-3">
358
+ <div className="overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-sm">
359
+ <AreaChart
360
+ title="Last 7 days"
361
+ categories={TREND_CATEGORIES}
362
+ stackedAreaSeries={TREND_SERIES}
363
+ chartSize={200}
364
+ showToolbar={false}
373
365
  />
374
- )}
375
- onClose={() => setVideoModal(false)}
376
- maxWidth="4xl"
377
- />
378
- <Container className="pb-20 pt-10">
379
- <div className="flex flex-col justify-center items-center text-center">
380
- <h1 className="text-xl md:text-3xl">If you meet both criteria,</h1>
381
- <h1 className="text-3xl font-semibold text-primary-800 md:text-5xl md:mt-2">
382
- You are a qualified applicant!
383
- </h1>
384
366
  </div>
385
- <div className="mt-8 flex flex-col gap-y-4 md:flex-row md:gap-x-8">
386
- {QUAL_ITEMS.map((item, i) => (
387
- <div
388
- key={i}
389
- className="p-6 flex flex-1 gap-x-4 items-start bg-white rounded-xl shadow-lg hover:shadow-xl md:p-10"
390
- >
391
- <div className="h-fit flex-shrink-0 text-primary-600">
392
- {item.icon}
393
- </div>
394
- <div className="flex flex-col gap-y-1">
395
- <p className="text-xl font-medium leading-none lg:text-2xl">
396
- {item.title}
397
- </p>
398
- <p className="text-sm text-gray-500 lg:text-base">
399
- {item.desc}
400
- </p>
401
- </div>
402
- </div>
403
- ))}
404
- </div>
405
- <div className="mt-14">
406
- <Grid
407
- data={gridItems}
408
- hidePagination
409
- loading={false}
410
- customGridItems={customGridItems}
411
- itemClassName="mb-5 !bg-gray-50 shadow-none w-full"
412
- gridColClassName="mb-0 gap-6 grid-cols-1 sm:grid-cols-3 md:gap-8"
413
- horizontalScroll
367
+ </div>
368
+
369
+ {/* Today's progress + Reminders — stacked on mobile, side-by-side
370
+ on desktop (md+) so each section gets ~50% of the row instead
371
+ of stretching its single goal bar across the full container. */}
372
+ <div className="mt-4 grid gap-4 md:grid-cols-2">
373
+ <div className="overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-sm">
374
+ <Collapse
375
+ title="Today's progress"
376
+ summary={`${PROGRESS_BARS.length} goals`}
377
+ defaultOpen
378
+ icon={<CheckCircleIcon className="h-5 w-5 text-primary-500" />}
379
+ contentClassName="space-y-4 px-4 py-4"
380
+ content={
381
+ <>
382
+ {PROGRESS_BARS.map((p) => (
383
+ <ProgressBar key={p.id} {...p} />
384
+ ))}
385
+ </>
386
+ }
414
387
  />
415
388
  </div>
416
- </Container>
417
- </div>
418
389
 
419
- <Container bgColor="bg-gray-100" className="py-16">
420
- <h2 className="text-3xl font-semibold text-primary-800 text-center md:text-5xl">
421
- Why Choose Us?
422
- </h2>
423
- <div className="my-14 gap-y-6 grid sm:grid-cols-2 sm:gap-x-6 md:mt-20 lg:grid-cols-3 lg:gap-x-8">
424
- {WHY_ITEMS.map((item, i) => (
425
- <div key={i}>
426
- <div className="justify-center flex">
427
- <img
428
- src={item.image}
429
- alt={item.title}
430
- className="mb-6 w-20 h-20 rounded-full object-cover md:mb-8 md:w-32 md:h-32"
390
+ {/* Reminders — Modern Mobile pattern from Collapse stories: bold
391
+ 3-stop primary gradient on collapseContainerCss + notCollapse
392
+ ContainerCss (the container bg). White contentClassName covers
393
+ the body when expanded, so the gradient only shows on the
394
+ header bar. White title text + primary-50 summary read cleanly
395
+ on the gradient. */}
396
+ <div className="overflow-hidden rounded-2xl shadow-md">
397
+ <Collapse
398
+ title="Reminders"
399
+ summary={`${REMINDER_ITEMS.length} pending`}
400
+ defaultOpen
401
+ icon={<BellIcon className="h-5 w-5 text-white" />}
402
+ collapseContainerCss="bg-gradient-to-br from-primary-500 via-primary-400 to-violet-500 !border-0"
403
+ notCollapseContainerCss="bg-gradient-to-br from-primary-500 via-primary-400 to-violet-500"
404
+ titleClassName="text-white text-base font-semibold"
405
+ summaryClassName="text-primary-50"
406
+ iconClassName="w-5 h-5 text-white"
407
+ contentClassName="p-0 bg-white border-t border-primary-100"
408
+ content={
409
+ <NewList
410
+ list={REMINDER_ITEMS}
411
+ className="rounded-none border-0 shadow-none"
431
412
  />
432
- </div>
433
- <p className="mb-2 text-xl text-primary-800 text-center font-medium md:text-2xl">
434
- {item.title}
435
- </p>
436
- <p className="text-sm text-center md:text-base">{item.desc}</p>
437
- </div>
438
- ))}
413
+ }
414
+ />
415
+ </div>
439
416
  </div>
440
- </Container>
441
417
 
442
- <div id="calculator-section">
443
- <Container bgColor="bg-white" className="py-14">
444
- <div className="text-center mb-10">
445
- <h2 className="text-3xl font-semibold text-primary-800 md:text-5xl">
446
- Solar Savings Calculator
418
+ {/* Recent activity — emoji avatars. Full width on desktop to match
419
+ the Progress/Reminders row above. */}
420
+ <div className="mt-4">
421
+ <div className="mb-2 flex items-center justify-between">
422
+ <h2 className="text-sm font-bold uppercase tracking-wide text-gray-500">
423
+ Recent activity
447
424
  </h2>
448
- <p className="mt-3 text-gray-500 text-base">
449
- Estimate your savings based on your property and usage details.
450
- </p>
451
- </div>
452
- <div className="bg-primary-900 rounded-xl px-8 py-5 mb-8">
453
- <p className="text-white font-semibold text-lg">
454
- Let Us Know Your Details
455
- </p>
425
+ <button
426
+ type="button"
427
+ className="text-xs font-semibold text-primary-600 hover:text-primary-700"
428
+ >
429
+ View all →
430
+ </button>
456
431
  </div>
457
- <p className="text-sm font-semibold text-gray-700 mb-4 uppercase tracking-wide">
458
- B. Property Details
459
- </p>
460
- <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
461
- <Select
462
- label="Roof Type"
463
- value="option-a"
464
- options={[
465
- { key: "option-a", label: "Flat Roof" },
466
- { key: "option-b", label: "Pitched Roof" },
467
- { key: "option-c", label: "Metal Roof" },
468
- ]}
469
- />
470
- <Select
471
- label="Electricity Tariff"
472
- value="option-a"
473
- options={[
474
- { key: "option-a", label: "Residential (TNB)" },
475
- { key: "option-b", label: "Commercial (TNB)" },
476
- { key: "option-c", label: "Industrial (TNB)" },
477
- ]}
478
- />
479
- <Select
480
- label="Grid Connection"
481
- value="option-a"
482
- options={[
483
- { key: "option-a", label: "Single Phase" },
484
- { key: "option-b", label: "Three Phase" },
485
- ]}
486
- />
487
- <TextInput
488
- label="Monthly Bill (RM)"
489
- type="number"
490
- value="500"
491
- placeholder="e.g. 500"
492
- />
493
- </div>
494
- <div className="mt-12 mb-4 text-center">
495
- <h3 className="text-2xl font-semibold text-primary-800 md:text-3xl">
496
- Comparison between Solar PV System and Solar + Battery Storage
497
- </h3>
498
- <p className="mt-2 text-gray-500 text-sm">
499
- Based on your inputs, here are the recommended options for you.
500
- </p>
501
- </div>
502
- <Grid
503
- data={PRODUCT_CARDS}
504
- loading={false}
505
- hidePagination
506
- customGridItems={PRODUCT_GRID_ITEMS}
507
- itemClassName="!bg-gray-50 shadow-none"
508
- gridColClassName="gap-6 grid-cols-1 sm:grid-cols-2"
509
- />
510
- </Container>
511
- </div>
512
-
513
- <div className="w-full flex flex-col bg-primary-900 lg:flex-row">
514
- <div className="hidden overflow-hidden lg:w-1/2 lg:block">
515
- <img
516
- src="https://images.unsplash.com/photo-1508514177221-188b1cf16e9d?auto=format&fit=crop&w=800&q=80"
517
- alt="how it works"
518
- className="w-full h-full object-cover"
519
- />
432
+ <NewList list={RECENT_ITEMS} />
520
433
  </div>
521
- <div className="w-full flex flex-col justify-center text-white p-8 md:p-14 lg:w-1/2">
522
- <h1 className="text-2xl font-semibold mb-8 sm:text-3xl md:text-4xl">
523
- How it works
524
- </h1>
525
- <IconList
526
- iconList={HOW_IT_WORKS_STEPS.map((step) => ({
527
- name: step.title,
528
- content: step.description,
529
- icon: step.icon,
530
- }))}
531
- className="text-white [&_p]:text-white [&_dd]:text-gray-200"
532
- />
434
+
435
+ {/* Bottom CTA — Button (type="normal" -> primary-500) */}
436
+ <div className="mt-6 md:mx-auto md:max-w-xs">
533
437
  <Button
534
- text="GET A FREE QUOTE"
535
- type="light"
536
- size="small"
537
- onClick={() => {}}
538
- className="mt-8 w-full sm:w-fit"
438
+ type="normal"
439
+ text="Get more insights"
440
+ icon={<SparklesIcon className="h-4 w-4" />}
539
441
  />
540
442
  </div>
541
- </div>
542
-
543
- <Container bgColor="bg-gray-50" className="py-14">
544
- <h2 className="mb-14 text-3xl font-semibold text-primary-800 text-center md:text-5xl">
545
- Frequently Asked Questions (FAQ)
546
- </h2>
547
- <div className="bg-white rounded-3xl text-primary-900 shadow-xl">
548
- <FAQContent faqList={FAQ_LIST} />
549
- </div>
550
443
  </Container>
551
444
 
552
- <Container bgColor="bg-white" className="py-10">
553
- <h2 className="text-3xl font-semibold text-primary-800 text-center md:text-5xl">
554
- See what our customers say about us!
555
- </h2>
556
- <div className="mt-10">
557
- <GoogleReview placeId="" minRatingScore={4} />
558
- </div>
559
- </Container>
560
-
561
- <Container bgColor="bg-white" className="py-10">
562
- <ActionSection
563
- title="Interested to save money? Switch today!"
564
- buttonText="GET A FREE QUOTE"
565
- backgroundImgSrc="https://images.unsplash.com/photo-1508514177221-188b1cf16e9d?auto=format&fit=crop&w=1920&q=80"
566
- backgroundImgStyle={{ bgPosition: "bottom" }}
567
- onClick={() => {}}
445
+ {/* DESKTOP FOOTER — UI Web FooterSection. Hidden on mobile;
446
+ BottomTab handles thumb-reach nav there. */}
447
+ <div className="hidden md:block">
448
+ <FooterSection
449
+ caption={`© ${TODAY.getFullYear()} Blixify. All rights reserved.`}
450
+ footerList={FOOTER_LIST}
568
451
  />
569
- </Container>
452
+ </div>
570
453
 
571
- <FooterSection
572
- linkType="external"
573
- caption={`© ${new Date().getFullYear()} SolarSave. All rights reserved.`}
574
- footerList={[
575
- {
576
- title: "SolarSave",
577
- subList: [
578
- { name: "About Us", link: "/about" },
579
- { name: "How It Works", link: "/how-it-works" },
580
- { name: "Terms & Conditions", link: "/terms" },
581
- { name: "Privacy Policy", link: "/privacy" },
582
- ],
583
- },
584
- {
585
- title: "My Account",
586
- subList: [
587
- { name: "Sign In", link: "/signIn" },
588
- { name: "FAQ", link: "/faq" },
589
- ],
590
- },
591
- ]}
592
- logoCloud={
593
- <div>
594
- <div className="flex items-center space-x-2 mb-3">
595
- <span className="font-semibold text-gray-900">SolarSave</span>
596
- </div>
597
- <p className="text-sm text-gray-500">
598
- Lorem ipsum dolor sit amet consectetur adipiscing elit.
599
- </p>
600
- </div>
601
- }
602
- />
454
+ {/* MOBILE BOTTOM TAB — only on < md. On desktop the footer above
455
+ handles secondary nav; bottom tab would duplicate the header. */}
456
+ <div className="md:hidden">
457
+ <BottomTab
458
+ tabData={BOTTOM_TABS}
459
+ selectedTab="Home"
460
+ bottomTabClassName="fixed bottom-0 left-0 right-0 shadow-lg"
461
+ />
462
+ </div>
603
463
  </div>
604
464
  );
605
- });
465
+ };