@bernierllc/email-ui
Version:
React UI components for email management, templates, scheduling, and analytics
35 lines (33 loc) • 7.86 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/*
Copyright (c) 2025 Bernier LLC
This file is licensed to the client under a limited-use license.
The client may use and modify this code *only within the scope of the project it was delivered for*.
Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
*/
import { useState } from 'react';
export const AnalyticsDashboard = ({ analytics, isLoading = false, onRefresh, onExport, className = '', style, }) => {
const [viewType, setViewType] = useState('overview');
const totalMetrics = analytics.reduce((acc, item) => ({
sent: acc.sent + item.sent,
delivered: acc.delivered + item.delivered,
opened: acc.opened + item.opened,
clicked: acc.clicked + item.clicked,
bounced: acc.bounced + item.bounced,
complained: acc.complained + item.complained,
}), { sent: 0, delivered: 0, opened: 0, clicked: 0, bounced: 0, complained: 0 });
const overallRates = {
openRate: totalMetrics.delivered > 0 ? (totalMetrics.opened / totalMetrics.delivered) * 100 : 0,
clickRate: totalMetrics.opened > 0 ? (totalMetrics.clicked / totalMetrics.opened) * 100 : 0,
bounceRate: totalMetrics.sent > 0 ? (totalMetrics.bounced / totalMetrics.sent) * 100 : 0,
deliveryRate: totalMetrics.sent > 0 ? (totalMetrics.delivered / totalMetrics.sent) * 100 : 0,
};
const formatDate = (date) => {
return date.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric'
});
};
const MetricCard = ({ title, value, suffix = '', trend }) => (_jsxs("div", { className: "metric-card", children: [_jsxs("div", { className: "metric-card__header", children: [_jsx("h3", { className: "metric-card__title", children: title }), trend !== undefined && (_jsxs("span", { className: `metric-card__trend ${trend >= 0 ? 'positive' : 'negative'}`, children: [trend >= 0 ? '↑' : '↓', " ", Math.abs(trend).toFixed(1), "%"] }))] }), _jsxs("div", { className: "metric-card__value", children: [typeof value === 'number' ? value.toLocaleString() : value, suffix] })] }));
return (_jsxs("div", { className: `analytics-dashboard ${className}`, style: style, children: [_jsxs("div", { className: "analytics-dashboard__header", children: [_jsx("h2", { className: "analytics-dashboard__title", children: "Email Analytics" }), _jsxs("div", { className: "analytics-dashboard__controls", children: [_jsx("div", { className: "view-toggles", children: ['overview', 'trends', 'breakdown'].map(view => (_jsx("button", { onClick: () => setViewType(view), className: `btn btn--small ${viewType === view ? 'btn--primary' : 'btn--secondary'}`, children: view.charAt(0).toUpperCase() + view.slice(1) }, view))) }), _jsxs("div", { className: "analytics-dashboard__actions", children: [onRefresh && (_jsx("button", { onClick: onRefresh, disabled: isLoading, className: "btn btn--secondary btn--small", children: isLoading ? 'Refreshing...' : 'Refresh' })), onExport && (_jsxs("div", { className: "export-dropdown", children: [_jsx("button", { className: "btn btn--secondary btn--small", children: "Export" }), _jsxs("div", { className: "dropdown-menu", children: [_jsx("button", { onClick: () => onExport('csv'), children: "Export CSV" }), _jsx("button", { onClick: () => onExport('pdf'), children: "Export PDF" })] })] }))] })] })] }), viewType === 'overview' && (_jsxs("div", { className: "analytics-overview", children: [_jsxs("div", { className: "metrics-grid", children: [_jsx(MetricCard, { title: "Total Sent", value: totalMetrics.sent }), _jsx(MetricCard, { title: "Delivery Rate", value: overallRates.deliveryRate, suffix: "%" }), _jsx(MetricCard, { title: "Open Rate", value: overallRates.openRate, suffix: "%" }), _jsx(MetricCard, { title: "Click Rate", value: overallRates.clickRate, suffix: "%" }), _jsx(MetricCard, { title: "Bounce Rate", value: overallRates.bounceRate, suffix: "%" })] }), _jsxs("div", { className: "performance-summary", children: [_jsx("h3", { children: "Performance Summary" }), _jsxs("div", { className: "summary-stats", children: [_jsxs("div", { className: "stat-row", children: [_jsx("span", { className: "stat-label", children: "Delivered:" }), _jsx("span", { className: "stat-value", children: totalMetrics.delivered.toLocaleString() }), _jsx("div", { className: "stat-bar", children: _jsx("div", { className: "stat-bar__fill stat-bar__fill--delivered", style: { width: `${overallRates.deliveryRate}%` } }) })] }), _jsxs("div", { className: "stat-row", children: [_jsx("span", { className: "stat-label", children: "Opened:" }), _jsx("span", { className: "stat-value", children: totalMetrics.opened.toLocaleString() }), _jsx("div", { className: "stat-bar", children: _jsx("div", { className: "stat-bar__fill stat-bar__fill--opened", style: { width: `${overallRates.openRate}%` } }) })] }), _jsxs("div", { className: "stat-row", children: [_jsx("span", { className: "stat-label", children: "Clicked:" }), _jsx("span", { className: "stat-value", children: totalMetrics.clicked.toLocaleString() }), _jsx("div", { className: "stat-bar", children: _jsx("div", { className: "stat-bar__fill stat-bar__fill--clicked", style: { width: `${overallRates.clickRate}%` } }) })] })] })] })] })), viewType === 'trends' && (_jsxs("div", { className: "analytics-trends", children: [_jsx("h3", { children: "Performance Trends" }), _jsx("div", { className: "trends-list", children: analytics.map((item, index) => (_jsxs("div", { className: "trend-item", children: [_jsxs("div", { className: "trend-item__header", children: [_jsxs("span", { className: "trend-item__date", children: [formatDate(item.period.start), " - ", formatDate(item.period.end)] }), _jsxs("span", { className: "trend-item__sent", children: [item.sent, " sent"] })] }), _jsxs("div", { className: "trend-item__metrics", children: [_jsxs("div", { className: "metric", children: [_jsx("span", { className: "metric__label", children: "Open Rate:" }), _jsxs("span", { className: "metric__value", children: [item.openRate.toFixed(1), "%"] })] }), _jsxs("div", { className: "metric", children: [_jsx("span", { className: "metric__label", children: "Click Rate:" }), _jsxs("span", { className: "metric__value", children: [item.clickRate.toFixed(1), "%"] })] }), _jsxs("div", { className: "metric", children: [_jsx("span", { className: "metric__label", children: "Bounce Rate:" }), _jsxs("span", { className: "metric__value", children: [item.bounceRate.toFixed(1), "%"] })] })] })] }, index))) })] })), viewType === 'breakdown' && (_jsx("div", { className: "analytics-breakdown", children: _jsx("div", { className: "breakdown-table", children: _jsxs("table", { className: "data-table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "Period" }), _jsx("th", { children: "Sent" }), _jsx("th", { children: "Delivered" }), _jsx("th", { children: "Opened" }), _jsx("th", { children: "Clicked" }), _jsx("th", { children: "Bounced" }), _jsx("th", { children: "Open Rate" }), _jsx("th", { children: "Click Rate" }), _jsx("th", { children: "Bounce Rate" })] }) }), _jsx("tbody", { children: analytics.map((item, index) => (_jsxs("tr", { children: [_jsxs("td", { children: [formatDate(item.period.start), " - ", formatDate(item.period.end)] }), _jsx("td", { children: item.sent.toLocaleString() }), _jsx("td", { children: item.delivered.toLocaleString() }), _jsx("td", { children: item.opened.toLocaleString() }), _jsx("td", { children: item.clicked.toLocaleString() }), _jsx("td", { children: item.bounced.toLocaleString() }), _jsxs("td", { children: [item.openRate.toFixed(2), "%"] }), _jsxs("td", { children: [item.clickRate.toFixed(2), "%"] }), _jsxs("td", { children: [item.bounceRate.toFixed(2), "%"] })] }, index))) })] }) }) }))] }));
};