Refactor el comando 'items-lista' para mejorar la gestión de paginación y la estructura del mensaje, añadiendo botones de navegación y optimizando la construcción del payload.

This commit is contained in:
Shni
2025-10-14 15:04:23 -05:00
parent 852b1d02a2
commit b49447e2bd

View File

@@ -1,130 +1,146 @@
import type { CommandMessage } from '../../../core/types/commands'; import type { CommandMessage } from "../../../core/types/commands";
import type Amayo from '../../../core/client'; import type Amayo from "../../../core/client";
import { prisma } from '../../../core/database/prisma'; import { prisma } from "../../../core/database/prisma";
import { ComponentType, ButtonStyle } from 'discord-api-types/v10'; import { ComponentType, ButtonStyle } from "discord-api-types/v10";
import type { MessageComponentInteraction, TextBasedChannel } from 'discord.js'; import type { MessageComponentInteraction, TextBasedChannel } from "discord.js";
import { buildDisplay, dividerBlock, textBlock } from '../../../core/lib/componentsV2'; import {
buildDisplay,
dividerBlock,
textBlock,
} from "../../../core/lib/componentsV2";
export const command: CommandMessage = { export const command: CommandMessage = {
name: 'items-lista', name: "items-lista",
type: 'message', type: "message",
aliases: ['lista-items', 'items-list'], aliases: ["lista-items", "items-list"],
cooldown: 5, cooldown: 5,
description: 'Ver lista de todos los items del servidor', description: "Ver lista de todos los items del servidor",
usage: 'items-lista [pagina]', usage: "items-lista [pagina]",
run: async (message, args, client: Amayo) => { run: async (message, args, client: Amayo) => {
const guildId = message.guild!.id; const guildId = message.guild!.id;
const page = parseInt(args[0]) || 1;
const perPage = 8; const perPage = 8;
const total = await prisma.economyItem.count({ async function buildPayload(page: number) {
where: { OR: [{ guildId }, { guildId: null }] } const total = await prisma.economyItem.count({
}); where: { OR: [{ guildId }, { guildId: null }] },
});
const items = await prisma.economyItem.findMany({
where: { OR: [{ guildId }, { guildId: null }] },
orderBy: [{ category: "asc" }, { name: "asc" }],
skip: (page - 1) * perPage,
take: perPage,
});
const items = await prisma.economyItem.findMany({ const totalPages = Math.max(1, Math.ceil(total / perPage));
where: { OR: [{ guildId }, { guildId: null }] },
orderBy: [{ category: 'asc' }, { name: 'asc' }],
skip: (page - 1) * perPage,
take: perPage
});
if (items.length === 0) { const displayBlocks = [
await message.reply('No hay items configurados en este servidor.'); textBlock(`# 🛠️ Lista de Items`),
dividerBlock(),
textBlock(`Página ${page}/${totalPages} • Total: ${total}`),
dividerBlock({ divider: false, spacing: 2 }),
...items.flatMap((item, index) => {
const lines = [
`**${item.name || item.key}**`,
`└ Key: \`${item.key}\``,
`└ Categoría: ${item.category || "*Sin categoría*"}`,
`${item.stackable ? "📚 Apilable" : "🔒 No apilable"}${
item.maxPerInventory ? ` (Máx: ${item.maxPerInventory})` : ""
}${item.guildId === guildId ? " • 📍 Local" : " • 🌐 Global"}`,
].join("\n");
const blocks = [textBlock(lines)];
if (index < items.length - 1) {
blocks.push(dividerBlock({ divider: false, spacing: 1 }));
}
return blocks;
}),
];
const display = buildDisplay(0x00d9ff, displayBlocks);
const buttons: any[] = [];
if (page > 1) {
buttons.push({
type: ComponentType.Button,
style: ButtonStyle.Secondary,
label: "◀ Anterior",
custom_id: `items_prev_${page}`,
});
}
if (page < totalPages) {
buttons.push({
type: ComponentType.Button,
style: ButtonStyle.Secondary,
label: "Siguiente ▶",
custom_id: `items_next_${page}`,
});
}
buttons.push({
type: ComponentType.Button,
style: ButtonStyle.Primary,
label: "Ver Detalle",
custom_id: "items_detail",
});
const components: any[] = [display];
if (buttons.length > 0)
components.push({ type: ComponentType.ActionRow, components: buttons });
return { components, total, totalPages };
}
const page = parseInt(args[0]) || 1;
const channel = message.channel as TextBasedChannel & { send: Function };
const initial = await buildPayload(page);
if (initial.total === 0) {
await message.reply("No hay items configurados en este servidor.");
return; return;
} }
const totalPages = Math.ceil(total / perPage);
const displayBlocks = [
textBlock(`# 🛠️ Lista de Items`),
dividerBlock(),
textBlock(`Página ${page}/${totalPages} • Total: ${total}`),
dividerBlock({ divider: false, spacing: 2 }),
...items.flatMap((item, index) => {
const lines = [
`**${item.name || item.key}**`,
`└ Key: \`${item.key}\``,
`└ Categoría: ${item.category || '*Sin categoría*'}`,
`${item.stackable ? '📚 Apilable' : '🔒 No apilable'}${item.maxPerInventory ? ` (Máx: ${item.maxPerInventory})` : ''}${item.guildId === guildId ? ' • 📍 Local' : ' • 🌐 Global'}`,
].join('\n');
const blocks = [textBlock(lines)];
if (index < items.length - 1) {
blocks.push(dividerBlock({ divider: false, spacing: 1 }));
}
return blocks;
})
];
const display = buildDisplay(0x00D9FF, displayBlocks);
const buttons: any[] = [];
if (page > 1) {
buttons.push({
type: ComponentType.Button,
style: ButtonStyle.Secondary,
label: '◀ Anterior',
custom_id: `items_prev_${page}`
});
}
if (page < totalPages) {
buttons.push({
type: ComponentType.Button,
style: ButtonStyle.Secondary,
label: 'Siguiente ▶',
custom_id: `items_next_${page}`
});
}
buttons.push({
type: ComponentType.Button,
style: ButtonStyle.Primary,
label: 'Ver Detalle',
custom_id: 'items_detail'
});
const channel = message.channel as TextBasedChannel & { send: Function };
const msg = await (channel.send as any)({ const msg = await (channel.send as any)({
content: null, content: null,
flags: 32768, flags: 32768,
reply: { messageReference: message.id }, reply: { messageReference: message.id },
components: [ components: initial.components,
display,
...(buttons.length > 0 ? [{
type: ComponentType.ActionRow,
components: buttons
}] : [])
]
}); });
const collector = msg.createMessageComponentCollector({ let collector = msg.createMessageComponentCollector({
time: 5 * 60_000, time: 5 * 60_000,
filter: (i) => i.user.id === message.author.id filter: (i) => i.user.id === message.author.id,
}); });
collector.on('collect', async (i: MessageComponentInteraction) => { collector.on("collect", async (i: MessageComponentInteraction) => {
if (!i.isButton()) return; if (!i.isButton()) return;
if (i.customId.startsWith('items_prev_')) { if (
const currentPage = parseInt(i.customId.split('_')[2]); i.customId.startsWith("items_prev_") ||
i.customId.startsWith("items_next_")
) {
const parts = i.customId.split("_");
const currentPage = parseInt(parts[2]);
const newPage = i.customId.startsWith("items_prev_")
? currentPage - 1
: currentPage + 1;
await i.deferUpdate(); await i.deferUpdate();
args[0] = String(currentPage - 1); // rebuild payload and edit message
await command.run!(message, args, client); try {
collector.stop(); const p = await buildPayload(newPage);
} else if (i.customId.startsWith('items_next_')) { await msg.edit({ content: null, components: p.components });
const currentPage = parseInt(i.customId.split('_')[2]); } catch (e) {
await i.deferUpdate(); await i.followUp({
args[0] = String(currentPage + 1); content: `❌ Error actualizando página: ${(e as any).message || e}`,
await command.run!(message, args, client); flags: 64,
collector.stop(); });
} else if (i.customId === 'items_detail') { }
return;
}
if (i.customId === "items_detail") {
await i.reply({ await i.reply({
content: '💡 Usa `!item-ver <key>` para ver detalles de un item específico.', content:
flags: 64 "💡 Usa `!item-ver <key>` para ver detalles de un item específico.",
flags: 64,
}); });
} }
}); });
} },
}; };