import { createCommand } from "@shared/lib/utils"; import { SlashCommandBuilder, MessageFlags } from "discord.js"; import { questService } from "@shared/modules/quest/quest.service"; import { createSuccessEmbed } from "@lib/embeds"; import { getQuestListComponents, getAvailableQuestsComponents, getQuestActionRows } from "@/modules/quest/quest.view"; export const quests = createCommand({ data: new SlashCommandBuilder() .setName("quests") .setDescription("View your active and available quests"), execute: async (interaction) => { const response = await interaction.deferReply({ flags: MessageFlags.Ephemeral }); const userId = interaction.user.id; let currentView: 'active' | 'available' = 'active'; let currentPage = 0; const updateView = async (viewType: 'active' | 'available', page: number = 0) => { currentView = viewType; currentPage = page; const userQuests = await questService.getUserQuests(userId); const availableQuests = await questService.getAvailableQuests(userId); const activeQuests = userQuests.filter(entry => entry.completedAt === null); const totalItems = viewType === 'active' ? activeQuests.length : availableQuests.length; const containers = viewType === 'active' ? getQuestListComponents(userQuests, page) : getAvailableQuestsComponents(availableQuests, page); const actionRows = getQuestActionRows(viewType, totalItems, page); await interaction.editReply({ content: null, embeds: null as any, components: [...containers, ...actionRows] as any, flags: MessageFlags.IsComponentsV2, allowedMentions: { parse: [] } }); }; // Initial view await updateView('active'); const collector = response.createMessageComponentCollector({ time: 120000, // 2 minutes componentType: undefined // Allow buttons }); collector.on('collect', async (i) => { if (i.user.id !== interaction.user.id) return; try { if (i.customId === "quest_view_active") { await i.deferUpdate(); await updateView('active', 0); } else if (i.customId === "quest_view_available") { await i.deferUpdate(); await updateView('available', 0); } else if (i.customId === "quest_page_prev") { await i.deferUpdate(); await updateView(currentView, Math.max(0, currentPage - 1)); } else if (i.customId === "quest_page_next") { await i.deferUpdate(); await updateView(currentView, currentPage + 1); } else if (i.customId.startsWith("quest_accept:")) { const questIdStr = i.customId.split(":")[1]; if (!questIdStr) return; const questId = parseInt(questIdStr); await questService.assignQuest(userId, questId); await i.reply({ embeds: [createSuccessEmbed(`You have accepted a new quest!`, "Quest Accepted")], flags: MessageFlags.Ephemeral }); // Stay on current view/page but refresh (accepted quest disappears from available) await updateView(currentView, currentPage); } } catch (error) { console.error("Quest interaction error:", error); await i.followUp({ content: "Something went wrong while processing your quest interaction.", flags: MessageFlags.Ephemeral }); } }); collector.on('end', () => { interaction.editReply({ components: [] }).catch(() => {}); }); } });