feat: mejorar la presentación de precios y agregar iconos personalizados en la tienda

This commit is contained in:
2025-10-08 22:24:44 -05:00
parent 063b61bca2
commit 0b7f27d552

View File

@@ -8,6 +8,7 @@ import {
ButtonStyle, ButtonStyle,
MessageFlags, MessageFlags,
StringSelectMenuInteraction, StringSelectMenuInteraction,
email,
} from "discord.js"; } from "discord.js";
import { prisma } from "../../../core/database/prisma"; import { prisma } from "../../../core/database/prisma";
import { getOrCreateWallet, buyFromOffer } from "../../../game/economy/service"; import { getOrCreateWallet, buyFromOffer } from "../../../game/economy/service";
@@ -24,33 +25,34 @@ function parseItemProps(json: unknown): ItemProps {
function formatPrice(price: any): string { function formatPrice(price: any): string {
const parts: string[] = []; const parts: string[] = [];
if (price.coins) parts.push(`💰 ${price.coins}`); if (price.coins) parts.push(`<:coin:1425667511013081169> ${price.coins}`);
if (price.items && price.items.length > 0) { if (price.items && price.items.length > 0) {
for (const item of price.items) { for (const item of price.items) {
parts.push(`📦 ${item.itemKey} x${item.qty}`); parts.push(`📦 ${item.itemKey} x${item.qty}`);
} }
} }
return parts.join(" + ") || "¿Gratis?"; return parts.join(" + ") || "<:free:1425681948172357732>";
} }
function getItemIcon(props: ItemProps, category?: string): string { function getItemIcon(props: ItemProps, category?: string): string {
if (props.tool) { if (props.tool) {
const t = props.tool.type; const t = props.tool.type;
if (t === "pickaxe") return "⛏️"; if (t === "pickaxe") return "<:pickaxe_default:1424589544585695398>";
if (t === "rod") return "🎣"; if (t === "rod") return "<:rod:1425680136912633866>";
if (t === "sword") return "🗡️"; if (t === "sword") return "<:27621stonesword:1424591948102107167>";
if (t === "bow") return "🏹"; if (t === "bow") return "<:bow:1425680803756511232>";
if (t === "halberd") return "⚔️"; if (t === "halberd") return "<:hgard:1425681197316571217>";
if (t === "net") return "🕸️"; if (t === "net") return "<:net:1425681511788576839>";
return "🔧"; return "<:table:1425673712312782879>";
} }
if (props.damage && props.damage > 0) return "⚔️"; if (props.damage && props.damage > 0) return "<:damage:1425670476449189998>";
if (props.defense && props.defense > 0) return "🛡️"; if (props.defense && props.defense > 0)
if (props.food) return "🍖"; return "<:defens:1425670433910427862>";
if (props.chest) return "📦"; if (props.food) return "<:clipmushroom:1425679121954115704>";
if (props.chest) return "<:legendchest:1425679137565179914>";
if (category === "consumables") return "🧪"; if (category === "consumables") return "🧪";
if (category === "materials") return "🔨"; if (category === "materials") return "🔨";
return "📦"; return "<:emptybox:1425678700753588305>";
} }
export const command: CommandMessage = { export const command: CommandMessage = {
@@ -201,7 +203,7 @@ async function buildShopPanel(
components: [ components: [
{ {
type: 10, type: 10,
content: `# <a:seven:1425666197466255481> Tienda - Ofertas Disponibles`, content: `### <a:seven:1425666197466255481> Tienda - Ofertas Disponibles`,
}, },
{ {
type: 10, type: 10,
@@ -257,8 +259,8 @@ async function buildShopPanel(
container.components.push({ container.components.push({
type: 10, type: 10,
content: `${label}\n\n${ content: `${label}\n\n${
item.description || "Sin descripción" item.description || undefined
}${statsInfo}\n\n<:price:1425673879094820906> Precio: ${price}${stockInfo}`, }${statsInfo}\n\nPrecio: ${price}${stockInfo}`,
}); });
container.components.push({ container.components.push({
@@ -295,12 +297,17 @@ async function buildShopPanel(
components: [ components: [
{ {
type: 10, type: 10,
content: `${label}${selectedMark}\n<:coin:1425667511013081169> ${price}${stockText}`, content: `${label}${selectedMark}\n${price}${stockText}`,
}, },
], ],
accessory: { accessory: {
type: 2, type: 2,
style: isSelected ? ButtonStyle.Success : ButtonStyle.Primary, style: isSelected ? ButtonStyle.Success : ButtonStyle.Primary,
emoji: {
name: isSelected
? "<:Sup_res:1420535051162095747>"
: "<:preview:1425678718918987976>",
},
label: isSelected ? "Seleccionado" : "Ver", label: isSelected ? "Seleccionado" : "Ver",
custom_id: `shop_view_${offer.id}`, custom_id: `shop_view_${offer.id}`,
}, },
@@ -314,21 +321,24 @@ async function buildShopPanel(
{ {
type: ComponentType.Button, type: ComponentType.Button,
style: ButtonStyle.Secondary, style: ButtonStyle.Secondary,
label: "◀️ Anterior", //label: "<:blueskip2:1425682929782362122>",
emoji: { name: "<:blueskip2:1425682929782362122>" },
custom_id: "shop_prev_page", custom_id: "shop_prev_page",
disabled: safePage <= 1, disabled: safePage <= 1,
}, },
{ {
type: ComponentType.Button, type: ComponentType.Button,
style: ButtonStyle.Secondary, style: ButtonStyle.Secondary,
label: `Página ${safePage}/${totalPages}`, label: `${safePage}/${totalPages}`,
emoji: { name: "<:apoint:1336536296767750298>" },
custom_id: "shop_current_page", custom_id: "shop_current_page",
disabled: true, disabled: true,
}, },
{ {
type: ComponentType.Button, type: ComponentType.Button,
style: ButtonStyle.Secondary, style: ButtonStyle.Secondary,
label: "Siguiente ▶️", //label: "<:blueskip:1425682992801644627>",
emoji: { name: "<:blueskip:1425682992801644627>" },
custom_id: "shop_next_page", custom_id: "shop_next_page",
disabled: safePage >= totalPages, disabled: safePage >= totalPages,
}, },
@@ -341,27 +351,31 @@ async function buildShopPanel(
{ {
type: ComponentType.Button, type: ComponentType.Button,
style: ButtonStyle.Success, style: ButtonStyle.Success,
label: "🛒 Comprar (x1)", label: "Comprar (x1)",
emoji: { name: "<:onlineshopping:1425684275008897064>" },
custom_id: "shop_buy_1", custom_id: "shop_buy_1",
disabled: !selectedOfferId, disabled: !selectedOfferId,
}, },
{ {
type: ComponentType.Button, type: ComponentType.Button,
style: ButtonStyle.Success, style: ButtonStyle.Success,
label: "🛒 Comprar (x5)", label: "Comprar (x5)",
emoji: { name: "<:onlineshopping:1425684275008897064>" },
custom_id: "shop_buy_5", custom_id: "shop_buy_5",
disabled: !selectedOfferId, disabled: !selectedOfferId,
}, },
{ {
type: ComponentType.Button, type: ComponentType.Button,
style: ButtonStyle.Primary, style: ButtonStyle.Primary,
label: "🔄 Actualizar", label: "Actualizar",
emoji: { name: "<:reload:1425684687753580645>" },
custom_id: "shop_refresh", custom_id: "shop_refresh",
}, },
{ {
type: ComponentType.Button, type: ComponentType.Button,
style: ButtonStyle.Danger, style: ButtonStyle.Danger,
label: "Cerrar", label: "Cerrar",
emoji: { name: "<:Cross:1420535096208920576>" },
custom_id: "shop_close", custom_id: "shop_close",
}, },
], ],
@@ -403,7 +417,7 @@ async function handleButtonInteraction(
const selectedOfferId = sessionState.selectedOfferId; const selectedOfferId = sessionState.selectedOfferId;
if (!selectedOfferId) { if (!selectedOfferId) {
await interaction.reply({ await interaction.reply({
content: " Primero selecciona un item.", content: "<:Cross:1420535096208920576> Primero selecciona un item.",
flags: MessageFlags.Ephemeral, flags: MessageFlags.Ephemeral,
}); });
return; return;
@@ -420,7 +434,7 @@ async function handleButtonInteraction(
fallbackIcon: resolveItemIcon(result.item.icon), fallbackIcon: resolveItemIcon(result.item.icon),
}); });
await interaction.followUp({ await interaction.followUp({
content: ` **Compra exitosa!**\n🛒 ${purchaseLabel} x${result.qty}\n<:coin:1425667511013081169> Te quedan: ${wallet.coins} monedas`, content: `<:Sup_res:1420535051162095747> **Compra exitosa!**\n🛒 ${purchaseLabel} x${result.qty}\n<:coin:1425667511013081169> Te quedan: ${wallet.coins} monedas`,
flags: MessageFlags.Ephemeral, flags: MessageFlags.Ephemeral,
}); });
@@ -435,7 +449,9 @@ async function handleButtonInteraction(
}); });
} catch (error: any) { } catch (error: any) {
await interaction.followUp({ await interaction.followUp({
content: `❌ No se pudo comprar: ${error?.message ?? error}`, content: `<:Cross:1420535096208920576> No se pudo comprar: ${
error?.message ?? error
}`,
flags: MessageFlags.Ephemeral, flags: MessageFlags.Ephemeral,
}); });
} }
@@ -513,7 +529,7 @@ async function buildExpiredPanel(): Promise<any[]> {
components: [ components: [
{ {
type: 10, type: 10,
content: " **Tienda Expirada**", content: "<:timeout:1425685226088169513> **Tienda Expirada**",
}, },
{ {
type: 14, type: 14,
@@ -538,7 +554,7 @@ async function buildClosedPanel(): Promise<any[]> {
components: [ components: [
{ {
type: 10, type: 10,
content: " **Tienda Cerrada**", content: "<:Sup_res:1420535051162095747> **Tienda Cerrada**",
}, },
{ {
type: 14, type: 14,
@@ -547,7 +563,8 @@ async function buildClosedPanel(): Promise<any[]> {
}, },
{ {
type: 10, type: 10,
content: "¡Gracias por visitar la tienda!\nVuelve pronto. 🛒", content:
"¡Gracias por visitar la tienda!\nVuelve pronto. <:onlineshopping:1425684275008897064>",
}, },
], ],
}; };