@asgerami/zemenay-blog
Version:
Plug-and-play blog system for Next.js - Get a fully functional blog running in minutes with zero configuration
128 lines (127 loc) • 12.8 kB
JavaScript
;
"use client";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnalyticsDashboard = AnalyticsDashboard;
exports.PostAnalytics = PostAnalytics;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const analytics_1 = require("../lib/analytics");
function AnalyticsDashboard({ className = "", }) {
const [metrics, setMetrics] = (0, react_1.useState)(null);
const [popularPosts, setPopularPosts] = (0, react_1.useState)([]);
const [loading, setLoading] = (0, react_1.useState)(true);
const [error, setError] = (0, react_1.useState)(null);
const [timeframe, setTimeframe] = (0, react_1.useState)("month");
(0, react_1.useEffect)(() => {
loadAnalytics();
}, [timeframe]);
const loadAnalytics = async () => {
setLoading(true);
setError(null);
try {
// Load overall metrics
const metricsResult = await (0, analytics_1.getBlogAnalytics)();
if (metricsResult.success && metricsResult.data) {
setMetrics(metricsResult.data);
}
else {
setError(metricsResult.error || "Failed to load metrics");
}
// Load popular posts
const popularResult = await (0, analytics_1.getPopularPosts)(10, timeframe);
if (popularResult.success && popularResult.data) {
setPopularPosts(popularResult.data);
}
else {
console.error("Failed to load popular posts:", popularResult.error);
}
}
catch (err) {
setError(err instanceof Error ? err.message : "Unknown error");
}
finally {
setLoading(false);
}
};
if (loading) {
return ((0, jsx_runtime_1.jsx)("div", { className: `analytics-dashboard ${className}`, children: (0, jsx_runtime_1.jsxs)("div", { className: "analytics-loading", children: [(0, jsx_runtime_1.jsx)("div", { className: "loading-spinner" }), (0, jsx_runtime_1.jsx)("p", { children: "Loading analytics..." })] }) }));
}
if (error) {
return ((0, jsx_runtime_1.jsx)("div", { className: `analytics-dashboard ${className}`, children: (0, jsx_runtime_1.jsxs)("div", { className: "analytics-error", children: [(0, jsx_runtime_1.jsx)("h3", { children: "Error Loading Analytics" }), (0, jsx_runtime_1.jsx)("p", { children: error }), (0, jsx_runtime_1.jsx)("button", { onClick: loadAnalytics, className: "retry-btn", children: "Try Again" })] }) }));
}
return ((0, jsx_runtime_1.jsxs)("div", { className: `analytics-dashboard ${className}`, children: [(0, jsx_runtime_1.jsxs)("div", { className: "dashboard-header", children: [(0, jsx_runtime_1.jsx)("h2", { children: "\uD83D\uDCCA Blog Analytics" }), (0, jsx_runtime_1.jsxs)("div", { className: "timeframe-selector", children: [(0, jsx_runtime_1.jsx)("label", { children: "Popular Posts Timeframe:" }), (0, jsx_runtime_1.jsxs)("select", { value: timeframe, onChange: (e) => setTimeframe(e.target.value), className: "timeframe-select", children: [(0, jsx_runtime_1.jsx)("option", { value: "day", children: "Last 24 Hours" }), (0, jsx_runtime_1.jsx)("option", { value: "week", children: "Last Week" }), (0, jsx_runtime_1.jsx)("option", { value: "month", children: "Last Month" }), (0, jsx_runtime_1.jsx)("option", { value: "all", children: "All Time" })] })] })] }), metrics && ((0, jsx_runtime_1.jsxs)("div", { className: "metrics-grid", children: [(0, jsx_runtime_1.jsxs)("div", { className: "metric-card", children: [(0, jsx_runtime_1.jsx)("div", { className: "metric-icon", children: "\uD83D\uDCDD" }), (0, jsx_runtime_1.jsxs)("div", { className: "metric-content", children: [(0, jsx_runtime_1.jsx)("h3", { children: "Total Posts" }), (0, jsx_runtime_1.jsx)("div", { className: "metric-value", children: metrics.total_posts.toLocaleString() })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "metric-card", children: [(0, jsx_runtime_1.jsx)("div", { className: "metric-icon", children: "\uD83D\uDC40" }), (0, jsx_runtime_1.jsxs)("div", { className: "metric-content", children: [(0, jsx_runtime_1.jsx)("h3", { children: "Total Views" }), (0, jsx_runtime_1.jsx)("div", { className: "metric-value", children: metrics.total_views.toLocaleString() })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "metric-card", children: [(0, jsx_runtime_1.jsx)("div", { className: "metric-icon", children: "\uD83D\uDC65" }), (0, jsx_runtime_1.jsxs)("div", { className: "metric-content", children: [(0, jsx_runtime_1.jsx)("h3", { children: "Unique Visitors" }), (0, jsx_runtime_1.jsx)("div", { className: "metric-value", children: metrics.unique_visitors.toLocaleString() })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "metric-card", children: [(0, jsx_runtime_1.jsx)("div", { className: "metric-icon", children: "\uD83D\uDCC8" }), (0, jsx_runtime_1.jsxs)("div", { className: "metric-content", children: [(0, jsx_runtime_1.jsx)("h3", { children: "Views (30 Days)" }), (0, jsx_runtime_1.jsx)("div", { className: "metric-value", children: metrics.views_last_30_days.toLocaleString() })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "metric-card", children: [(0, jsx_runtime_1.jsx)("div", { className: "metric-icon", children: "\u2B50" }), (0, jsx_runtime_1.jsxs)("div", { className: "metric-content", children: [(0, jsx_runtime_1.jsx)("h3", { children: "Avg Views/Post" }), (0, jsx_runtime_1.jsx)("div", { className: "metric-value", children: metrics.average_views_per_post.toLocaleString() })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "metric-card", children: [(0, jsx_runtime_1.jsx)("div", { className: "metric-icon", children: "\uD83D\uDD52" }), (0, jsx_runtime_1.jsxs)("div", { className: "metric-content", children: [(0, jsx_runtime_1.jsx)("h3", { children: "Last Updated" }), (0, jsx_runtime_1.jsx)("div", { className: "metric-value metric-date", children: new Date(metrics.last_updated).toLocaleDateString() })] })] })] })), (0, jsx_runtime_1.jsxs)("div", { className: "popular-posts-section", children: [(0, jsx_runtime_1.jsxs)("h3", { children: ["\uD83D\uDD25 Popular Posts (", timeframe === "all" ? "All Time" : `Last ${timeframe}`, ")"] }), popularPosts.length > 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "popular-posts-list", children: popularPosts.map((post, index) => ((0, jsx_runtime_1.jsxs)("div", { className: "popular-post-item", children: [(0, jsx_runtime_1.jsxs)("div", { className: "post-rank", children: ["#", index + 1] }), (0, jsx_runtime_1.jsxs)("div", { className: "post-info", children: [(0, jsx_runtime_1.jsx)("h4", { className: "post-title", children: post.title }), (0, jsx_runtime_1.jsxs)("div", { className: "post-meta", children: [(0, jsx_runtime_1.jsxs)("span", { className: "post-views", children: ["\uD83D\uDC40 ", post.view_count, " views"] }), (0, jsx_runtime_1.jsxs)("span", { className: "post-date", children: ["\uD83D\uDCC5 ", new Date(post.created_at).toLocaleDateString()] })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "post-actions", children: (0, jsx_runtime_1.jsx)("a", { href: `/blog/${post.slug}`, target: "_blank", rel: "noopener noreferrer", className: "view-post-btn", children: "View Post" }) })] }, post.id))) })) : ((0, jsx_runtime_1.jsx)("div", { className: "no-data", children: (0, jsx_runtime_1.jsx)("p", { children: "No popular posts data available for the selected timeframe." }) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "dashboard-footer", children: [(0, jsx_runtime_1.jsxs)("p", { className: "last-updated", children: ["Last updated:", " ", metrics ? new Date(metrics.last_updated).toLocaleString() : "Never"] }), (0, jsx_runtime_1.jsx)("button", { onClick: loadAnalytics, className: "refresh-btn", children: "\uD83D\uDD04 Refresh Data" })] })] }));
}
function PostAnalytics({ postId, className = "" }) {
const [analytics, setAnalytics] = (0, react_1.useState)(null);
const [loading, setLoading] = (0, react_1.useState)(true);
const [error, setError] = (0, react_1.useState)(null);
(0, react_1.useEffect)(() => {
loadPostAnalytics();
}, [postId]);
const loadPostAnalytics = async () => {
setLoading(true);
setError(null);
try {
const { getPostAnalytics } = await Promise.resolve().then(() => __importStar(require("../lib/analytics")));
const result = await getPostAnalytics(postId);
if (result.success && result.data) {
setAnalytics(result.data);
}
else {
setError(result.error || "Failed to load post analytics");
}
}
catch (err) {
setError(err instanceof Error ? err.message : "Unknown error");
}
finally {
setLoading(false);
}
};
if (loading) {
return ((0, jsx_runtime_1.jsx)("div", { className: `post-analytics ${className}`, children: (0, jsx_runtime_1.jsxs)("div", { className: "analytics-loading", children: [(0, jsx_runtime_1.jsx)("div", { className: "loading-spinner" }), (0, jsx_runtime_1.jsx)("p", { children: "Loading post analytics..." })] }) }));
}
if (error) {
return ((0, jsx_runtime_1.jsx)("div", { className: `post-analytics ${className}`, children: (0, jsx_runtime_1.jsx)("div", { className: "analytics-error", children: (0, jsx_runtime_1.jsxs)("p", { children: ["Error: ", error] }) }) }));
}
if (!analytics) {
return ((0, jsx_runtime_1.jsx)("div", { className: `post-analytics ${className}`, children: (0, jsx_runtime_1.jsx)("p", { children: "No analytics data available." }) }));
}
return ((0, jsx_runtime_1.jsxs)("div", { className: `post-analytics ${className}`, children: [(0, jsx_runtime_1.jsx)("h3", { children: "\uD83D\uDCCA Post Analytics" }), (0, jsx_runtime_1.jsxs)("div", { className: "post-metrics-grid", children: [(0, jsx_runtime_1.jsxs)("div", { className: "post-metric", children: [(0, jsx_runtime_1.jsx)("span", { className: "metric-label", children: "Total Views:" }), (0, jsx_runtime_1.jsx)("span", { className: "metric-value", children: analytics.total_views })] }), (0, jsx_runtime_1.jsxs)("div", { className: "post-metric", children: [(0, jsx_runtime_1.jsx)("span", { className: "metric-label", children: "Unique Views:" }), (0, jsx_runtime_1.jsx)("span", { className: "metric-value", children: analytics.unique_views })] }), (0, jsx_runtime_1.jsxs)("div", { className: "post-metric", children: [(0, jsx_runtime_1.jsx)("span", { className: "metric-label", children: "Reading Time:" }), (0, jsx_runtime_1.jsxs)("span", { className: "metric-value", children: [analytics.reading_time, " min"] })] })] }), Object.keys(analytics.referrers).length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "referrers-section", children: [(0, jsx_runtime_1.jsx)("h4", { children: "\uD83D\uDD17 Top Referrers" }), (0, jsx_runtime_1.jsx)("div", { className: "referrers-list", children: Object.entries(analytics.referrers)
.sort(([, a], [, b]) => b - a)
.slice(0, 5)
.map(([referrer, count]) => ((0, jsx_runtime_1.jsxs)("div", { className: "referrer-item", children: [(0, jsx_runtime_1.jsx)("span", { className: "referrer-name", children: referrer === "direct" ? "🔗 Direct" : `🌐 ${referrer}` }), (0, jsx_runtime_1.jsxs)("span", { className: "referrer-count", children: [count, " views"] })] }, referrer))) })] }))] }));
}