primus-react-ui 1.0.10 → 1.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +347 -22
- package/dist/index.d.ts +347 -22
- package/dist/index.js +1867 -106
- package/dist/index.mjs +1829 -105
- package/package.json +7 -4
- package/src/tailwind-preset.js +59 -0
package/dist/index.js
CHANGED
|
@@ -33,8 +33,13 @@ __export(index_exports, {
|
|
|
33
33
|
AICopilot: () => AICopilot,
|
|
34
34
|
AccountDashboard: () => AccountDashboard,
|
|
35
35
|
AgentDirectory: () => AgentDirectory,
|
|
36
|
+
Badge: () => Badge,
|
|
37
|
+
Button: () => Button,
|
|
38
|
+
Card: () => Card,
|
|
39
|
+
Checkbox: () => Checkbox,
|
|
36
40
|
CheckoutForm: () => CheckoutForm,
|
|
37
41
|
ClaimStatusTracker: () => ClaimStatusTracker,
|
|
42
|
+
Container: () => Container,
|
|
38
43
|
CreditCardVisual: () => CreditCardVisual,
|
|
39
44
|
CreditScoreCard: () => CreditScoreCard,
|
|
40
45
|
DashboardGrid: () => DashboardGrid,
|
|
@@ -42,29 +47,64 @@ __export(index_exports, {
|
|
|
42
47
|
FeatureFlagToggle: () => FeatureFlagToggle,
|
|
43
48
|
FileUploader: () => FileUploader,
|
|
44
49
|
FraudDetectionDashboard: () => FraudDetectionDashboard,
|
|
50
|
+
Grid: () => Grid,
|
|
51
|
+
Input: () => Input,
|
|
45
52
|
KYCVerification: () => KYCVerification,
|
|
46
53
|
LoanCalculator: () => LoanCalculator,
|
|
47
54
|
LogViewer: () => LogViewer,
|
|
48
55
|
LoginPage: () => LoginPage,
|
|
56
|
+
Modal: () => Modal,
|
|
49
57
|
NotificationBell: () => NotificationBell,
|
|
50
|
-
NotificationFeed: () =>
|
|
58
|
+
NotificationFeed: () => PrimusNotificationFeed,
|
|
51
59
|
PolicyCard: () => PolicyCard,
|
|
52
60
|
PremiumCalculator: () => PremiumCalculator,
|
|
61
|
+
PrimusActivityFeed: () => PrimusActivityFeed,
|
|
62
|
+
PrimusAreaChart: () => PrimusAreaChart,
|
|
63
|
+
PrimusBadge: () => Badge,
|
|
64
|
+
PrimusBarChart: () => PrimusBarChart,
|
|
65
|
+
PrimusButton: () => Button,
|
|
66
|
+
PrimusCard: () => Card,
|
|
67
|
+
PrimusChartBase: () => PrimusChartBase,
|
|
68
|
+
PrimusCheckbox: () => Checkbox,
|
|
69
|
+
PrimusContainer: () => Container,
|
|
53
70
|
PrimusDashboard: () => PrimusDashboard,
|
|
54
71
|
PrimusDataTable: () => PrimusDataTable,
|
|
72
|
+
PrimusDateRangePicker: () => PrimusDateRangePicker,
|
|
73
|
+
PrimusExportMenu: () => PrimusExportMenu,
|
|
74
|
+
PrimusFilterBar: () => PrimusFilterBar,
|
|
75
|
+
PrimusGrid: () => Grid,
|
|
55
76
|
PrimusHeader: () => PrimusHeader,
|
|
77
|
+
PrimusInput: () => Input,
|
|
56
78
|
PrimusLayout: () => PrimusLayout,
|
|
79
|
+
PrimusLineChart: () => PrimusLineChart,
|
|
57
80
|
PrimusLogin: () => PrimusLogin,
|
|
58
81
|
PrimusModal: () => PrimusModal,
|
|
82
|
+
PrimusModalComponent: () => Modal,
|
|
59
83
|
PrimusNotificationCenter: () => PrimusNotificationCenter,
|
|
84
|
+
PrimusNotificationFeed: () => PrimusNotificationFeed,
|
|
60
85
|
PrimusNotifications: () => PrimusNotifications,
|
|
86
|
+
PrimusPieChart: () => PrimusPieChart,
|
|
61
87
|
PrimusProvider: () => PrimusProvider,
|
|
88
|
+
PrimusRadioGroup: () => RadioGroup,
|
|
89
|
+
PrimusSearch: () => PrimusSearch,
|
|
90
|
+
PrimusSelect: () => Select,
|
|
62
91
|
PrimusSidebar: () => PrimusSidebar,
|
|
92
|
+
PrimusSparkline: () => PrimusSparkline,
|
|
93
|
+
PrimusStack: () => Stack,
|
|
63
94
|
PrimusStatCard: () => PrimusStatCard,
|
|
95
|
+
PrimusTable: () => Table,
|
|
96
|
+
PrimusTextarea: () => Textarea,
|
|
64
97
|
PrimusThemeProvider: () => PrimusThemeProvider,
|
|
65
98
|
PrimusThemeToggle: () => PrimusThemeToggle,
|
|
99
|
+
PrimusToggle: () => Toggle,
|
|
66
100
|
QuoteComparison: () => QuoteComparison,
|
|
101
|
+
RadioGroup: () => RadioGroup,
|
|
67
102
|
SecurityDashboard: () => SecurityDashboard,
|
|
103
|
+
Select: () => Select,
|
|
104
|
+
Stack: () => Stack,
|
|
105
|
+
Table: () => Table,
|
|
106
|
+
Textarea: () => Textarea,
|
|
107
|
+
Toggle: () => Toggle,
|
|
68
108
|
TransactionHistory: () => TransactionHistory,
|
|
69
109
|
UserProfile: () => UserProfile,
|
|
70
110
|
themeColors: () => themeColors,
|
|
@@ -1191,75 +1231,191 @@ var usePrimusAuth = () => {
|
|
|
1191
1231
|
|
|
1192
1232
|
// src/components/shared/Button.tsx
|
|
1193
1233
|
var import_react15 = __toESM(require("react"));
|
|
1194
|
-
var import_clsx = require("clsx");
|
|
1195
|
-
var import_tailwind_merge = require("tailwind-merge");
|
|
1196
1234
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1197
|
-
function cn(...inputs) {
|
|
1198
|
-
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
1199
|
-
}
|
|
1200
1235
|
var Button = import_react15.default.forwardRef(
|
|
1201
|
-
({
|
|
1236
|
+
({ style, variant = "primary", size = "md", color = "sapphire", disabled, ...props }, ref) => {
|
|
1237
|
+
const [isHovered, setIsHovered] = import_react15.default.useState(false);
|
|
1238
|
+
const colorStyles = {
|
|
1239
|
+
sapphire: {
|
|
1240
|
+
solid: "#1341a7",
|
|
1241
|
+
// Updated to user spec
|
|
1242
|
+
text: "#ffffff",
|
|
1243
|
+
hover: "rgba(19, 65, 167, 0.9)",
|
|
1244
|
+
subtle: "rgba(19, 65, 167, 0.12)"
|
|
1245
|
+
},
|
|
1246
|
+
emerald: {
|
|
1247
|
+
solid: "#418872",
|
|
1248
|
+
// Updated to user spec
|
|
1249
|
+
text: "#ffffff",
|
|
1250
|
+
hover: "rgba(65, 136, 114, 0.9)",
|
|
1251
|
+
subtle: "rgba(65, 136, 114, 0.12)"
|
|
1252
|
+
},
|
|
1253
|
+
ruby: {
|
|
1254
|
+
solid: "#ac0f0f",
|
|
1255
|
+
// Updated to user spec
|
|
1256
|
+
text: "#ffffff",
|
|
1257
|
+
hover: "rgba(172, 15, 15, 0.9)",
|
|
1258
|
+
subtle: "rgba(172, 15, 15, 0.12)"
|
|
1259
|
+
}
|
|
1260
|
+
};
|
|
1261
|
+
const selectedColor = colorStyles[color];
|
|
1262
|
+
const baseStyles = {
|
|
1263
|
+
display: "inline-flex",
|
|
1264
|
+
alignItems: "center",
|
|
1265
|
+
justifyContent: "center",
|
|
1266
|
+
whiteSpace: "nowrap",
|
|
1267
|
+
borderRadius: "0.5rem",
|
|
1268
|
+
fontSize: "0.875rem",
|
|
1269
|
+
lineHeight: "1.25rem",
|
|
1270
|
+
fontWeight: "600",
|
|
1271
|
+
transition: "all 0.15s cubic-bezier(0.4, 0, 0.2, 1)",
|
|
1272
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
1273
|
+
opacity: disabled ? 0.5 : 1,
|
|
1274
|
+
pointerEvents: disabled ? "none" : "auto",
|
|
1275
|
+
outline: "none",
|
|
1276
|
+
border: "none",
|
|
1277
|
+
boxShadow: isHovered && !disabled ? "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)" : "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
|
|
1278
|
+
transform: isHovered && !disabled ? "translateY(-1px)" : "none"
|
|
1279
|
+
};
|
|
1280
|
+
const variantStyles = {
|
|
1281
|
+
primary: {
|
|
1282
|
+
normal: {
|
|
1283
|
+
backgroundColor: selectedColor.solid,
|
|
1284
|
+
color: selectedColor.text
|
|
1285
|
+
},
|
|
1286
|
+
hover: {
|
|
1287
|
+
backgroundColor: selectedColor.hover
|
|
1288
|
+
}
|
|
1289
|
+
},
|
|
1290
|
+
secondary: {
|
|
1291
|
+
normal: {
|
|
1292
|
+
backgroundColor: "#f3f4f6",
|
|
1293
|
+
color: "#111827"
|
|
1294
|
+
},
|
|
1295
|
+
hover: {
|
|
1296
|
+
backgroundColor: "rgba(243, 244, 246, 0.8)"
|
|
1297
|
+
}
|
|
1298
|
+
},
|
|
1299
|
+
outline: {
|
|
1300
|
+
normal: {
|
|
1301
|
+
backgroundColor: "#ffffff",
|
|
1302
|
+
color: selectedColor.solid,
|
|
1303
|
+
border: `1px solid ${selectedColor.solid}`
|
|
1304
|
+
},
|
|
1305
|
+
hover: {
|
|
1306
|
+
backgroundColor: selectedColor.subtle
|
|
1307
|
+
}
|
|
1308
|
+
},
|
|
1309
|
+
ghost: {
|
|
1310
|
+
normal: {
|
|
1311
|
+
backgroundColor: "transparent",
|
|
1312
|
+
color: selectedColor.solid
|
|
1313
|
+
},
|
|
1314
|
+
hover: {
|
|
1315
|
+
backgroundColor: selectedColor.subtle
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
};
|
|
1319
|
+
const sizeStyles = {
|
|
1320
|
+
sm: { height: "2.25rem", padding: "0 0.75rem" },
|
|
1321
|
+
md: { height: "2.5rem", padding: "0.5rem 1rem" },
|
|
1322
|
+
lg: { height: "2.75rem", padding: "0 2rem" }
|
|
1323
|
+
};
|
|
1324
|
+
const currentVariant = variantStyles[variant];
|
|
1325
|
+
const combinedStyles = {
|
|
1326
|
+
...baseStyles,
|
|
1327
|
+
...currentVariant.normal,
|
|
1328
|
+
...isHovered && !disabled ? currentVariant.hover : {},
|
|
1329
|
+
...sizeStyles[size],
|
|
1330
|
+
...style
|
|
1331
|
+
};
|
|
1202
1332
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1203
1333
|
"button",
|
|
1204
1334
|
{
|
|
1205
1335
|
ref,
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
"bg-gray-100 text-gray-900 hover:bg-gray-100/80": variant === "secondary",
|
|
1211
|
-
"border border-gray-200 bg-white hover:bg-gray-100 hover:text-gray-900": variant === "outline",
|
|
1212
|
-
"hover:bg-gray-100 hover:text-gray-900": variant === "ghost",
|
|
1213
|
-
"h-9 px-3": size === "sm",
|
|
1214
|
-
"h-10 px-4 py-2": size === "md",
|
|
1215
|
-
"h-11 px-8": size === "lg"
|
|
1216
|
-
},
|
|
1217
|
-
className
|
|
1218
|
-
),
|
|
1336
|
+
style: combinedStyles,
|
|
1337
|
+
onMouseEnter: () => setIsHovered(true),
|
|
1338
|
+
onMouseLeave: () => setIsHovered(false),
|
|
1339
|
+
disabled,
|
|
1219
1340
|
...props
|
|
1220
1341
|
}
|
|
1221
1342
|
);
|
|
1222
1343
|
}
|
|
1223
1344
|
);
|
|
1345
|
+
Button.displayName = "Button";
|
|
1224
1346
|
|
|
1225
1347
|
// src/components/auth/UserProfile.tsx
|
|
1226
1348
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1227
|
-
var UserProfile = (
|
|
1228
|
-
|
|
1229
|
-
|
|
1349
|
+
var UserProfile = ({
|
|
1350
|
+
user: userOverride,
|
|
1351
|
+
showLogout = true,
|
|
1352
|
+
onLogout
|
|
1353
|
+
}) => {
|
|
1354
|
+
const { user: contextUser, logout, isAuthenticated } = usePrimusAuth();
|
|
1355
|
+
const resolvedUser = userOverride ?? (isAuthenticated ? contextUser : null);
|
|
1356
|
+
if (!resolvedUser) {
|
|
1230
1357
|
return null;
|
|
1231
1358
|
}
|
|
1359
|
+
const handleLogout = async () => {
|
|
1360
|
+
if (onLogout) {
|
|
1361
|
+
onLogout();
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1364
|
+
await logout();
|
|
1365
|
+
};
|
|
1232
1366
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-4 p-4 rounded-lg bg-gray-50 border border-gray-200", children: [
|
|
1233
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "h-10 w-10 rounded-full bg-primus-100 flex items-center justify-center text-primus-600 font-bold", children:
|
|
1367
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "h-10 w-10 rounded-full bg-primus-100 flex items-center justify-center text-primus-600 font-bold", children: resolvedUser.name?.charAt(0) || "U" }),
|
|
1234
1368
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1", children: [
|
|
1235
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-sm font-medium text-gray-900", children:
|
|
1236
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-xs text-gray-500", children:
|
|
1369
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-sm font-medium text-gray-900", children: resolvedUser.name }),
|
|
1370
|
+
resolvedUser.email && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-xs text-gray-500", children: resolvedUser.email })
|
|
1237
1371
|
] }),
|
|
1238
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Button, { variant: "outline", size: "sm", onClick:
|
|
1372
|
+
showLogout && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Button, { variant: "outline", size: "sm", onClick: handleLogout, children: "Sign out" })
|
|
1239
1373
|
] });
|
|
1240
1374
|
};
|
|
1241
1375
|
|
|
1242
1376
|
// src/hooks/useNotifications.ts
|
|
1243
1377
|
var import_react16 = require("react");
|
|
1244
|
-
var useNotifications = (
|
|
1378
|
+
var useNotifications = ({
|
|
1379
|
+
apiUrl = "http://localhost:5221",
|
|
1380
|
+
useMock = false,
|
|
1381
|
+
mockData = []
|
|
1382
|
+
} = {}) => {
|
|
1245
1383
|
const [notifications, setNotifications] = (0, import_react16.useState)([]);
|
|
1246
1384
|
const [unreadCount, setUnreadCount] = (0, import_react16.useState)(0);
|
|
1247
1385
|
const [loading, setLoading] = (0, import_react16.useState)(true);
|
|
1386
|
+
const safeMockData = (0, import_react16.useMemo)(() => mockData || [], [JSON.stringify(mockData)]);
|
|
1387
|
+
const DEFAULT_MOCK_DATA = [
|
|
1388
|
+
{ id: "1", title: "Welcome", message: "Welcome to Primus UI", type: "info", timestamp: (/* @__PURE__ */ new Date()).toISOString(), read: false },
|
|
1389
|
+
{ id: "2", title: "System Update", message: "Maintenance scheduled", type: "warning", timestamp: (/* @__PURE__ */ new Date()).toISOString(), read: false },
|
|
1390
|
+
{ id: "3", title: "Payment Success", message: "Your payment was processed", type: "success", timestamp: (/* @__PURE__ */ new Date()).toISOString(), read: false }
|
|
1391
|
+
];
|
|
1248
1392
|
(0, import_react16.useEffect)(() => {
|
|
1393
|
+
if (useMock) {
|
|
1394
|
+
const data = safeMockData.length > 0 ? safeMockData : DEFAULT_MOCK_DATA;
|
|
1395
|
+
setNotifications(data);
|
|
1396
|
+
setUnreadCount(data.filter((n) => !n.read).length);
|
|
1397
|
+
setLoading(false);
|
|
1398
|
+
return;
|
|
1399
|
+
}
|
|
1249
1400
|
fetchNotifications();
|
|
1250
|
-
const interval = setInterval(fetchNotifications,
|
|
1401
|
+
const interval = setInterval(fetchNotifications, 1e4);
|
|
1251
1402
|
return () => clearInterval(interval);
|
|
1252
|
-
}, []);
|
|
1403
|
+
}, [useMock, safeMockData]);
|
|
1253
1404
|
const fetchNotifications = async () => {
|
|
1405
|
+
if (useMock) return;
|
|
1254
1406
|
try {
|
|
1255
1407
|
const response = await fetch(`${apiUrl}/notifications`);
|
|
1256
1408
|
if (response.ok) {
|
|
1257
1409
|
const data = await response.json();
|
|
1258
1410
|
setNotifications(data);
|
|
1259
1411
|
setUnreadCount(data.filter((n) => !n.read).length);
|
|
1412
|
+
} else {
|
|
1413
|
+
throw new Error("API unavailable");
|
|
1260
1414
|
}
|
|
1261
1415
|
} catch (error) {
|
|
1262
|
-
console.
|
|
1416
|
+
console.warn("Failed to fetch notifications, using mock data:", error);
|
|
1417
|
+
setNotifications((prev) => prev.length === 0 ? DEFAULT_MOCK_DATA : prev);
|
|
1418
|
+
setUnreadCount((prev) => notifications.length === 0 ? DEFAULT_MOCK_DATA.filter((n) => !n.read).length : prev);
|
|
1263
1419
|
} finally {
|
|
1264
1420
|
setLoading(false);
|
|
1265
1421
|
}
|
|
@@ -1286,7 +1442,7 @@ var useNotifications = (apiUrl = "http://localhost:5221") => {
|
|
|
1286
1442
|
var import_outline = require("@heroicons/react/24/outline");
|
|
1287
1443
|
var import_react17 = require("@headlessui/react");
|
|
1288
1444
|
var import_react18 = require("react");
|
|
1289
|
-
var
|
|
1445
|
+
var import_clsx = require("clsx");
|
|
1290
1446
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1291
1447
|
var NotificationIcon = ({ type }) => {
|
|
1292
1448
|
switch (type) {
|
|
@@ -1300,10 +1456,10 @@ var NotificationIcon = ({ type }) => {
|
|
|
1300
1456
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_outline.InformationCircleIcon, { className: "h-6 w-6 text-blue-500" });
|
|
1301
1457
|
}
|
|
1302
1458
|
};
|
|
1303
|
-
var
|
|
1304
|
-
const { notifications, unreadCount, markAsRead, markAllAsRead } = useNotifications();
|
|
1305
|
-
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react17.Popover, { className: "relative", children: ({ open }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
1306
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react17.Popover.Button, { className: (0,
|
|
1459
|
+
var PrimusNotificationFeed = ({ useMock, mockData, apiUrl, className }) => {
|
|
1460
|
+
const { notifications, unreadCount, markAsRead, markAllAsRead } = useNotifications({ useMock, mockData, apiUrl });
|
|
1461
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react17.Popover, { className: (0, import_clsx.clsx)("relative", className), children: ({ open }) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
1462
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react17.Popover.Button, { className: (0, import_clsx.clsx)(
|
|
1307
1463
|
"relative p-2 rounded-full hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-primus-500",
|
|
1308
1464
|
open && "bg-gray-100"
|
|
1309
1465
|
), children: [
|
|
@@ -1335,7 +1491,7 @@ var NotificationFeed = () => {
|
|
|
1335
1491
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "max-h-96 overflow-y-auto", children: notifications.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "px-4 py-6 text-center text-sm text-gray-500", children: "No new notifications" }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "divide-y divide-gray-100", children: notifications.map((notification) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
1336
1492
|
"div",
|
|
1337
1493
|
{
|
|
1338
|
-
className: (0,
|
|
1494
|
+
className: (0, import_clsx.clsx)(
|
|
1339
1495
|
"flex gap-3 px-4 py-4 hover:bg-gray-50 transition-colors cursor-pointer",
|
|
1340
1496
|
!notification.read && "bg-blue-50/50"
|
|
1341
1497
|
),
|
|
@@ -1364,7 +1520,13 @@ var import_react19 = require("react");
|
|
|
1364
1520
|
var import_lucide_react = require("lucide-react");
|
|
1365
1521
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1366
1522
|
var API_URL = "http://localhost:5222";
|
|
1367
|
-
function PrimusNotificationCenter({
|
|
1523
|
+
function PrimusNotificationCenter({
|
|
1524
|
+
theme: themeOverride,
|
|
1525
|
+
apiUrl = API_URL,
|
|
1526
|
+
pollInterval = 3e3,
|
|
1527
|
+
useMock = false,
|
|
1528
|
+
mockData
|
|
1529
|
+
}) {
|
|
1368
1530
|
const themeContext = usePrimusTheme();
|
|
1369
1531
|
const theme = themeOverride || themeContext.theme;
|
|
1370
1532
|
const t = themeColors[theme];
|
|
@@ -1388,13 +1550,37 @@ function PrimusNotificationCenter({ theme: themeOverride, apiUrl = API_URL }) {
|
|
|
1388
1550
|
}
|
|
1389
1551
|
}, [apiUrl]);
|
|
1390
1552
|
(0, import_react19.useEffect)(() => {
|
|
1553
|
+
if (useMock || mockData) {
|
|
1554
|
+
const next = mockData ?? [];
|
|
1555
|
+
setNotifications(next);
|
|
1556
|
+
setUnreadCount(next.filter((n) => !n.read).length);
|
|
1557
|
+
return;
|
|
1558
|
+
}
|
|
1391
1559
|
fetchNotifications();
|
|
1392
|
-
const interval = setInterval(fetchNotifications,
|
|
1560
|
+
const interval = setInterval(fetchNotifications, pollInterval);
|
|
1393
1561
|
return () => clearInterval(interval);
|
|
1394
|
-
}, [fetchNotifications]);
|
|
1562
|
+
}, [fetchNotifications, pollInterval, useMock, mockData]);
|
|
1395
1563
|
const sendNotification = async () => {
|
|
1396
1564
|
if (!newTitle.trim() || !newMessage.trim()) return;
|
|
1397
1565
|
setSending(true);
|
|
1566
|
+
if (useMock || mockData) {
|
|
1567
|
+
const next = {
|
|
1568
|
+
id: `mock-${Date.now()}`,
|
|
1569
|
+
title: newTitle,
|
|
1570
|
+
message: newMessage,
|
|
1571
|
+
type: newType,
|
|
1572
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1573
|
+
read: false
|
|
1574
|
+
};
|
|
1575
|
+
setNotifications((prev) => [next, ...prev]);
|
|
1576
|
+
setUnreadCount((prev) => prev + 1);
|
|
1577
|
+
setNewTitle("");
|
|
1578
|
+
setNewMessage("");
|
|
1579
|
+
setNewType("info");
|
|
1580
|
+
setShowSendForm(false);
|
|
1581
|
+
setSending(false);
|
|
1582
|
+
return;
|
|
1583
|
+
}
|
|
1398
1584
|
try {
|
|
1399
1585
|
const response = await fetch(`${apiUrl}/api/notifications`, {
|
|
1400
1586
|
method: "POST",
|
|
@@ -1414,8 +1600,13 @@ function PrimusNotificationCenter({ theme: themeOverride, apiUrl = API_URL }) {
|
|
|
1414
1600
|
setSending(false);
|
|
1415
1601
|
};
|
|
1416
1602
|
const markAsRead = async (id) => {
|
|
1603
|
+
if (useMock || mockData) {
|
|
1604
|
+
setNotifications((prev) => prev.map((n) => n.id === id ? { ...n, read: true } : n));
|
|
1605
|
+
setUnreadCount((prev) => Math.max(0, prev - 1));
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1417
1608
|
try {
|
|
1418
|
-
await fetch(`${apiUrl}/api/notifications/${id}/read`, { method: "
|
|
1609
|
+
await fetch(`${apiUrl}/api/notifications/${id}/read`, { method: "POST" });
|
|
1419
1610
|
setNotifications((prev) => prev.map((n) => n.id === id ? { ...n, read: true } : n));
|
|
1420
1611
|
setUnreadCount((prev) => Math.max(0, prev - 1));
|
|
1421
1612
|
} catch {
|
|
@@ -1655,35 +1846,84 @@ var import_react22 = require("react");
|
|
|
1655
1846
|
|
|
1656
1847
|
// src/components/shared/Input.tsx
|
|
1657
1848
|
var import_react21 = __toESM(require("react"));
|
|
1658
|
-
var
|
|
1659
|
-
var
|
|
1849
|
+
var import_clsx2 = require("clsx");
|
|
1850
|
+
var import_solid = require("@heroicons/react/20/solid");
|
|
1660
1851
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1852
|
+
var sizeClasses = {
|
|
1853
|
+
sm: "h-8 text-xs",
|
|
1854
|
+
md: "h-10 text-sm",
|
|
1855
|
+
lg: "h-12 text-base"
|
|
1856
|
+
};
|
|
1857
|
+
var iconSizeClasses = {
|
|
1858
|
+
sm: "w-4 h-4 [&>*]:w-full [&>*]:h-full",
|
|
1859
|
+
md: "w-5 h-5 [&>*]:w-full [&>*]:h-full",
|
|
1860
|
+
lg: "w-6 h-6 [&>*]:w-full [&>*]:h-full"
|
|
1861
|
+
};
|
|
1664
1862
|
var Input = import_react21.default.forwardRef(
|
|
1665
|
-
({ className, label, error, ...props }, ref) => {
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1669
|
-
"
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1863
|
+
({ className, style, label, error, disabled, startIcon, endIcon, onClear, value, onChange, size = "md", loading = false, ...props }, ref) => {
|
|
1864
|
+
const hasValue = value !== void 0 && value !== "" && value !== null;
|
|
1865
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: (0, import_clsx2.clsx)("w-full", className), style, children: [
|
|
1866
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { className: (0, import_clsx2.clsx)(
|
|
1867
|
+
"block font-medium mb-1.5",
|
|
1868
|
+
size === "sm" ? "text-xs" : "text-sm",
|
|
1869
|
+
disabled ? "text-gray-400 opacity-70" : "text-gray-700"
|
|
1870
|
+
), children: label }),
|
|
1871
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: (0, import_clsx2.clsx)(
|
|
1872
|
+
"relative flex items-center w-full rounded-lg transition-all duration-200 ease-in-out bg-white overflow-hidden",
|
|
1873
|
+
"border",
|
|
1874
|
+
error ? "border-red-500 hover:border-red-600 focus-within:ring-2 focus-within:ring-red-500/20 focus-within:border-red-500" : "border-gray-200 hover:border-gray-300 focus-within:ring-2 focus-within:ring-primus-500/20 focus-within:border-primus-500",
|
|
1875
|
+
disabled && "bg-gray-50 opacity-60 cursor-not-allowed"
|
|
1876
|
+
), children: [
|
|
1877
|
+
startIcon && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: (0, import_clsx2.clsx)(
|
|
1878
|
+
"flex-shrink-0 pl-3 pr-2 text-gray-400 select-none pointer-events-none flex items-center justify-center",
|
|
1879
|
+
iconSizeClasses[size]
|
|
1880
|
+
), children: startIcon }),
|
|
1881
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1882
|
+
"input",
|
|
1883
|
+
{
|
|
1884
|
+
ref,
|
|
1885
|
+
disabled,
|
|
1886
|
+
value,
|
|
1887
|
+
onChange,
|
|
1888
|
+
className: (0, import_clsx2.clsx)(
|
|
1889
|
+
"flex-1 w-full border-none bg-transparent p-0 placeholder:text-gray-400 focus:ring-0 outline-none",
|
|
1890
|
+
sizeClasses[size],
|
|
1891
|
+
// Adjust padding based on icon presence
|
|
1892
|
+
!startIcon && "pl-3",
|
|
1893
|
+
!endIcon && !onClear && !loading && "pr-3"
|
|
1894
|
+
),
|
|
1895
|
+
...props
|
|
1896
|
+
}
|
|
1897
|
+
),
|
|
1898
|
+
onClear && hasValue && !disabled && !loading && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex-shrink-0 pr-2 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1899
|
+
"button",
|
|
1900
|
+
{
|
|
1901
|
+
type: "button",
|
|
1902
|
+
onClick: (e) => {
|
|
1903
|
+
e.stopPropagation();
|
|
1904
|
+
onClear();
|
|
1905
|
+
},
|
|
1906
|
+
className: "p-1 rounded-full text-gray-400 hover:text-gray-600 hover:bg-gray-100 transition-colors",
|
|
1907
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_solid.XMarkIcon, { className: "h-4 w-4" })
|
|
1908
|
+
}
|
|
1909
|
+
) }),
|
|
1910
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex-shrink-0 pr-3 pl-2 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("svg", { className: "animate-spin h-5 w-5 text-primus-500", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
|
|
1911
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
1912
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
|
|
1913
|
+
] }) }),
|
|
1914
|
+
endIcon && !loading && (onClear ? !hasValue : true) && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: (0, import_clsx2.clsx)(
|
|
1915
|
+
"flex-shrink-0 pr-3 pl-2 text-gray-400 select-none pointer-events-none flex items-center justify-center",
|
|
1916
|
+
iconSizeClasses[size]
|
|
1917
|
+
), children: endIcon })
|
|
1918
|
+
] }),
|
|
1919
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "mt-1.5 text-xs text-red-500 flex items-center gap-1 animate-in slide-in-from-top-1 fade-in duration-200", children: error })
|
|
1681
1920
|
] });
|
|
1682
1921
|
}
|
|
1683
1922
|
);
|
|
1923
|
+
Input.displayName = "Input";
|
|
1684
1924
|
|
|
1685
1925
|
// src/components/payments/CheckoutForm.tsx
|
|
1686
|
-
var
|
|
1926
|
+
var import_solid2 = require("@heroicons/react/24/solid");
|
|
1687
1927
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1688
1928
|
var CheckoutForm = ({
|
|
1689
1929
|
amount,
|
|
@@ -1742,7 +1982,7 @@ var CheckoutForm = ({
|
|
|
1742
1982
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex justify-between items-center mb-6", children: [
|
|
1743
1983
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { className: "text-lg font-medium text-gray-900", children: "Payment Details" }),
|
|
1744
1984
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center text-gray-500 text-sm", children: [
|
|
1745
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1985
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_solid2.LockClosedIcon, { className: "h-4 w-4 mr-1" }),
|
|
1746
1986
|
"Secure Payment"
|
|
1747
1987
|
] })
|
|
1748
1988
|
] }),
|
|
@@ -1751,11 +1991,11 @@ var CheckoutForm = ({
|
|
|
1751
1991
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-2xl font-bold text-gray-900", children: new Intl.NumberFormat("en-US", { style: "currency", currency }).format(amount) })
|
|
1752
1992
|
] }),
|
|
1753
1993
|
error && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "mb-4 p-3 bg-red-50 border border-red-200 rounded-lg flex items-start gap-2", children: [
|
|
1754
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1994
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_solid2.XCircleIcon, { className: "h-5 w-5 text-red-500 flex-shrink-0 mt-0.5" }),
|
|
1755
1995
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-sm text-red-700", children: error })
|
|
1756
1996
|
] }),
|
|
1757
1997
|
success && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "mb-4 p-3 bg-green-50 border border-green-200 rounded-lg flex items-start gap-2", children: [
|
|
1758
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1998
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_solid2.CheckCircleIcon, { className: "h-5 w-5 text-green-500 flex-shrink-0 mt-0.5" }),
|
|
1759
1999
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-sm text-green-700", children: "Payment successful!" })
|
|
1760
2000
|
] }),
|
|
1761
2001
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
|
|
@@ -1826,18 +2066,18 @@ var CheckoutForm = ({
|
|
|
1826
2066
|
var import_outline2 = require("@heroicons/react/24/outline");
|
|
1827
2067
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1828
2068
|
var DocumentViewer = ({
|
|
1829
|
-
document,
|
|
2069
|
+
document: document2,
|
|
1830
2070
|
onClose,
|
|
1831
2071
|
onDownload
|
|
1832
2072
|
}) => {
|
|
1833
2073
|
const renderContent = () => {
|
|
1834
|
-
switch (
|
|
2074
|
+
switch (document2.type) {
|
|
1835
2075
|
case "image":
|
|
1836
2076
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
1837
2077
|
"img",
|
|
1838
2078
|
{
|
|
1839
|
-
src:
|
|
1840
|
-
alt:
|
|
2079
|
+
src: document2.url,
|
|
2080
|
+
alt: document2.name,
|
|
1841
2081
|
className: "max-w-full max-h-[80vh] object-contain mx-auto shadow-lg rounded"
|
|
1842
2082
|
}
|
|
1843
2083
|
);
|
|
@@ -1845,14 +2085,14 @@ var DocumentViewer = ({
|
|
|
1845
2085
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "bg-gray-100 p-8 rounded-lg text-center h-[600px] flex items-center justify-center border-2 border-dashed border-gray-300", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "text-gray-500", children: [
|
|
1846
2086
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_outline2.DocumentArrowDownIcon, { className: "h-16 w-16 mx-auto mb-4 text-gray-400" }),
|
|
1847
2087
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "font-medium", children: "PDF Preview" }),
|
|
1848
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-sm mt-2", children:
|
|
2088
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-sm mt-2", children: document2.name }),
|
|
1849
2089
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Button, { variant: "outline", size: "sm", className: "mt-4", onClick: onDownload, children: "Download to view" })
|
|
1850
2090
|
] }) });
|
|
1851
2091
|
default:
|
|
1852
2092
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "bg-white p-8 rounded shadow border border-gray-200 h-[600px] overflow-auto font-mono text-sm leading-relaxed", children: [
|
|
1853
2093
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("p", { children: [
|
|
1854
2094
|
"Document Content: ",
|
|
1855
|
-
|
|
2095
|
+
document2.name
|
|
1856
2096
|
] }),
|
|
1857
2097
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-4 text-gray-500", children: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." })
|
|
1858
2098
|
] });
|
|
@@ -1861,13 +2101,13 @@ var DocumentViewer = ({
|
|
|
1861
2101
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col h-full bg-gray-50 rounded-lg overflow-hidden border border-gray-200", children: [
|
|
1862
2102
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "bg-white border-b border-gray-200 px-4 py-3 flex items-center justify-between shadow-sm", children: [
|
|
1863
2103
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
1864
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "h-8 w-8 bg-primus-100 rounded flex items-center justify-center text-primus-700", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "uppercase text-xs font-bold", children:
|
|
2104
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "h-8 w-8 bg-primus-100 rounded flex items-center justify-center text-primus-700", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "uppercase text-xs font-bold", children: document2.type }) }),
|
|
1865
2105
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
|
|
1866
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { className: "text-sm font-semibold text-gray-900", children:
|
|
1867
|
-
|
|
1868
|
-
|
|
2106
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { className: "text-sm font-semibold text-gray-900", children: document2.name }),
|
|
2107
|
+
document2.size && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("p", { className: "text-xs text-gray-500", children: [
|
|
2108
|
+
document2.size,
|
|
1869
2109
|
" \u2022 ",
|
|
1870
|
-
|
|
2110
|
+
document2.date
|
|
1871
2111
|
] })
|
|
1872
2112
|
] })
|
|
1873
2113
|
] }),
|
|
@@ -1883,7 +2123,7 @@ var DocumentViewer = ({
|
|
|
1883
2123
|
};
|
|
1884
2124
|
|
|
1885
2125
|
// src/components/banking/cards/CreditCardVisual.tsx
|
|
1886
|
-
var
|
|
2126
|
+
var import_clsx3 = require("clsx");
|
|
1887
2127
|
var import_outline3 = require("@heroicons/react/24/outline");
|
|
1888
2128
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1889
2129
|
var CreditCardVisual = ({
|
|
@@ -1905,7 +2145,7 @@ var CreditCardVisual = ({
|
|
|
1905
2145
|
return "bg-gradient-to-br from-gray-900 to-gray-800";
|
|
1906
2146
|
}
|
|
1907
2147
|
};
|
|
1908
|
-
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: (0,
|
|
2148
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: (0, import_clsx3.clsx)(
|
|
1909
2149
|
"w-80 h-48 rounded-2xl p-6 text-white shadow-xl relative overflow-hidden transition-transform hover:scale-105 duration-300",
|
|
1910
2150
|
getBackground()
|
|
1911
2151
|
), children: [
|
|
@@ -1935,7 +2175,7 @@ var CreditCardVisual = ({
|
|
|
1935
2175
|
|
|
1936
2176
|
// src/components/banking/transactions/TransactionHistory.tsx
|
|
1937
2177
|
var import_outline4 = require("@heroicons/react/24/outline");
|
|
1938
|
-
var
|
|
2178
|
+
var import_clsx4 = require("clsx");
|
|
1939
2179
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1940
2180
|
var TransactionHistory = ({
|
|
1941
2181
|
transactions,
|
|
@@ -1958,7 +2198,7 @@ var TransactionHistory = ({
|
|
|
1958
2198
|
className: "px-6 py-4 flex items-center justify-between hover:bg-gray-50 cursor-pointer transition-colors",
|
|
1959
2199
|
children: [
|
|
1960
2200
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-4", children: [
|
|
1961
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: (0,
|
|
2201
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: (0, import_clsx4.clsx)(
|
|
1962
2202
|
"h-10 w-10 rounded-full flex items-center justify-center",
|
|
1963
2203
|
t.type === "credit" ? "bg-green-100" : "bg-gray-100"
|
|
1964
2204
|
), children: getIcon(t) }),
|
|
@@ -1968,7 +2208,7 @@ var TransactionHistory = ({
|
|
|
1968
2208
|
] })
|
|
1969
2209
|
] }),
|
|
1970
2210
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "text-right", children: [
|
|
1971
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("p", { className: (0,
|
|
2211
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("p", { className: (0, import_clsx4.clsx)(
|
|
1972
2212
|
"text-sm font-semibold",
|
|
1973
2213
|
t.type === "credit" ? "text-green-600" : "text-gray-900"
|
|
1974
2214
|
), children: [
|
|
@@ -1985,7 +2225,7 @@ var TransactionHistory = ({
|
|
|
1985
2225
|
};
|
|
1986
2226
|
|
|
1987
2227
|
// src/components/insurance/policies/PolicyCard.tsx
|
|
1988
|
-
var
|
|
2228
|
+
var import_clsx5 = require("clsx");
|
|
1989
2229
|
var import_outline5 = require("@heroicons/react/24/outline");
|
|
1990
2230
|
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1991
2231
|
var PolicyCard = ({
|
|
@@ -2005,7 +2245,7 @@ var PolicyCard = ({
|
|
|
2005
2245
|
" Insurance"
|
|
2006
2246
|
] })
|
|
2007
2247
|
] }),
|
|
2008
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: (0,
|
|
2248
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: (0, import_clsx5.clsx)(
|
|
2009
2249
|
"px-2.5 py-0.5 rounded-full text-xs font-medium uppercase tracking-wide",
|
|
2010
2250
|
status === "active" ? "bg-green-100 text-green-800" : status === "pending" ? "bg-yellow-100 text-yellow-800" : "bg-gray-100 text-gray-800"
|
|
2011
2251
|
), children: status })
|
|
@@ -2044,8 +2284,8 @@ var PolicyCard = ({
|
|
|
2044
2284
|
};
|
|
2045
2285
|
|
|
2046
2286
|
// src/components/insurance/claims/ClaimStatusTracker.tsx
|
|
2047
|
-
var
|
|
2048
|
-
var
|
|
2287
|
+
var import_clsx6 = require("clsx");
|
|
2288
|
+
var import_solid3 = require("@heroicons/react/24/solid");
|
|
2049
2289
|
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2050
2290
|
var ClaimStatusTracker = ({
|
|
2051
2291
|
claimId,
|
|
@@ -2059,14 +2299,14 @@ var ClaimStatusTracker = ({
|
|
|
2059
2299
|
claimId
|
|
2060
2300
|
] })
|
|
2061
2301
|
] }),
|
|
2062
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("nav", { "aria-label": "Progress", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("ol", { role: "list", className: "overflow-hidden", children: steps.map((step, stepIdx) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("li", { className: (0,
|
|
2302
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("nav", { "aria-label": "Progress", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("ol", { role: "list", className: "overflow-hidden", children: steps.map((step, stepIdx) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("li", { className: (0, import_clsx6.clsx)(
|
|
2063
2303
|
"relative pb-10",
|
|
2064
2304
|
stepIdx === steps.length - 1 ? "pb-0" : ""
|
|
2065
2305
|
), children: [
|
|
2066
2306
|
stepIdx !== steps.length - 1 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2067
2307
|
"div",
|
|
2068
2308
|
{
|
|
2069
|
-
className: (0,
|
|
2309
|
+
className: (0, import_clsx6.clsx)(
|
|
2070
2310
|
"absolute top-4 left-4 -ml-px h-full w-0.5",
|
|
2071
2311
|
step.status === "completed" ? "bg-primus-600" : "bg-gray-200"
|
|
2072
2312
|
),
|
|
@@ -2074,12 +2314,12 @@ var ClaimStatusTracker = ({
|
|
|
2074
2314
|
}
|
|
2075
2315
|
) : null,
|
|
2076
2316
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "relative flex items-start group", children: [
|
|
2077
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "h-9 flex items-center", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: (0,
|
|
2317
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "h-9 flex items-center", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: (0, import_clsx6.clsx)(
|
|
2078
2318
|
"relative z-10 w-8 h-8 flex items-center justify-center rounded-full ring-1 ring-white",
|
|
2079
2319
|
step.status === "completed" ? "bg-primus-600" : step.status === "current" ? "bg-white border-2 border-primus-600" : "bg-white border-2 border-gray-300"
|
|
2080
|
-
), children: step.status === "completed" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2320
|
+
), children: step.status === "completed" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_solid3.CheckIcon, { className: "w-5 h-5 text-white", "aria-hidden": "true" }) : step.status === "current" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "h-2.5 w-2.5 bg-primus-600 rounded-full" }) : null }) }),
|
|
2081
2321
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "ml-4 min-w-0 flex flex-col", children: [
|
|
2082
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: (0,
|
|
2322
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: (0, import_clsx6.clsx)(
|
|
2083
2323
|
"text-sm font-medium",
|
|
2084
2324
|
step.status === "upcoming" ? "text-gray-500" : "text-gray-900"
|
|
2085
2325
|
), children: step.label }),
|
|
@@ -2235,9 +2475,14 @@ var PrimusSidebar = ({
|
|
|
2235
2475
|
logo && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "h-20 flex items-center px-6 relative z-10 border-b border-white/5", children: logo }),
|
|
2236
2476
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("nav", { className: "flex-1 py-6 px-3 overflow-y-auto relative z-10", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("ul", { className: "space-y-1", children: items.map((item) => {
|
|
2237
2477
|
const isActive = activeId === item.id || item.active;
|
|
2478
|
+
const link = item.href ?? item.route;
|
|
2479
|
+
const Wrapper = link ? "a" : "button";
|
|
2238
2480
|
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
2239
|
-
|
|
2481
|
+
Wrapper,
|
|
2240
2482
|
{
|
|
2483
|
+
href: link,
|
|
2484
|
+
target: item.target,
|
|
2485
|
+
rel: item.target === "_blank" ? "noreferrer" : void 0,
|
|
2241
2486
|
onClick: () => {
|
|
2242
2487
|
item.onClick?.();
|
|
2243
2488
|
onItemClick?.(item);
|
|
@@ -2310,11 +2555,16 @@ function PrimusDataTable({
|
|
|
2310
2555
|
actions,
|
|
2311
2556
|
emptyMessage = "No data available",
|
|
2312
2557
|
searchPlaceholder = "Filter...",
|
|
2313
|
-
searchable = true
|
|
2558
|
+
searchable = true,
|
|
2559
|
+
paginated = false,
|
|
2560
|
+
pageSize = 10,
|
|
2561
|
+
pageIndex,
|
|
2562
|
+
onPageChange
|
|
2314
2563
|
}) {
|
|
2315
2564
|
const [search, setSearch] = (0, import_react26.useState)("");
|
|
2316
2565
|
const [sortKey, setSortKey] = (0, import_react26.useState)(null);
|
|
2317
2566
|
const [sortDir, setSortDir] = (0, import_react26.useState)("asc");
|
|
2567
|
+
const [internalPageIndex, setInternalPageIndex] = (0, import_react26.useState)(0);
|
|
2318
2568
|
const filteredData = (0, import_react26.useMemo)(() => {
|
|
2319
2569
|
let result = [...data];
|
|
2320
2570
|
if (search) {
|
|
@@ -2342,16 +2592,33 @@ function PrimusDataTable({
|
|
|
2342
2592
|
setSortKey(key);
|
|
2343
2593
|
setSortDir("asc");
|
|
2344
2594
|
}
|
|
2595
|
+
if (paginated) {
|
|
2596
|
+
goToPage(0);
|
|
2597
|
+
}
|
|
2598
|
+
};
|
|
2599
|
+
const effectivePageIndex = pageIndex ?? internalPageIndex;
|
|
2600
|
+
const totalPages = Math.max(1, Math.ceil(filteredData.length / Math.max(pageSize, 1)));
|
|
2601
|
+
const currentPageIndex = Math.min(Math.max(effectivePageIndex, 0), totalPages - 1);
|
|
2602
|
+
const pageData = paginated ? filteredData.slice(currentPageIndex * pageSize, currentPageIndex * pageSize + pageSize) : filteredData;
|
|
2603
|
+
const selectionScope = paginated ? pageData : filteredData;
|
|
2604
|
+
const isScopeSelected = selectionScope.length > 0 && selectionScope.every((row) => selectedKeys.includes(row[rowKey]));
|
|
2605
|
+
const goToPage = (nextIndex) => {
|
|
2606
|
+
const clamped = Math.min(Math.max(nextIndex, 0), totalPages - 1);
|
|
2607
|
+
if (pageIndex === void 0) {
|
|
2608
|
+
setInternalPageIndex(clamped);
|
|
2609
|
+
}
|
|
2610
|
+
onPageChange?.({ pageIndex: clamped, pageSize });
|
|
2345
2611
|
};
|
|
2346
2612
|
const toggleSelect = (key) => {
|
|
2347
2613
|
const newKeys = selectedKeys.includes(key) ? selectedKeys.filter((k) => k !== key) : [...selectedKeys, key];
|
|
2348
2614
|
onSelectionChange?.(newKeys);
|
|
2349
2615
|
};
|
|
2350
2616
|
const toggleSelectAll = () => {
|
|
2351
|
-
|
|
2617
|
+
const scopeKeys = selectionScope.map((row) => row[rowKey]);
|
|
2618
|
+
if (isScopeSelected) {
|
|
2352
2619
|
onSelectionChange?.([]);
|
|
2353
2620
|
} else {
|
|
2354
|
-
onSelectionChange?.(
|
|
2621
|
+
onSelectionChange?.(scopeKeys);
|
|
2355
2622
|
}
|
|
2356
2623
|
};
|
|
2357
2624
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-col space-y-4", children: [
|
|
@@ -2363,7 +2630,12 @@ function PrimusDataTable({
|
|
|
2363
2630
|
type: "text",
|
|
2364
2631
|
placeholder: searchPlaceholder,
|
|
2365
2632
|
value: search,
|
|
2366
|
-
onChange: (e) =>
|
|
2633
|
+
onChange: (e) => {
|
|
2634
|
+
setSearch(e.target.value);
|
|
2635
|
+
if (paginated) {
|
|
2636
|
+
goToPage(0);
|
|
2637
|
+
}
|
|
2638
|
+
},
|
|
2367
2639
|
className: "w-64 pl-10 pr-4 py-2 bg-white/5 border border-white/10 rounded-lg text-sm text-gray-200 placeholder-gray-500 focus:outline-none focus:ring-1 focus:ring-purple-500/50 focus:bg-white/10 transition-all hover:bg-white/10"
|
|
2368
2640
|
}
|
|
2369
2641
|
)
|
|
@@ -2374,7 +2646,7 @@ function PrimusDataTable({
|
|
|
2374
2646
|
"input",
|
|
2375
2647
|
{
|
|
2376
2648
|
type: "checkbox",
|
|
2377
|
-
checked:
|
|
2649
|
+
checked: isScopeSelected,
|
|
2378
2650
|
onChange: toggleSelectAll,
|
|
2379
2651
|
className: "rounded border-gray-600 bg-gray-800 text-purple-600 focus:ring-offset-gray-900 focus:ring-purple-500 transition-colors cursor-pointer"
|
|
2380
2652
|
}
|
|
@@ -2397,7 +2669,7 @@ function PrimusDataTable({
|
|
|
2397
2669
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("tbody", { className: "divide-y divide-white/5", children: loading ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("td", { colSpan: columns.length + (selectable ? 1 : 0) + (actions ? 1 : 0), className: "px-6 py-24 text-center text-gray-500", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-col items-center justify-center gap-3", children: [
|
|
2398
2670
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "w-6 h-6 border-2 border-purple-500/50 border-t-purple-500 rounded-full animate-spin" }),
|
|
2399
2671
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-sm font-medium", children: "Loading data..." })
|
|
2400
|
-
] }) }) }) : filteredData.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("td", { colSpan: columns.length + (selectable ? 1 : 0) + (actions ? 1 : 0), className: "px-6 py-24 text-center text-gray-500", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "text-sm", children: emptyMessage }) }) }) :
|
|
2672
|
+
] }) }) }) : filteredData.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("td", { colSpan: columns.length + (selectable ? 1 : 0) + (actions ? 1 : 0), className: "px-6 py-24 text-center text-gray-500", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "text-sm", children: emptyMessage }) }) }) : pageData.map((row) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
2401
2673
|
"tr",
|
|
2402
2674
|
{
|
|
2403
2675
|
onClick: () => onRowClick?.(row),
|
|
@@ -2422,7 +2694,35 @@ function PrimusDataTable({
|
|
|
2422
2694
|
},
|
|
2423
2695
|
String(row[rowKey])
|
|
2424
2696
|
)) })
|
|
2425
|
-
] }) }) })
|
|
2697
|
+
] }) }) }),
|
|
2698
|
+
paginated && totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center justify-between text-sm text-gray-400 px-2", children: [
|
|
2699
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2700
|
+
"button",
|
|
2701
|
+
{
|
|
2702
|
+
type: "button",
|
|
2703
|
+
onClick: () => goToPage(currentPageIndex - 1),
|
|
2704
|
+
disabled: currentPageIndex === 0,
|
|
2705
|
+
className: "px-3 py-2 rounded-lg border border-white/10 bg-white/5 hover:bg-white/10 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
2706
|
+
children: "Previous"
|
|
2707
|
+
}
|
|
2708
|
+
),
|
|
2709
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { children: [
|
|
2710
|
+
"Page ",
|
|
2711
|
+
currentPageIndex + 1,
|
|
2712
|
+
" of ",
|
|
2713
|
+
totalPages
|
|
2714
|
+
] }),
|
|
2715
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2716
|
+
"button",
|
|
2717
|
+
{
|
|
2718
|
+
type: "button",
|
|
2719
|
+
onClick: () => goToPage(currentPageIndex + 1),
|
|
2720
|
+
disabled: currentPageIndex >= totalPages - 1,
|
|
2721
|
+
className: "px-3 py-2 rounded-lg border border-white/10 bg-white/5 hover:bg-white/10 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
2722
|
+
children: "Next"
|
|
2723
|
+
}
|
|
2724
|
+
)
|
|
2725
|
+
] })
|
|
2426
2726
|
] });
|
|
2427
2727
|
}
|
|
2428
2728
|
|
|
@@ -2437,7 +2737,7 @@ var PrimusModal = ({
|
|
|
2437
2737
|
size = "md"
|
|
2438
2738
|
}) => {
|
|
2439
2739
|
if (!open) return null;
|
|
2440
|
-
const
|
|
2740
|
+
const sizeClasses2 = {
|
|
2441
2741
|
sm: "max-w-sm",
|
|
2442
2742
|
md: "max-w-md",
|
|
2443
2743
|
lg: "max-w-lg",
|
|
@@ -2451,7 +2751,7 @@ var PrimusModal = ({
|
|
|
2451
2751
|
onClick: onClose
|
|
2452
2752
|
}
|
|
2453
2753
|
),
|
|
2454
|
-
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: `relative w-full ${
|
|
2754
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: `relative w-full ${sizeClasses2[size]} mx-4 bg-gray-800 rounded-xl border border-gray-700 shadow-2xl`, children: [
|
|
2455
2755
|
title && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between px-6 py-4 border-b border-gray-700", children: [
|
|
2456
2756
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("h2", { className: "text-lg font-semibold text-white", children: title }),
|
|
2457
2757
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
@@ -2491,12 +2791,28 @@ var PrimusStatCard = ({
|
|
|
2491
2791
|
neutral: "\u2192"
|
|
2492
2792
|
};
|
|
2493
2793
|
const renderSparkline = () => {
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2794
|
+
if (!trend || trend.length === 0) {
|
|
2795
|
+
return null;
|
|
2796
|
+
}
|
|
2797
|
+
const max = Math.max(...trend);
|
|
2798
|
+
const min = Math.min(...trend);
|
|
2799
|
+
const range = max - min || 1;
|
|
2800
|
+
const divisor = trend.length > 1 ? trend.length - 1 : 1;
|
|
2801
|
+
const points = trend.map((value2, index) => {
|
|
2802
|
+
const x = index / divisor * 100;
|
|
2803
|
+
const y = 100 - (value2 - min) / range * 100;
|
|
2804
|
+
return { x, y };
|
|
2805
|
+
});
|
|
2806
|
+
const linePath = points.map((point, index) => `${index === 0 ? "M" : "L"} ${point.x} ${point.y}`).join(" ");
|
|
2807
|
+
const areaPath = `${linePath} L 100 100 L 0 100 Z`;
|
|
2808
|
+
const gradientId = `gradient-${title.replace(/\s/g, "")}`;
|
|
2809
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("svg", { className: "w-full h-12 opacity-60 absolute bottom-0 left-0", viewBox: "0 0 100 100", preserveAspectRatio: "none", "data-trend": trend.join(","), children: [
|
|
2810
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
2811
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("stop", { offset: "0%", stopColor: "currentColor", stopOpacity: "0.25" }),
|
|
2498
2812
|
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("stop", { offset: "100%", stopColor: "currentColor", stopOpacity: "0" })
|
|
2499
|
-
] }) })
|
|
2813
|
+
] }) }),
|
|
2814
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("path", { d: areaPath, fill: `url(#${gradientId})`, stroke: "none" }),
|
|
2815
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("path", { d: linePath, fill: "none", stroke: "currentColor", strokeWidth: "1.8", opacity: "0.6" })
|
|
2500
2816
|
] });
|
|
2501
2817
|
};
|
|
2502
2818
|
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "relative overflow-hidden bg-slate-900/40 backdrop-blur-md rounded-2xl border border-white/5 hover:border-white/10 transition-all duration-300 group", children: [
|
|
@@ -2550,13 +2866,1423 @@ var DashboardGrid = ({
|
|
|
2550
2866
|
};
|
|
2551
2867
|
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: `grid gap-6 ${colClasses[columns]}`, children });
|
|
2552
2868
|
};
|
|
2869
|
+
|
|
2870
|
+
// src/components/dashboard/PrimusActivityFeed.tsx
|
|
2871
|
+
var import_react27 = require("react");
|
|
2872
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
2873
|
+
var statusClasses = {
|
|
2874
|
+
success: "bg-emerald-500/10 text-emerald-300 border-emerald-500/30",
|
|
2875
|
+
warning: "bg-amber-500/10 text-amber-300 border-amber-500/30",
|
|
2876
|
+
error: "bg-rose-500/10 text-rose-300 border-rose-500/30",
|
|
2877
|
+
info: "bg-blue-500/10 text-blue-300 border-blue-500/30"
|
|
2878
|
+
};
|
|
2879
|
+
var PrimusActivityFeed = ({
|
|
2880
|
+
items,
|
|
2881
|
+
maxItems = 10,
|
|
2882
|
+
showTimestamps = true,
|
|
2883
|
+
groupByDate = false,
|
|
2884
|
+
loading = false
|
|
2885
|
+
}) => {
|
|
2886
|
+
const visibleItems = (0, import_react27.useMemo)(() => items.slice(0, maxItems), [items, maxItems]);
|
|
2887
|
+
const groups = (0, import_react27.useMemo)(() => {
|
|
2888
|
+
if (!groupByDate) {
|
|
2889
|
+
return [{ label: "", items: visibleItems }];
|
|
2890
|
+
}
|
|
2891
|
+
const map = /* @__PURE__ */ new Map();
|
|
2892
|
+
visibleItems.forEach((item) => {
|
|
2893
|
+
const label = formatDate(item.timestamp);
|
|
2894
|
+
const list = map.get(label) ?? [];
|
|
2895
|
+
list.push(item);
|
|
2896
|
+
map.set(label, list);
|
|
2897
|
+
});
|
|
2898
|
+
return Array.from(map.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
|
|
2899
|
+
}, [groupByDate, visibleItems]);
|
|
2900
|
+
if (loading) {
|
|
2901
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "rounded-xl border border-white/10 bg-slate-900/40 p-6 text-sm text-gray-400", children: "Loading activity..." });
|
|
2902
|
+
}
|
|
2903
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "rounded-xl border border-white/10 bg-slate-900/40 p-6 space-y-6", children: groups.map((group, index) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { children: [
|
|
2904
|
+
group.label && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "text-xs uppercase tracking-wide text-gray-500 mb-3", children: group.label }),
|
|
2905
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "space-y-4", children: group.items.map((item, itemIndex) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-start gap-4", children: [
|
|
2906
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: `mt-1 h-2.5 w-2.5 rounded-full border ${statusClasses[item.status ?? "info"]}` }),
|
|
2907
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex-1", children: [
|
|
2908
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center justify-between gap-4", children: [
|
|
2909
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "text-sm font-medium text-gray-100", children: item.title }),
|
|
2910
|
+
showTimestamps && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "text-xs text-gray-500", children: formatTime(item.timestamp) })
|
|
2911
|
+
] }),
|
|
2912
|
+
item.description && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "text-xs text-gray-400 mt-1", children: item.description })
|
|
2913
|
+
] })
|
|
2914
|
+
] }, item.id ?? `${itemIndex}-${item.title}`)) })
|
|
2915
|
+
] }, `${group.label}-${index}`)) });
|
|
2916
|
+
};
|
|
2917
|
+
var formatDate = (value) => {
|
|
2918
|
+
if (!value) {
|
|
2919
|
+
return "";
|
|
2920
|
+
}
|
|
2921
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
2922
|
+
if (Number.isNaN(date.getTime())) {
|
|
2923
|
+
return String(value);
|
|
2924
|
+
}
|
|
2925
|
+
return date.toLocaleDateString();
|
|
2926
|
+
};
|
|
2927
|
+
var formatTime = (value) => {
|
|
2928
|
+
if (!value) {
|
|
2929
|
+
return "";
|
|
2930
|
+
}
|
|
2931
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
2932
|
+
if (Number.isNaN(date.getTime())) {
|
|
2933
|
+
return "";
|
|
2934
|
+
}
|
|
2935
|
+
return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
2936
|
+
};
|
|
2937
|
+
|
|
2938
|
+
// src/components/charts/PrimusChartBase.tsx
|
|
2939
|
+
var import_react28 = require("react");
|
|
2940
|
+
var import_chart = require("chart.js");
|
|
2941
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
2942
|
+
var registered = false;
|
|
2943
|
+
var ensureRegistered = () => {
|
|
2944
|
+
if (!registered) {
|
|
2945
|
+
import_chart.Chart.register(...import_chart.registerables);
|
|
2946
|
+
registered = true;
|
|
2947
|
+
}
|
|
2948
|
+
};
|
|
2949
|
+
var PrimusChartBase = ({
|
|
2950
|
+
type,
|
|
2951
|
+
data,
|
|
2952
|
+
labels = [],
|
|
2953
|
+
series = [],
|
|
2954
|
+
options,
|
|
2955
|
+
responsive = true,
|
|
2956
|
+
maintainAspectRatio = false,
|
|
2957
|
+
legend = true,
|
|
2958
|
+
height = 300,
|
|
2959
|
+
width,
|
|
2960
|
+
ariaLabel = "Chart",
|
|
2961
|
+
className,
|
|
2962
|
+
datasetTransform
|
|
2963
|
+
}) => {
|
|
2964
|
+
const canvasRef = (0, import_react28.useRef)(null);
|
|
2965
|
+
const chartRef = (0, import_react28.useRef)(null);
|
|
2966
|
+
const builtData = (0, import_react28.useMemo)(() => {
|
|
2967
|
+
if (data) {
|
|
2968
|
+
return data;
|
|
2969
|
+
}
|
|
2970
|
+
const datasets = series.map((item) => {
|
|
2971
|
+
const color = item.color ?? item.borderColor ?? "#3b82f6";
|
|
2972
|
+
const background = item.backgroundColor ?? color;
|
|
2973
|
+
let dataset = {
|
|
2974
|
+
label: item.name,
|
|
2975
|
+
data: item.data,
|
|
2976
|
+
borderColor: item.borderColor ?? color,
|
|
2977
|
+
backgroundColor: background,
|
|
2978
|
+
fill: item.fill
|
|
2979
|
+
};
|
|
2980
|
+
if (datasetTransform) {
|
|
2981
|
+
dataset = datasetTransform(dataset);
|
|
2982
|
+
}
|
|
2983
|
+
return dataset;
|
|
2984
|
+
});
|
|
2985
|
+
return {
|
|
2986
|
+
labels,
|
|
2987
|
+
datasets
|
|
2988
|
+
};
|
|
2989
|
+
}, [data, labels, series, datasetTransform]);
|
|
2990
|
+
const builtOptions = (0, import_react28.useMemo)(() => {
|
|
2991
|
+
const mergedPlugins = {
|
|
2992
|
+
...options?.plugins ?? {},
|
|
2993
|
+
legend: {
|
|
2994
|
+
display: legend,
|
|
2995
|
+
...options?.plugins?.legend ?? {}
|
|
2996
|
+
}
|
|
2997
|
+
};
|
|
2998
|
+
return {
|
|
2999
|
+
responsive,
|
|
3000
|
+
maintainAspectRatio,
|
|
3001
|
+
...options ?? {},
|
|
3002
|
+
plugins: mergedPlugins,
|
|
3003
|
+
scales: {
|
|
3004
|
+
...options?.scales ?? {}
|
|
3005
|
+
}
|
|
3006
|
+
};
|
|
3007
|
+
}, [options, responsive, maintainAspectRatio, legend]);
|
|
3008
|
+
(0, import_react28.useEffect)(() => {
|
|
3009
|
+
ensureRegistered();
|
|
3010
|
+
const canvas = canvasRef.current;
|
|
3011
|
+
if (!canvas) {
|
|
3012
|
+
return void 0;
|
|
3013
|
+
}
|
|
3014
|
+
const ctx = canvas.getContext("2d");
|
|
3015
|
+
if (!ctx) {
|
|
3016
|
+
return void 0;
|
|
3017
|
+
}
|
|
3018
|
+
if (chartRef.current) {
|
|
3019
|
+
chartRef.current.destroy();
|
|
3020
|
+
chartRef.current = null;
|
|
3021
|
+
}
|
|
3022
|
+
chartRef.current = new import_chart.Chart(ctx, {
|
|
3023
|
+
type,
|
|
3024
|
+
data: builtData,
|
|
3025
|
+
options: builtOptions
|
|
3026
|
+
});
|
|
3027
|
+
return () => {
|
|
3028
|
+
chartRef.current?.destroy();
|
|
3029
|
+
chartRef.current = null;
|
|
3030
|
+
};
|
|
3031
|
+
}, [type, builtData, builtOptions]);
|
|
3032
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className, style: { height, width }, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("canvas", { ref: canvasRef, "aria-label": ariaLabel, role: "img" }) });
|
|
3033
|
+
};
|
|
3034
|
+
|
|
3035
|
+
// src/components/charts/PrimusLineChart.tsx
|
|
3036
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
3037
|
+
var PrimusLineChart = (props) => {
|
|
3038
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
3039
|
+
PrimusChartBase,
|
|
3040
|
+
{
|
|
3041
|
+
...props,
|
|
3042
|
+
type: "line",
|
|
3043
|
+
datasetTransform: (dataset) => ({
|
|
3044
|
+
tension: 0.35,
|
|
3045
|
+
pointRadius: 2,
|
|
3046
|
+
pointHoverRadius: 4,
|
|
3047
|
+
borderWidth: 2,
|
|
3048
|
+
fill: dataset.fill ?? false,
|
|
3049
|
+
...dataset
|
|
3050
|
+
})
|
|
3051
|
+
}
|
|
3052
|
+
);
|
|
3053
|
+
};
|
|
3054
|
+
|
|
3055
|
+
// src/components/charts/PrimusAreaChart.tsx
|
|
3056
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
3057
|
+
var PrimusAreaChart = (props) => {
|
|
3058
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
3059
|
+
PrimusChartBase,
|
|
3060
|
+
{
|
|
3061
|
+
...props,
|
|
3062
|
+
type: "line",
|
|
3063
|
+
datasetTransform: (dataset) => ({
|
|
3064
|
+
tension: 0.35,
|
|
3065
|
+
pointRadius: 2,
|
|
3066
|
+
pointHoverRadius: 4,
|
|
3067
|
+
borderWidth: 2,
|
|
3068
|
+
fill: dataset.fill ?? true,
|
|
3069
|
+
...dataset
|
|
3070
|
+
})
|
|
3071
|
+
}
|
|
3072
|
+
);
|
|
3073
|
+
};
|
|
3074
|
+
|
|
3075
|
+
// src/components/charts/PrimusBarChart.tsx
|
|
3076
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
3077
|
+
var PrimusBarChart = ({ stacked = false, options, ...props }) => {
|
|
3078
|
+
const mergedOptions = {
|
|
3079
|
+
...options,
|
|
3080
|
+
scales: {
|
|
3081
|
+
x: { stacked, ...options?.scales?.x ?? {} },
|
|
3082
|
+
y: { stacked, ...options?.scales?.y ?? {} },
|
|
3083
|
+
...options?.scales ?? {}
|
|
3084
|
+
}
|
|
3085
|
+
};
|
|
3086
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
3087
|
+
PrimusChartBase,
|
|
3088
|
+
{
|
|
3089
|
+
...props,
|
|
3090
|
+
type: "bar",
|
|
3091
|
+
options: mergedOptions,
|
|
3092
|
+
datasetTransform: (dataset) => ({
|
|
3093
|
+
borderRadius: 6,
|
|
3094
|
+
borderSkipped: false,
|
|
3095
|
+
...dataset
|
|
3096
|
+
})
|
|
3097
|
+
}
|
|
3098
|
+
);
|
|
3099
|
+
};
|
|
3100
|
+
|
|
3101
|
+
// src/components/charts/PrimusPieChart.tsx
|
|
3102
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
3103
|
+
var PrimusPieChart = ({ donut = false, cutout = "55%", options, ...props }) => {
|
|
3104
|
+
const mergedOptions = {
|
|
3105
|
+
...options,
|
|
3106
|
+
cutout: donut ? cutout : void 0
|
|
3107
|
+
};
|
|
3108
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
3109
|
+
PrimusChartBase,
|
|
3110
|
+
{
|
|
3111
|
+
...props,
|
|
3112
|
+
type: donut ? "doughnut" : "pie",
|
|
3113
|
+
options: mergedOptions,
|
|
3114
|
+
datasetTransform: (dataset) => ({
|
|
3115
|
+
borderWidth: 1,
|
|
3116
|
+
borderColor: "transparent",
|
|
3117
|
+
...dataset
|
|
3118
|
+
})
|
|
3119
|
+
}
|
|
3120
|
+
);
|
|
3121
|
+
};
|
|
3122
|
+
|
|
3123
|
+
// src/components/charts/PrimusSparkline.tsx
|
|
3124
|
+
var import_react29 = require("react");
|
|
3125
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
3126
|
+
var PrimusSparkline = ({
|
|
3127
|
+
series = [],
|
|
3128
|
+
data,
|
|
3129
|
+
type = "line",
|
|
3130
|
+
height = 48,
|
|
3131
|
+
width = 160,
|
|
3132
|
+
strokeWidth = 2,
|
|
3133
|
+
className,
|
|
3134
|
+
ariaLabel = "Sparkline"
|
|
3135
|
+
}) => {
|
|
3136
|
+
const values = data ?? series[0]?.data ?? [];
|
|
3137
|
+
const color = series[0]?.color ?? series[0]?.borderColor ?? "#3b82f6";
|
|
3138
|
+
const { linePath, areaPath } = (0, import_react29.useMemo)(() => {
|
|
3139
|
+
if (!values.length) {
|
|
3140
|
+
return { linePath: "", areaPath: "" };
|
|
3141
|
+
}
|
|
3142
|
+
const max = Math.max(...values);
|
|
3143
|
+
const min = Math.min(...values);
|
|
3144
|
+
const range = max - min || 1;
|
|
3145
|
+
const divisor = values.length > 1 ? values.length - 1 : 1;
|
|
3146
|
+
const points = values.map((value, index) => {
|
|
3147
|
+
const x = index / divisor * 100;
|
|
3148
|
+
const y = 100 - (value - min) / range * 100;
|
|
3149
|
+
return { x, y };
|
|
3150
|
+
});
|
|
3151
|
+
const line = points.map((point, index) => `${index === 0 ? "M" : "L"} ${point.x} ${point.y}`).join(" ");
|
|
3152
|
+
const area = `${line} L 100 100 L 0 100 Z`;
|
|
3153
|
+
return { linePath: line, areaPath: area };
|
|
3154
|
+
}, [values]);
|
|
3155
|
+
if (!values.length) {
|
|
3156
|
+
return null;
|
|
3157
|
+
}
|
|
3158
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
3159
|
+
"svg",
|
|
3160
|
+
{
|
|
3161
|
+
className,
|
|
3162
|
+
width,
|
|
3163
|
+
height,
|
|
3164
|
+
viewBox: "0 0 100 100",
|
|
3165
|
+
preserveAspectRatio: "none",
|
|
3166
|
+
"aria-label": ariaLabel,
|
|
3167
|
+
role: "img",
|
|
3168
|
+
children: [
|
|
3169
|
+
type === "area" && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("path", { d: areaPath, fill: color, opacity: 0.2, stroke: "none" }),
|
|
3170
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("path", { d: linePath, fill: "none", stroke: color, strokeWidth })
|
|
3171
|
+
]
|
|
3172
|
+
}
|
|
3173
|
+
);
|
|
3174
|
+
};
|
|
3175
|
+
|
|
3176
|
+
// src/components/shared/Checkbox.tsx
|
|
3177
|
+
var import_react30 = __toESM(require("react"));
|
|
3178
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
3179
|
+
var Checkbox = import_react30.default.forwardRef(
|
|
3180
|
+
({ style, label, error, disabled, className, ...props }, ref) => {
|
|
3181
|
+
const containerStyles = {
|
|
3182
|
+
display: "flex",
|
|
3183
|
+
alignItems: "center",
|
|
3184
|
+
gap: "0.5rem"
|
|
3185
|
+
};
|
|
3186
|
+
const checkboxWrapperStyles = {
|
|
3187
|
+
position: "relative",
|
|
3188
|
+
display: "inline-flex",
|
|
3189
|
+
alignItems: "center",
|
|
3190
|
+
justifyContent: "center"
|
|
3191
|
+
};
|
|
3192
|
+
const checkboxStyles = {
|
|
3193
|
+
width: "1.25rem",
|
|
3194
|
+
height: "1.25rem",
|
|
3195
|
+
borderRadius: "0.25rem",
|
|
3196
|
+
border: error ? "2px solid #ef4444" : "2px solid #e5e7eb",
|
|
3197
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
3198
|
+
opacity: disabled ? 0.5 : 1,
|
|
3199
|
+
accentColor: "#111827"
|
|
3200
|
+
};
|
|
3201
|
+
const labelStyles = {
|
|
3202
|
+
fontSize: "0.875rem",
|
|
3203
|
+
lineHeight: "1.25rem",
|
|
3204
|
+
color: "#374151",
|
|
3205
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
3206
|
+
opacity: disabled ? 0.7 : 1,
|
|
3207
|
+
userSelect: "none"
|
|
3208
|
+
};
|
|
3209
|
+
const errorTextStyles = {
|
|
3210
|
+
fontSize: "0.875rem",
|
|
3211
|
+
lineHeight: "1.25rem",
|
|
3212
|
+
color: "#ef4444",
|
|
3213
|
+
marginTop: "0.25rem",
|
|
3214
|
+
marginLeft: "1.75rem"
|
|
3215
|
+
};
|
|
3216
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
|
|
3217
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: containerStyles, children: [
|
|
3218
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { style: checkboxWrapperStyles, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
3219
|
+
"input",
|
|
3220
|
+
{
|
|
3221
|
+
ref,
|
|
3222
|
+
type: "checkbox",
|
|
3223
|
+
style: {
|
|
3224
|
+
...checkboxStyles,
|
|
3225
|
+
...style
|
|
3226
|
+
},
|
|
3227
|
+
disabled,
|
|
3228
|
+
...props
|
|
3229
|
+
}
|
|
3230
|
+
) }),
|
|
3231
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("label", { style: labelStyles, onClick: (e) => {
|
|
3232
|
+
if (!disabled) {
|
|
3233
|
+
const input = e.currentTarget.previousElementSibling?.querySelector("input");
|
|
3234
|
+
input?.click();
|
|
3235
|
+
}
|
|
3236
|
+
}, children: label })
|
|
3237
|
+
] }),
|
|
3238
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { style: errorTextStyles, children: error })
|
|
3239
|
+
] });
|
|
3240
|
+
}
|
|
3241
|
+
);
|
|
3242
|
+
Checkbox.displayName = "Checkbox";
|
|
3243
|
+
|
|
3244
|
+
// src/components/shared/RadioGroup.tsx
|
|
3245
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
3246
|
+
var RadioGroup = ({
|
|
3247
|
+
name,
|
|
3248
|
+
options,
|
|
3249
|
+
value,
|
|
3250
|
+
onChange,
|
|
3251
|
+
error,
|
|
3252
|
+
disabled,
|
|
3253
|
+
orientation = "vertical"
|
|
3254
|
+
}) => {
|
|
3255
|
+
const containerStyles = {
|
|
3256
|
+
display: "flex",
|
|
3257
|
+
flexDirection: orientation === "vertical" ? "column" : "row",
|
|
3258
|
+
gap: orientation === "vertical" ? "0.75rem" : "1.5rem"
|
|
3259
|
+
};
|
|
3260
|
+
const optionStyles = {
|
|
3261
|
+
display: "flex",
|
|
3262
|
+
alignItems: "center",
|
|
3263
|
+
gap: "0.5rem"
|
|
3264
|
+
};
|
|
3265
|
+
const radioStyles = {
|
|
3266
|
+
width: "1.25rem",
|
|
3267
|
+
height: "1.25rem",
|
|
3268
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
3269
|
+
opacity: disabled ? 0.5 : 1,
|
|
3270
|
+
accentColor: "#111827"
|
|
3271
|
+
};
|
|
3272
|
+
const labelStyles = {
|
|
3273
|
+
fontSize: "0.875rem",
|
|
3274
|
+
lineHeight: "1.25rem",
|
|
3275
|
+
color: "#374151",
|
|
3276
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
3277
|
+
userSelect: "none"
|
|
3278
|
+
};
|
|
3279
|
+
const errorTextStyles = {
|
|
3280
|
+
fontSize: "0.875rem",
|
|
3281
|
+
lineHeight: "1.25rem",
|
|
3282
|
+
color: "#ef4444",
|
|
3283
|
+
marginTop: "0.5rem"
|
|
3284
|
+
};
|
|
3285
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { children: [
|
|
3286
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { style: containerStyles, children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { style: optionStyles, children: [
|
|
3287
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
3288
|
+
"input",
|
|
3289
|
+
{
|
|
3290
|
+
type: "radio",
|
|
3291
|
+
name,
|
|
3292
|
+
value: option.value,
|
|
3293
|
+
checked: value === option.value,
|
|
3294
|
+
onChange: () => onChange?.(option.value),
|
|
3295
|
+
disabled: disabled || option.disabled,
|
|
3296
|
+
style: radioStyles
|
|
3297
|
+
}
|
|
3298
|
+
),
|
|
3299
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
3300
|
+
"label",
|
|
3301
|
+
{
|
|
3302
|
+
style: {
|
|
3303
|
+
...labelStyles,
|
|
3304
|
+
opacity: disabled || option.disabled ? 0.5 : 1
|
|
3305
|
+
},
|
|
3306
|
+
onClick: () => {
|
|
3307
|
+
if (!disabled && !option.disabled) {
|
|
3308
|
+
onChange?.(option.value);
|
|
3309
|
+
}
|
|
3310
|
+
},
|
|
3311
|
+
children: option.label
|
|
3312
|
+
}
|
|
3313
|
+
)
|
|
3314
|
+
] }, option.value)) }),
|
|
3315
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { style: errorTextStyles, children: error })
|
|
3316
|
+
] });
|
|
3317
|
+
};
|
|
3318
|
+
RadioGroup.displayName = "RadioGroup";
|
|
3319
|
+
|
|
3320
|
+
// src/components/shared/Select.tsx
|
|
3321
|
+
var import_react31 = __toESM(require("react"));
|
|
3322
|
+
var import_react32 = require("@headlessui/react");
|
|
3323
|
+
var import_solid4 = require("@heroicons/react/20/solid");
|
|
3324
|
+
var import_clsx7 = require("clsx");
|
|
3325
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
3326
|
+
var Select = ({
|
|
3327
|
+
label,
|
|
3328
|
+
error,
|
|
3329
|
+
options,
|
|
3330
|
+
placeholder = "Select option...",
|
|
3331
|
+
value,
|
|
3332
|
+
onChange,
|
|
3333
|
+
multiple = false,
|
|
3334
|
+
disabled = false,
|
|
3335
|
+
className
|
|
3336
|
+
}) => {
|
|
3337
|
+
const [query, setQuery] = (0, import_react31.useState)("");
|
|
3338
|
+
const filteredOptions = query === "" ? options : options.filter(
|
|
3339
|
+
(option) => option.label.toLowerCase().replace(/\s+/g, "").includes(query.toLowerCase().replace(/\s+/g, ""))
|
|
3340
|
+
);
|
|
3341
|
+
const getLabel = (val) => options.find((o) => o.value === val)?.label || val;
|
|
3342
|
+
const removeChip = (valToRemove) => {
|
|
3343
|
+
if (Array.isArray(value)) {
|
|
3344
|
+
onChange?.(value.filter((v) => v !== valToRemove));
|
|
3345
|
+
}
|
|
3346
|
+
};
|
|
3347
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: (0, import_clsx7.clsx)("w-full", className), children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
3348
|
+
import_react32.Combobox,
|
|
3349
|
+
{
|
|
3350
|
+
value,
|
|
3351
|
+
onChange: (val) => {
|
|
3352
|
+
onChange?.(val);
|
|
3353
|
+
},
|
|
3354
|
+
multiple,
|
|
3355
|
+
disabled,
|
|
3356
|
+
children: ({}) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "relative", children: [
|
|
3357
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react32.Combobox.Label, { className: "block text-sm font-medium text-gray-700 mb-1", children: label }),
|
|
3358
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: (0, import_clsx7.clsx)(
|
|
3359
|
+
"relative w-full cursor-default overflow-hidden rounded-lg bg-white text-left focus-within:ring-2 focus-within:ring-primus-500",
|
|
3360
|
+
"border transition-all duration-200 ease-in-out",
|
|
3361
|
+
error ? "border-red-500 focus-within:ring-red-500" : "border-gray-300",
|
|
3362
|
+
disabled && "opacity-50 cursor-not-allowed bg-gray-50"
|
|
3363
|
+
), children: [
|
|
3364
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: (0, import_clsx7.clsx)(
|
|
3365
|
+
"flex flex-wrap items-center gap-1.5 w-full py-1.5 pl-3 pr-10 text-sm",
|
|
3366
|
+
"min-h-[2.5rem]"
|
|
3367
|
+
), children: [
|
|
3368
|
+
multiple && Array.isArray(value) && value.map((val) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "inline-flex items-center gap-1 rounded bg-primus-50 px-2 py-0.5 text-xs font-medium text-primus-700 ring-1 ring-inset ring-primus-700/10 max-w-[150px]", children: [
|
|
3369
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "truncate", children: getLabel(val) }),
|
|
3370
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
3371
|
+
"button",
|
|
3372
|
+
{
|
|
3373
|
+
type: "button",
|
|
3374
|
+
className: "group relative -mr-1 h-3.5 w-3.5 rounded-sm hover:bg-primus-600/20 flex-shrink-0 cursor-pointer",
|
|
3375
|
+
onClick: (e) => {
|
|
3376
|
+
e.preventDefault();
|
|
3377
|
+
e.stopPropagation();
|
|
3378
|
+
removeChip(val);
|
|
3379
|
+
},
|
|
3380
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
3381
|
+
children: [
|
|
3382
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "sr-only", children: "Remove" }),
|
|
3383
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_solid4.XMarkIcon, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
|
|
3384
|
+
]
|
|
3385
|
+
}
|
|
3386
|
+
)
|
|
3387
|
+
] }, val)),
|
|
3388
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
3389
|
+
import_react32.Combobox.Input,
|
|
3390
|
+
{
|
|
3391
|
+
className: "border-none p-0 text-gray-900 focus:ring-0 outline-none placeholder:text-gray-400 bg-transparent min-w-[50px] flex-1 text-sm leading-5 py-0.5",
|
|
3392
|
+
displayValue: (val) => !multiple && val ? getLabel(val) : query,
|
|
3393
|
+
placeholder: multiple && Array.isArray(value) && value.length > 0 ? "" : placeholder,
|
|
3394
|
+
onChange: (event) => setQuery(event.target.value)
|
|
3395
|
+
}
|
|
3396
|
+
)
|
|
3397
|
+
] }),
|
|
3398
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react32.Combobox.Button, { className: "absolute inset-y-0 right-0 flex items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
3399
|
+
import_solid4.ChevronUpDownIcon,
|
|
3400
|
+
{
|
|
3401
|
+
className: "h-5 w-5 text-gray-400",
|
|
3402
|
+
"aria-hidden": "true"
|
|
3403
|
+
}
|
|
3404
|
+
) })
|
|
3405
|
+
] }),
|
|
3406
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
3407
|
+
import_react32.Transition,
|
|
3408
|
+
{
|
|
3409
|
+
as: import_react31.default.Fragment,
|
|
3410
|
+
leave: "transition ease-in duration-100",
|
|
3411
|
+
leaveFrom: "opacity-100",
|
|
3412
|
+
leaveTo: "opacity-0",
|
|
3413
|
+
afterLeave: () => setQuery(""),
|
|
3414
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_react32.Combobox.Options, { className: "absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm", children: filteredOptions.length === 0 && query !== "" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "relative cursor-default select-none py-2 px-4 text-gray-700", children: "Nothing found." }) : filteredOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
3415
|
+
import_react32.Combobox.Option,
|
|
3416
|
+
{
|
|
3417
|
+
className: ({ active }) => (0, import_clsx7.clsx)(
|
|
3418
|
+
"relative cursor-default select-none py-2 pl-10 pr-4",
|
|
3419
|
+
active ? "bg-primus-600 text-white" : "text-gray-900"
|
|
3420
|
+
),
|
|
3421
|
+
value: option.value,
|
|
3422
|
+
disabled: option.disabled,
|
|
3423
|
+
children: ({ selected, active }) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
|
|
3424
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: (0, import_clsx7.clsx)("block truncate", selected ? "font-medium" : "font-normal"), children: option.label }),
|
|
3425
|
+
selected ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
3426
|
+
"span",
|
|
3427
|
+
{
|
|
3428
|
+
className: (0, import_clsx7.clsx)(
|
|
3429
|
+
"absolute inset-y-0 left-0 flex items-center pl-3",
|
|
3430
|
+
active ? "text-white" : "text-primus-600"
|
|
3431
|
+
),
|
|
3432
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_solid4.CheckIcon, { className: "h-5 w-5", "aria-hidden": "true" })
|
|
3433
|
+
}
|
|
3434
|
+
) : null
|
|
3435
|
+
] })
|
|
3436
|
+
},
|
|
3437
|
+
option.value
|
|
3438
|
+
)) })
|
|
3439
|
+
}
|
|
3440
|
+
),
|
|
3441
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "mt-1 text-sm text-red-500", children: error })
|
|
3442
|
+
] })
|
|
3443
|
+
}
|
|
3444
|
+
) });
|
|
3445
|
+
};
|
|
3446
|
+
|
|
3447
|
+
// src/components/shared/Toggle.tsx
|
|
3448
|
+
var import_react33 = __toESM(require("react"));
|
|
3449
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
3450
|
+
var Toggle = ({
|
|
3451
|
+
checked = false,
|
|
3452
|
+
onChange,
|
|
3453
|
+
disabled = false,
|
|
3454
|
+
label,
|
|
3455
|
+
size = "md"
|
|
3456
|
+
}) => {
|
|
3457
|
+
const [isHovered, setIsHovered] = import_react33.default.useState(false);
|
|
3458
|
+
const sizes = {
|
|
3459
|
+
sm: { width: "2.25rem", height: "1.25rem", thumbSize: "0.875rem" },
|
|
3460
|
+
md: { width: "2.75rem", height: "1.5rem", thumbSize: "1.125rem" },
|
|
3461
|
+
lg: { width: "3.5rem", height: "2rem", thumbSize: "1.625rem" }
|
|
3462
|
+
};
|
|
3463
|
+
const currentSize = sizes[size];
|
|
3464
|
+
const containerStyles = {
|
|
3465
|
+
display: "flex",
|
|
3466
|
+
alignItems: "center",
|
|
3467
|
+
gap: "0.75rem"
|
|
3468
|
+
};
|
|
3469
|
+
const switchStyles = {
|
|
3470
|
+
position: "relative",
|
|
3471
|
+
display: "inline-block",
|
|
3472
|
+
width: currentSize.width,
|
|
3473
|
+
height: currentSize.height,
|
|
3474
|
+
backgroundColor: checked ? "#111827" : "#e5e7eb",
|
|
3475
|
+
borderRadius: "9999px",
|
|
3476
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
3477
|
+
transition: "background-color 0.2s ease",
|
|
3478
|
+
opacity: disabled ? 0.5 : isHovered ? 0.9 : 1
|
|
3479
|
+
};
|
|
3480
|
+
const thumbStyles = {
|
|
3481
|
+
position: "absolute",
|
|
3482
|
+
top: "50%",
|
|
3483
|
+
left: checked ? `calc(100% - ${currentSize.thumbSize} - 0.125rem)` : "0.125rem",
|
|
3484
|
+
transform: "translateY(-50%)",
|
|
3485
|
+
width: currentSize.thumbSize,
|
|
3486
|
+
height: currentSize.thumbSize,
|
|
3487
|
+
backgroundColor: "#ffffff",
|
|
3488
|
+
borderRadius: "50%",
|
|
3489
|
+
transition: "left 0.2s ease",
|
|
3490
|
+
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.1)"
|
|
3491
|
+
};
|
|
3492
|
+
const labelStyles = {
|
|
3493
|
+
fontSize: "0.875rem",
|
|
3494
|
+
lineHeight: "1.25rem",
|
|
3495
|
+
color: "#374151",
|
|
3496
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
3497
|
+
userSelect: "none"
|
|
3498
|
+
};
|
|
3499
|
+
const handleClick = () => {
|
|
3500
|
+
if (!disabled) {
|
|
3501
|
+
onChange?.(!checked);
|
|
3502
|
+
}
|
|
3503
|
+
};
|
|
3504
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { style: containerStyles, children: [
|
|
3505
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3506
|
+
"div",
|
|
3507
|
+
{
|
|
3508
|
+
style: switchStyles,
|
|
3509
|
+
onClick: handleClick,
|
|
3510
|
+
onMouseEnter: () => setIsHovered(true),
|
|
3511
|
+
onMouseLeave: () => setIsHovered(false),
|
|
3512
|
+
role: "switch",
|
|
3513
|
+
"aria-checked": checked,
|
|
3514
|
+
tabIndex: disabled ? -1 : 0,
|
|
3515
|
+
onKeyDown: (e) => {
|
|
3516
|
+
if (e.key === " " || e.key === "Enter") {
|
|
3517
|
+
e.preventDefault();
|
|
3518
|
+
handleClick();
|
|
3519
|
+
}
|
|
3520
|
+
},
|
|
3521
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { style: thumbStyles })
|
|
3522
|
+
}
|
|
3523
|
+
),
|
|
3524
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("label", { style: labelStyles, onClick: handleClick, children: label })
|
|
3525
|
+
] });
|
|
3526
|
+
};
|
|
3527
|
+
Toggle.displayName = "Toggle";
|
|
3528
|
+
|
|
3529
|
+
// src/components/shared/Textarea.tsx
|
|
3530
|
+
var import_react34 = __toESM(require("react"));
|
|
3531
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
3532
|
+
var Textarea = import_react34.default.forwardRef(
|
|
3533
|
+
({ style, label, error, disabled, resize = "vertical", ...props }, ref) => {
|
|
3534
|
+
const [isFocused, setIsFocused] = import_react34.default.useState(false);
|
|
3535
|
+
const containerStyles = {
|
|
3536
|
+
width: "100%"
|
|
3537
|
+
};
|
|
3538
|
+
const labelStyles = {
|
|
3539
|
+
fontSize: "0.875rem",
|
|
3540
|
+
lineHeight: "1.25rem",
|
|
3541
|
+
fontWeight: "500",
|
|
3542
|
+
marginBottom: "0.5rem",
|
|
3543
|
+
display: "block",
|
|
3544
|
+
color: "#374151",
|
|
3545
|
+
cursor: disabled ? "not-allowed" : "default",
|
|
3546
|
+
opacity: disabled ? 0.7 : 1
|
|
3547
|
+
};
|
|
3548
|
+
const textareaStyles = {
|
|
3549
|
+
display: "flex",
|
|
3550
|
+
minHeight: "5rem",
|
|
3551
|
+
width: "100%",
|
|
3552
|
+
borderRadius: "0.375rem",
|
|
3553
|
+
border: error ? "1px solid #ef4444" : "1px solid #e5e7eb",
|
|
3554
|
+
backgroundColor: "#ffffff",
|
|
3555
|
+
padding: "0.5rem 0.75rem",
|
|
3556
|
+
fontSize: "0.875rem",
|
|
3557
|
+
lineHeight: "1.5rem",
|
|
3558
|
+
outline: "none",
|
|
3559
|
+
transition: "all 0.2s ease",
|
|
3560
|
+
cursor: disabled ? "not-allowed" : "text",
|
|
3561
|
+
opacity: disabled ? 0.5 : 1,
|
|
3562
|
+
resize,
|
|
3563
|
+
fontFamily: "inherit",
|
|
3564
|
+
boxShadow: isFocused ? error ? "0 0 0 2px rgba(239, 68, 68, 0.2)" : "0 0 0 2px rgba(3, 7, 18, 0.1)" : "none"
|
|
3565
|
+
};
|
|
3566
|
+
const errorTextStyles = {
|
|
3567
|
+
fontSize: "0.875rem",
|
|
3568
|
+
lineHeight: "1.25rem",
|
|
3569
|
+
color: "#ef4444",
|
|
3570
|
+
marginTop: "0.25rem"
|
|
3571
|
+
};
|
|
3572
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { style: containerStyles, children: [
|
|
3573
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("label", { style: labelStyles, children: label }),
|
|
3574
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3575
|
+
"textarea",
|
|
3576
|
+
{
|
|
3577
|
+
ref,
|
|
3578
|
+
style: {
|
|
3579
|
+
...textareaStyles,
|
|
3580
|
+
...style
|
|
3581
|
+
},
|
|
3582
|
+
onFocus: () => setIsFocused(true),
|
|
3583
|
+
onBlur: () => setIsFocused(false),
|
|
3584
|
+
disabled,
|
|
3585
|
+
...props
|
|
3586
|
+
}
|
|
3587
|
+
),
|
|
3588
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { style: errorTextStyles, children: error })
|
|
3589
|
+
] });
|
|
3590
|
+
}
|
|
3591
|
+
);
|
|
3592
|
+
Textarea.displayName = "Textarea";
|
|
3593
|
+
|
|
3594
|
+
// src/components/shared/Card.tsx
|
|
3595
|
+
var import_react35 = __toESM(require("react"));
|
|
3596
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
3597
|
+
var Card = import_react35.default.forwardRef(
|
|
3598
|
+
({ style, variant = "default", padding = "md", children, ...props }, ref) => {
|
|
3599
|
+
const [isHovered, setIsHovered] = import_react35.default.useState(false);
|
|
3600
|
+
const paddingStyles = {
|
|
3601
|
+
none: "0",
|
|
3602
|
+
sm: "0.75rem",
|
|
3603
|
+
md: "1.5rem",
|
|
3604
|
+
lg: "2rem"
|
|
3605
|
+
};
|
|
3606
|
+
const variantStyles = {
|
|
3607
|
+
default: {
|
|
3608
|
+
normal: {
|
|
3609
|
+
backgroundColor: "#ffffff",
|
|
3610
|
+
border: "1px solid #e5e7eb",
|
|
3611
|
+
boxShadow: "0 1px 2px rgba(0, 0, 0, 0.05)"
|
|
3612
|
+
},
|
|
3613
|
+
hover: {
|
|
3614
|
+
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)"
|
|
3615
|
+
}
|
|
3616
|
+
},
|
|
3617
|
+
outlined: {
|
|
3618
|
+
normal: {
|
|
3619
|
+
backgroundColor: "#ffffff",
|
|
3620
|
+
border: "2px solid #e5e7eb",
|
|
3621
|
+
boxShadow: "none"
|
|
3622
|
+
},
|
|
3623
|
+
hover: {
|
|
3624
|
+
borderColor: "#d1d5db"
|
|
3625
|
+
}
|
|
3626
|
+
},
|
|
3627
|
+
elevated: {
|
|
3628
|
+
normal: {
|
|
3629
|
+
backgroundColor: "#ffffff",
|
|
3630
|
+
border: "none",
|
|
3631
|
+
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)"
|
|
3632
|
+
},
|
|
3633
|
+
hover: {
|
|
3634
|
+
boxShadow: "0 10px 15px rgba(0, 0, 0, 0.15)",
|
|
3635
|
+
transform: "translateY(-2px)"
|
|
3636
|
+
}
|
|
3637
|
+
}
|
|
3638
|
+
};
|
|
3639
|
+
const baseStyles = {
|
|
3640
|
+
borderRadius: "0.5rem",
|
|
3641
|
+
padding: paddingStyles[padding],
|
|
3642
|
+
transition: "all 0.2s ease"
|
|
3643
|
+
};
|
|
3644
|
+
const currentVariant = variantStyles[variant];
|
|
3645
|
+
const combinedStyles = {
|
|
3646
|
+
...baseStyles,
|
|
3647
|
+
...currentVariant.normal,
|
|
3648
|
+
...isHovered ? currentVariant.hover : {},
|
|
3649
|
+
...style
|
|
3650
|
+
};
|
|
3651
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
3652
|
+
"div",
|
|
3653
|
+
{
|
|
3654
|
+
ref,
|
|
3655
|
+
style: combinedStyles,
|
|
3656
|
+
onMouseEnter: () => setIsHovered(true),
|
|
3657
|
+
onMouseLeave: () => setIsHovered(false),
|
|
3658
|
+
...props,
|
|
3659
|
+
children
|
|
3660
|
+
}
|
|
3661
|
+
);
|
|
3662
|
+
}
|
|
3663
|
+
);
|
|
3664
|
+
Card.displayName = "Card";
|
|
3665
|
+
|
|
3666
|
+
// src/components/shared/Badge.tsx
|
|
3667
|
+
var import_react36 = __toESM(require("react"));
|
|
3668
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
3669
|
+
var Badge = import_react36.default.forwardRef(
|
|
3670
|
+
({ style, variant = "default", size = "md", children, ...props }, ref) => {
|
|
3671
|
+
const variantStyles = {
|
|
3672
|
+
default: {
|
|
3673
|
+
backgroundColor: "#f3f4f6",
|
|
3674
|
+
color: "#374151"
|
|
3675
|
+
},
|
|
3676
|
+
success: {
|
|
3677
|
+
backgroundColor: "#d1fae5",
|
|
3678
|
+
color: "#065f46"
|
|
3679
|
+
},
|
|
3680
|
+
warning: {
|
|
3681
|
+
backgroundColor: "#fef3c7",
|
|
3682
|
+
color: "#92400e"
|
|
3683
|
+
},
|
|
3684
|
+
error: {
|
|
3685
|
+
backgroundColor: "#fee2e2",
|
|
3686
|
+
color: "#991b1b"
|
|
3687
|
+
},
|
|
3688
|
+
info: {
|
|
3689
|
+
backgroundColor: "#dbeafe",
|
|
3690
|
+
color: "#1e40af"
|
|
3691
|
+
}
|
|
3692
|
+
};
|
|
3693
|
+
const sizeStyles = {
|
|
3694
|
+
sm: {
|
|
3695
|
+
fontSize: "0.75rem",
|
|
3696
|
+
lineHeight: "1rem",
|
|
3697
|
+
padding: "0.125rem 0.5rem"
|
|
3698
|
+
},
|
|
3699
|
+
md: {
|
|
3700
|
+
fontSize: "0.875rem",
|
|
3701
|
+
lineHeight: "1.25rem",
|
|
3702
|
+
padding: "0.25rem 0.75rem"
|
|
3703
|
+
},
|
|
3704
|
+
lg: {
|
|
3705
|
+
fontSize: "1rem",
|
|
3706
|
+
lineHeight: "1.5rem",
|
|
3707
|
+
padding: "0.375rem 1rem"
|
|
3708
|
+
}
|
|
3709
|
+
};
|
|
3710
|
+
const baseStyles = {
|
|
3711
|
+
display: "inline-flex",
|
|
3712
|
+
alignItems: "center",
|
|
3713
|
+
borderRadius: "9999px",
|
|
3714
|
+
fontWeight: "500",
|
|
3715
|
+
whiteSpace: "nowrap"
|
|
3716
|
+
};
|
|
3717
|
+
const combinedStyles = {
|
|
3718
|
+
...baseStyles,
|
|
3719
|
+
...variantStyles[variant],
|
|
3720
|
+
...sizeStyles[size],
|
|
3721
|
+
...style
|
|
3722
|
+
};
|
|
3723
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { ref, style: combinedStyles, ...props, children });
|
|
3724
|
+
}
|
|
3725
|
+
);
|
|
3726
|
+
Badge.displayName = "Badge";
|
|
3727
|
+
|
|
3728
|
+
// src/components/shared/Table.tsx
|
|
3729
|
+
var import_react37 = __toESM(require("react"));
|
|
3730
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
3731
|
+
function Table({
|
|
3732
|
+
columns,
|
|
3733
|
+
data,
|
|
3734
|
+
striped = false,
|
|
3735
|
+
hoverable = true,
|
|
3736
|
+
bordered = true,
|
|
3737
|
+
style
|
|
3738
|
+
}) {
|
|
3739
|
+
const [hoveredRow, setHoveredRow] = import_react37.default.useState(null);
|
|
3740
|
+
const tableStyles = {
|
|
3741
|
+
width: "100%",
|
|
3742
|
+
borderCollapse: "collapse",
|
|
3743
|
+
fontSize: "0.875rem",
|
|
3744
|
+
lineHeight: "1.25rem",
|
|
3745
|
+
...style
|
|
3746
|
+
};
|
|
3747
|
+
const theadStyles = {
|
|
3748
|
+
backgroundColor: "#f9fafb",
|
|
3749
|
+
borderBottom: "2px solid #e5e7eb"
|
|
3750
|
+
};
|
|
3751
|
+
const thStyles = {
|
|
3752
|
+
padding: "0.75rem 1rem",
|
|
3753
|
+
textAlign: "left",
|
|
3754
|
+
fontWeight: "600",
|
|
3755
|
+
color: "#374151",
|
|
3756
|
+
borderBottom: bordered ? "1px solid #e5e7eb" : "none"
|
|
3757
|
+
};
|
|
3758
|
+
const getTdStyles = (rowIndex) => ({
|
|
3759
|
+
padding: "0.75rem 1rem",
|
|
3760
|
+
borderBottom: bordered ? "1px solid #e5e7eb" : "none",
|
|
3761
|
+
backgroundColor: hoverable && hoveredRow === rowIndex ? "#f9fafb" : striped && rowIndex % 2 === 1 ? "#f9fafb" : "#ffffff",
|
|
3762
|
+
transition: "background-color 0.15s ease"
|
|
3763
|
+
});
|
|
3764
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { style: { overflowX: "auto", borderRadius: "0.5rem", border: bordered ? "1px solid #e5e7eb" : "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("table", { style: tableStyles, children: [
|
|
3765
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("thead", { style: theadStyles, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("tr", { children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3766
|
+
"th",
|
|
3767
|
+
{
|
|
3768
|
+
style: {
|
|
3769
|
+
...thStyles,
|
|
3770
|
+
width: column.width
|
|
3771
|
+
},
|
|
3772
|
+
children: column.header
|
|
3773
|
+
},
|
|
3774
|
+
column.key
|
|
3775
|
+
)) }) }),
|
|
3776
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("tbody", { children: data.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3777
|
+
"tr",
|
|
3778
|
+
{
|
|
3779
|
+
onMouseEnter: () => hoverable && setHoveredRow(rowIndex),
|
|
3780
|
+
onMouseLeave: () => hoverable && setHoveredRow(null),
|
|
3781
|
+
children: columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("td", { style: getTdStyles(rowIndex), children: column.render ? column.render(row) : row[column.key] }, column.key))
|
|
3782
|
+
},
|
|
3783
|
+
rowIndex
|
|
3784
|
+
)) })
|
|
3785
|
+
] }) });
|
|
3786
|
+
}
|
|
3787
|
+
Table.displayName = "Table";
|
|
3788
|
+
|
|
3789
|
+
// src/components/shared/Container.tsx
|
|
3790
|
+
var import_react38 = __toESM(require("react"));
|
|
3791
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
3792
|
+
var Container = import_react38.default.forwardRef(
|
|
3793
|
+
({ style, maxWidth = "lg", padding = "md", children, ...props }, ref) => {
|
|
3794
|
+
const maxWidthStyles = {
|
|
3795
|
+
sm: "640px",
|
|
3796
|
+
md: "768px",
|
|
3797
|
+
lg: "1024px",
|
|
3798
|
+
xl: "1280px",
|
|
3799
|
+
"2xl": "1536px",
|
|
3800
|
+
full: "100%"
|
|
3801
|
+
};
|
|
3802
|
+
const paddingStyles = {
|
|
3803
|
+
none: "0",
|
|
3804
|
+
sm: "1rem",
|
|
3805
|
+
md: "1.5rem",
|
|
3806
|
+
lg: "2rem"
|
|
3807
|
+
};
|
|
3808
|
+
const containerStyles = {
|
|
3809
|
+
width: "100%",
|
|
3810
|
+
maxWidth: maxWidthStyles[maxWidth],
|
|
3811
|
+
marginLeft: "auto",
|
|
3812
|
+
marginRight: "auto",
|
|
3813
|
+
paddingLeft: paddingStyles[padding],
|
|
3814
|
+
paddingRight: paddingStyles[padding],
|
|
3815
|
+
...style
|
|
3816
|
+
};
|
|
3817
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { ref, style: containerStyles, ...props, children });
|
|
3818
|
+
}
|
|
3819
|
+
);
|
|
3820
|
+
Container.displayName = "Container";
|
|
3821
|
+
|
|
3822
|
+
// src/components/shared/Grid.tsx
|
|
3823
|
+
var import_react39 = __toESM(require("react"));
|
|
3824
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
3825
|
+
var Grid = import_react39.default.forwardRef(
|
|
3826
|
+
({ style, columns = 3, rows, gap = "md", width = "100%", height = "auto", responsive = true, children, ...props }, ref) => {
|
|
3827
|
+
const gapStyles = {
|
|
3828
|
+
none: "0",
|
|
3829
|
+
sm: "0.5rem",
|
|
3830
|
+
md: "1rem",
|
|
3831
|
+
lg: "1.5rem",
|
|
3832
|
+
xl: "2rem"
|
|
3833
|
+
};
|
|
3834
|
+
const gridStyles = {
|
|
3835
|
+
display: "grid",
|
|
3836
|
+
gridTemplateColumns: responsive ? `repeat(auto-fit, minmax(${Math.floor(100 / columns)}%, 1fr))` : `repeat(${columns}, 1fr)`,
|
|
3837
|
+
gridTemplateRows: rows ? `repeat(${rows}, 1fr)` : void 0,
|
|
3838
|
+
gap: gapStyles[gap] || gap,
|
|
3839
|
+
width,
|
|
3840
|
+
height,
|
|
3841
|
+
...style
|
|
3842
|
+
};
|
|
3843
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { ref, style: gridStyles, ...props, children });
|
|
3844
|
+
}
|
|
3845
|
+
);
|
|
3846
|
+
Grid.displayName = "Grid";
|
|
3847
|
+
|
|
3848
|
+
// src/components/shared/Stack.tsx
|
|
3849
|
+
var import_react40 = __toESM(require("react"));
|
|
3850
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
3851
|
+
var Stack = import_react40.default.forwardRef(
|
|
3852
|
+
({ style, direction = "vertical", gap = "md", align = "stretch", justify = "start", children, ...props }, ref) => {
|
|
3853
|
+
const gapStyles = {
|
|
3854
|
+
none: "0",
|
|
3855
|
+
sm: "0.5rem",
|
|
3856
|
+
md: "1rem",
|
|
3857
|
+
lg: "1.5rem",
|
|
3858
|
+
xl: "2rem"
|
|
3859
|
+
};
|
|
3860
|
+
const alignStyles = {
|
|
3861
|
+
start: "flex-start",
|
|
3862
|
+
center: "center",
|
|
3863
|
+
end: "flex-end",
|
|
3864
|
+
stretch: "stretch"
|
|
3865
|
+
};
|
|
3866
|
+
const justifyStyles = {
|
|
3867
|
+
start: "flex-start",
|
|
3868
|
+
center: "center",
|
|
3869
|
+
end: "flex-end",
|
|
3870
|
+
between: "space-between",
|
|
3871
|
+
around: "space-around"
|
|
3872
|
+
};
|
|
3873
|
+
const stackStyles = {
|
|
3874
|
+
display: "flex",
|
|
3875
|
+
flexDirection: direction === "vertical" ? "column" : "row",
|
|
3876
|
+
gap: gapStyles[gap],
|
|
3877
|
+
alignItems: alignStyles[align],
|
|
3878
|
+
justifyContent: justifyStyles[justify],
|
|
3879
|
+
...style
|
|
3880
|
+
};
|
|
3881
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { ref, style: stackStyles, ...props, children });
|
|
3882
|
+
}
|
|
3883
|
+
);
|
|
3884
|
+
Stack.displayName = "Stack";
|
|
3885
|
+
|
|
3886
|
+
// src/components/shared/Modal.tsx
|
|
3887
|
+
var import_react41 = __toESM(require("react"));
|
|
3888
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
3889
|
+
var Modal = ({
|
|
3890
|
+
isOpen,
|
|
3891
|
+
onClose,
|
|
3892
|
+
title,
|
|
3893
|
+
children,
|
|
3894
|
+
size = "md",
|
|
3895
|
+
closeOnOverlayClick = true
|
|
3896
|
+
}) => {
|
|
3897
|
+
import_react41.default.useEffect(() => {
|
|
3898
|
+
if (isOpen) {
|
|
3899
|
+
document.body.style.overflow = "hidden";
|
|
3900
|
+
} else {
|
|
3901
|
+
document.body.style.overflow = "unset";
|
|
3902
|
+
}
|
|
3903
|
+
return () => {
|
|
3904
|
+
document.body.style.overflow = "unset";
|
|
3905
|
+
};
|
|
3906
|
+
}, [isOpen]);
|
|
3907
|
+
if (!isOpen) return null;
|
|
3908
|
+
const sizeStyles = {
|
|
3909
|
+
sm: "400px",
|
|
3910
|
+
md: "600px",
|
|
3911
|
+
lg: "800px",
|
|
3912
|
+
xl: "1000px"
|
|
3913
|
+
};
|
|
3914
|
+
const overlayStyles = {
|
|
3915
|
+
position: "fixed",
|
|
3916
|
+
top: 0,
|
|
3917
|
+
left: 0,
|
|
3918
|
+
right: 0,
|
|
3919
|
+
bottom: 0,
|
|
3920
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
3921
|
+
display: "flex",
|
|
3922
|
+
alignItems: "center",
|
|
3923
|
+
justifyContent: "center",
|
|
3924
|
+
zIndex: 1e3,
|
|
3925
|
+
padding: "1rem"
|
|
3926
|
+
};
|
|
3927
|
+
const modalStyles = {
|
|
3928
|
+
backgroundColor: "#ffffff",
|
|
3929
|
+
borderRadius: "0.5rem",
|
|
3930
|
+
boxShadow: "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
|
|
3931
|
+
width: "100%",
|
|
3932
|
+
maxWidth: sizeStyles[size],
|
|
3933
|
+
maxHeight: "90vh",
|
|
3934
|
+
display: "flex",
|
|
3935
|
+
flexDirection: "column"
|
|
3936
|
+
};
|
|
3937
|
+
const headerStyles = {
|
|
3938
|
+
padding: "1.5rem",
|
|
3939
|
+
borderBottom: "1px solid #e5e7eb",
|
|
3940
|
+
display: "flex",
|
|
3941
|
+
alignItems: "center",
|
|
3942
|
+
justifyContent: "space-between"
|
|
3943
|
+
};
|
|
3944
|
+
const titleStyles = {
|
|
3945
|
+
fontSize: "1.25rem",
|
|
3946
|
+
lineHeight: "1.75rem",
|
|
3947
|
+
fontWeight: "600",
|
|
3948
|
+
color: "#111827"
|
|
3949
|
+
};
|
|
3950
|
+
const closeButtonStyles = {
|
|
3951
|
+
padding: "0.5rem",
|
|
3952
|
+
borderRadius: "0.375rem",
|
|
3953
|
+
border: "none",
|
|
3954
|
+
backgroundColor: "transparent",
|
|
3955
|
+
cursor: "pointer",
|
|
3956
|
+
fontSize: "1.5rem",
|
|
3957
|
+
lineHeight: "1",
|
|
3958
|
+
color: "#6b7280",
|
|
3959
|
+
transition: "background-color 0.2s ease"
|
|
3960
|
+
};
|
|
3961
|
+
const contentStyles = {
|
|
3962
|
+
padding: "1.5rem",
|
|
3963
|
+
overflowY: "auto",
|
|
3964
|
+
flex: 1
|
|
3965
|
+
};
|
|
3966
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3967
|
+
"div",
|
|
3968
|
+
{
|
|
3969
|
+
style: overlayStyles,
|
|
3970
|
+
onClick: closeOnOverlayClick ? onClose : void 0,
|
|
3971
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
3972
|
+
"div",
|
|
3973
|
+
{
|
|
3974
|
+
style: modalStyles,
|
|
3975
|
+
onClick: (e) => e.stopPropagation(),
|
|
3976
|
+
children: [
|
|
3977
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { style: headerStyles, children: [
|
|
3978
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("h2", { style: titleStyles, children: title }),
|
|
3979
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3980
|
+
"button",
|
|
3981
|
+
{
|
|
3982
|
+
style: closeButtonStyles,
|
|
3983
|
+
onClick: onClose,
|
|
3984
|
+
"aria-label": "Close modal",
|
|
3985
|
+
children: "\xD7"
|
|
3986
|
+
}
|
|
3987
|
+
)
|
|
3988
|
+
] }),
|
|
3989
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { style: contentStyles, children })
|
|
3990
|
+
]
|
|
3991
|
+
}
|
|
3992
|
+
)
|
|
3993
|
+
}
|
|
3994
|
+
);
|
|
3995
|
+
};
|
|
3996
|
+
Modal.displayName = "Modal";
|
|
3997
|
+
|
|
3998
|
+
// src/components/shared/DateRangePicker.tsx
|
|
3999
|
+
var import_react42 = require("react");
|
|
4000
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
4001
|
+
var PrimusDateRangePicker = ({
|
|
4002
|
+
startDate = null,
|
|
4003
|
+
endDate = null,
|
|
4004
|
+
ranges = [],
|
|
4005
|
+
min,
|
|
4006
|
+
max,
|
|
4007
|
+
disabled = false,
|
|
4008
|
+
onRangeChange
|
|
4009
|
+
}) => {
|
|
4010
|
+
const [start, setStart] = (0, import_react42.useState)(startDate ?? "");
|
|
4011
|
+
const [end, setEnd] = (0, import_react42.useState)(endDate ?? "");
|
|
4012
|
+
(0, import_react42.useEffect)(() => {
|
|
4013
|
+
setStart(startDate ?? "");
|
|
4014
|
+
}, [startDate]);
|
|
4015
|
+
(0, import_react42.useEffect)(() => {
|
|
4016
|
+
setEnd(endDate ?? "");
|
|
4017
|
+
}, [endDate]);
|
|
4018
|
+
const normalizedRanges = (0, import_react42.useMemo)(() => {
|
|
4019
|
+
return ranges.map((range) => typeof range === "string" ? resolvePreset(range) : range).filter((range) => !!range);
|
|
4020
|
+
}, [ranges]);
|
|
4021
|
+
const handleStartChange = (value) => {
|
|
4022
|
+
setStart(value);
|
|
4023
|
+
onRangeChange?.({ startDate: value || null, endDate: end || null });
|
|
4024
|
+
};
|
|
4025
|
+
const handleEndChange = (value) => {
|
|
4026
|
+
setEnd(value);
|
|
4027
|
+
onRangeChange?.({ startDate: start || null, endDate: value || null });
|
|
4028
|
+
};
|
|
4029
|
+
const applyRange = (range) => {
|
|
4030
|
+
const nextStart = toDateInputValue(range.start);
|
|
4031
|
+
const nextEnd = toDateInputValue(range.end);
|
|
4032
|
+
setStart(nextStart);
|
|
4033
|
+
setEnd(nextEnd);
|
|
4034
|
+
onRangeChange?.({ startDate: nextStart, endDate: nextEnd, label: range.label });
|
|
4035
|
+
};
|
|
4036
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "space-y-3", children: [
|
|
4037
|
+
normalizedRanges.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "flex flex-wrap gap-2", children: normalizedRanges.map((range) => /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
4038
|
+
"button",
|
|
4039
|
+
{
|
|
4040
|
+
type: "button",
|
|
4041
|
+
disabled,
|
|
4042
|
+
onClick: () => applyRange(range),
|
|
4043
|
+
className: "px-3 py-1.5 rounded-full text-xs font-medium border border-white/10 bg-white/5 text-gray-200 hover:bg-white/10 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
4044
|
+
children: range.label
|
|
4045
|
+
},
|
|
4046
|
+
range.label
|
|
4047
|
+
)) }),
|
|
4048
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex flex-col md:flex-row gap-3", children: [
|
|
4049
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
4050
|
+
"input",
|
|
4051
|
+
{
|
|
4052
|
+
type: "date",
|
|
4053
|
+
value: start,
|
|
4054
|
+
min,
|
|
4055
|
+
max,
|
|
4056
|
+
disabled,
|
|
4057
|
+
onChange: (e) => handleStartChange(e.target.value),
|
|
4058
|
+
className: "w-full px-3 py-2 rounded-lg border border-white/10 bg-white/5 text-gray-200 text-sm focus:outline-none focus:ring-1 focus:ring-purple-500/50"
|
|
4059
|
+
}
|
|
4060
|
+
),
|
|
4061
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
4062
|
+
"input",
|
|
4063
|
+
{
|
|
4064
|
+
type: "date",
|
|
4065
|
+
value: end,
|
|
4066
|
+
min,
|
|
4067
|
+
max,
|
|
4068
|
+
disabled,
|
|
4069
|
+
onChange: (e) => handleEndChange(e.target.value),
|
|
4070
|
+
className: "w-full px-3 py-2 rounded-lg border border-white/10 bg-white/5 text-gray-200 text-sm focus:outline-none focus:ring-1 focus:ring-purple-500/50"
|
|
4071
|
+
}
|
|
4072
|
+
)
|
|
4073
|
+
] })
|
|
4074
|
+
] });
|
|
4075
|
+
};
|
|
4076
|
+
var resolvePreset = (label) => {
|
|
4077
|
+
const today = /* @__PURE__ */ new Date();
|
|
4078
|
+
const startOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate());
|
|
4079
|
+
switch (label.toLowerCase()) {
|
|
4080
|
+
case "today":
|
|
4081
|
+
return { label, start: startOfDay, end: startOfDay };
|
|
4082
|
+
case "last 7 days": {
|
|
4083
|
+
const start = new Date(startOfDay);
|
|
4084
|
+
start.setDate(start.getDate() - 6);
|
|
4085
|
+
return { label, start, end: startOfDay };
|
|
4086
|
+
}
|
|
4087
|
+
case "last 30 days": {
|
|
4088
|
+
const start = new Date(startOfDay);
|
|
4089
|
+
start.setDate(start.getDate() - 29);
|
|
4090
|
+
return { label, start, end: startOfDay };
|
|
4091
|
+
}
|
|
4092
|
+
case "this month": {
|
|
4093
|
+
const start = new Date(today.getFullYear(), today.getMonth(), 1);
|
|
4094
|
+
const end = new Date(today.getFullYear(), today.getMonth() + 1, 0);
|
|
4095
|
+
return { label, start, end };
|
|
4096
|
+
}
|
|
4097
|
+
default:
|
|
4098
|
+
return null;
|
|
4099
|
+
}
|
|
4100
|
+
};
|
|
4101
|
+
var toDateInputValue = (value) => {
|
|
4102
|
+
if (typeof value === "string") {
|
|
4103
|
+
return value;
|
|
4104
|
+
}
|
|
4105
|
+
const year = value.getFullYear();
|
|
4106
|
+
const month = String(value.getMonth() + 1).padStart(2, "0");
|
|
4107
|
+
const day = String(value.getDate()).padStart(2, "0");
|
|
4108
|
+
return `${year}-${month}-${day}`;
|
|
4109
|
+
};
|
|
4110
|
+
|
|
4111
|
+
// src/components/shared/FilterBar.tsx
|
|
4112
|
+
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
4113
|
+
var PrimusFilterBar = ({
|
|
4114
|
+
filters,
|
|
4115
|
+
activeFilters,
|
|
4116
|
+
onChange,
|
|
4117
|
+
children
|
|
4118
|
+
}) => {
|
|
4119
|
+
const updateFilter = (key, value) => {
|
|
4120
|
+
const next = {
|
|
4121
|
+
...activeFilters,
|
|
4122
|
+
[key]: value
|
|
4123
|
+
};
|
|
4124
|
+
onChange?.(next);
|
|
4125
|
+
};
|
|
4126
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "flex flex-wrap gap-4 items-end", children: [
|
|
4127
|
+
filters.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "min-w-[220px]", children: [
|
|
4128
|
+
filter.type === "select" && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
4129
|
+
Select,
|
|
4130
|
+
{
|
|
4131
|
+
label: filter.label,
|
|
4132
|
+
placeholder: filter.placeholder,
|
|
4133
|
+
options: filter.options ?? [],
|
|
4134
|
+
value: activeFilters[filter.key] ?? "",
|
|
4135
|
+
onChange: (value) => updateFilter(filter.key, value)
|
|
4136
|
+
}
|
|
4137
|
+
),
|
|
4138
|
+
filter.type === "toggle" && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
4139
|
+
Toggle,
|
|
4140
|
+
{
|
|
4141
|
+
label: filter.label,
|
|
4142
|
+
checked: Boolean(activeFilters[filter.key]),
|
|
4143
|
+
onChange: (checked) => updateFilter(filter.key, checked)
|
|
4144
|
+
}
|
|
4145
|
+
),
|
|
4146
|
+
filter.type === "search" && /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
4147
|
+
Input,
|
|
4148
|
+
{
|
|
4149
|
+
label: filter.label,
|
|
4150
|
+
placeholder: filter.placeholder ?? "Search...",
|
|
4151
|
+
value: activeFilters[filter.key] ?? "",
|
|
4152
|
+
onChange: (event) => updateFilter(filter.key, event.target.value)
|
|
4153
|
+
}
|
|
4154
|
+
)
|
|
4155
|
+
] }, filter.key)),
|
|
4156
|
+
children
|
|
4157
|
+
] });
|
|
4158
|
+
};
|
|
4159
|
+
|
|
4160
|
+
// src/components/shared/ExportMenu.tsx
|
|
4161
|
+
var import_react43 = require("react");
|
|
4162
|
+
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
4163
|
+
var PrimusExportMenu = ({
|
|
4164
|
+
formats = ["CSV", "PDF", "PNG", "JSON"],
|
|
4165
|
+
includeCharts = true,
|
|
4166
|
+
includeStats = true,
|
|
4167
|
+
includeTables = true,
|
|
4168
|
+
onExport
|
|
4169
|
+
}) => {
|
|
4170
|
+
const [format, setFormat] = (0, import_react43.useState)(formats[0] ?? "CSV");
|
|
4171
|
+
const [charts, setCharts] = (0, import_react43.useState)(includeCharts);
|
|
4172
|
+
const [stats, setStats] = (0, import_react43.useState)(includeStats);
|
|
4173
|
+
const [tables, setTables] = (0, import_react43.useState)(includeTables);
|
|
4174
|
+
(0, import_react43.useEffect)(() => {
|
|
4175
|
+
if (!formats.includes(format)) {
|
|
4176
|
+
setFormat(formats[0] ?? "CSV");
|
|
4177
|
+
}
|
|
4178
|
+
}, [formats, format]);
|
|
4179
|
+
const handleExport = () => {
|
|
4180
|
+
onExport?.({
|
|
4181
|
+
format,
|
|
4182
|
+
includeCharts: charts,
|
|
4183
|
+
includeStats: stats,
|
|
4184
|
+
includeTables: tables
|
|
4185
|
+
});
|
|
4186
|
+
};
|
|
4187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
4188
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4189
|
+
"select",
|
|
4190
|
+
{
|
|
4191
|
+
value: format,
|
|
4192
|
+
onChange: (event) => setFormat(event.target.value),
|
|
4193
|
+
className: "px-3 py-2 rounded-lg border border-white/10 bg-white/5 text-gray-200 text-sm",
|
|
4194
|
+
children: formats.map((item) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("option", { value: item, children: item }, item))
|
|
4195
|
+
}
|
|
4196
|
+
),
|
|
4197
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("label", { className: "flex items-center gap-2 text-xs text-gray-300", children: [
|
|
4198
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("input", { type: "checkbox", checked: charts, onChange: (e) => setCharts(e.target.checked) }),
|
|
4199
|
+
"Charts"
|
|
4200
|
+
] }),
|
|
4201
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("label", { className: "flex items-center gap-2 text-xs text-gray-300", children: [
|
|
4202
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("input", { type: "checkbox", checked: stats, onChange: (e) => setStats(e.target.checked) }),
|
|
4203
|
+
"Stats"
|
|
4204
|
+
] }),
|
|
4205
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("label", { className: "flex items-center gap-2 text-xs text-gray-300", children: [
|
|
4206
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("input", { type: "checkbox", checked: tables, onChange: (e) => setTables(e.target.checked) }),
|
|
4207
|
+
"Tables"
|
|
4208
|
+
] }),
|
|
4209
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4210
|
+
"button",
|
|
4211
|
+
{
|
|
4212
|
+
type: "button",
|
|
4213
|
+
onClick: handleExport,
|
|
4214
|
+
className: "px-4 py-2 rounded-lg bg-purple-600 text-white text-sm font-medium hover:bg-purple-500",
|
|
4215
|
+
children: "Export"
|
|
4216
|
+
}
|
|
4217
|
+
)
|
|
4218
|
+
] });
|
|
4219
|
+
};
|
|
4220
|
+
|
|
4221
|
+
// src/components/shared/Search.tsx
|
|
4222
|
+
var import_react44 = require("react");
|
|
4223
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
4224
|
+
var PrimusSearch = ({
|
|
4225
|
+
placeholder = "Search...",
|
|
4226
|
+
debounce = 300,
|
|
4227
|
+
value = "",
|
|
4228
|
+
showSuggestions = false,
|
|
4229
|
+
suggestions = [],
|
|
4230
|
+
onSearch
|
|
4231
|
+
}) => {
|
|
4232
|
+
const [query, setQuery] = (0, import_react44.useState)(value);
|
|
4233
|
+
(0, import_react44.useEffect)(() => {
|
|
4234
|
+
setQuery(value);
|
|
4235
|
+
}, [value]);
|
|
4236
|
+
(0, import_react44.useEffect)(() => {
|
|
4237
|
+
const handle = window.setTimeout(() => {
|
|
4238
|
+
onSearch?.(query);
|
|
4239
|
+
}, debounce);
|
|
4240
|
+
return () => window.clearTimeout(handle);
|
|
4241
|
+
}, [query, debounce, onSearch]);
|
|
4242
|
+
const visibleSuggestions = (0, import_react44.useMemo)(() => {
|
|
4243
|
+
if (!showSuggestions || !suggestions.length) {
|
|
4244
|
+
return [];
|
|
4245
|
+
}
|
|
4246
|
+
if (!query) {
|
|
4247
|
+
return suggestions.slice(0, 5);
|
|
4248
|
+
}
|
|
4249
|
+
return suggestions.filter((item) => item.toLowerCase().includes(query.toLowerCase())).slice(0, 5);
|
|
4250
|
+
}, [suggestions, query, showSuggestions]);
|
|
4251
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "relative", children: [
|
|
4252
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
4253
|
+
"input",
|
|
4254
|
+
{
|
|
4255
|
+
type: "text",
|
|
4256
|
+
value: query,
|
|
4257
|
+
placeholder,
|
|
4258
|
+
onChange: (event) => setQuery(event.target.value),
|
|
4259
|
+
className: "w-full px-3 py-2 rounded-lg border border-white/10 bg-white/5 text-gray-200 text-sm focus:outline-none focus:ring-1 focus:ring-purple-500/50"
|
|
4260
|
+
}
|
|
4261
|
+
),
|
|
4262
|
+
visibleSuggestions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "absolute mt-2 w-full rounded-lg border border-white/10 bg-slate-900/90 backdrop-blur-sm shadow-lg z-10", children: visibleSuggestions.map((item) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
4263
|
+
"button",
|
|
4264
|
+
{
|
|
4265
|
+
type: "button",
|
|
4266
|
+
onClick: () => setQuery(item),
|
|
4267
|
+
className: "w-full text-left px-3 py-2 text-sm text-gray-200 hover:bg-white/10",
|
|
4268
|
+
children: item
|
|
4269
|
+
},
|
|
4270
|
+
item
|
|
4271
|
+
)) })
|
|
4272
|
+
] });
|
|
4273
|
+
};
|
|
2553
4274
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2554
4275
|
0 && (module.exports = {
|
|
2555
4276
|
AICopilot,
|
|
2556
4277
|
AccountDashboard,
|
|
2557
4278
|
AgentDirectory,
|
|
4279
|
+
Badge,
|
|
4280
|
+
Button,
|
|
4281
|
+
Card,
|
|
4282
|
+
Checkbox,
|
|
2558
4283
|
CheckoutForm,
|
|
2559
4284
|
ClaimStatusTracker,
|
|
4285
|
+
Container,
|
|
2560
4286
|
CreditCardVisual,
|
|
2561
4287
|
CreditScoreCard,
|
|
2562
4288
|
DashboardGrid,
|
|
@@ -2564,29 +4290,64 @@ var DashboardGrid = ({
|
|
|
2564
4290
|
FeatureFlagToggle,
|
|
2565
4291
|
FileUploader,
|
|
2566
4292
|
FraudDetectionDashboard,
|
|
4293
|
+
Grid,
|
|
4294
|
+
Input,
|
|
2567
4295
|
KYCVerification,
|
|
2568
4296
|
LoanCalculator,
|
|
2569
4297
|
LogViewer,
|
|
2570
4298
|
LoginPage,
|
|
4299
|
+
Modal,
|
|
2571
4300
|
NotificationBell,
|
|
2572
4301
|
NotificationFeed,
|
|
2573
4302
|
PolicyCard,
|
|
2574
4303
|
PremiumCalculator,
|
|
4304
|
+
PrimusActivityFeed,
|
|
4305
|
+
PrimusAreaChart,
|
|
4306
|
+
PrimusBadge,
|
|
4307
|
+
PrimusBarChart,
|
|
4308
|
+
PrimusButton,
|
|
4309
|
+
PrimusCard,
|
|
4310
|
+
PrimusChartBase,
|
|
4311
|
+
PrimusCheckbox,
|
|
4312
|
+
PrimusContainer,
|
|
2575
4313
|
PrimusDashboard,
|
|
2576
4314
|
PrimusDataTable,
|
|
4315
|
+
PrimusDateRangePicker,
|
|
4316
|
+
PrimusExportMenu,
|
|
4317
|
+
PrimusFilterBar,
|
|
4318
|
+
PrimusGrid,
|
|
2577
4319
|
PrimusHeader,
|
|
4320
|
+
PrimusInput,
|
|
2578
4321
|
PrimusLayout,
|
|
4322
|
+
PrimusLineChart,
|
|
2579
4323
|
PrimusLogin,
|
|
2580
4324
|
PrimusModal,
|
|
4325
|
+
PrimusModalComponent,
|
|
2581
4326
|
PrimusNotificationCenter,
|
|
4327
|
+
PrimusNotificationFeed,
|
|
2582
4328
|
PrimusNotifications,
|
|
4329
|
+
PrimusPieChart,
|
|
2583
4330
|
PrimusProvider,
|
|
4331
|
+
PrimusRadioGroup,
|
|
4332
|
+
PrimusSearch,
|
|
4333
|
+
PrimusSelect,
|
|
2584
4334
|
PrimusSidebar,
|
|
4335
|
+
PrimusSparkline,
|
|
4336
|
+
PrimusStack,
|
|
2585
4337
|
PrimusStatCard,
|
|
4338
|
+
PrimusTable,
|
|
4339
|
+
PrimusTextarea,
|
|
2586
4340
|
PrimusThemeProvider,
|
|
2587
4341
|
PrimusThemeToggle,
|
|
4342
|
+
PrimusToggle,
|
|
2588
4343
|
QuoteComparison,
|
|
4344
|
+
RadioGroup,
|
|
2589
4345
|
SecurityDashboard,
|
|
4346
|
+
Select,
|
|
4347
|
+
Stack,
|
|
4348
|
+
Table,
|
|
4349
|
+
Textarea,
|
|
4350
|
+
Toggle,
|
|
2590
4351
|
TransactionHistory,
|
|
2591
4352
|
UserProfile,
|
|
2592
4353
|
themeColors,
|