refactor: Abbreviate item rarity values from full names to single-letter codes across the application.

This commit is contained in:
syntaxbullet
2026-02-06 13:00:41 +01:00
parent db4e7313c3
commit 1929f0dd1f
10 changed files with 37 additions and 43 deletions

View File

@@ -23,7 +23,7 @@ export const renderWizard = (userId: string, isDraft = true) => {
draft = { draft = {
name: "New Item", name: "New Item",
description: "No description", description: "No description",
rarity: "Common", rarity: "C",
type: ItemType.MATERIAL, type: ItemType.MATERIAL,
price: null, price: null,
iconUrl: "", iconUrl: "",

View File

@@ -87,7 +87,7 @@ export const getDetailsModal = (current: DraftItem) => {
modal.addComponents( modal.addComponents(
new ActionRowBuilder<TextInputBuilder>().addComponents(new TextInputBuilder().setCustomId("name").setLabel("Name").setValue(current.name).setStyle(TextInputStyle.Short).setRequired(true)), new ActionRowBuilder<TextInputBuilder>().addComponents(new TextInputBuilder().setCustomId("name").setLabel("Name").setValue(current.name).setStyle(TextInputStyle.Short).setRequired(true)),
new ActionRowBuilder<TextInputBuilder>().addComponents(new TextInputBuilder().setCustomId("desc").setLabel("Description").setValue(current.description).setStyle(TextInputStyle.Paragraph).setRequired(false)), new ActionRowBuilder<TextInputBuilder>().addComponents(new TextInputBuilder().setCustomId("desc").setLabel("Description").setValue(current.description).setStyle(TextInputStyle.Paragraph).setRequired(false)),
new ActionRowBuilder<TextInputBuilder>().addComponents(new TextInputBuilder().setCustomId("rarity").setLabel("Rarity").setValue(current.rarity).setStyle(TextInputStyle.Short).setPlaceholder("Common, Rare, Legendary...").setRequired(true)) new ActionRowBuilder<TextInputBuilder>().addComponents(new TextInputBuilder().setCustomId("rarity").setLabel("Rarity").setValue(current.rarity).setStyle(TextInputStyle.Short).setPlaceholder("C, R, SR, SSR").setRequired(true))
); );
return modal; return modal;
}; };

View File

@@ -59,7 +59,7 @@ export const items = pgTable('items', {
id: serial('id').primaryKey(), id: serial('id').primaryKey(),
name: varchar('name', { length: 255 }).unique().notNull(), name: varchar('name', { length: 255 }).unique().notNull(),
description: text('description'), description: text('description'),
rarity: varchar('rarity', { length: 20 }).default('Common'), rarity: varchar('rarity', { length: 20 }).default('C'),
// Economy & Visuals // Economy & Visuals
type: varchar('type', { length: 50 }).notNull().default('MATERIAL'), type: varchar('type', { length: 50 }).notNull().default('MATERIAL'),

View File

@@ -16,7 +16,7 @@ import type { ItemType } from "@shared/lib/constants";
export interface CreateItemDTO { export interface CreateItemDTO {
name: string; name: string;
description?: string | null; description?: string | null;
rarity?: 'Common' | 'Uncommon' | 'Rare' | 'Epic' | 'Legendary'; rarity?: 'C' | 'R' | 'SR' | 'SSR';
type: 'MATERIAL' | 'CONSUMABLE' | 'EQUIPMENT' | 'QUEST'; type: 'MATERIAL' | 'CONSUMABLE' | 'EQUIPMENT' | 'QUEST';
price?: bigint | null; price?: bigint | null;
iconUrl: string; iconUrl: string;
@@ -27,7 +27,7 @@ export interface CreateItemDTO {
export interface UpdateItemDTO { export interface UpdateItemDTO {
name?: string; name?: string;
description?: string | null; description?: string | null;
rarity?: 'Common' | 'Uncommon' | 'Rare' | 'Epic' | 'Legendary'; rarity?: 'C' | 'R' | 'SR' | 'SSR';
type?: 'MATERIAL' | 'CONSUMABLE' | 'EQUIPMENT' | 'QUEST'; type?: 'MATERIAL' | 'CONSUMABLE' | 'EQUIPMENT' | 'QUEST';
price?: bigint | null; price?: bigint | null;
iconUrl?: string; iconUrl?: string;
@@ -122,7 +122,7 @@ export const itemsService = {
.values({ .values({
name: data.name, name: data.name,
description: data.description ?? null, description: data.description ?? null,
rarity: data.rarity ?? 'Common', rarity: data.rarity ?? 'C',
type: data.type, type: data.type,
price: data.price ?? null, price: data.price ?? null,
iconUrl: data.iconUrl, iconUrl: data.iconUrl,

View File

@@ -39,7 +39,7 @@ import { Loader2, Coins, FileText, Image, Zap } from "lucide-react";
const itemFormSchema = z.object({ const itemFormSchema = z.object({
name: z.string().min(1, "Name is required").max(255, "Name is too long"), name: z.string().min(1, "Name is required").max(255, "Name is too long"),
description: z.string().optional().nullable(), 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"]), type: z.enum(["MATERIAL", "CONSUMABLE", "EQUIPMENT", "QUEST"]),
price: z.string().optional().nullable(), price: z.string().optional().nullable(),
consume: z.boolean(), consume: z.boolean(),
@@ -62,11 +62,10 @@ const ITEM_TYPES = [
]; ];
const RARITIES = [ const RARITIES = [
{ value: "Common", label: "Common" }, { value: "C", label: "C" },
{ value: "Uncommon", label: "Uncommon" }, { value: "R", label: "R" },
{ value: "Rare", label: "Rare" }, { value: "SR", label: "SR" },
{ value: "Epic", label: "Epic" }, { value: "SSR", label: "SSR" },
{ value: "Legendary", label: "Legendary" },
]; ];
export function ItemForm({ initialData, onSuccess, onCancel }: ItemFormProps) { export function ItemForm({ initialData, onSuccess, onCancel }: ItemFormProps) {
@@ -81,7 +80,7 @@ export function ItemForm({ initialData, onSuccess, onCancel }: ItemFormProps) {
defaultValues: { defaultValues: {
name: "", name: "",
description: "", description: "",
rarity: "Common" as const, rarity: "C" as const,
type: "MATERIAL" as const, type: "MATERIAL" as const,
price: "", price: "",
consume: false, consume: false,
@@ -95,7 +94,7 @@ export function ItemForm({ initialData, onSuccess, onCancel }: ItemFormProps) {
form.reset({ form.reset({
name: initialData.name, name: initialData.name,
description: initialData.description || "", description: initialData.description || "",
rarity: (initialData.rarity as FormValues["rarity"]) || "Common", rarity: (initialData.rarity as FormValues["rarity"]) || "C",
type: (initialData.type as FormValues["type"]) || "MATERIAL", type: (initialData.type as FormValues["type"]) || "MATERIAL",
price: initialData.price ? String(initialData.price) : "", price: initialData.price ? String(initialData.price) : "",
consume: initialData.usageData?.consume ?? false, consume: initialData.usageData?.consume ?? false,

View File

@@ -31,11 +31,10 @@ const ITEM_TYPES = [
]; ];
const RARITIES = [ const RARITIES = [
{ value: "Common", label: "Common", color: "text-zinc-400" }, { value: "C", label: "C", color: "text-zinc-400" },
{ value: "Uncommon", label: "Uncommon", color: "text-green-400" }, { value: "R", label: "R", color: "text-blue-400" },
{ value: "Rare", label: "Rare", color: "text-blue-400" }, { value: "SR", label: "SR", color: "text-purple-400" },
{ value: "Epic", label: "Epic", color: "text-purple-400" }, { value: "SSR", label: "SSR", color: "text-amber-400" },
{ value: "Legendary", label: "Legendary", color: "text-amber-400" },
]; ];
export function ItemsFilter({ filters, onFilterChange, onClearFilters }: ItemsFilterProps) { export function ItemsFilter({ filters, onFilterChange, onClearFilters }: ItemsFilterProps) {

View File

@@ -85,9 +85,9 @@ export function ItemsTable({
case 'type': case 'type':
return direction * (a.type || '').localeCompare(b.type || ''); return direction * (a.type || '').localeCompare(b.type || '');
case 'rarity': { case 'rarity': {
const rarityOrder = ['Common', 'Uncommon', 'Rare', 'Epic', 'Legendary']; const rarityOrder = ['C', 'R', 'SR', 'SSR'];
const aIndex = rarityOrder.indexOf(a.rarity || 'Common'); const aIndex = rarityOrder.indexOf(a.rarity || 'C');
const bIndex = rarityOrder.indexOf(b.rarity || 'Common'); const bIndex = rarityOrder.indexOf(b.rarity || 'C');
return direction * (aIndex - bIndex); return direction * (aIndex - bIndex);
} }
case 'price': { case 'price': {
@@ -280,7 +280,7 @@ export function ItemsTable({
{/* Rarity (hidden on mobile) */} {/* Rarity (hidden on mobile) */}
<div className="hidden md:block"> <div className="hidden md:block">
<RarityBadge rarity={item.rarity || 'Common'} size="sm" /> <RarityBadge rarity={item.rarity || 'C'} size="sm" />
</div> </div>
{/* Price (hidden on mobile) */} {/* Price (hidden on mobile) */}
@@ -297,7 +297,7 @@ export function ItemsTable({
{/* Mobile: badges */} {/* Mobile: badges */}
<div className="flex md:hidden items-center gap-2"> <div className="flex md:hidden items-center gap-2">
<RarityBadge rarity={item.rarity || 'Common'} size="sm" /> <RarityBadge rarity={item.rarity || 'C'} size="sm" />
</div> </div>
{/* Actions */} {/* Actions */}

View File

@@ -5,7 +5,7 @@
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
export type Rarity = 'Common' | 'Uncommon' | 'Rare' | 'Epic' | 'Legendary'; export type Rarity = 'C' | 'R' | 'SR' | 'SSR';
interface RarityBadgeProps { interface RarityBadgeProps {
rarity: Rarity | string; rarity: Rarity | string;
@@ -14,23 +14,19 @@ interface RarityBadgeProps {
} }
const rarityStyles: Record<Rarity, { bg: string; text: string; glow?: string }> = { const rarityStyles: Record<Rarity, { bg: string; text: string; glow?: string }> = {
Common: { C: {
bg: 'bg-zinc-600/30', bg: 'bg-zinc-600/30',
text: 'text-zinc-300', text: 'text-zinc-300',
}, },
Uncommon: { R: {
bg: 'bg-emerald-600/30',
text: 'text-emerald-400',
},
Rare: {
bg: 'bg-blue-600/30', bg: 'bg-blue-600/30',
text: 'text-blue-400', text: 'text-blue-400',
}, },
Epic: { SR: {
bg: 'bg-purple-600/30', bg: 'bg-purple-600/30',
text: 'text-purple-400', text: 'text-purple-400',
}, },
Legendary: { SSR: {
bg: 'bg-amber-600/30', bg: 'bg-amber-600/30',
text: 'text-amber-400', text: 'text-amber-400',
glow: 'shadow-[0_0_10px_rgba(251,191,36,0.4)]', 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) { 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]; const styles = rarityStyles[validRarity];
return ( return (

View File

@@ -41,7 +41,7 @@ export interface ItemsResponse {
export interface CreateItemData { export interface CreateItemData {
name: string; name: string;
description?: string | null; description?: string | null;
rarity?: 'Common' | 'Uncommon' | 'Rare' | 'Epic' | 'Legendary'; rarity?: 'C' | 'R' | 'SR' | 'SSR';
type: 'MATERIAL' | 'CONSUMABLE' | 'EQUIPMENT' | 'QUEST'; type: 'MATERIAL' | 'CONSUMABLE' | 'EQUIPMENT' | 'QUEST';
price?: string | null; price?: string | null;
iconUrl?: string; iconUrl?: string;

View File

@@ -28,7 +28,7 @@ let mockItems: MockItem[] = [
id: 1, id: 1,
name: "Health Potion", name: "Health Potion",
description: "Restores health", description: "Restores health",
rarity: "Common", rarity: "C",
type: "CONSUMABLE", type: "CONSUMABLE",
price: 100n, price: 100n,
iconUrl: "/assets/items/1.png", iconUrl: "/assets/items/1.png",
@@ -39,7 +39,7 @@ let mockItems: MockItem[] = [
id: 2, id: 2,
name: "Iron Sword", name: "Iron Sword",
description: "A basic sword", description: "A basic sword",
rarity: "Uncommon", rarity: "R",
type: "EQUIPMENT", type: "EQUIPMENT",
price: 500n, price: 500n,
iconUrl: "/assets/items/2.png", iconUrl: "/assets/items/2.png",
@@ -96,7 +96,7 @@ mock.module("@shared/modules/items/items.service", () => ({
id: mockIdCounter++, id: mockIdCounter++,
name: data.name, name: data.name,
description: data.description ?? null, description: data.description ?? null,
rarity: data.rarity ?? "Common", rarity: data.rarity ?? "C",
type: data.type, type: data.type,
price: data.price ?? null, price: data.price ?? null,
iconUrl: data.iconUrl, iconUrl: data.iconUrl,
@@ -154,7 +154,7 @@ describe("Items API", () => {
id: 1, id: 1,
name: "Health Potion", name: "Health Potion",
description: "Restores health", description: "Restores health",
rarity: "Common", rarity: "C",
type: "CONSUMABLE", type: "CONSUMABLE",
price: 100n, price: 100n,
iconUrl: "/assets/items/1.png", iconUrl: "/assets/items/1.png",
@@ -165,7 +165,7 @@ describe("Items API", () => {
id: 2, id: 2,
name: "Iron Sword", name: "Iron Sword",
description: "A basic sword", description: "A basic sword",
rarity: "Uncommon", rarity: "R",
type: "EQUIPMENT", type: "EQUIPMENT",
price: 500n, price: 500n,
iconUrl: "/assets/items/2.png", iconUrl: "/assets/items/2.png",
@@ -217,11 +217,11 @@ describe("Items API", () => {
}); });
test("should filter items by rarity", async () => { 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); expect(response.status).toBe(200);
const data = (await response.json()) as { items: MockItem[]; total: number }; 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 = { const newItem = {
name: "Magic Staff", name: "Magic Staff",
description: "A powerful staff", description: "A powerful staff",
rarity: "Rare", rarity: "SR",
type: "EQUIPMENT", type: "EQUIPMENT",
price: "1000", price: "1000",
iconUrl: "/assets/items/placeholder.png", iconUrl: "/assets/items/placeholder.png",