refactor: add inventory view layer
Create inventory.view.ts with UI logic extracted from commands: - getInventoryEmbed() for inventory display - getItemUseResultEmbed() for item use results Updated commands with proper type safety: - inventory.ts: add null check, convert user.id to string - use.ts: add null check, convert user.id to string Improves separation of concerns and type safety.
This commit is contained in:
@@ -2,7 +2,8 @@ import { createCommand } from "@/lib/utils";
|
|||||||
import { SlashCommandBuilder } from "discord.js";
|
import { SlashCommandBuilder } from "discord.js";
|
||||||
import { inventoryService } from "@/modules/inventory/inventory.service";
|
import { inventoryService } from "@/modules/inventory/inventory.service";
|
||||||
import { userService } from "@/modules/user/user.service";
|
import { userService } from "@/modules/user/user.service";
|
||||||
import { createWarningEmbed, createBaseEmbed } from "@lib/embeds";
|
import { createWarningEmbed } from "@lib/embeds";
|
||||||
|
import { getInventoryEmbed } from "@/modules/inventory/inventory.view";
|
||||||
|
|
||||||
export const inventory = createCommand({
|
export const inventory = createCommand({
|
||||||
data: new SlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
@@ -24,18 +25,19 @@ export const inventory = createCommand({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const user = await userService.getOrCreateUser(targetUser.id, targetUser.username);
|
const user = await userService.getOrCreateUser(targetUser.id, targetUser.username);
|
||||||
const items = await inventoryService.getInventory(user.id);
|
if (!user) {
|
||||||
|
await interaction.editReply({ embeds: [createWarningEmbed("Failed to load user data.", "Error")] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = await inventoryService.getInventory(user.id.toString());
|
||||||
|
|
||||||
if (!items || items.length === 0) {
|
if (!items || items.length === 0) {
|
||||||
await interaction.editReply({ embeds: [createWarningEmbed("Inventory is empty.", `${user.username}'s Inventory`)] });
|
await interaction.editReply({ embeds: [createWarningEmbed("Inventory is empty.", `${user.username}'s Inventory`)] });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const description = items.map(entry => {
|
const embed = getInventoryEmbed(items, user.username);
|
||||||
return `**${entry.item.name}** x${entry.quantity}`;
|
|
||||||
}).join("\n");
|
|
||||||
|
|
||||||
const embed = createBaseEmbed(`${user.username}'s Inventory`, description, "Blue");
|
|
||||||
|
|
||||||
await interaction.editReply({ embeds: [embed] });
|
await interaction.editReply({ embeds: [embed] });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import { createCommand } from "@/lib/utils";
|
|||||||
import { SlashCommandBuilder } from "discord.js";
|
import { SlashCommandBuilder } from "discord.js";
|
||||||
import { inventoryService } from "@/modules/inventory/inventory.service";
|
import { inventoryService } from "@/modules/inventory/inventory.service";
|
||||||
import { userService } from "@/modules/user/user.service";
|
import { userService } from "@/modules/user/user.service";
|
||||||
import { createErrorEmbed, createSuccessEmbed } from "@lib/embeds";
|
import { createErrorEmbed } from "@lib/embeds";
|
||||||
|
import { getItemUseResultEmbed } from "@/modules/inventory/inventory.view";
|
||||||
import { inventory, items } from "@/db/schema";
|
import { inventory, items } from "@/db/schema";
|
||||||
import { eq, and, like } from "drizzle-orm";
|
import { eq, and, like } from "drizzle-orm";
|
||||||
import { DrizzleClient } from "@/lib/DrizzleClient";
|
import { DrizzleClient } from "@/lib/DrizzleClient";
|
||||||
@@ -25,9 +26,13 @@ export const use = createCommand({
|
|||||||
|
|
||||||
const itemId = interaction.options.getNumber("item", true);
|
const itemId = interaction.options.getNumber("item", true);
|
||||||
const user = await userService.getOrCreateUser(interaction.user.id, interaction.user.username);
|
const user = await userService.getOrCreateUser(interaction.user.id, interaction.user.username);
|
||||||
|
if (!user) {
|
||||||
|
await interaction.editReply({ embeds: [createErrorEmbed("Failed to load user data.")] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await inventoryService.useItem(user.id, itemId);
|
const result = await inventoryService.useItem(user.id.toString(), itemId);
|
||||||
|
|
||||||
const usageData = result.usageData;
|
const usageData = result.usageData;
|
||||||
if (usageData) {
|
if (usageData) {
|
||||||
@@ -53,11 +58,7 @@ export const use = createCommand({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const embed = createSuccessEmbed(
|
const embed = getItemUseResultEmbed(result.results);
|
||||||
result.results.map(r => `• ${r}`).join("\n"),
|
|
||||||
`Used ${result.usageData.effects.length > 0 ? 'Item' : 'Item'}` // Generic title, improves below
|
|
||||||
);
|
|
||||||
embed.setTitle("Item Used!");
|
|
||||||
|
|
||||||
await interaction.editReply({ embeds: [embed] });
|
await interaction.editReply({ embeds: [embed] });
|
||||||
|
|
||||||
|
|||||||
40
src/modules/inventory/inventory.view.ts
Normal file
40
src/modules/inventory/inventory.view.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { EmbedBuilder } from "discord.js";
|
||||||
|
import type { ItemUsageData } from "@/lib/types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inventory entry with item details
|
||||||
|
*/
|
||||||
|
interface InventoryEntry {
|
||||||
|
quantity: bigint | null;
|
||||||
|
item: {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an embed displaying a user's inventory
|
||||||
|
*/
|
||||||
|
export function getInventoryEmbed(items: InventoryEntry[], username: string): EmbedBuilder {
|
||||||
|
const description = items.map(entry => {
|
||||||
|
return `**${entry.item.name}** x${entry.quantity}`;
|
||||||
|
}).join("\n");
|
||||||
|
|
||||||
|
return new EmbedBuilder()
|
||||||
|
.setTitle(`📦 ${username}'s Inventory`)
|
||||||
|
.setDescription(description)
|
||||||
|
.setColor(0x3498db); // Blue
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an embed showing the results of using an item
|
||||||
|
*/
|
||||||
|
export function getItemUseResultEmbed(results: string[], itemName?: string): EmbedBuilder {
|
||||||
|
const description = results.map(r => `• ${r}`).join("\n");
|
||||||
|
|
||||||
|
return new EmbedBuilder()
|
||||||
|
.setTitle("✅ Item Used!")
|
||||||
|
.setDescription(description)
|
||||||
|
.setColor(0x2ecc71); // Green/Success
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user