@umituz/web-dashboard 2.0.7 → 2.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/package.json +35 -77
  2. package/src/domains/layouts/components/BrandLogo.tsx +83 -0
  3. package/src/domains/layouts/components/DashboardHeader.tsx +240 -0
  4. package/src/domains/layouts/components/DashboardLayout.tsx +155 -0
  5. package/src/domains/layouts/components/DashboardSidebar.tsx +152 -0
  6. package/src/domains/layouts/components/index.ts +8 -0
  7. package/src/domains/layouts/hooks/dashboard.ts +81 -0
  8. package/src/domains/layouts/hooks/index.ts +8 -0
  9. package/src/domains/layouts/index.ts +11 -0
  10. package/{dist/layouts/theme/default.js → src/domains/layouts/theme/default.ts} +18 -11
  11. package/src/domains/layouts/theme/index.ts +18 -0
  12. package/src/domains/layouts/theme/presets.ts +96 -0
  13. package/src/domains/layouts/theme/utils.ts +67 -0
  14. package/src/domains/layouts/types/index.ts +9 -0
  15. package/src/domains/layouts/types/layout.ts +43 -0
  16. package/src/domains/layouts/types/notification.ts +19 -0
  17. package/src/domains/layouts/types/sidebar.ts +35 -0
  18. package/src/domains/layouts/types/theme.ts +64 -0
  19. package/src/domains/layouts/types/user.ts +35 -0
  20. package/src/domains/layouts/utils/dashboard.ts +96 -0
  21. package/src/domains/layouts/utils/index.ts +11 -0
  22. package/src/domains/onboarding/components/AppFocusStep.tsx +113 -0
  23. package/src/domains/onboarding/components/OnboardingWizard.tsx +262 -0
  24. package/src/domains/onboarding/components/PlanStep.tsx +208 -0
  25. package/src/domains/onboarding/components/PlatformsStep.tsx +109 -0
  26. package/src/domains/onboarding/components/UserTypeStep.tsx +135 -0
  27. package/src/domains/onboarding/components/index.ts +9 -0
  28. package/src/domains/onboarding/hooks/index.ts +5 -0
  29. package/{dist/onboarding/hooks/index.js → src/domains/onboarding/hooks/useOnboarding.ts} +65 -19
  30. package/src/domains/onboarding/index.ts +35 -0
  31. package/src/domains/onboarding/types/index.ts +16 -0
  32. package/src/domains/onboarding/types/onboarding.ts +214 -0
  33. package/src/domains/onboarding/utils/index.ts +15 -0
  34. package/src/domains/onboarding/utils/onboarding.ts +166 -0
  35. package/src/domains/settings/components/SettingsLayout.tsx +144 -0
  36. package/src/domains/settings/components/SettingsSection.tsx +106 -0
  37. package/src/domains/settings/components/index.ts +6 -0
  38. package/src/domains/settings/hooks/index.ts +7 -0
  39. package/src/domains/settings/hooks/useSettings.ts +80 -0
  40. package/src/domains/settings/index.ts +22 -0
  41. package/src/domains/settings/types/index.ts +11 -0
  42. package/src/domains/settings/types/settings.ts +81 -0
  43. package/src/domains/settings/utils/index.ts +11 -0
  44. package/src/domains/settings/utils/settings.ts +80 -0
  45. package/dist/layouts/components/BrandLogo.d.ts +0 -18
  46. package/dist/layouts/components/BrandLogo.js +0 -88
  47. package/dist/layouts/components/BrandLogo.js.map +0 -1
  48. package/dist/layouts/components/DashboardHeader.d.ts +0 -36
  49. package/dist/layouts/components/DashboardHeader.js +0 -225
  50. package/dist/layouts/components/DashboardHeader.js.map +0 -1
  51. package/dist/layouts/components/DashboardLayout.d.ts +0 -45
  52. package/dist/layouts/components/DashboardLayout.js +0 -501
  53. package/dist/layouts/components/DashboardLayout.js.map +0 -1
  54. package/dist/layouts/components/DashboardSidebar.d.ts +0 -29
  55. package/dist/layouts/components/DashboardSidebar.js +0 -189
  56. package/dist/layouts/components/DashboardSidebar.js.map +0 -1
  57. package/dist/layouts/components/index.d.ts +0 -10
  58. package/dist/layouts/components/index.js +0 -502
  59. package/dist/layouts/components/index.js.map +0 -1
  60. package/dist/layouts/hooks/dashboard.d.ts +0 -35
  61. package/dist/layouts/hooks/dashboard.js +0 -57
  62. package/dist/layouts/hooks/dashboard.js.map +0 -1
  63. package/dist/layouts/hooks/index.d.ts +0 -3
  64. package/dist/layouts/hooks/index.js +0 -57
  65. package/dist/layouts/hooks/index.js.map +0 -1
  66. package/dist/layouts/index.d.ts +0 -17
  67. package/dist/layouts/index.js +0 -756
  68. package/dist/layouts/index.js.map +0 -1
  69. package/dist/layouts/theme/default.d.ts +0 -18
  70. package/dist/layouts/theme/default.js.map +0 -1
  71. package/dist/layouts/theme/index.d.ts +0 -4
  72. package/dist/layouts/theme/index.js +0 -184
  73. package/dist/layouts/theme/index.js.map +0 -1
  74. package/dist/layouts/theme/presets.d.ts +0 -14
  75. package/dist/layouts/theme/presets.js +0 -137
  76. package/dist/layouts/theme/presets.js.map +0 -1
  77. package/dist/layouts/theme/utils.d.ts +0 -22
  78. package/dist/layouts/theme/utils.js +0 -181
  79. package/dist/layouts/theme/utils.js.map +0 -1
  80. package/dist/layouts/types/index.d.ts +0 -6
  81. package/dist/layouts/types/index.js +0 -2
  82. package/dist/layouts/types/index.js.map +0 -1
  83. package/dist/layouts/types/layout.d.ts +0 -45
  84. package/dist/layouts/types/layout.js +0 -2
  85. package/dist/layouts/types/layout.js.map +0 -1
  86. package/dist/layouts/types/notification.d.ts +0 -20
  87. package/dist/layouts/types/notification.js +0 -2
  88. package/dist/layouts/types/notification.js.map +0 -1
  89. package/dist/layouts/types/sidebar.d.ts +0 -36
  90. package/dist/layouts/types/sidebar.js +0 -2
  91. package/dist/layouts/types/sidebar.js.map +0 -1
  92. package/dist/layouts/types/theme.d.ts +0 -64
  93. package/dist/layouts/types/theme.js +0 -2
  94. package/dist/layouts/types/theme.js.map +0 -1
  95. package/dist/layouts/types/user.d.ts +0 -37
  96. package/dist/layouts/types/user.js +0 -2
  97. package/dist/layouts/types/user.js.map +0 -1
  98. package/dist/layouts/utils/dashboard.d.ts +0 -57
  99. package/dist/layouts/utils/dashboard.js +0 -44
  100. package/dist/layouts/utils/dashboard.js.map +0 -1
  101. package/dist/layouts/utils/index.d.ts +0 -1
  102. package/dist/layouts/utils/index.js +0 -44
  103. package/dist/layouts/utils/index.js.map +0 -1
  104. package/dist/onboarding/components/AppFocusStep.d.ts +0 -26
  105. package/dist/onboarding/components/AppFocusStep.js +0 -86
  106. package/dist/onboarding/components/AppFocusStep.js.map +0 -1
  107. package/dist/onboarding/components/OnboardingWizard.d.ts +0 -13
  108. package/dist/onboarding/components/OnboardingWizard.js +0 -332
  109. package/dist/onboarding/components/OnboardingWizard.js.map +0 -1
  110. package/dist/onboarding/components/PlanStep.d.ts +0 -21
  111. package/dist/onboarding/components/PlanStep.js +0 -167
  112. package/dist/onboarding/components/PlanStep.js.map +0 -1
  113. package/dist/onboarding/components/PlatformsStep.d.ts +0 -26
  114. package/dist/onboarding/components/PlatformsStep.js +0 -86
  115. package/dist/onboarding/components/PlatformsStep.js.map +0 -1
  116. package/dist/onboarding/components/UserTypeStep.d.ts +0 -30
  117. package/dist/onboarding/components/UserTypeStep.js +0 -93
  118. package/dist/onboarding/components/UserTypeStep.js.map +0 -1
  119. package/dist/onboarding/components/index.d.ts +0 -9
  120. package/dist/onboarding/components/index.js +0 -738
  121. package/dist/onboarding/components/index.js.map +0 -1
  122. package/dist/onboarding/hooks/index.d.ts +0 -4
  123. package/dist/onboarding/hooks/index.js.map +0 -1
  124. package/dist/onboarding/hooks/useOnboarding.d.ts +0 -50
  125. package/dist/onboarding/hooks/useOnboarding.js +0 -100
  126. package/dist/onboarding/hooks/useOnboarding.js.map +0 -1
  127. package/dist/onboarding/index.d.ts +0 -11
  128. package/dist/onboarding/index.js +0 -913
  129. package/dist/onboarding/index.js.map +0 -1
  130. package/dist/onboarding/types/index.d.ts +0 -3
  131. package/dist/onboarding/types/index.js +0 -2
  132. package/dist/onboarding/types/index.js.map +0 -1
  133. package/dist/onboarding/types/onboarding.d.ts +0 -209
  134. package/dist/onboarding/types/onboarding.js +0 -2
  135. package/dist/onboarding/types/onboarding.js.map +0 -1
  136. package/dist/onboarding/utils/index.d.ts +0 -4
  137. package/dist/onboarding/utils/index.js +0 -83
  138. package/dist/onboarding/utils/index.js.map +0 -1
  139. package/dist/onboarding/utils/onboarding.d.ts +0 -106
  140. package/dist/onboarding/utils/onboarding.js +0 -83
  141. package/dist/onboarding/utils/onboarding.js.map +0 -1
  142. package/dist/settings/components/SettingsLayout.d.ts +0 -19
  143. package/dist/settings/components/SettingsLayout.js +0 -170
  144. package/dist/settings/components/SettingsLayout.js.map +0 -1
  145. package/dist/settings/components/SettingsSection.d.ts +0 -24
  146. package/dist/settings/components/SettingsSection.js +0 -73
  147. package/dist/settings/components/SettingsSection.js.map +0 -1
  148. package/dist/settings/components/index.d.ts +0 -5
  149. package/dist/settings/components/index.js +0 -169
  150. package/dist/settings/components/index.js.map +0 -1
  151. package/dist/settings/hooks/index.d.ts +0 -3
  152. package/dist/settings/hooks/index.js +0 -59
  153. package/dist/settings/hooks/index.js.map +0 -1
  154. package/dist/settings/hooks/useSettings.d.ts +0 -25
  155. package/dist/settings/hooks/useSettings.js +0 -59
  156. package/dist/settings/hooks/useSettings.js.map +0 -1
  157. package/dist/settings/index.d.ts +0 -7
  158. package/dist/settings/index.js +0 -259
  159. package/dist/settings/index.js.map +0 -1
  160. package/dist/settings/types/index.d.ts +0 -2
  161. package/dist/settings/types/index.js +0 -2
  162. package/dist/settings/types/index.js.map +0 -1
  163. package/dist/settings/types/settings.d.ts +0 -79
  164. package/dist/settings/types/settings.js +0 -2
  165. package/dist/settings/types/settings.js.map +0 -1
  166. package/dist/settings/utils/index.d.ts +0 -3
  167. package/dist/settings/utils/index.js +0 -39
  168. package/dist/settings/utils/index.js.map +0 -1
  169. package/dist/settings/utils/settings.d.ts +0 -50
  170. package/dist/settings/utils/settings.js +0 -39
  171. package/dist/settings/utils/settings.js.map +0 -1
@@ -1,756 +0,0 @@
1
- "use client";
2
-
3
- // src/domains/layouts/components/DashboardLayout.tsx
4
- import { useState as useState3, useEffect } from "react";
5
- import { useLocation as useLocation2, Outlet, Navigate } from "react-router-dom";
6
- import { Skeleton } from "@umituz/web-design-system/atoms";
7
-
8
- // src/domains/layouts/components/DashboardSidebar.tsx
9
- import { useState } from "react";
10
- import { Link, useLocation } from "react-router-dom";
11
- import { useTranslation } from "react-i18next";
12
- import { Button } from "@umituz/web-design-system/atoms";
13
-
14
- // src/domains/layouts/components/BrandLogo.tsx
15
- import { cn } from "@umituz/web-design-system/utils";
16
- import { jsx, jsxs } from "react/jsx-runtime";
17
- var BrandLogo = ({ className, size = 32 }) => {
18
- return /* @__PURE__ */ jsxs(
19
- "svg",
20
- {
21
- width: size,
22
- height: size,
23
- viewBox: "0 0 100 100",
24
- fill: "none",
25
- xmlns: "http://www.w3.org/2000/svg",
26
- className: cn("shrink-0", className),
27
- children: [
28
- /* @__PURE__ */ jsx(
29
- "rect",
30
- {
31
- x: "15",
32
- y: "65",
33
- width: "70",
34
- height: "15",
35
- rx: "4",
36
- fill: "hsl(var(--primary))"
37
- }
38
- ),
39
- /* @__PURE__ */ jsx(
40
- "rect",
41
- {
42
- x: "25",
43
- y: "25",
44
- width: "12",
45
- height: "40",
46
- rx: "2",
47
- fill: "hsl(var(--primary))"
48
- }
49
- ),
50
- /* @__PURE__ */ jsx(
51
- "rect",
52
- {
53
- x: "44",
54
- y: "35",
55
- width: "12",
56
- height: "30",
57
- rx: "2",
58
- fill: "hsl(var(--primary))"
59
- }
60
- ),
61
- /* @__PURE__ */ jsx(
62
- "rect",
63
- {
64
- x: "63",
65
- y: "20",
66
- width: "12",
67
- height: "45",
68
- rx: "2",
69
- fill: "hsl(var(--primary))"
70
- }
71
- ),
72
- /* @__PURE__ */ jsx(
73
- "rect",
74
- {
75
- x: "20",
76
- y: "45",
77
- width: "60",
78
- height: "10",
79
- rx: "2",
80
- fill: "hsl(var(--secondary))"
81
- }
82
- ),
83
- /* @__PURE__ */ jsx(
84
- "circle",
85
- {
86
- cx: "50",
87
- cy: "20",
88
- r: "5",
89
- fill: "hsl(var(--secondary))"
90
- }
91
- )
92
- ]
93
- }
94
- );
95
- };
96
-
97
- // src/domains/layouts/components/DashboardSidebar.tsx
98
- import { PenTool, Menu, ChevronLeft, ChevronDown, ChevronRight } from "lucide-react";
99
-
100
- // src/domains/layouts/utils/dashboard.ts
101
- function formatNotificationTime(createdAt, t) {
102
- const date = new Date(createdAt);
103
- const secs = Math.floor((Date.now() - date.getTime()) / 1e3);
104
- if (secs < 60) return t("dashboard.activityFeed.times.justNow");
105
- if (secs < 3600) return t("dashboard.activityFeed.times.minutesAgo", { val: Math.floor(secs / 60) });
106
- if (secs < 86400) return t("dashboard.activityFeed.times.hoursAgo", { val: Math.floor(secs / 3600) });
107
- return t("dashboard.activityFeed.times.daysAgo", { val: Math.floor(secs / 86400) });
108
- }
109
- function isPathActive(currentPath, targetPath) {
110
- return currentPath === targetPath;
111
- }
112
- function getPageTitle(pathname, sidebarGroups, extraTitleMap) {
113
- for (const group of sidebarGroups) {
114
- const item = group.items.find((i) => i.path === pathname);
115
- if (item) return item.label;
116
- }
117
- if (extraTitleMap?.[pathname]) {
118
- return extraTitleMap[pathname];
119
- }
120
- return null;
121
- }
122
- function filterSidebarItems(items, user) {
123
- return items.filter((item) => {
124
- if (item.enabled === false) return false;
125
- if (!item.requiredApp) return true;
126
- if (item.requiredApp === "mobile") return user?.hasMobileApp ?? false;
127
- if (item.requiredApp === "web") return user?.hasWebApp ?? false;
128
- return true;
129
- });
130
- }
131
- function generateNotificationId() {
132
- return crypto.randomUUID();
133
- }
134
-
135
- // src/domains/layouts/components/DashboardSidebar.tsx
136
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
137
- var DashboardSidebar = ({
138
- collapsed,
139
- setCollapsed,
140
- sidebarGroups,
141
- brandName = "App",
142
- brandTagline = "grow smarter",
143
- createPostRoute = "/dashboard/create",
144
- user
145
- }) => {
146
- const location = useLocation();
147
- const { t } = useTranslation();
148
- const [collapsedGroups, setCollapsedGroups] = useState({});
149
- const toggleGroup = (title) => {
150
- setCollapsedGroups((prev) => ({
151
- ...prev,
152
- [title]: !prev[title]
153
- }));
154
- };
155
- return /* @__PURE__ */ jsxs2("div", { className: "flex h-full flex-col", children: [
156
- /* @__PURE__ */ jsxs2("div", { className: "flex h-16 items-center gap-3 border-b border-sidebar-border px-4 transition-all duration-300", children: [
157
- /* @__PURE__ */ jsx2(BrandLogo, { size: 32 }),
158
- !collapsed && /* @__PURE__ */ jsxs2("div", { className: "flex flex-col -gap-1", children: [
159
- /* @__PURE__ */ jsx2("span", { className: "text-2xl font-black text-sidebar-foreground tracking-tighter leading-none", children: brandName }),
160
- /* @__PURE__ */ jsx2("span", { className: "text-[11px] font-bold text-primary/70 lowercase tracking-tight mt-2 ml-1 select-none underline decoration-primary/40 underline-offset-[6px] decoration-2", children: brandTagline })
161
- ] })
162
- ] }),
163
- /* @__PURE__ */ jsx2("div", { className: "px-3 py-4 border-b border-sidebar-border/50", children: /* @__PURE__ */ jsx2(Link, { to: createPostRoute, children: /* @__PURE__ */ jsxs2(
164
- Button,
165
- {
166
- variant: "default",
167
- className: `w-full gap-3 shadow-glow transition-all active:scale-95 group overflow-hidden rounded-xl ${collapsed ? "px-0 justify-center h-10 w-10 mx-auto" : "justify-start px-4 h-11"}`,
168
- title: collapsed ? t("sidebar.createPost") : void 0,
169
- children: [
170
- /* @__PURE__ */ jsx2(PenTool, { className: `shrink-0 transition-transform duration-300 ${collapsed ? "h-5 w-5" : "h-4 w-4 group-hover:scale-110"}` }),
171
- !collapsed && /* @__PURE__ */ jsx2("span", { className: "font-bold tracking-tight", children: t("sidebar.createPost") })
172
- ]
173
- }
174
- ) }) }),
175
- /* @__PURE__ */ jsx2("nav", { className: "flex-1 overflow-y-auto px-2 py-3 scrollbar-hide", children: /* @__PURE__ */ jsx2("div", { className: "space-y-6", children: sidebarGroups.map((group) => {
176
- const filteredItems = filterSidebarItems(group.items, user);
177
- if (filteredItems.length === 0) return null;
178
- const isGroupCollapsed = collapsedGroups[group.title];
179
- return /* @__PURE__ */ jsxs2("div", { className: "space-y-1", children: [
180
- !collapsed && /* @__PURE__ */ jsxs2(
181
- "button",
182
- {
183
- onClick: () => toggleGroup(group.title),
184
- className: "w-full flex items-center justify-between px-3 mb-2 group/header",
185
- children: [
186
- /* @__PURE__ */ jsx2("span", { className: "text-[10px] font-bold uppercase tracking-widest text-sidebar-foreground/40 group-hover/header:text-sidebar-foreground/70 transition-colors", children: group.title === "sidebar.ai" ? `${brandName} AI` : t(group.title) }),
187
- isGroupCollapsed ? /* @__PURE__ */ jsx2(ChevronRight, { className: "h-3 w-3 text-sidebar-foreground/30 flex-shrink-0 group-hover/header:text-sidebar-foreground/50 transition-colors" }) : /* @__PURE__ */ jsx2(ChevronDown, { className: "h-3 w-3 text-sidebar-foreground/30 flex-shrink-0 group-hover/header:text-sidebar-foreground/50 transition-colors" })
188
- ]
189
- }
190
- ),
191
- (!isGroupCollapsed || collapsed) && filteredItems.map((item) => {
192
- const active = location.pathname === item.path;
193
- return /* @__PURE__ */ jsxs2(
194
- Link,
195
- {
196
- to: item.path,
197
- className: `flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-all duration-200 ${active ? "bg-sidebar-accent text-sidebar-accent-foreground shadow-sm" : "text-sidebar-foreground/70 hover:bg-sidebar-accent/40 hover:text-sidebar-foreground"} ${collapsed ? "justify-center" : ""}`,
198
- title: collapsed ? t(item.label) : void 0,
199
- children: [
200
- /* @__PURE__ */ jsx2(item.icon, { className: `h-4 w-4 shrink-0 transition-transform ${active && "scale-110"}` }),
201
- !collapsed && /* @__PURE__ */ jsx2("span", { children: t(item.label) })
202
- ]
203
- },
204
- item.path
205
- );
206
- })
207
- ] }, group.title);
208
- }) }) }),
209
- /* @__PURE__ */ jsx2("div", { className: "border-t border-sidebar-border p-3", children: /* @__PURE__ */ jsxs2("div", { className: `flex items-center ${collapsed ? "justify-center" : "justify-between"}`, children: [
210
- !collapsed && /* @__PURE__ */ jsx2("p", { className: "text-[10px] uppercase tracking-wider text-sidebar-foreground/40 font-bold px-2", children: t("sidebar.system") }),
211
- /* @__PURE__ */ jsx2(Button, { variant: "ghost", size: "icon", onClick: () => setCollapsed(!collapsed), className: "text-sidebar-foreground/70", children: collapsed ? /* @__PURE__ */ jsx2(Menu, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx2(ChevronLeft, { className: "h-4 w-4" }) })
212
- ] }) })
213
- ] });
214
- };
215
-
216
- // src/domains/layouts/components/DashboardHeader.tsx
217
- import React, { useState as useState2 } from "react";
218
- import {
219
- Bell,
220
- X,
221
- Sun,
222
- Moon,
223
- Menu as Menu2,
224
- User,
225
- Settings,
226
- LogOut,
227
- ChevronDown as ChevronDown2,
228
- CreditCard
229
- } from "lucide-react";
230
- import { Button as Button2 } from "@umituz/web-design-system/atoms";
231
- import { useNavigate } from "react-router-dom";
232
- import { useTranslation as useTranslation2 } from "react-i18next";
233
- import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
234
- var DashboardHeader = ({
235
- collapsed,
236
- setCollapsed,
237
- setMobileOpen,
238
- title,
239
- user,
240
- notifications = [],
241
- onLogout,
242
- onMarkAllRead,
243
- onDismissNotification,
244
- settingsRoute = "/dashboard/settings",
245
- profileRoute = "/dashboard/profile",
246
- billingRoute = "/dashboard/billing"
247
- }) => {
248
- const navigate = useNavigate();
249
- const { t } = useTranslation2();
250
- const [notifOpen, setNotifOpen] = useState2(false);
251
- const [profileOpen, setProfileOpen] = useState2(false);
252
- const unreadCount = notifications.filter((n) => !n.read).length;
253
- const markAllRead = () => {
254
- onMarkAllRead?.();
255
- };
256
- const handleLogout = async () => {
257
- try {
258
- await onLogout?.();
259
- navigate("/login");
260
- } catch {
261
- }
262
- };
263
- const ThemeToggle = () => {
264
- const [resolvedTheme, setResolvedTheme] = React.useState("light");
265
- return /* @__PURE__ */ jsx3(
266
- Button2,
267
- {
268
- variant: "ghost",
269
- size: "icon",
270
- onClick: () => setResolvedTheme(resolvedTheme === "light" ? "dark" : "light"),
271
- className: "text-muted-foreground h-9 w-9",
272
- title: resolvedTheme === "dark" ? t("common.tooltips.switchLight") : t("common.tooltips.switchDark"),
273
- children: resolvedTheme === "dark" ? /* @__PURE__ */ jsx3(Sun, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx3(Moon, { className: "h-4 w-4" })
274
- }
275
- );
276
- };
277
- return /* @__PURE__ */ jsxs3("header", { className: "flex h-14 items-center justify-between border-b border-border bg-card/50 backdrop-blur-md px-4 shrink-0 z-30", children: [
278
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-3", children: [
279
- /* @__PURE__ */ jsx3(Button2, { variant: "ghost", size: "icon", className: "md:hidden", onClick: () => setMobileOpen(true), children: /* @__PURE__ */ jsx3(Menu2, { className: "h-5 w-5" }) }),
280
- collapsed && /* @__PURE__ */ jsx3(Button2, { variant: "ghost", size: "icon", className: "hidden md:inline-flex", onClick: () => setCollapsed(false), children: /* @__PURE__ */ jsx3(Menu2, { className: "h-5 w-5" }) }),
281
- /* @__PURE__ */ jsx3("h2", { className: "text-sm font-semibold text-foreground", children: title })
282
- ] }),
283
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
284
- /* @__PURE__ */ jsx3(ThemeToggle, {}),
285
- /* @__PURE__ */ jsxs3("div", { className: "relative", children: [
286
- /* @__PURE__ */ jsxs3(
287
- Button2,
288
- {
289
- variant: "ghost",
290
- size: "icon",
291
- className: "text-muted-foreground relative h-9 w-9",
292
- onClick: () => {
293
- setNotifOpen(!notifOpen);
294
- setProfileOpen(false);
295
- },
296
- children: [
297
- /* @__PURE__ */ jsx3(Bell, { className: "h-4 w-4" }),
298
- unreadCount > 0 && /* @__PURE__ */ jsxs3("span", { className: "absolute top-2 right-2 flex h-2 w-2", children: [
299
- /* @__PURE__ */ jsx3("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-destructive opacity-75" }),
300
- /* @__PURE__ */ jsx3("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-destructive" })
301
- ] })
302
- ]
303
- }
304
- ),
305
- notifOpen && /* @__PURE__ */ jsxs3(Fragment, { children: [
306
- /* @__PURE__ */ jsx3("div", { className: "fixed inset-0 z-40", onClick: () => setNotifOpen(false) }),
307
- /* @__PURE__ */ jsxs3("div", { className: "absolute top-12 right-0 w-80 bg-popover border border-border rounded-xl shadow-xl z-50 overflow-hidden animate-in fade-in zoom-in-95 duration-200", children: [
308
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between px-4 py-3 border-b border-border bg-muted/50", children: [
309
- /* @__PURE__ */ jsx3("h3", { className: "text-xs font-bold uppercase tracking-wider text-foreground", children: t("dashboard.notifications.title") }),
310
- unreadCount > 0 && /* @__PURE__ */ jsx3("button", { onClick: markAllRead, className: "text-[10px] font-bold text-primary hover:underline uppercase", children: t("dashboard.notifications.markAllRead") })
311
- ] }),
312
- /* @__PURE__ */ jsxs3("div", { className: "max-h-[400px] overflow-y-auto", children: [
313
- notifications.map((n) => /* @__PURE__ */ jsxs3("div", { className: `px-4 py-3 border-b border-border last:border-0 flex items-start gap-3 transition-colors hover:bg-muted/30 ${!n.read ? "bg-primary/5" : ""}`, children: [
314
- /* @__PURE__ */ jsxs3("div", { className: "flex-1 min-w-0", children: [
315
- /* @__PURE__ */ jsx3("p", { className: "text-sm text-foreground leading-snug", children: n.text }),
316
- /* @__PURE__ */ jsxs3("p", { className: "text-[10px] text-muted-foreground mt-1 flex items-center gap-1", children: [
317
- /* @__PURE__ */ jsx3("span", { className: "inline-block w-1 h-1 rounded-full bg-muted-foreground/30" }),
318
- formatNotificationTime(n.createdAt, t)
319
- ] })
320
- ] }),
321
- /* @__PURE__ */ jsx3(
322
- "button",
323
- {
324
- onClick: () => onDismissNotification?.(n.id),
325
- className: "text-muted-foreground/50 hover:text-foreground shrink-0 transition-colors",
326
- children: /* @__PURE__ */ jsx3(X, { className: "h-3 w-3" })
327
- }
328
- )
329
- ] }, n.id)),
330
- notifications.length === 0 && /* @__PURE__ */ jsxs3("div", { className: "px-4 py-10 text-center", children: [
331
- /* @__PURE__ */ jsx3("div", { className: "mx-auto w-10 h-10 rounded-full bg-muted flex items-center justify-center mb-3", children: /* @__PURE__ */ jsx3(Bell, { className: "h-5 w-5 text-muted-foreground/50" }) }),
332
- /* @__PURE__ */ jsx3("p", { className: "text-sm text-muted-foreground", children: t("dashboard.notifications.none") })
333
- ] })
334
- ] })
335
- ] })
336
- ] })
337
- ] }),
338
- /* @__PURE__ */ jsx3("div", { className: "h-6 w-px bg-border mx-1" }),
339
- /* @__PURE__ */ jsxs3("div", { className: "relative", children: [
340
- /* @__PURE__ */ jsxs3(
341
- "button",
342
- {
343
- onClick: () => {
344
- setProfileOpen(!profileOpen);
345
- setNotifOpen(false);
346
- },
347
- className: "flex items-center gap-2 p-1 pl-1 rounded-full hover:bg-muted transition-colors group",
348
- children: [
349
- /* @__PURE__ */ jsx3("div", { className: "w-8 h-8 rounded-full bg-primary/10 flex items-center justify-center text-[10px] font-bold text-primary overflow-hidden border border-primary/20 ring-primary/20 group-hover:ring-4 transition-all", children: user?.avatar && /* @__PURE__ */ jsx3("img", { src: user.avatar, alt: "User", className: "w-full h-full object-cover" }) }),
350
- /* @__PURE__ */ jsx3(ChevronDown2, { className: `h-4 w-4 text-muted-foreground transition-transform duration-200 ${profileOpen && "rotate-180"}` })
351
- ]
352
- }
353
- ),
354
- profileOpen && /* @__PURE__ */ jsxs3(Fragment, { children: [
355
- /* @__PURE__ */ jsx3("div", { className: "fixed inset-0 z-40", onClick: () => setProfileOpen(false) }),
356
- /* @__PURE__ */ jsxs3("div", { className: "absolute top-12 right-0 w-56 bg-popover border border-border rounded-xl shadow-xl z-50 overflow-hidden animate-in fade-in zoom-in-95 duration-200 p-1.5", children: [
357
- /* @__PURE__ */ jsxs3("div", { className: "px-3 py-2 border-b border-border/50 mb-1", children: [
358
- /* @__PURE__ */ jsx3("p", { className: "text-sm font-bold text-foreground", children: user?.name || t("common.roles.user") }),
359
- /* @__PURE__ */ jsx3("p", { className: "text-xs text-muted-foreground truncate", children: user?.email })
360
- ] }),
361
- /* @__PURE__ */ jsxs3("div", { className: "space-y-0.5", children: [
362
- /* @__PURE__ */ jsxs3(
363
- "button",
364
- {
365
- onClick: () => {
366
- navigate(profileRoute);
367
- setProfileOpen(false);
368
- },
369
- className: "flex w-full items-center gap-2.5 px-3 py-2 text-sm text-foreground hover:bg-muted rounded-lg transition-colors",
370
- children: [
371
- /* @__PURE__ */ jsx3(User, { className: "h-4 w-4 text-muted-foreground" }),
372
- t("common.profile")
373
- ]
374
- }
375
- ),
376
- /* @__PURE__ */ jsxs3(
377
- "button",
378
- {
379
- onClick: () => {
380
- navigate(billingRoute);
381
- setProfileOpen(false);
382
- },
383
- className: "flex w-full items-center gap-2.5 px-3 py-2 text-sm text-foreground hover:bg-muted rounded-lg transition-colors",
384
- children: [
385
- /* @__PURE__ */ jsx3(CreditCard, { className: "h-4 w-4 text-muted-foreground" }),
386
- t("common.billing")
387
- ]
388
- }
389
- ),
390
- /* @__PURE__ */ jsxs3(
391
- "button",
392
- {
393
- onClick: () => {
394
- navigate(settingsRoute);
395
- setProfileOpen(false);
396
- },
397
- className: "flex w-full items-center gap-2.5 px-3 py-2 text-sm text-foreground hover:bg-muted rounded-lg transition-colors",
398
- children: [
399
- /* @__PURE__ */ jsx3(Settings, { className: "h-4 w-4 text-muted-foreground" }),
400
- t("common.settings")
401
- ]
402
- }
403
- )
404
- ] }),
405
- /* @__PURE__ */ jsx3("div", { className: "h-px bg-border my-1.5" }),
406
- /* @__PURE__ */ jsxs3(
407
- "button",
408
- {
409
- onClick: handleLogout,
410
- className: "flex w-full items-center gap-2.5 px-3 py-2 text-sm text-destructive hover:bg-destructive/10 rounded-lg transition-colors font-medium",
411
- children: [
412
- /* @__PURE__ */ jsx3(LogOut, { className: "h-4 w-4" }),
413
- t("common.logout")
414
- ]
415
- }
416
- )
417
- ] })
418
- ] })
419
- ] })
420
- ] })
421
- ] });
422
- };
423
-
424
- // src/domains/layouts/components/DashboardLayout.tsx
425
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
426
- var DashboardLayout = ({
427
- config,
428
- user,
429
- authLoading = false,
430
- isAuthenticated = true,
431
- notifications = [],
432
- onLogout,
433
- onMarkAllRead,
434
- onDismissNotification,
435
- loginRoute = "/login"
436
- }) => {
437
- const location = useLocation2();
438
- const [collapsed, setCollapsed] = useState3(false);
439
- const [mobileOpen, setMobileOpen] = useState3(false);
440
- const [loading, setLoading] = useState3(true);
441
- useEffect(() => {
442
- setLoading(true);
443
- const timer = setTimeout(() => setLoading(false), 300);
444
- return () => clearTimeout(timer);
445
- }, [location.pathname]);
446
- useEffect(() => {
447
- setMobileOpen(false);
448
- }, [location.pathname]);
449
- if (authLoading) return null;
450
- if (!isAuthenticated) return /* @__PURE__ */ jsx4(Navigate, { to: loginRoute, replace: true });
451
- const activeItem = config.sidebarGroups.flatMap((group) => group.items).find((i) => i.path === location.pathname);
452
- const getTitle = () => {
453
- if (!activeItem) return config.extraTitleMap?.[location.pathname] || "Dashboard";
454
- return activeItem.label;
455
- };
456
- const currentTitle = getTitle();
457
- return /* @__PURE__ */ jsxs4("div", { className: "flex h-screen w-full bg-background font-sans", children: [
458
- /* @__PURE__ */ jsx4(
459
- "aside",
460
- {
461
- className: `hidden md:flex flex-col shrink-0 border-r border-sidebar-border bg-sidebar transition-all duration-300 ${collapsed ? "w-16" : "w-60"}`,
462
- children: /* @__PURE__ */ jsx4(
463
- DashboardSidebar,
464
- {
465
- collapsed,
466
- setCollapsed,
467
- sidebarGroups: config.sidebarGroups,
468
- brandName: config.brandName,
469
- brandTagline: config.brandTagline,
470
- user
471
- }
472
- )
473
- }
474
- ),
475
- mobileOpen && /* @__PURE__ */ jsxs4("div", { className: "fixed inset-0 z-50 md:hidden", children: [
476
- /* @__PURE__ */ jsx4("div", { className: "absolute inset-0 bg-background/80 backdrop-blur-sm", onClick: () => setMobileOpen(false) }),
477
- /* @__PURE__ */ jsx4("aside", { className: "absolute left-0 top-0 h-full w-60 border-r border-sidebar-border bg-sidebar shadow-xl", children: /* @__PURE__ */ jsx4(
478
- DashboardSidebar,
479
- {
480
- collapsed: false,
481
- setCollapsed: () => setMobileOpen(false),
482
- sidebarGroups: config.sidebarGroups,
483
- brandName: config.brandName,
484
- brandTagline: config.brandTagline,
485
- user
486
- }
487
- ) })
488
- ] }),
489
- /* @__PURE__ */ jsxs4("div", { className: "flex flex-1 flex-col overflow-hidden min-w-0", children: [
490
- /* @__PURE__ */ jsx4(
491
- DashboardHeader,
492
- {
493
- collapsed,
494
- setCollapsed,
495
- setMobileOpen,
496
- title: currentTitle,
497
- user,
498
- notifications,
499
- onLogout,
500
- onMarkAllRead,
501
- onDismissNotification
502
- }
503
- ),
504
- /* @__PURE__ */ jsx4("main", { className: "flex-1 overflow-y-auto p-4 md:p-8", children: loading ? /* @__PURE__ */ jsxs4("div", { className: "mx-auto w-full max-w-7xl space-y-6", children: [
505
- /* @__PURE__ */ jsx4(Skeleton, { className: "h-8 w-1/3 rounded-xl" }),
506
- /* @__PURE__ */ jsx4("div", { className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-4", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsx4(Skeleton, { className: "h-28 rounded-2xl" }, i)) }),
507
- /* @__PURE__ */ jsx4(Skeleton, { className: "h-64 rounded-[32px]" })
508
- ] }) : /* @__PURE__ */ jsx4(Outlet, {}) })
509
- ] })
510
- ] });
511
- };
512
-
513
- // src/domains/layouts/hooks/dashboard.ts
514
- import { useState as useState4, useCallback } from "react";
515
- function useNotifications(initialNotifications = []) {
516
- const [notifications, setNotifications] = useState4(initialNotifications);
517
- const markAllRead = useCallback(() => {
518
- setNotifications(
519
- (prev) => prev.map((n) => ({ ...n, read: true }))
520
- );
521
- }, []);
522
- const dismiss = useCallback((id) => {
523
- setNotifications((prev) => prev.filter((n) => n.id !== id));
524
- }, []);
525
- const add = useCallback((notification) => {
526
- const newNotification = {
527
- ...notification,
528
- id: crypto.randomUUID(),
529
- read: false,
530
- createdAt: /* @__PURE__ */ new Date()
531
- };
532
- setNotifications((prev) => [newNotification, ...prev]);
533
- }, []);
534
- return {
535
- notifications,
536
- markAllRead,
537
- dismiss,
538
- add
539
- };
540
- }
541
- function useSidebar(initialCollapsed = false) {
542
- const [collapsed, setCollapsed] = useState4(initialCollapsed);
543
- const [mobileOpen, setMobileOpen] = useState4(false);
544
- const toggle = useCallback(() => {
545
- setCollapsed((prev) => !prev);
546
- }, []);
547
- const openMobile = useCallback(() => {
548
- setMobileOpen(true);
549
- }, []);
550
- const closeMobile = useCallback(() => {
551
- setMobileOpen(false);
552
- }, []);
553
- return {
554
- collapsed,
555
- setCollapsed,
556
- toggle,
557
- mobileOpen,
558
- setMobileOpen,
559
- openMobile,
560
- closeMobile
561
- };
562
- }
563
-
564
- // src/domains/layouts/theme/default.ts
565
- var DEFAULT_DASHBOARD_THEME = {
566
- primary: "hsl(222.2 47.4% 11.2%)",
567
- secondary: "hsl(217.2 32.6% 17.5%)",
568
- sidebarBackground: "hsl(222.2 47.4% 11.2%)",
569
- sidebarForeground: "hsl(210 40% 98%)",
570
- sidebarBorder: "hsl(217.2 32.6% 17.5%)",
571
- headerBackground: "hsla(0, 0%, 100%, 0.8)",
572
- background: "hsl(0 0% 100%)",
573
- foreground: "hsl(222.2 84% 4.9%)",
574
- border: "hsl(214.3 31.8% 91.4%)",
575
- accent: "hsl(217.2 91.2% 59.8%)",
576
- accentForeground: "hsl(0 0% 100%)",
577
- destructive: "hsl(0 84.2% 60.2%)",
578
- destructiveForeground: "hsl(0 0% 98%)",
579
- muted: "hsl(210 40% 96.1%)",
580
- mutedForeground: "hsl(215.4 16.3% 46.9%)",
581
- card: "hsl(0 0% 100%)",
582
- cardForeground: "hsl(222.2 84% 4.9%)",
583
- popover: "hsl(0 0% 100%)",
584
- popoverForeground: "hsl(222.2 84% 4.9%)",
585
- radius: "0.5rem"
586
- };
587
- var DEFAULT_DASHBOARD_THEME_DARK = {
588
- primary: "hsl(217.2 91.2% 59.8%)",
589
- secondary: "hsl(217.2 32.6% 17.5%)",
590
- sidebarBackground: "hsl(222.2 47.4% 11.2%)",
591
- sidebarForeground: "hsl(210 40% 98%)",
592
- sidebarBorder: "hsl(217.2 32.6% 17.5%)",
593
- headerBackground: "hsla(222.2 47.4% 11.2%, 0.8)",
594
- background: "hsl(222.2 84% 4.9%)",
595
- foreground: "hsl(210 40% 98%)",
596
- border: "hsl(217.2 32.6% 17.5%)",
597
- accent: "hsl(217.2 91.2% 59.8%)",
598
- accentForeground: "hsl(0 0% 100%)",
599
- destructive: "hsl(0 62.8% 30.6%)",
600
- destructiveForeground: "hsl(0 0% 98%)",
601
- muted: "hsl(217.2 32.6% 17.5%)",
602
- mutedForeground: "hsl(215 20.2% 65.1%)",
603
- card: "hsl(222.2 84% 4.9%)",
604
- cardForeground: "hsl(210 40% 98%)",
605
- popover: "hsl(222.2 84% 4.9%)",
606
- popoverForeground: "hsl(210 40% 98%)",
607
- radius: "0.5rem"
608
- };
609
-
610
- // src/domains/layouts/theme/presets.ts
611
- var DASHBOARD_THEME_PRESETS = [
612
- {
613
- name: "default",
614
- theme: DEFAULT_DASHBOARD_THEME,
615
- dark: false
616
- },
617
- {
618
- name: "default-dark",
619
- theme: DEFAULT_DASHBOARD_THEME_DARK,
620
- dark: true
621
- },
622
- {
623
- name: "blue",
624
- theme: {
625
- ...DEFAULT_DASHBOARD_THEME,
626
- primary: "hsl(221.2 83.2% 53.3%)",
627
- accent: "hsl(221.2 83.2% 53.3%)"
628
- },
629
- dark: false
630
- },
631
- {
632
- name: "blue-dark",
633
- theme: {
634
- ...DEFAULT_DASHBOARD_THEME_DARK,
635
- primary: "hsl(221.2 83.2% 53.3%)",
636
- accent: "hsl(221.2 83.2% 53.3%)"
637
- },
638
- dark: true
639
- },
640
- {
641
- name: "purple",
642
- theme: {
643
- ...DEFAULT_DASHBOARD_THEME,
644
- primary: "hsl(271.5 81.3% 55.9%)",
645
- accent: "hsl(271.5 81.3% 55.9%)"
646
- },
647
- dark: false
648
- },
649
- {
650
- name: "purple-dark",
651
- theme: {
652
- ...DEFAULT_DASHBOARD_THEME_DARK,
653
- primary: "hsl(271.5 81.3% 55.9%)",
654
- accent: "hsl(271.5 81.3% 55.9%)"
655
- },
656
- dark: true
657
- },
658
- {
659
- name: "green",
660
- theme: {
661
- ...DEFAULT_DASHBOARD_THEME,
662
- primary: "hsl(142.1 76.2% 36.3%)",
663
- accent: "hsl(142.1 76.2% 36.3%)"
664
- },
665
- dark: false
666
- },
667
- {
668
- name: "green-dark",
669
- theme: {
670
- ...DEFAULT_DASHBOARD_THEME_DARK,
671
- primary: "hsl(142.1 76.2% 36.3%)",
672
- accent: "hsl(142.1 76.2% 36.3%)"
673
- },
674
- dark: true
675
- },
676
- {
677
- name: "orange",
678
- theme: {
679
- ...DEFAULT_DASHBOARD_THEME,
680
- primary: "hsl(24.6 95% 53.1%)",
681
- accent: "hsl(24.6 95% 53.1%)"
682
- },
683
- dark: false
684
- },
685
- {
686
- name: "orange-dark",
687
- theme: {
688
- ...DEFAULT_DASHBOARD_THEME_DARK,
689
- primary: "hsl(24.6 95% 53.1%)",
690
- accent: "hsl(24.6 95% 53.1%)"
691
- },
692
- dark: true
693
- }
694
- ];
695
-
696
- // src/domains/layouts/theme/utils.ts
697
- function applyDashboardTheme(theme) {
698
- if (typeof document === "undefined") return;
699
- const root = document.documentElement;
700
- const cssVars = {
701
- "--primary": theme.primary,
702
- "--secondary": theme.secondary,
703
- "--sidebar": theme.sidebarBackground,
704
- "--sidebar-foreground": theme.sidebarForeground,
705
- "--sidebar-border": theme.sidebarBorder,
706
- "--background": theme.background,
707
- "--foreground": theme.foreground,
708
- "--border": theme.border,
709
- "--accent": theme.accent,
710
- "--accent-foreground": theme.accentForeground,
711
- "--destructive": theme.destructive,
712
- "--destructive-foreground": theme.destructiveForeground,
713
- "--muted": theme.muted,
714
- "--muted-foreground": theme.mutedForeground,
715
- "--card": theme.card,
716
- "--card-foreground": theme.cardForeground,
717
- "--popover": theme.popover,
718
- "--popover-foreground": theme.popoverForeground,
719
- "--radius": theme.radius
720
- };
721
- Object.entries(cssVars).forEach(([key, value]) => {
722
- if (value) {
723
- root.style.setProperty(key, value);
724
- }
725
- });
726
- }
727
- function getDashboardThemePreset(name) {
728
- return DASHBOARD_THEME_PRESETS.find((preset) => preset.name === name);
729
- }
730
- function mergeDashboardTheme(customTheme, dark = false) {
731
- const baseTheme = dark ? DEFAULT_DASHBOARD_THEME_DARK : DEFAULT_DASHBOARD_THEME;
732
- return {
733
- ...baseTheme,
734
- ...customTheme
735
- };
736
- }
737
- export {
738
- BrandLogo,
739
- DASHBOARD_THEME_PRESETS,
740
- DEFAULT_DASHBOARD_THEME,
741
- DEFAULT_DASHBOARD_THEME_DARK,
742
- DashboardHeader,
743
- DashboardLayout,
744
- DashboardSidebar,
745
- applyDashboardTheme,
746
- filterSidebarItems,
747
- formatNotificationTime,
748
- generateNotificationId,
749
- getDashboardThemePreset,
750
- getPageTitle,
751
- isPathActive,
752
- mergeDashboardTheme,
753
- useNotifications,
754
- useSidebar
755
- };
756
- //# sourceMappingURL=index.js.map