diff --git a/src/commands/leveling/leaderboard.ts b/src/commands/leveling/leaderboard.ts index 29ca91f..bfda294 100644 --- a/src/commands/leveling/leaderboard.ts +++ b/src/commands/leveling/leaderboard.ts @@ -3,7 +3,8 @@ import { SlashCommandBuilder } from "discord.js"; import { DrizzleClient } from "@/lib/DrizzleClient"; import { users } from "@/db/schema"; import { desc } from "drizzle-orm"; -import { createWarningEmbed, createBaseEmbed } from "@lib/embeds"; +import { createWarningEmbed } from "@lib/embeds"; +import { getLeaderboardEmbed } from "@/modules/leveling/leveling.view"; export const leaderboard = createCommand({ data: new SlashCommandBuilder() @@ -34,13 +35,7 @@ export const leaderboard = createCommand({ return; } - const description = leaders.map((user, index) => { - const medal = index === 0 ? "🥇" : index === 1 ? "🥈" : index === 2 ? "🥉" : `${index + 1}.`; - const value = isXp ? `Lvl ${user.level} (${user.xp} XP)` : `${user.balance} 🪙`; - return `${medal} **${user.username}** — ${value}`; - }).join("\n"); - - const embed = createBaseEmbed(isXp ? "🏆 XP Leaderboard" : "💰 Richest Players", description, "Gold"); + const embed = getLeaderboardEmbed(leaders, isXp ? 'xp' : 'balance'); await interaction.editReply({ embeds: [embed] }); } diff --git a/src/modules/leveling/leveling.view.ts b/src/modules/leveling/leveling.view.ts new file mode 100644 index 0000000..5140f35 --- /dev/null +++ b/src/modules/leveling/leveling.view.ts @@ -0,0 +1,48 @@ +import { EmbedBuilder } from "discord.js"; + +/** + * User data for leaderboard display + */ +interface LeaderboardUser { + username: string; + level: number | null; + xp: bigint | null; + balance: bigint | null; +} + +/** + * Returns the appropriate medal emoji for a ranking position + */ +function getMedalEmoji(index: number): string { + if (index === 0) return "🥇"; + if (index === 1) return "🥈"; + if (index === 2) return "🥉"; + return `${index + 1}.`; +} + +/** + * Formats a single leaderboard entry based on type + */ +function formatLeaderEntry(user: LeaderboardUser, index: number, type: 'xp' | 'balance'): string { + const medal = getMedalEmoji(index); + const value = type === 'xp' + ? `Lvl ${user.level ?? 1} (${user.xp ?? 0n} XP)` + : `${user.balance ?? 0n} 🪙`; + return `${medal} **${user.username}** — ${value}`; +} + +/** + * Creates a leaderboard embed for either XP or Balance rankings + */ +export function getLeaderboardEmbed(leaders: LeaderboardUser[], type: 'xp' | 'balance'): EmbedBuilder { + const description = leaders.map((user, index) => + formatLeaderEntry(user, index, type) + ).join("\n"); + + const title = type === 'xp' ? "🏆 XP Leaderboard" : "💰 Richest Players"; + + return new EmbedBuilder() + .setTitle(title) + .setDescription(description) + .setColor(0xFFD700); // Gold +}