fix: add pagination to quest list to stay within Discord component limits
All checks were successful
Deploy to Production / test (push) Successful in 45s

The available quests view was exceeding Discord's 40-component container
limit when many quests existed, causing an API error. Paginate both
active and available quest views at 7 quests per page with prev/next
navigation buttons.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
syntaxbullet
2026-03-28 14:20:53 +01:00
parent 0f871026eb
commit e56e133a69
2 changed files with 72 additions and 23 deletions

View File

@@ -16,16 +16,24 @@ export const quests = createCommand({
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 updateView = async (viewType: 'active' | 'available') => {
const userQuests = await questService.getUserQuests(userId);
const availableQuests = await questService.getAvailableQuests(userId);
const containers = viewType === 'active'
? getQuestListComponents(userQuests)
: getAvailableQuestsComponents(availableQuests);
const activeQuests = userQuests.filter(entry => entry.completedAt === null);
const totalItems = viewType === 'active' ? activeQuests.length : availableQuests.length;
const actionRows = getQuestActionRows(viewType);
const containers = viewType === 'active'
? getQuestListComponents(userQuests, page)
: getAvailableQuestsComponents(availableQuests, page);
const actionRows = getQuestActionRows(viewType, totalItems, page);
await interaction.editReply({
content: null,
@@ -50,10 +58,16 @@ export const quests = createCommand({
try {
if (i.customId === "quest_view_active") {
await i.deferUpdate();
await updateView('active');
await updateView('active', 0);
} else if (i.customId === "quest_view_available") {
await i.deferUpdate();
await updateView('available');
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;
@@ -65,7 +79,8 @@ export const quests = createCommand({
flags: MessageFlags.Ephemeral
});
await updateView('active');
// Stay on current view/page but refresh (accepted quest disappears from available)
await updateView(currentView, currentPage);
}
} catch (error) {
console.error("Quest interaction error:", error);