From 1929f0dd1fc36d2e6c035c1fb4f7e943e8ee5f80 Mon Sep 17 00:00:00 2001 From: syntaxbullet Date: Fri, 6 Feb 2026 13:00:41 +0100 Subject: [PATCH] refactor: Abbreviate item rarity values from full names to single-letter codes across the application. --- bot/modules/admin/item_wizard.ts | 2 +- bot/modules/admin/item_wizard.view.ts | 2 +- shared/db/schema.ts | 2 +- shared/modules/items/items.service.ts | 6 +++--- web/src/components/item-form.tsx | 15 +++++++-------- web/src/components/items-filter.tsx | 9 ++++----- web/src/components/items-table.tsx | 10 +++++----- web/src/components/rarity-badge.tsx | 16 ++++++---------- web/src/hooks/use-items.ts | 2 +- web/src/server.items.test.ts | 16 ++++++++-------- 10 files changed, 37 insertions(+), 43 deletions(-) diff --git a/bot/modules/admin/item_wizard.ts b/bot/modules/admin/item_wizard.ts index 7e18889..864e618 100644 --- a/bot/modules/admin/item_wizard.ts +++ b/bot/modules/admin/item_wizard.ts @@ -23,7 +23,7 @@ export const renderWizard = (userId: string, isDraft = true) => { draft = { name: "New Item", description: "No description", - rarity: "Common", + rarity: "C", type: ItemType.MATERIAL, price: null, iconUrl: "", diff --git a/bot/modules/admin/item_wizard.view.ts b/bot/modules/admin/item_wizard.view.ts index f9aa952..268858c 100644 --- a/bot/modules/admin/item_wizard.view.ts +++ b/bot/modules/admin/item_wizard.view.ts @@ -87,7 +87,7 @@ export const getDetailsModal = (current: DraftItem) => { modal.addComponents( new ActionRowBuilder().addComponents(new TextInputBuilder().setCustomId("name").setLabel("Name").setValue(current.name).setStyle(TextInputStyle.Short).setRequired(true)), new ActionRowBuilder().addComponents(new TextInputBuilder().setCustomId("desc").setLabel("Description").setValue(current.description).setStyle(TextInputStyle.Paragraph).setRequired(false)), - new ActionRowBuilder().addComponents(new TextInputBuilder().setCustomId("rarity").setLabel("Rarity").setValue(current.rarity).setStyle(TextInputStyle.Short).setPlaceholder("Common, Rare, Legendary...").setRequired(true)) + new ActionRowBuilder().addComponents(new TextInputBuilder().setCustomId("rarity").setLabel("Rarity").setValue(current.rarity).setStyle(TextInputStyle.Short).setPlaceholder("C, R, SR, SSR").setRequired(true)) ); return modal; }; diff --git a/shared/db/schema.ts b/shared/db/schema.ts index d96b875..7bff479 100644 --- a/shared/db/schema.ts +++ b/shared/db/schema.ts @@ -59,7 +59,7 @@ export const items = pgTable('items', { id: serial('id').primaryKey(), name: varchar('name', { length: 255 }).unique().notNull(), description: text('description'), - rarity: varchar('rarity', { length: 20 }).default('Common'), + rarity: varchar('rarity', { length: 20 }).default('C'), // Economy & Visuals type: varchar('type', { length: 50 }).notNull().default('MATERIAL'), diff --git a/shared/modules/items/items.service.ts b/shared/modules/items/items.service.ts index 8157381..b062d12 100644 --- a/shared/modules/items/items.service.ts +++ b/shared/modules/items/items.service.ts @@ -16,7 +16,7 @@ import type { ItemType } from "@shared/lib/constants"; export interface CreateItemDTO { name: string; description?: string | null; - rarity?: 'Common' | 'Uncommon' | 'Rare' | 'Epic' | 'Legendary'; + rarity?: 'C' | 'R' | 'SR' | 'SSR'; type: 'MATERIAL' | 'CONSUMABLE' | 'EQUIPMENT' | 'QUEST'; price?: bigint | null; iconUrl: string; @@ -27,7 +27,7 @@ export interface CreateItemDTO { export interface UpdateItemDTO { name?: string; description?: string | null; - rarity?: 'Common' | 'Uncommon' | 'Rare' | 'Epic' | 'Legendary'; + rarity?: 'C' | 'R' | 'SR' | 'SSR'; type?: 'MATERIAL' | 'CONSUMABLE' | 'EQUIPMENT' | 'QUEST'; price?: bigint | null; iconUrl?: string; @@ -122,7 +122,7 @@ export const itemsService = { .values({ name: data.name, description: data.description ?? null, - rarity: data.rarity ?? 'Common', + rarity: data.rarity ?? 'C', type: data.type, price: data.price ?? null, iconUrl: data.iconUrl, diff --git a/web/src/components/item-form.tsx b/web/src/components/item-form.tsx index 26374ba..628b1b9 100644 --- a/web/src/components/item-form.tsx +++ b/web/src/components/item-form.tsx @@ -39,7 +39,7 @@ import { Loader2, Coins, FileText, Image, Zap } from "lucide-react"; const itemFormSchema = z.object({ name: z.string().min(1, "Name is required").max(255, "Name is too long"), description: z.string().optional().nullable(), - rarity: z.enum(["Common", "Uncommon", "Rare", "Epic", "Legendary"]), + rarity: z.enum(["C", "R", "SR", "SSR"]), type: z.enum(["MATERIAL", "CONSUMABLE", "EQUIPMENT", "QUEST"]), price: z.string().optional().nullable(), consume: z.boolean(), @@ -62,11 +62,10 @@ const ITEM_TYPES = [ ]; const RARITIES = [ - { value: "Common", label: "Common" }, - { value: "Uncommon", label: "Uncommon" }, - { value: "Rare", label: "Rare" }, - { value: "Epic", label: "Epic" }, - { value: "Legendary", label: "Legendary" }, + { value: "C", label: "C" }, + { value: "R", label: "R" }, + { value: "SR", label: "SR" }, + { value: "SSR", label: "SSR" }, ]; export function ItemForm({ initialData, onSuccess, onCancel }: ItemFormProps) { @@ -81,7 +80,7 @@ export function ItemForm({ initialData, onSuccess, onCancel }: ItemFormProps) { defaultValues: { name: "", description: "", - rarity: "Common" as const, + rarity: "C" as const, type: "MATERIAL" as const, price: "", consume: false, @@ -95,7 +94,7 @@ export function ItemForm({ initialData, onSuccess, onCancel }: ItemFormProps) { form.reset({ name: initialData.name, description: initialData.description || "", - rarity: (initialData.rarity as FormValues["rarity"]) || "Common", + rarity: (initialData.rarity as FormValues["rarity"]) || "C", type: (initialData.type as FormValues["type"]) || "MATERIAL", price: initialData.price ? String(initialData.price) : "", consume: initialData.usageData?.consume ?? false, diff --git a/web/src/components/items-filter.tsx b/web/src/components/items-filter.tsx index 526ecc4..c967635 100644 --- a/web/src/components/items-filter.tsx +++ b/web/src/components/items-filter.tsx @@ -31,11 +31,10 @@ const ITEM_TYPES = [ ]; const RARITIES = [ - { value: "Common", label: "Common", color: "text-zinc-400" }, - { value: "Uncommon", label: "Uncommon", color: "text-green-400" }, - { value: "Rare", label: "Rare", color: "text-blue-400" }, - { value: "Epic", label: "Epic", color: "text-purple-400" }, - { value: "Legendary", label: "Legendary", color: "text-amber-400" }, + { value: "C", label: "C", color: "text-zinc-400" }, + { value: "R", label: "R", color: "text-blue-400" }, + { value: "SR", label: "SR", color: "text-purple-400" }, + { value: "SSR", label: "SSR", color: "text-amber-400" }, ]; export function ItemsFilter({ filters, onFilterChange, onClearFilters }: ItemsFilterProps) { diff --git a/web/src/components/items-table.tsx b/web/src/components/items-table.tsx index b7825dd..71d98f5 100644 --- a/web/src/components/items-table.tsx +++ b/web/src/components/items-table.tsx @@ -85,9 +85,9 @@ export function ItemsTable({ case 'type': return direction * (a.type || '').localeCompare(b.type || ''); case 'rarity': { - const rarityOrder = ['Common', 'Uncommon', 'Rare', 'Epic', 'Legendary']; - const aIndex = rarityOrder.indexOf(a.rarity || 'Common'); - const bIndex = rarityOrder.indexOf(b.rarity || 'Common'); + const rarityOrder = ['C', 'R', 'SR', 'SSR']; + const aIndex = rarityOrder.indexOf(a.rarity || 'C'); + const bIndex = rarityOrder.indexOf(b.rarity || 'C'); return direction * (aIndex - bIndex); } case 'price': { @@ -280,7 +280,7 @@ export function ItemsTable({ {/* Rarity (hidden on mobile) */}
- +
{/* Price (hidden on mobile) */} @@ -297,7 +297,7 @@ export function ItemsTable({ {/* Mobile: badges */}
- +
{/* Actions */} diff --git a/web/src/components/rarity-badge.tsx b/web/src/components/rarity-badge.tsx index 0d3e5e4..5bba2f7 100644 --- a/web/src/components/rarity-badge.tsx +++ b/web/src/components/rarity-badge.tsx @@ -5,7 +5,7 @@ import { cn } from "@/lib/utils"; -export type Rarity = 'Common' | 'Uncommon' | 'Rare' | 'Epic' | 'Legendary'; +export type Rarity = 'C' | 'R' | 'SR' | 'SSR'; interface RarityBadgeProps { rarity: Rarity | string; @@ -14,23 +14,19 @@ interface RarityBadgeProps { } const rarityStyles: Record = { - Common: { + C: { bg: 'bg-zinc-600/30', text: 'text-zinc-300', }, - Uncommon: { - bg: 'bg-emerald-600/30', - text: 'text-emerald-400', - }, - Rare: { + R: { bg: 'bg-blue-600/30', text: 'text-blue-400', }, - Epic: { + SR: { bg: 'bg-purple-600/30', text: 'text-purple-400', }, - Legendary: { + SSR: { bg: 'bg-amber-600/30', text: 'text-amber-400', glow: 'shadow-[0_0_10px_rgba(251,191,36,0.4)]', @@ -44,7 +40,7 @@ const sizeStyles = { }; export function RarityBadge({ rarity, className, size = 'md' }: RarityBadgeProps) { - const validRarity = (rarity in rarityStyles ? rarity : 'Common') as Rarity; + const validRarity = (rarity in rarityStyles ? rarity : 'C') as Rarity; const styles = rarityStyles[validRarity]; return ( diff --git a/web/src/hooks/use-items.ts b/web/src/hooks/use-items.ts index c6b5780..7c1b5d4 100644 --- a/web/src/hooks/use-items.ts +++ b/web/src/hooks/use-items.ts @@ -41,7 +41,7 @@ export interface ItemsResponse { export interface CreateItemData { name: string; description?: string | null; - rarity?: 'Common' | 'Uncommon' | 'Rare' | 'Epic' | 'Legendary'; + rarity?: 'C' | 'R' | 'SR' | 'SSR'; type: 'MATERIAL' | 'CONSUMABLE' | 'EQUIPMENT' | 'QUEST'; price?: string | null; iconUrl?: string; diff --git a/web/src/server.items.test.ts b/web/src/server.items.test.ts index 2ac20c4..67d4871 100644 --- a/web/src/server.items.test.ts +++ b/web/src/server.items.test.ts @@ -28,7 +28,7 @@ let mockItems: MockItem[] = [ id: 1, name: "Health Potion", description: "Restores health", - rarity: "Common", + rarity: "C", type: "CONSUMABLE", price: 100n, iconUrl: "/assets/items/1.png", @@ -39,7 +39,7 @@ let mockItems: MockItem[] = [ id: 2, name: "Iron Sword", description: "A basic sword", - rarity: "Uncommon", + rarity: "R", type: "EQUIPMENT", price: 500n, iconUrl: "/assets/items/2.png", @@ -96,7 +96,7 @@ mock.module("@shared/modules/items/items.service", () => ({ id: mockIdCounter++, name: data.name, description: data.description ?? null, - rarity: data.rarity ?? "Common", + rarity: data.rarity ?? "C", type: data.type, price: data.price ?? null, iconUrl: data.iconUrl, @@ -154,7 +154,7 @@ describe("Items API", () => { id: 1, name: "Health Potion", description: "Restores health", - rarity: "Common", + rarity: "C", type: "CONSUMABLE", price: 100n, iconUrl: "/assets/items/1.png", @@ -165,7 +165,7 @@ describe("Items API", () => { id: 2, name: "Iron Sword", description: "A basic sword", - rarity: "Uncommon", + rarity: "R", type: "EQUIPMENT", price: 500n, iconUrl: "/assets/items/2.png", @@ -217,11 +217,11 @@ describe("Items API", () => { }); test("should filter items by rarity", async () => { - const response = await fetch(`${baseUrl}/api/items?rarity=Common`); + const response = await fetch(`${baseUrl}/api/items?rarity=C`); expect(response.status).toBe(200); const data = (await response.json()) as { items: MockItem[]; total: number }; - expect(data.items.every((item) => item.rarity === "Common")).toBe(true); + expect(data.items.every((item) => item.rarity === "C")).toBe(true); }); }); @@ -255,7 +255,7 @@ describe("Items API", () => { const newItem = { name: "Magic Staff", description: "A powerful staff", - rarity: "Rare", + rarity: "SR", type: "EQUIPMENT", price: "1000", iconUrl: "/assets/items/placeholder.png",