gov-layout 1.2.24 → 1.2.25

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 CHANGED
@@ -82,6 +82,7 @@ interface SidebarUserProfileProps {
82
82
  }
83
83
  declare function SidebarUserProfile({ user, roleLabel, onLogout, collapsed, onProfile, }: SidebarUserProfileProps): react_jsx_runtime.JSX.Element | null;
84
84
 
85
+ type NotificationCategory = 'action' | 'general';
85
86
  interface NotificationItem {
86
87
  id: string | number;
87
88
  title: string;
@@ -89,6 +90,8 @@ interface NotificationItem {
89
90
  date: string;
90
91
  type: 'info' | 'success' | 'warning' | 'error' | 'reminder';
91
92
  isRead: boolean;
93
+ /** หมวดหมู่การแจ้งเตือน: 'action' = ต้องดำเนินการ, 'general' = แจ้งเตือนทั่วไป */
94
+ category?: NotificationCategory;
92
95
  }
93
96
  interface UserHeaderProps {
94
97
  user?: {
@@ -262,4 +265,4 @@ declare const Icons: {
262
265
  readonly Trash: typeof TrashIcon;
263
266
  };
264
267
 
265
- export { AlertTriangleIcon, BarChartIcon, BellIcon, BottomBar, type BottomBarProps, BuildingIcon, CalendarIcon, CheckCircleIcon, ClipboardIcon, DatabaseIcon, DownloadIcon, EditIcon, EyeIcon, FONT_SIZE_OPTIONS, FileTextIcon, FolderIcon, type FontSizeKey, type FontSizeOption, FontSizeSettings, GearIcon, HeartIcon, HelpCircleIcon, HistoryIcon, HomeIcon, type IconProps, Icons, LogOutIcon, MailIcon, MapPinIcon, type MenuItem, type NotificationItem, PhoneIcon, PlusCircleIcon, PrinterIcon, SearchIcon, SettingsPanel, SettingsProvider, ShieldIcon, SidebarHeader, SidebarMenu, SidebarUserProfile, StaffSidebar, type StaffSidebarProps, StarIcon, type Theme, ThemeSettings, TrashIcon, UploadIcon, type User, UserHeader, UserIcon, UserSidebar, UsersIcon, WrenchIcon, XCircleIcon, useDarkMode, useSettings };
268
+ export { AlertTriangleIcon, BarChartIcon, BellIcon, BottomBar, type BottomBarProps, BuildingIcon, CalendarIcon, CheckCircleIcon, ClipboardIcon, DatabaseIcon, DownloadIcon, EditIcon, EyeIcon, FONT_SIZE_OPTIONS, FileTextIcon, FolderIcon, type FontSizeKey, type FontSizeOption, FontSizeSettings, GearIcon, HeartIcon, HelpCircleIcon, HistoryIcon, HomeIcon, type IconProps, Icons, LogOutIcon, MailIcon, MapPinIcon, type MenuItem, type NotificationCategory, type NotificationItem, PhoneIcon, PlusCircleIcon, PrinterIcon, SearchIcon, SettingsPanel, SettingsProvider, ShieldIcon, SidebarHeader, SidebarMenu, SidebarUserProfile, StaffSidebar, type StaffSidebarProps, StarIcon, type Theme, ThemeSettings, TrashIcon, UploadIcon, type User, UserHeader, UserIcon, UserSidebar, UsersIcon, WrenchIcon, XCircleIcon, useDarkMode, useSettings };
package/dist/index.d.ts CHANGED
@@ -82,6 +82,7 @@ interface SidebarUserProfileProps {
82
82
  }
83
83
  declare function SidebarUserProfile({ user, roleLabel, onLogout, collapsed, onProfile, }: SidebarUserProfileProps): react_jsx_runtime.JSX.Element | null;
84
84
 
85
+ type NotificationCategory = 'action' | 'general';
85
86
  interface NotificationItem {
86
87
  id: string | number;
87
88
  title: string;
@@ -89,6 +90,8 @@ interface NotificationItem {
89
90
  date: string;
90
91
  type: 'info' | 'success' | 'warning' | 'error' | 'reminder';
91
92
  isRead: boolean;
93
+ /** หมวดหมู่การแจ้งเตือน: 'action' = ต้องดำเนินการ, 'general' = แจ้งเตือนทั่วไป */
94
+ category?: NotificationCategory;
92
95
  }
93
96
  interface UserHeaderProps {
94
97
  user?: {
@@ -262,4 +265,4 @@ declare const Icons: {
262
265
  readonly Trash: typeof TrashIcon;
263
266
  };
264
267
 
265
- export { AlertTriangleIcon, BarChartIcon, BellIcon, BottomBar, type BottomBarProps, BuildingIcon, CalendarIcon, CheckCircleIcon, ClipboardIcon, DatabaseIcon, DownloadIcon, EditIcon, EyeIcon, FONT_SIZE_OPTIONS, FileTextIcon, FolderIcon, type FontSizeKey, type FontSizeOption, FontSizeSettings, GearIcon, HeartIcon, HelpCircleIcon, HistoryIcon, HomeIcon, type IconProps, Icons, LogOutIcon, MailIcon, MapPinIcon, type MenuItem, type NotificationItem, PhoneIcon, PlusCircleIcon, PrinterIcon, SearchIcon, SettingsPanel, SettingsProvider, ShieldIcon, SidebarHeader, SidebarMenu, SidebarUserProfile, StaffSidebar, type StaffSidebarProps, StarIcon, type Theme, ThemeSettings, TrashIcon, UploadIcon, type User, UserHeader, UserIcon, UserSidebar, UsersIcon, WrenchIcon, XCircleIcon, useDarkMode, useSettings };
268
+ export { AlertTriangleIcon, BarChartIcon, BellIcon, BottomBar, type BottomBarProps, BuildingIcon, CalendarIcon, CheckCircleIcon, ClipboardIcon, DatabaseIcon, DownloadIcon, EditIcon, EyeIcon, FONT_SIZE_OPTIONS, FileTextIcon, FolderIcon, type FontSizeKey, type FontSizeOption, FontSizeSettings, GearIcon, HeartIcon, HelpCircleIcon, HistoryIcon, HomeIcon, type IconProps, Icons, LogOutIcon, MailIcon, MapPinIcon, type MenuItem, type NotificationCategory, type NotificationItem, PhoneIcon, PlusCircleIcon, PrinterIcon, SearchIcon, SettingsPanel, SettingsProvider, ShieldIcon, SidebarHeader, SidebarMenu, SidebarUserProfile, StaffSidebar, type StaffSidebarProps, StarIcon, type Theme, ThemeSettings, TrashIcon, UploadIcon, type User, UserHeader, UserIcon, UserSidebar, UsersIcon, WrenchIcon, XCircleIcon, useDarkMode, useSettings };
package/dist/index.js CHANGED
@@ -1130,6 +1130,7 @@ function UserHeader({
1130
1130
  const displayName = `${user?.firstName || ""} ${user?.lastName || ""}`.trim() || "\u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49";
1131
1131
  const firstChar = user?.firstName?.charAt(0) || "\u0E1C";
1132
1132
  const [isNotifOpen, setIsNotifOpen] = react.useState(false);
1133
+ const [activeFilter, setActiveFilter] = react.useState("all");
1133
1134
  const notifRef = react.useRef(null);
1134
1135
  const isDark = useDarkMode();
1135
1136
  react.useEffect(() => {
@@ -1142,6 +1143,13 @@ function UserHeader({
1142
1143
  return () => document.removeEventListener("mousedown", handleClickOutside);
1143
1144
  }, []);
1144
1145
  const unreadCount = notifications.filter((n) => !n.isRead).length;
1146
+ const actionCount = notifications.filter((n) => n.category === "action").length;
1147
+ const generalCount = notifications.filter((n) => !n.category || n.category === "general").length;
1148
+ const filteredNotifications = notifications.filter((n) => {
1149
+ if (activeFilter === "all") return true;
1150
+ if (activeFilter === "action") return n.category === "action";
1151
+ return !n.category || n.category === "general";
1152
+ });
1145
1153
  return /* @__PURE__ */ jsxRuntime.jsx(
1146
1154
  "header",
1147
1155
  {
@@ -1340,34 +1348,95 @@ function UserHeader({
1340
1348
  "div",
1341
1349
  {
1342
1350
  style: {
1343
- padding: "16px",
1344
- borderBottom: `1px solid ${isDark ? "#374151" : "#f3f4f6"}`,
1345
- display: "flex",
1346
- alignItems: "center",
1347
- justifyContent: "space-between",
1351
+ padding: "16px 16px 0",
1348
1352
  background: isDark ? "#1f2937" : "#fafafa"
1349
1353
  },
1350
1354
  children: [
1351
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600, fontSize: "14px", color: isDark ? "#ffffff" : "#111" }, children: "\u0E01\u0E32\u0E23\u0E41\u0E08\u0E49\u0E07\u0E40\u0E15\u0E37\u0E2D\u0E19" }),
1352
- onMarkAllRead && /* @__PURE__ */ jsxRuntime.jsx(
1353
- "button",
1355
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "12px" }, children: [
1356
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600, fontSize: "14px", color: isDark ? "#ffffff" : "#111" }, children: "\u0E01\u0E32\u0E23\u0E41\u0E08\u0E49\u0E07\u0E40\u0E15\u0E37\u0E2D\u0E19" }),
1357
+ onMarkAllRead && /* @__PURE__ */ jsxRuntime.jsx(
1358
+ "button",
1359
+ {
1360
+ onClick: onMarkAllRead,
1361
+ style: {
1362
+ fontSize: "12px",
1363
+ color: "var(--color-alias-color-brand-primary, #1e7d55)",
1364
+ background: "none",
1365
+ border: "none",
1366
+ cursor: "pointer",
1367
+ fontWeight: 500
1368
+ },
1369
+ children: "\u0E2D\u0E48\u0E32\u0E19\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14"
1370
+ }
1371
+ )
1372
+ ] }),
1373
+ /* @__PURE__ */ jsxRuntime.jsx(
1374
+ "div",
1354
1375
  {
1355
- onClick: onMarkAllRead,
1356
1376
  style: {
1357
- fontSize: "12px",
1358
- color: "var(--color-alias-color-brand-primary, #1e7d55)",
1359
- background: "none",
1360
- border: "none",
1361
- cursor: "pointer",
1362
- fontWeight: 500
1377
+ display: "flex",
1378
+ gap: "6px",
1379
+ paddingBottom: "12px",
1380
+ borderBottom: `1px solid ${isDark ? "#374151" : "#e5e7eb"}`
1363
1381
  },
1364
- children: "\u0E2D\u0E48\u0E32\u0E19\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14"
1382
+ children: [
1383
+ { key: "all", label: "\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14", count: notifications.length },
1384
+ { key: "action", label: "\u0E15\u0E49\u0E2D\u0E07\u0E14\u0E33\u0E40\u0E19\u0E34\u0E19\u0E01\u0E32\u0E23", count: actionCount },
1385
+ { key: "general", label: "\u0E41\u0E08\u0E49\u0E07\u0E40\u0E15\u0E37\u0E2D\u0E19\u0E17\u0E31\u0E48\u0E27\u0E44\u0E1B", count: generalCount }
1386
+ ].map((tab) => {
1387
+ const isActive = activeFilter === tab.key;
1388
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1389
+ "button",
1390
+ {
1391
+ onClick: () => setActiveFilter(tab.key),
1392
+ style: {
1393
+ display: "inline-flex",
1394
+ alignItems: "center",
1395
+ gap: "5px",
1396
+ padding: "5px 10px",
1397
+ fontSize: "12px",
1398
+ fontWeight: isActive ? 600 : 400,
1399
+ color: isActive ? isDark ? "#ffffff" : "#1e7d55" : isDark ? "#9ca3af" : "#6b7280",
1400
+ background: isActive ? isDark ? "rgba(30,125,85,0.2)" : "rgba(30,125,85,0.08)" : "transparent",
1401
+ border: `1px solid ${isActive ? isDark ? "rgba(30,125,85,0.4)" : "rgba(30,125,85,0.25)" : isDark ? "#4b5563" : "#e5e7eb"}`,
1402
+ borderRadius: "16px",
1403
+ cursor: "pointer",
1404
+ transition: "all 0.15s ease",
1405
+ whiteSpace: "nowrap"
1406
+ },
1407
+ children: [
1408
+ tab.label,
1409
+ /* @__PURE__ */ jsxRuntime.jsx(
1410
+ "span",
1411
+ {
1412
+ style: {
1413
+ minWidth: "18px",
1414
+ height: "18px",
1415
+ display: "inline-flex",
1416
+ alignItems: "center",
1417
+ justifyContent: "center",
1418
+ borderRadius: "9px",
1419
+ fontSize: "10px",
1420
+ fontWeight: 700,
1421
+ lineHeight: 1,
1422
+ padding: "0 4px",
1423
+ background: isActive ? isDark ? "#1e7d55" : "#1e7d55" : isDark ? "#4b5563" : "#e5e7eb",
1424
+ color: isActive ? "#ffffff" : isDark ? "#d1d5db" : "#6b7280"
1425
+ },
1426
+ children: tab.count
1427
+ }
1428
+ )
1429
+ ]
1430
+ },
1431
+ tab.key
1432
+ );
1433
+ })
1365
1434
  }
1366
1435
  )
1367
1436
  ]
1368
1437
  }
1369
1438
  ),
1370
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { maxHeight: "60vh", overflowY: "auto" }, children: notifications.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
1439
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { maxHeight: "60vh", overflowY: "auto" }, children: filteredNotifications.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
1371
1440
  "div",
1372
1441
  {
1373
1442
  style: {
@@ -1376,21 +1445,22 @@ function UserHeader({
1376
1445
  color: "#9ca3af",
1377
1446
  fontSize: "14px"
1378
1447
  },
1379
- children: "\u{1F514} \u0E44\u0E21\u0E48\u0E21\u0E35\u0E01\u0E32\u0E23\u0E41\u0E08\u0E49\u0E07\u0E40\u0E15\u0E37\u0E2D\u0E19\u0E43\u0E2B\u0E21\u0E48"
1448
+ children: activeFilter === "all" ? "\u{1F514} \u0E44\u0E21\u0E48\u0E21\u0E35\u0E01\u0E32\u0E23\u0E41\u0E08\u0E49\u0E07\u0E40\u0E15\u0E37\u0E2D\u0E19\u0E43\u0E2B\u0E21\u0E48" : activeFilter === "action" ? "\u2705 \u0E44\u0E21\u0E48\u0E21\u0E35\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E17\u0E35\u0E48\u0E15\u0E49\u0E2D\u0E07\u0E14\u0E33\u0E40\u0E19\u0E34\u0E19\u0E01\u0E32\u0E23" : "\u{1F4CB} \u0E44\u0E21\u0E48\u0E21\u0E35\u0E01\u0E32\u0E23\u0E41\u0E08\u0E49\u0E07\u0E40\u0E15\u0E37\u0E2D\u0E19\u0E17\u0E31\u0E48\u0E27\u0E44\u0E1B"
1380
1449
  }
1381
- ) : notifications.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
1450
+ ) : filteredNotifications.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
1382
1451
  "div",
1383
1452
  {
1384
1453
  onClick: () => onNotificationClick?.(item),
1385
1454
  style: {
1386
1455
  padding: "12px 16px",
1387
- borderBottom: "1px solid #f9fafb",
1456
+ borderBottom: `1px solid ${isDark ? "#2d3748" : "#f3f4f6"}`,
1388
1457
  cursor: "pointer",
1389
1458
  background: !item.isRead ? isDark ? "rgba(59,130,246,0.15)" : "rgba(219,234,254,0.3)" : "transparent",
1390
1459
  position: "relative",
1391
1460
  display: "flex",
1392
1461
  gap: "12px",
1393
- alignItems: "flex-start"
1462
+ alignItems: "flex-start",
1463
+ transition: "background-color 0.15s ease"
1394
1464
  },
1395
1465
  onMouseEnter: (e) => {
1396
1466
  e.currentTarget.style.backgroundColor = isDark ? "#1f2937" : "#f9fafb";
@@ -1432,6 +1502,22 @@ function UserHeader({
1432
1502
  }
1433
1503
  ),
1434
1504
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
1505
+ item.category === "action" && /* @__PURE__ */ jsxRuntime.jsx(
1506
+ "span",
1507
+ {
1508
+ style: {
1509
+ display: "inline-block",
1510
+ fontSize: "10px",
1511
+ fontWeight: 600,
1512
+ color: "#b45309",
1513
+ background: "#fef3c7",
1514
+ padding: "1px 6px",
1515
+ borderRadius: "4px",
1516
+ marginBottom: "4px"
1517
+ },
1518
+ children: "\u0E15\u0E49\u0E2D\u0E07\u0E14\u0E33\u0E40\u0E19\u0E34\u0E19\u0E01\u0E32\u0E23"
1519
+ }
1520
+ ),
1435
1521
  /* @__PURE__ */ jsxRuntime.jsx(
1436
1522
  "p",
1437
1523
  {