UNPKG

@defikitdotnet/x-ai-combat

Version:

XCombatAI - Social Media Engagement Template for the Agent Framework

103 lines 14.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); /** * LeaderboardPanel component * * Displays a leaderboard of users based on Fame Points */ const LeaderboardPanel = ({ agentId, limit = 10, showHeader = true, skipTopThree = false, initialPeriod = 'all', initialShowExplanation = false }) => { const [leaderboard, setLeaderboard] = (0, react_1.useState)([]); const [loading, setLoading] = (0, react_1.useState)(true); const [error, setError] = (0, react_1.useState)(null); const [totalUsers, setTotalUsers] = (0, react_1.useState)(0); const [lastUpdated, setLastUpdated] = (0, react_1.useState)(''); const [showExplanation, setShowExplanation] = (0, react_1.useState)(initialShowExplanation); const [periodLabel, setPeriodLabel] = (0, react_1.useState)('All time'); const [selectedPeriod, setSelectedPeriod] = (0, react_1.useState)(initialPeriod); console.log('limit', limit); console.log('skipTopThree', skipTopThree); console.log('initialPeriod', initialPeriod); console.log('selectedPeriod', selectedPeriod); console.log('initialShowExplanation', initialShowExplanation); const periodOptions = [ { id: 'current_day', label: 'Today' }, { id: 'current_week', label: 'This week' }, { id: 'current_month', label: 'This month' }, { id: 'all', label: 'All time' } ]; // useEffect(() => { // const fetchLeaderboard = async () => { // try { // const backendUrl = process.env.NEXT_PUBLIC_BACKEND_URL || 'http://localhost:3005'; // setLoading(true); // const response = await fetch(`${backendUrl}/xaicombat/api/interactions/leaderboard?limit=${skipTopThree ? limit + 3 : limit}&period=${selectedPeriod}&agentId=${agentId}`, { // credentials: 'include' // Include cookies for JWT authentication // }); // if (!response.ok) { // throw new Error('Failed to fetch leaderboard'); // } // const responseData = await response.json() as LeaderboardResponse; // // If skipTopThree is true, filter out the top 3 users // const filteredData = skipTopThree // ? responseData.data.filter(entry => entry.rank > 3) // : responseData.data; // setLeaderboard(filteredData); // setTotalUsers(responseData.totalUsers); // setLastUpdated(responseData.lastUpdated); // setPeriodLabel(responseData.periodLabel || periodOptions.find(p => p.id === selectedPeriod)?.label || 'All time'); // } catch (err) { // setError((err as Error).message); // console.error('Error fetching leaderboard:', err); // } finally { // setLoading(false); // } // }; // fetchLeaderboard(); // }, [limit, skipTopThree, selectedPeriod, initialPeriod]); // useEffect(() => { // setShowExplanation(initialShowExplanation); // }, [initialShowExplanation]); const handlePeriodChange = (period) => { setSelectedPeriod(period); }; // Get avatar size based on rank const getAvatarSize = (rank) => { if (rank === 1) return "h-14 w-14"; if (rank === 2) return "h-12 w-12"; if (rank === 3) return "h-12 w-12"; return "h-10 w-10"; }; // Get border style based on rank const getAvatarBorder = (rank) => { if (rank === 1) return "border-2 border-brand-400"; if (rank === 2) return "border-2 border-gray-300"; if (rank === 3) return "border-2 border-brand-700"; return "border border-gray-200 dark:border-gray-700"; }; // Get background style based on rank const getRowBackground = (rank) => { if (rank === 1) return "bg-brand-50 dark:bg-brand-900/20 border border-brand-100 dark:border-brand-800"; if (rank === 2) return "bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700"; if (rank === 3) return "bg-brand-50 dark:bg-brand-900/10 border border-brand-100 dark:border-brand-800"; return "bg-background dark:bg-foreground border border-gray-100 dark:border-gray-800"; }; return ((0, jsx_runtime_1.jsx)("div", { className: "relative", children: (0, jsx_runtime_1.jsxs)("div", { className: `${showHeader ? 'bg-background dark:bg-foreground rounded-lg shadow-md' : ''} w-full`, children: [showHeader && ((0, jsx_runtime_1.jsxs)("div", { className: "bg-brand-400 dark:bg-brand-500 text-text-dark p-4 rounded-t-lg", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex justify-between items-center", children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-xl font-semibold", children: "Fame Points Leaderboard" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setShowExplanation(!showExplanation), className: "bg-text-dark/20 hover:bg-text-dark/30 text-text-dark px-2 py-1 rounded-full text-xs transition duration-200", children: showExplanation ? 'Hide' : '?' })] }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-text-dark/80 mt-1", children: totalUsers > 0 ? `Top ${leaderboard.length} of ${totalUsers} users` : 'Fame points rankings' })] })), showExplanation && ((0, jsx_runtime_1.jsx)("div", { className: "bg-brand-50 dark:bg-brand-900/50 p-4 border-b border-brand-100 dark:border-brand-800", children: (0, jsx_runtime_1.jsxs)("div", { className: "max-h-[300px] overflow-y-auto pr-2", children: [(0, jsx_runtime_1.jsx)("h3", { className: "font-semibold text-brand-800 dark:text-brand-200 text-lg mb-2", children: "Fame Points Scoring System" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-brand-700 dark:text-brand-300 mb-3", children: "Fame Points are calculated based on interactions your posts receive when you tag our bot on X/Twitter." }), (0, jsx_runtime_1.jsxs)("div", { className: "mb-3", children: [(0, jsx_runtime_1.jsx)("h4", { className: "font-medium text-brand-800 dark:text-brand-200 mb-2", children: "How it works:" }), (0, jsx_runtime_1.jsxs)("ol", { className: "list-decimal pl-5 mb-3 space-y-1 text-sm text-brand-700 dark:text-brand-300", children: [(0, jsx_runtime_1.jsx)("li", { children: "Tag our bot in your X/Twitter posts" }), (0, jsx_runtime_1.jsx)("li", { children: "Our system tracks all interactions those posts receive" }), (0, jsx_runtime_1.jsx)("li", { children: "Each type of interaction awards different point values" }), (0, jsx_runtime_1.jsx)("li", { children: "Points accumulate to determine your rank on the leaderboard" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-2 gap-2 mb-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center bg-white dark:bg-foreground p-2 rounded border border-brand-100 dark:border-brand-800", children: [(0, jsx_runtime_1.jsx)("span", { role: "img", "aria-label": "Like", className: "text-lg mr-2", children: "\u2764\uFE0F" }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium text-sm text-brand-800 dark:text-brand-200", children: "0.5 points" }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-brand-600 dark:text-brand-400", children: "per like" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center bg-white dark:bg-foreground p-2 rounded border border-brand-100 dark:border-brand-800", children: [(0, jsx_runtime_1.jsx)("span", { role: "img", "aria-label": "Retweet", className: "text-lg mr-2", children: "\uD83D\uDD04" }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium text-sm text-brand-800 dark:text-brand-200", children: "2 points" }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-brand-600 dark:text-brand-400", children: "per retweet" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center bg-white dark:bg-foreground p-2 rounded border border-brand-100 dark:border-brand-800", children: [(0, jsx_runtime_1.jsx)("span", { role: "img", "aria-label": "Quote", className: "text-lg mr-2", children: "\uD83D\uDCAC" }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium text-sm text-brand-800 dark:text-brand-200", children: "2 points" }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-brand-600 dark:text-brand-400", children: "per quote" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center bg-white dark:bg-foreground p-2 rounded border border-brand-100 dark:border-brand-800", children: [(0, jsx_runtime_1.jsx)("span", { role: "img", "aria-label": "Reply", className: "text-lg mr-2", children: "\u21A9\uFE0F" }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium text-sm text-brand-800 dark:text-brand-200", children: "1 point" }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-brand-600 dark:text-brand-400", children: "per reply" })] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-white dark:bg-foreground p-3 rounded border border-brand-100 dark:border-brand-800 text-sm", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-medium text-brand-800 dark:text-brand-200 mb-1", children: "Example: Post with 10 likes, 5 retweets, 2 quotes, 8 replies" }), (0, jsx_runtime_1.jsxs)("div", { className: "grid grid-cols-4 gap-1 text-xs", children: [(0, jsx_runtime_1.jsx)("div", { children: "10\u00D70.5 = 5" }), (0, jsx_runtime_1.jsx)("div", { children: "5\u00D72 = 10" }), (0, jsx_runtime_1.jsx)("div", { children: "2\u00D72 = 4" }), (0, jsx_runtime_1.jsx)("div", { children: "8\u00D71 = 8" })] }), (0, jsx_runtime_1.jsx)("div", { className: "mt-1 pt-1 border-t text-right font-medium text-brand-800 dark:text-brand-200", children: "Total: 27 points" })] })] }) })), (0, jsx_runtime_1.jsxs)("div", { className: `${showHeader ? 'px-4 pt-4' : 'mb-4'}`, children: [(0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap gap-2 mb-4", children: periodOptions.map((option) => ((0, jsx_runtime_1.jsx)("button", { onClick: () => handlePeriodChange(option.id), className: `px-3 py-1 rounded-full text-xs font-medium transition-colors ${selectedPeriod === option.id ? 'bg-brand-600 dark:bg-brand-600 text-text-dark' : 'bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700'}`, children: option.label }, option.id))) }), (0, jsx_runtime_1.jsxs)("div", { className: "text-sm text-gray-500 dark:text-gray-400 font-medium mb-2", children: [periodLabel, " Rankings"] })] }), (0, jsx_runtime_1.jsx)("div", { className: showHeader ? 'p-4 pt-2' : '', children: loading ? ((0, jsx_runtime_1.jsx)("div", { className: "flex justify-center p-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "animate-pulse space-y-3 w-full", children: [(0, jsx_runtime_1.jsx)("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-3/4" }), (0, jsx_runtime_1.jsx)("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-1/2" }), (0, jsx_runtime_1.jsx)("div", { className: "h-4 bg-gray-200 dark:bg-gray-700 rounded w-2/3" })] }) })) : error ? ((0, jsx_runtime_1.jsxs)("div", { className: "text-red-500 dark:text-red-400 p-4", children: ["Error: ", error] })) : leaderboard.length === 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "text-gray-500 dark:text-gray-400 p-4 text-center", children: "No leaderboard data available for this time period." })) : ((0, jsx_runtime_1.jsx)("div", { className: "space-y-3", children: leaderboard.map((entry) => ((0, jsx_runtime_1.jsxs)("div", { className: `flex items-center justify-between p-3 rounded-lg ${getRowBackground(entry.rank)}`, children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-8 h-8 flex items-center justify-center mr-2", children: (0, jsx_runtime_1.jsx)("span", { className: `font-bold text-lg ${entry.rank <= 3 ? 'text-brand-500 dark:text-brand-400' : 'text-gray-600 dark:text-gray-400'}`, children: entry.rank }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center", children: [(0, jsx_runtime_1.jsx)("div", { className: `rounded-full overflow-hidden flex-shrink-0 ${getAvatarSize(entry.rank)} ${getAvatarBorder(entry.rank)} bg-gray-200 dark:bg-gray-700 flex items-center justify-center`, children: (0, jsx_runtime_1.jsx)("img", { src: `https://unavatar.io/twitter/${entry.username}`, alt: `@${entry.username}`, className: "h-full w-full object-cover", onError: (e) => { const target = e.target; target.src = `https://ui-avatars.com/api/?name=${entry.username}&background=random`; } }) }), (0, jsx_runtime_1.jsxs)("div", { className: "ml-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: "font-medium text-gray-900 dark:text-gray-100", children: ["@", entry.username] }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-gray-500 dark:text-gray-400", children: entry.lastActive ? `Active ${new Date(entry.lastActive).toLocaleDateString()}` : 'Recently active' })] })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "text-right", children: [(0, jsx_runtime_1.jsx)("div", { className: "font-bold text-brand-500 dark:text-brand-400", children: entry.famePoints.toFixed(1) }), (0, jsx_runtime_1.jsx)("div", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Fame Points" })] })] }, entry.userId))) })) }), lastUpdated && !loading && !error && leaderboard.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "text-xs text-gray-400 dark:text-gray-500 text-right mt-4 pr-2 pb-2", children: ["Updated: ", new Date(lastUpdated).toLocaleString()] }))] }) })); }; exports.default = LeaderboardPanel; //# sourceMappingURL=LeaderboardPanel.js.map