@variamosple/variamos-components 0.2.0 → 0.2.1

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.
@@ -1,47 +1,54 @@
1
- import { jsxs as o, jsx as e } from "react/jsx-runtime";
2
- import { Navbar as t, Container as h, Nav as i } from "react-bootstrap";
1
+ import { jsxs as o, jsx as e, Fragment as g } from "react/jsx-runtime";
2
+ import { useState as N } from "react";
3
+ import { Navbar as a, Container as k, Nav as n } from "react-bootstrap";
3
4
  import "../../Context/AnalyticsContext.js";
4
- import { useMenu as f } from "../../Context/MenuContext.js";
5
- import { useRouter as g } from "../../Context/RouterContext.js";
6
- import { useSession as N } from "../../Context/SessionContext.js";
5
+ import { useMenu as w } from "../../Context/MenuContext.js";
6
+ import { useRouter as C } from "../../Context/RouterContext.js";
7
+ import { useSession as S } from "../../Context/SessionContext.js";
7
8
  import "../../Context/NotificationContext.js";
8
- import { HeaderOptions as k } from "./HeaderOptions.js";
9
- import { MenuItemComponent as n } from "./MenuItem.js";
10
- import { SubHeader as b } from "./SubHeader.js";
11
- const B = ({
12
- logoUrl: a,
13
- logoAlt: m = "App logo",
14
- signInUrl: s,
15
- adminApiUrl: c
9
+ import { HeaderOptions as b } from "./HeaderOptions.js";
10
+ import { MenuItemComponent as m } from "./MenuItem.js";
11
+ import { SubHeader as v } from "./SubHeader.js";
12
+ import { NotificationBell as x } from "../Notifications/NotificationBell.js";
13
+ import { NotificationDrawer as D } from "../Notifications/NotificationDrawer.js";
14
+ const E = ({
15
+ logoUrl: s,
16
+ logoAlt: l = "App logo",
17
+ signInUrl: c,
18
+ adminApiUrl: p
16
19
  }) => {
17
- const { items: l } = f(), { navigate: p } = g(), { isAuthenticated: d, isLoading: u } = N();
20
+ const { items: d } = w(), { navigate: f } = C(), { isAuthenticated: r, isLoading: h } = S(), [u, t] = N(!1);
18
21
  return /* @__PURE__ */ o("header", { className: "sticky-top", children: [
19
- /* @__PURE__ */ e(t, { bg: "dark", variant: "dark", children: /* @__PURE__ */ o(h, { fluid: !0, children: [
20
- /* @__PURE__ */ e(t.Brand, { onClick: () => p("/"), children: /* @__PURE__ */ e(
22
+ /* @__PURE__ */ e(a, { bg: "dark", variant: "dark", children: /* @__PURE__ */ o(k, { fluid: !0, children: [
23
+ /* @__PURE__ */ e(a.Brand, { onClick: () => f("/"), children: /* @__PURE__ */ e(
21
24
  "img",
22
25
  {
23
- src: a,
26
+ src: s,
24
27
  height: "30",
25
28
  className: "d-inline-block align-top",
26
- alt: m
29
+ alt: l
27
30
  }
28
31
  ) }),
29
- /* @__PURE__ */ e(i, { className: "me-auto", children: l.map((r) => /* @__PURE__ */ e(n, { ...r }, r.title)) }),
30
- /* @__PURE__ */ o(i, { className: "me-5 pe-5", children: [
31
- /* @__PURE__ */ e(k, { adminApiUrl: c }),
32
- !u && !d && /* @__PURE__ */ e(
33
- n,
32
+ /* @__PURE__ */ e(n, { className: "me-auto", children: d.map((i) => /* @__PURE__ */ e(m, { ...i }, i.title)) }),
33
+ /* @__PURE__ */ o(n, { className: "me-5 pe-5 align-items-center", children: [
34
+ r && /* @__PURE__ */ o(g, { children: [
35
+ /* @__PURE__ */ e(x, { onClick: () => t(!0), className: "me-2" }),
36
+ /* @__PURE__ */ e(D, { show: u, onClose: () => t(!1) })
37
+ ] }),
38
+ /* @__PURE__ */ e(b, { adminApiUrl: p }),
39
+ !h && !r && /* @__PURE__ */ e(
40
+ m,
34
41
  {
35
42
  title: "Sign In",
36
43
  type: "location",
37
- location: s
44
+ location: c
38
45
  }
39
46
  )
40
47
  ] })
41
48
  ] }) }),
42
- /* @__PURE__ */ e(b, {})
49
+ /* @__PURE__ */ e(v, {})
43
50
  ] });
44
51
  };
45
52
  export {
46
- B as Header
53
+ E as Header
47
54
  };
@@ -1,22 +1,22 @@
1
1
  import { jsxs as r, jsx as e } from "react/jsx-runtime";
2
2
  import { Button as a, Badge as n } from "react-bootstrap";
3
- import { Bell as s } from "react-bootstrap-icons";
4
- import { useNotifications as l } from "../../Context/NotificationContext.js";
3
+ import { Bell as l } from "react-bootstrap-icons";
4
+ import { useNotifications as s } from "../../Context/NotificationContext.js";
5
5
  const f = ({
6
6
  onClick: o,
7
7
  className: i = ""
8
8
  }) => {
9
- const { unreadCount: t } = l();
9
+ const { unreadCount: t } = s();
10
10
  return /* @__PURE__ */ r(
11
11
  a,
12
12
  {
13
13
  variant: "link",
14
14
  onClick: o,
15
- className: `position-relative p-2 text-dark ${i}`,
15
+ className: `position-relative p-2 text-light ${i}`,
16
16
  "aria-label": "Notifications",
17
17
  style: { boxShadow: "none" },
18
18
  children: [
19
- /* @__PURE__ */ e(s, { size: 22 }),
19
+ /* @__PURE__ */ e(l, { size: 22 }),
20
20
  t > 0 && /* @__PURE__ */ e(
21
21
  n,
22
22
  {
@@ -1,10 +1,10 @@
1
- import { jsxs as i, jsx as e, Fragment as x } from "react/jsx-runtime";
2
- import { useState as b, useEffect as z } from "react";
3
- import { Offcanvas as o, Button as r, Nav as l, Spinner as C, ListGroup as N } from "react-bootstrap";
4
- import { ArrowLeft as L, Gear as R, Inbox as E, Trash as g, CheckAll as I, CircleFill as K } from "react-bootstrap-icons";
5
- import { useNotifications as B } from "../../Context/NotificationContext.js";
6
- import { NotificationSettings as F } from "./NotificationSettings.js";
7
- const _ = {
1
+ import { jsxs as i, jsx as e, Fragment as N } from "react/jsx-runtime";
2
+ import { useState as y, useEffect as L } from "react";
3
+ import { Offcanvas as d, Button as r, Nav as c, Spinner as E } from "react-bootstrap";
4
+ import { ArrowLeft as M, Gear as H, Inbox as I, Trash as b, CheckAll as K, CircleFill as R } from "react-bootstrap-icons";
5
+ import { useNotifications as _ } from "../../Context/NotificationContext.js";
6
+ import { NotificationSettings as B } from "./NotificationSettings.js";
7
+ const F = {
8
8
  review_assigned: {
9
9
  title: "Language Review Assigned",
10
10
  body: "You have been assigned to review the translation for {{languageName}}."
@@ -16,50 +16,55 @@ const _ = {
16
16
  test_template: {
17
17
  title: "Notification Test",
18
18
  body: "Hello {{name}}, this is a real-time notification test."
19
+ },
20
+ admin_alert: {
21
+ title: "{{title}}",
22
+ body: "{{body}}"
19
23
  }
20
- }, P = ({
21
- show: c,
22
- onClose: y
24
+ }, G = ({
25
+ show: m,
26
+ onClose: u
23
27
  }) => {
24
28
  const {
25
- notifications: d,
26
- isLoading: u,
27
- fetchNotifications: v,
28
- markAsRead: k,
29
- markAllAsRead: w,
30
- emptyTrash: S
31
- } = B(), [a, T] = b("inbox"), [m, h] = b(!1);
32
- z(() => {
33
- c && v(a);
34
- }, [c, a]);
35
- const f = (t, n) => {
29
+ notifications: f,
30
+ isLoading: v,
31
+ fetchNotifications: k,
32
+ markAsRead: w,
33
+ markAllAsRead: S,
34
+ emptyTrash: T,
35
+ deleteNotification: z
36
+ } = _(), [n, C] = y("inbox"), [p, x] = y(!1);
37
+ L(() => {
38
+ m && k(n);
39
+ }, [m, n]);
40
+ const g = (t, a) => {
36
41
  let s = t;
37
- for (const p of Object.keys(n))
38
- s = s.replace(new RegExp(`{{${p}}}`, "g"), String(n[p]));
42
+ for (const l of Object.keys(a))
43
+ s = s.replace(new RegExp(`{{${l}}}`, "g"), String(a[l]));
39
44
  return s;
40
45
  }, j = (t) => {
41
- const n = _[t.templateKey] || {
46
+ const a = F[t.templateKey] || {
42
47
  title: "New Alert",
43
48
  body: `Notification template: ${t.templateKey}`
44
49
  };
45
50
  return {
46
- title: f(n.title, t.variables),
47
- body: f(n.body, t.variables)
51
+ title: g(a.title, t.variables),
52
+ body: g(a.body, t.variables)
48
53
  };
49
54
  }, A = (t) => new Date(t).toLocaleDateString(void 0, {
50
55
  hour: "2-digit",
51
56
  minute: "2-digit"
52
57
  });
53
- return /* @__PURE__ */ i(o, { show: c, onHide: y, placement: "end", className: "text-dark", children: [
54
- /* @__PURE__ */ e(o.Header, { closeButton: !0, className: "border-bottom", children: /* @__PURE__ */ e(o.Title, { className: "d-flex align-items-center w-100", children: m ? /* @__PURE__ */ i(x, { children: [
58
+ return /* @__PURE__ */ i(d, { show: m, onHide: u, placement: "end", className: "text-dark", children: [
59
+ /* @__PURE__ */ e(d.Header, { closeButton: !0, className: "border-bottom", children: /* @__PURE__ */ e(d.Title, { className: "d-flex align-items-center w-100", children: p ? /* @__PURE__ */ i(N, { children: [
55
60
  /* @__PURE__ */ e(
56
61
  r,
57
62
  {
58
63
  variant: "link",
59
64
  className: "p-0 me-2 text-dark",
60
- onClick: () => h(!1),
65
+ onClick: () => x(!1),
61
66
  "aria-label": "Back",
62
- children: /* @__PURE__ */ e(L, { size: 20 })
67
+ children: /* @__PURE__ */ e(M, { size: 20 })
63
68
  }
64
69
  ),
65
70
  /* @__PURE__ */ e("span", { children: "Settings" })
@@ -70,42 +75,42 @@ const _ = {
70
75
  {
71
76
  variant: "link",
72
77
  className: "p-0 text-secondary",
73
- onClick: () => h(!0),
78
+ onClick: () => x(!0),
74
79
  "aria-label": "Notification Settings",
75
80
  style: { boxShadow: "none" },
76
- children: /* @__PURE__ */ e(R, { size: 20 })
81
+ children: /* @__PURE__ */ e(H, { size: 20 })
77
82
  }
78
83
  )
79
84
  ] }) }) }),
80
- /* @__PURE__ */ e(o.Body, { className: "p-0 d-flex flex-column h-100", children: m ? /* @__PURE__ */ e("div", { className: "p-3", children: /* @__PURE__ */ e(F, {}) }) : /* @__PURE__ */ i(x, { children: [
85
+ /* @__PURE__ */ e(d.Body, { className: "p-0 d-flex flex-column h-100", children: p ? /* @__PURE__ */ e("div", { className: "p-3", children: /* @__PURE__ */ e(B, {}) }) : /* @__PURE__ */ i(N, { children: [
81
86
  /* @__PURE__ */ i(
82
- l,
87
+ c,
83
88
  {
84
89
  variant: "tabs",
85
- activeKey: a,
86
- onSelect: (t) => T(t),
90
+ activeKey: n,
91
+ onSelect: (t) => C(t),
87
92
  className: "px-3 pt-2 bg-light border-bottom",
88
93
  children: [
89
- /* @__PURE__ */ e(l.Item, { children: /* @__PURE__ */ i(l.Link, { eventKey: "inbox", className: "d-flex align-items-center", children: [
90
- /* @__PURE__ */ e(E, { className: "me-2" }),
94
+ /* @__PURE__ */ e(c.Item, { children: /* @__PURE__ */ i(c.Link, { eventKey: "inbox", className: "d-flex align-items-center", children: [
95
+ /* @__PURE__ */ e(I, { className: "me-2" }),
91
96
  "Inbox"
92
97
  ] }) }),
93
- /* @__PURE__ */ e(l.Item, { children: /* @__PURE__ */ i(l.Link, { eventKey: "trash", className: "d-flex align-items-center", children: [
94
- /* @__PURE__ */ e(g, { className: "me-2" }),
98
+ /* @__PURE__ */ e(c.Item, { children: /* @__PURE__ */ i(c.Link, { eventKey: "trash", className: "d-flex align-items-center", children: [
99
+ /* @__PURE__ */ e(b, { className: "me-2" }),
95
100
  "Trash"
96
101
  ] }) })
97
102
  ]
98
103
  }
99
104
  ),
100
- d.length > 0 && /* @__PURE__ */ e("div", { className: "d-flex justify-content-end align-items-center p-2 bg-light border-bottom px-3", children: a === "inbox" ? /* @__PURE__ */ i(
105
+ f.length > 0 && /* @__PURE__ */ e("div", { className: "d-flex justify-content-end align-items-center p-2 bg-light border-bottom px-3", children: n === "inbox" ? /* @__PURE__ */ i(
101
106
  r,
102
107
  {
103
108
  variant: "link",
104
109
  size: "sm",
105
110
  className: "p-0 text-primary text-decoration-none d-flex align-items-center",
106
- onClick: w,
111
+ onClick: S,
107
112
  children: [
108
- /* @__PURE__ */ e(I, { className: "me-1", size: 18 }),
113
+ /* @__PURE__ */ e(K, { className: "me-1", size: 18 }),
109
114
  "Mark all as read"
110
115
  ]
111
116
  }
@@ -115,44 +120,75 @@ const _ = {
115
120
  variant: "link",
116
121
  size: "sm",
117
122
  className: "p-0 text-danger text-decoration-none d-flex align-items-center",
118
- onClick: S,
123
+ onClick: T,
119
124
  children: [
120
- /* @__PURE__ */ e(g, { className: "me-1", size: 16 }),
125
+ /* @__PURE__ */ e(b, { className: "me-1", size: 16 }),
121
126
  "Empty Trash"
122
127
  ]
123
128
  }
124
129
  ) }),
125
- /* @__PURE__ */ e("div", { className: "flex-grow-1 overflow-auto", children: u ? /* @__PURE__ */ e("div", { className: "text-center py-5", children: /* @__PURE__ */ e(C, { animation: "border", variant: "primary" }) }) : d.length === 0 ? /* @__PURE__ */ e("div", { className: "text-center py-5 text-muted", children: /* @__PURE__ */ e("p", { className: "mb-0", children: a === "inbox" ? "Your inbox is empty!" : "No deleted notifications." }) }) : /* @__PURE__ */ e(N, { variant: "flush", children: d.map((t) => {
126
- const { title: n, body: s } = j(t);
130
+ /* @__PURE__ */ e("div", { className: "flex-grow-1 overflow-auto bg-light pt-3", children: v ? /* @__PURE__ */ e("div", { className: "text-center py-5", children: /* @__PURE__ */ e(E, { animation: "border", variant: "primary" }) }) : f.length === 0 ? /* @__PURE__ */ e("div", { className: "text-center py-5 text-muted", children: /* @__PURE__ */ e("p", { className: "mb-0", children: n === "inbox" ? "Your inbox is empty!" : "No deleted notifications." }) }) : /* @__PURE__ */ e("div", { className: "px-3", children: f.map((t) => {
131
+ const { title: a, body: s } = j(t), l = n === "inbox" && !t.isRead;
127
132
  return /* @__PURE__ */ e(
128
- N.Item,
133
+ "div",
129
134
  {
130
- className: `p-3 border-bottom position-relative ${a === "inbox" && !t.isRead ? "bg-light" : ""}`,
131
- style: { transition: "background-color 0.2s" },
135
+ className: `p-3 mb-2 rounded border shadow-sm ${l ? "bg-white border-primary-subtle" : "bg-white border-light"}`,
136
+ style: {
137
+ transition: "all 0.2s ease-in-out",
138
+ borderLeft: l ? "4px solid #0d6efd" : "1px solid #dee2e6"
139
+ },
132
140
  children: /* @__PURE__ */ i("div", { className: "d-flex justify-content-between align-items-start", children: [
133
- /* @__PURE__ */ i("div", { className: "pe-3", children: [
141
+ /* @__PURE__ */ i("div", { className: "pe-2 flex-grow-1", children: [
134
142
  /* @__PURE__ */ e(
135
143
  "h6",
136
144
  {
137
- className: `mb-1 ${a === "inbox" && !t.isRead ? "font-weight-bold text-dark" : "text-secondary"}`,
138
- style: { fontSize: "0.95rem" },
139
- children: n
145
+ className: `mb-1 ${l ? "fw-bold text-dark" : "text-secondary fw-semibold"}`,
146
+ style: { fontSize: "0.9rem", lineHeight: "1.25" },
147
+ children: a
148
+ }
149
+ ),
150
+ /* @__PURE__ */ e(
151
+ "p",
152
+ {
153
+ className: "mb-2 text-muted",
154
+ style: { fontSize: "0.8rem", color: "#6c757d", lineHeight: "1.3" },
155
+ children: s
140
156
  }
141
157
  ),
142
- /* @__PURE__ */ e("p", { className: "text-muted small mb-2", children: s }),
143
- /* @__PURE__ */ e("span", { className: "text-muted", style: { fontSize: "0.75rem" }, children: A(t.createdAt) })
158
+ /* @__PURE__ */ e("span", { className: "text-muted d-block", style: { fontSize: "0.7rem" }, children: A(t.createdAt) })
144
159
  ] }),
145
- a === "inbox" && !t.isRead && /* @__PURE__ */ e(
146
- r,
147
- {
148
- variant: "link",
149
- className: "p-0 text-primary border-0",
150
- onClick: () => k(t.id),
151
- title: "Mark as read",
152
- style: { boxShadow: "none" },
153
- children: /* @__PURE__ */ e(K, { size: 10, className: "text-primary" })
154
- }
155
- )
160
+ /* @__PURE__ */ i("div", { className: "d-flex align-items-center gap-2", children: [
161
+ l && /* @__PURE__ */ e(
162
+ r,
163
+ {
164
+ variant: "link",
165
+ className: "p-1 text-primary border-0 d-flex align-items-center",
166
+ onClick: () => w(t.id),
167
+ title: "Mark as read",
168
+ style: { boxShadow: "none" },
169
+ children: /* @__PURE__ */ e(R, { size: 8, className: "text-primary" })
170
+ }
171
+ ),
172
+ n === "inbox" && /* @__PURE__ */ e(
173
+ r,
174
+ {
175
+ variant: "link",
176
+ className: "p-1 text-secondary border-0 d-flex align-items-center",
177
+ onClick: () => z(t.id),
178
+ title: "Move to trash",
179
+ style: { boxShadow: "none" },
180
+ onMouseEnter: (h) => {
181
+ const o = h.currentTarget.querySelector("svg");
182
+ o && (o.style.fill = "#dc3545");
183
+ },
184
+ onMouseLeave: (h) => {
185
+ const o = h.currentTarget.querySelector("svg");
186
+ o && (o.style.fill = "currentColor");
187
+ },
188
+ children: /* @__PURE__ */ e(b, { size: 14, style: { transition: "fill 0.2s" } })
189
+ }
190
+ )
191
+ ] })
156
192
  ] })
157
193
  },
158
194
  t.id
@@ -162,5 +198,5 @@ const _ = {
162
198
  ] });
163
199
  };
164
200
  export {
165
- P as NotificationDrawer
201
+ G as NotificationDrawer
166
202
  };
@@ -21,6 +21,7 @@ interface NotificationContextType {
21
21
  markAsRead: (id: string) => Promise<void>;
22
22
  markAllAsRead: () => Promise<void>;
23
23
  emptyTrash: () => Promise<void>;
24
+ deleteNotification: (id: string) => Promise<void>;
24
25
  fetchPreferences: () => Promise<void>;
25
26
  updatePreferences: (updates: Partial<UserNotificationPreferences>) => Promise<void>;
26
27
  }