forked from syntaxbullet/AuroraBot-discord
refactor: extract further UI components into views
This commit is contained in:
@@ -14,6 +14,7 @@ import { UserError } from "@/lib/errors";
|
|||||||
import { items } from "@/db/schema";
|
import { items } from "@/db/schema";
|
||||||
import { ilike, isNotNull, and } from "drizzle-orm";
|
import { ilike, isNotNull, and } from "drizzle-orm";
|
||||||
import { DrizzleClient } from "@/lib/DrizzleClient";
|
import { DrizzleClient } from "@/lib/DrizzleClient";
|
||||||
|
import { getShopListingMessage } from "@/modules/economy/shop.view";
|
||||||
|
|
||||||
export const listing = createCommand({
|
export const listing = createCommand({
|
||||||
data: new SlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
@@ -53,22 +54,14 @@ export const listing = createCommand({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const embed = createBaseEmbed(`Shop: ${item.name}`, item.description || "No description available.", "Green")
|
const listingMessage = getShopListingMessage({
|
||||||
.addFields({ name: "Price", value: `${item.price} 🪙`, inline: true })
|
...item,
|
||||||
.setThumbnail(item.iconUrl || null)
|
formattedPrice: `${item.price} 🪙`,
|
||||||
.setImage(item.imageUrl || null)
|
price: item.price
|
||||||
.setFooter({ text: "Click the button below to purchase instantly." });
|
});
|
||||||
|
|
||||||
const buyButton = new ButtonBuilder()
|
|
||||||
.setCustomId(`shop_buy_${item.id}`)
|
|
||||||
.setLabel(`Buy for ${item.price} 🪙`)
|
|
||||||
.setStyle(ButtonStyle.Success)
|
|
||||||
.setEmoji("🛒");
|
|
||||||
|
|
||||||
const actionRow = new ActionRowBuilder<ButtonBuilder>().addComponents(buyButton);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await targetChannel.send({ embeds: [embed], components: [actionRow] });
|
await targetChannel.send(listingMessage);
|
||||||
await interaction.editReply({ content: `✅ Listing for **${item.name}** posted in ${targetChannel}.` });
|
await interaction.editReply({ content: `✅ Listing for **${item.name}** posted in ${targetChannel}.` });
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (error instanceof UserError) {
|
if (error instanceof UserError) {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { createCommand } from "@/lib/utils";
|
import { createCommand } from "@/lib/utils";
|
||||||
import { SlashCommandBuilder, ChannelType, ActionRowBuilder, ButtonBuilder, ButtonStyle, ThreadAutoArchiveDuration, MessageFlags } from "discord.js";
|
import { SlashCommandBuilder, ChannelType, ThreadAutoArchiveDuration, MessageFlags } from "discord.js";
|
||||||
import { TradeService } from "@/modules/trade/trade.service";
|
import { TradeService } from "@/modules/trade/trade.service";
|
||||||
import { createErrorEmbed, createWarningEmbed, createBaseEmbed } from "@lib/embeds";
|
import { getTradeDashboard } from "@/modules/trade/trade.view";
|
||||||
|
import { createErrorEmbed, createWarningEmbed } from "@lib/embeds";
|
||||||
|
|
||||||
export const trade = createCommand({
|
export const trade = createCommand({
|
||||||
data: new SlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
@@ -58,29 +59,15 @@ export const trade = createCommand({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup Session
|
// Setup Session
|
||||||
TradeService.createSession(thread.id,
|
const session = TradeService.createSession(thread.id,
|
||||||
{ id: interaction.user.id, username: interaction.user.username },
|
{ id: interaction.user.id, username: interaction.user.username },
|
||||||
{ id: targetUser.id, username: targetUser.username }
|
{ id: targetUser.id, username: targetUser.username }
|
||||||
);
|
);
|
||||||
|
|
||||||
// Send Dashboard to Thread
|
// Send Dashboard to Thread
|
||||||
const embed = createBaseEmbed("🤝 Trading Session", `Trade started between ${interaction.user} and ${targetUser}.\nUse the controls below to build your offer.`, 0xFFD700)
|
const dashboard = getTradeDashboard(session);
|
||||||
.addFields(
|
|
||||||
{ name: interaction.user.username, value: "*Empty Offer*", inline: true },
|
|
||||||
{ name: targetUser.username, value: "*Empty Offer*", inline: true }
|
|
||||||
)
|
|
||||||
.setFooter({ text: "Both parties must click Lock to confirm trade." });
|
|
||||||
|
|
||||||
const row = new ActionRowBuilder<ButtonBuilder>()
|
await thread.send({ content: `${interaction.user} ${targetUser} Welcome to your trading session!`, ...dashboard });
|
||||||
.addComponents(
|
|
||||||
new ButtonBuilder().setCustomId('trade_add_item').setLabel('Add Item').setStyle(ButtonStyle.Secondary),
|
|
||||||
new ButtonBuilder().setCustomId('trade_add_money').setLabel('Add Money').setStyle(ButtonStyle.Success),
|
|
||||||
new ButtonBuilder().setCustomId('trade_remove_item').setLabel('Remove Item').setStyle(ButtonStyle.Secondary),
|
|
||||||
new ButtonBuilder().setCustomId('trade_lock').setLabel('Lock / Unlock').setStyle(ButtonStyle.Primary),
|
|
||||||
new ButtonBuilder().setCustomId('trade_cancel').setLabel('Cancel').setStyle(ButtonStyle.Danger),
|
|
||||||
);
|
|
||||||
|
|
||||||
await thread.send({ content: `${interaction.user} ${targetUser} Welcome to your trading session!`, embeds: [embed], components: [row] });
|
|
||||||
|
|
||||||
// Update original reply
|
// Update original reply
|
||||||
await interaction.editReply({ content: `✅ Trade opened: <#${thread.id}>` });
|
await interaction.editReply({ content: `✅ Trade opened: <#${thread.id}>` });
|
||||||
|
|||||||
20
src/modules/economy/shop.view.ts
Normal file
20
src/modules/economy/shop.view.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js";
|
||||||
|
import { createBaseEmbed } from "@/lib/embeds";
|
||||||
|
|
||||||
|
export function getShopListingMessage(item: { id: number; name: string; description: string | null; formattedPrice: string; iconUrl: string | null; imageUrl: string | null; price: number | bigint }) {
|
||||||
|
const embed = createBaseEmbed(`Shop: ${item.name}`, item.description || "No description available.", "Green")
|
||||||
|
.addFields({ name: "Price", value: item.formattedPrice, inline: true })
|
||||||
|
.setThumbnail(item.iconUrl || null)
|
||||||
|
.setImage(item.imageUrl || null)
|
||||||
|
.setFooter({ text: "Click the button below to purchase instantly." });
|
||||||
|
|
||||||
|
const buyButton = new ButtonBuilder()
|
||||||
|
.setCustomId(`shop_buy_${item.id}`)
|
||||||
|
.setLabel(`Buy for ${item.price} 🪙`)
|
||||||
|
.setStyle(ButtonStyle.Success)
|
||||||
|
.setEmoji("🛒");
|
||||||
|
|
||||||
|
const row = new ActionRowBuilder<ButtonBuilder>().addComponents(buyButton);
|
||||||
|
|
||||||
|
return { embeds: [embed], components: [row] };
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user