@quanticjs/notification-ui 9.0.1 → 9.0.2
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.cjs +120 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +120 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3531,11 +3531,8 @@ function OperationsOverview({ basePath = "/api", className }) {
|
|
|
3531
3531
|
const windowHours = data.windowHours;
|
|
3532
3532
|
const channels = data.channels ?? [];
|
|
3533
3533
|
const dlqPending = data.dlqPending;
|
|
3534
|
-
const
|
|
3535
|
-
|
|
3536
|
-
{ label: `Delivered (${windowHours}h)`, value: data.totalDelivered },
|
|
3537
|
-
{ label: `Failed (${windowHours}h)`, value: data.totalFailed }
|
|
3538
|
-
];
|
|
3534
|
+
const deliveryRate = ratePct(data.totalDelivered, data.totalSends);
|
|
3535
|
+
const failureRate = ratePct(data.totalFailed, data.totalSends);
|
|
3539
3536
|
return /* @__PURE__ */ jsxs27("section", { "aria-label": "Operations overview", className: cn27("flex flex-col gap-5", className), children: [
|
|
3540
3537
|
/* @__PURE__ */ jsxs27("div", { className: "flex flex-wrap items-baseline justify-between gap-2", children: [
|
|
3541
3538
|
/* @__PURE__ */ jsxs27("div", { children: [
|
|
@@ -3551,7 +3548,29 @@ function OperationsOverview({ basePath = "/api", className }) {
|
|
|
3551
3548
|
formatDateTime7(data.generatedAt)
|
|
3552
3549
|
] })
|
|
3553
3550
|
] }),
|
|
3554
|
-
/* @__PURE__ */
|
|
3551
|
+
/* @__PURE__ */ jsxs27("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-3", children: [
|
|
3552
|
+
/* @__PURE__ */ jsx30(StatCard, { label: `Sent (${windowHours}h)`, value: data.totalSends, icon: /* @__PURE__ */ jsx30(SendIcon, {}) }),
|
|
3553
|
+
/* @__PURE__ */ jsx30(
|
|
3554
|
+
StatCard,
|
|
3555
|
+
{
|
|
3556
|
+
label: "Delivery rate",
|
|
3557
|
+
value: deliveryRate,
|
|
3558
|
+
icon: /* @__PURE__ */ jsx30(CheckIcon, {}),
|
|
3559
|
+
delta: `${data.totalDelivered} delivered`,
|
|
3560
|
+
trend: "up"
|
|
3561
|
+
}
|
|
3562
|
+
),
|
|
3563
|
+
/* @__PURE__ */ jsx30(
|
|
3564
|
+
StatCard,
|
|
3565
|
+
{
|
|
3566
|
+
label: "Failure rate",
|
|
3567
|
+
value: failureRate,
|
|
3568
|
+
icon: /* @__PURE__ */ jsx30(AlertIcon4, {}),
|
|
3569
|
+
delta: `${data.totalFailed} failed`,
|
|
3570
|
+
trend: data.totalFailed > 0 ? "down" : "flat"
|
|
3571
|
+
}
|
|
3572
|
+
)
|
|
3573
|
+
] }),
|
|
3555
3574
|
/* @__PURE__ */ jsx30(Card5, { children: /* @__PURE__ */ jsxs27(CardContent, { className: "flex flex-wrap items-center gap-x-8 gap-y-3 p-5", children: [
|
|
3556
3575
|
/* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2", children: [
|
|
3557
3576
|
/* @__PURE__ */ jsx30("span", { className: "text-sm text-muted-foreground", children: "DLQ pending" }),
|
|
@@ -3567,31 +3586,104 @@ function OperationsOverview({ basePath = "/api", className }) {
|
|
|
3567
3586
|
] })
|
|
3568
3587
|
] }) }),
|
|
3569
3588
|
/* @__PURE__ */ jsxs27(Card5, { children: [
|
|
3570
|
-
/* @__PURE__ */
|
|
3571
|
-
|
|
3572
|
-
/* @__PURE__ */ jsx30("
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3589
|
+
/* @__PURE__ */ jsxs27(CardHeader, { children: [
|
|
3590
|
+
/* @__PURE__ */ jsx30(CardTitle, { children: "Channel health" }),
|
|
3591
|
+
/* @__PURE__ */ jsx30("p", { className: "text-sm text-muted-foreground", children: "Delivery success by channel" })
|
|
3592
|
+
] }),
|
|
3593
|
+
/* @__PURE__ */ jsx30(CardContent, { className: "p-0", children: channels.length === 0 ? /* @__PURE__ */ jsx30("p", { className: "px-5 py-8 text-center text-sm text-muted-foreground", children: "No channel activity" }) : /* @__PURE__ */ jsx30("ul", { className: "divide-y divide-border", children: channels.map((row) => {
|
|
3594
|
+
const success = ratePct(row.delivered, row.sends);
|
|
3595
|
+
return /* @__PURE__ */ jsxs27("li", { className: "flex items-center gap-3 px-5 py-3.5", children: [
|
|
3596
|
+
/* @__PURE__ */ jsx30(
|
|
3597
|
+
"span",
|
|
3598
|
+
{
|
|
3599
|
+
"aria-hidden": "true",
|
|
3600
|
+
className: "grid size-9 shrink-0 place-items-center rounded-md bg-primary/10 text-primary [&_svg]:size-4",
|
|
3601
|
+
children: /* @__PURE__ */ jsx30(ChannelIcon, { channel: row.channel })
|
|
3602
|
+
}
|
|
3603
|
+
),
|
|
3604
|
+
/* @__PURE__ */ jsxs27("div", { className: "min-w-0 flex-1", children: [
|
|
3605
|
+
/* @__PURE__ */ jsxs27("div", { className: "flex items-center justify-between gap-2", children: [
|
|
3606
|
+
/* @__PURE__ */ jsxs27("span", { className: "flex items-center gap-2 text-sm font-medium capitalize text-foreground", children: [
|
|
3607
|
+
row.channel,
|
|
3608
|
+
/* @__PURE__ */ jsxs27(StatusBadge6, { variant: row.failed > 0 ? "warning" : "success", appearance: "dot", children: [
|
|
3609
|
+
success,
|
|
3610
|
+
" success"
|
|
3611
|
+
] })
|
|
3612
|
+
] }),
|
|
3613
|
+
/* @__PURE__ */ jsxs27("span", { className: "shrink-0 text-xs tabular-nums text-muted-foreground", children: [
|
|
3614
|
+
row.sends,
|
|
3615
|
+
" sent"
|
|
3616
|
+
] })
|
|
3617
|
+
] }),
|
|
3618
|
+
/* @__PURE__ */ jsxs27("div", { className: "mt-2 flex h-1.5 overflow-hidden rounded-full bg-muted", children: [
|
|
3619
|
+
/* @__PURE__ */ jsx30("span", { className: "bg-success", style: { width: `${barPct(row.delivered, row.sends)}%` } }),
|
|
3620
|
+
/* @__PURE__ */ jsx30("span", { className: "bg-destructive", style: { width: `${barPct(row.failed, row.sends)}%` } })
|
|
3621
|
+
] }),
|
|
3622
|
+
/* @__PURE__ */ jsxs27("div", { className: "mt-1.5 text-xs tabular-nums text-muted-foreground", children: [
|
|
3623
|
+
row.delivered,
|
|
3624
|
+
" delivered \xB7 ",
|
|
3625
|
+
row.failed,
|
|
3626
|
+
" failed"
|
|
3627
|
+
] })
|
|
3628
|
+
] })
|
|
3629
|
+
] }, row.channel);
|
|
3630
|
+
}) }) })
|
|
3592
3631
|
] })
|
|
3593
3632
|
] });
|
|
3594
3633
|
}
|
|
3634
|
+
function ratePct(n, total) {
|
|
3635
|
+
if (total <= 0) return "\u2014";
|
|
3636
|
+
return `${(n / total * 100).toFixed(2)}%`;
|
|
3637
|
+
}
|
|
3638
|
+
function barPct(n, total) {
|
|
3639
|
+
if (total <= 0) return 0;
|
|
3640
|
+
return Math.min(100, n / total * 100);
|
|
3641
|
+
}
|
|
3642
|
+
function SendIcon() {
|
|
3643
|
+
return /* @__PURE__ */ jsxs27("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
3644
|
+
/* @__PURE__ */ jsx30("path", { d: "M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z" }),
|
|
3645
|
+
/* @__PURE__ */ jsx30("path", { d: "m21.854 2.147-10.94 10.939" })
|
|
3646
|
+
] });
|
|
3647
|
+
}
|
|
3648
|
+
function CheckIcon() {
|
|
3649
|
+
return /* @__PURE__ */ jsxs27("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
3650
|
+
/* @__PURE__ */ jsx30("path", { d: "M21.801 10A10 10 0 1 1 17 3.335" }),
|
|
3651
|
+
/* @__PURE__ */ jsx30("path", { d: "m9 11 3 3L22 4" })
|
|
3652
|
+
] });
|
|
3653
|
+
}
|
|
3654
|
+
function AlertIcon4() {
|
|
3655
|
+
return /* @__PURE__ */ jsxs27("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
3656
|
+
/* @__PURE__ */ jsx30("circle", { cx: "12", cy: "12", r: "10" }),
|
|
3657
|
+
/* @__PURE__ */ jsx30("path", { d: "m15 9-6 6" }),
|
|
3658
|
+
/* @__PURE__ */ jsx30("path", { d: "m9 9 6 6" })
|
|
3659
|
+
] });
|
|
3660
|
+
}
|
|
3661
|
+
function ChannelIcon({ channel }) {
|
|
3662
|
+
switch (channel) {
|
|
3663
|
+
case "email":
|
|
3664
|
+
return /* @__PURE__ */ jsxs27("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
3665
|
+
/* @__PURE__ */ jsx30("rect", { width: "20", height: "16", x: "2", y: "4", rx: "2" }),
|
|
3666
|
+
/* @__PURE__ */ jsx30("path", { d: "m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" })
|
|
3667
|
+
] });
|
|
3668
|
+
case "sms":
|
|
3669
|
+
return /* @__PURE__ */ jsx30("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx30("path", { d: "M7.9 20A9 9 0 1 0 4 16.1L2 22Z" }) });
|
|
3670
|
+
case "push":
|
|
3671
|
+
case "inapp":
|
|
3672
|
+
case "in-app":
|
|
3673
|
+
return /* @__PURE__ */ jsxs27("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
3674
|
+
/* @__PURE__ */ jsx30("path", { d: "M10.268 21a2 2 0 0 0 3.464 0" }),
|
|
3675
|
+
/* @__PURE__ */ jsx30("path", { d: "M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326" })
|
|
3676
|
+
] });
|
|
3677
|
+
case "webhook":
|
|
3678
|
+
return /* @__PURE__ */ jsxs27("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
3679
|
+
/* @__PURE__ */ jsx30("path", { d: "M10 6.5a3.5 3.5 0 1 1 6 2.45" }),
|
|
3680
|
+
/* @__PURE__ */ jsx30("path", { d: "M6 10.5a3.5 3.5 0 1 0 5 3.15" }),
|
|
3681
|
+
/* @__PURE__ */ jsx30("path", { d: "M14 17.5a3.5 3.5 0 1 0 1-6.85" })
|
|
3682
|
+
] });
|
|
3683
|
+
default:
|
|
3684
|
+
return /* @__PURE__ */ jsx30("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx30("circle", { cx: "12", cy: "12", r: "4" }) });
|
|
3685
|
+
}
|
|
3686
|
+
}
|
|
3595
3687
|
|
|
3596
3688
|
// src/delivery-log-explorer.tsx
|
|
3597
3689
|
import { useState as useState15 } from "react";
|