@defikitdotnet/x-ai-combat
Version:
XCombatAI - Social Media Engagement Template for the Agent Framework
103 lines • 14.3 kB
JavaScript
;
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