import type { BuilderSlotKey } from "@/types/builderSlots"; /** * Normalize backend part roles into a canonical kebab-case form. * - trims whitespace * - lowercases * - converts snake_case / ENUM_CASE to kebab-case */ export const normalizePartRole = (role: string) => role.trim().toLowerCase().replace(/_/g, "-"); /** * Maps canonical kebab-case CategoryIds to their associated part roles from the backend. * * Notes: * - Keep the list here as the *source of truth*. * - The derived `PART_ROLE_TO_CATEGORY` map below stores both the original and normalized keys. */ export const CATEGORY_TO_PART_ROLES: Partial> = { // ===== UPPER ===== "upper-receiver": ["upper-receiver"], // (optional) Back-compat if anything still uses the old ids: // upper: ["upper-receiver", "upper"], "complete-upper": ["complete-upper"], barrel: ["barrel"], "gas-block": ["gas-block"], "gas-tube": ["gas-tube"], "muzzle-device": ["muzzle-device", "compensator", "brake"], suppressor: ["suppressor"], handguard: ["handguard"], "charging-handle": ["charging-handle"], bcg: ["bcg", "bolt-carrier-group"], // ===== LOWER ===== "lower-receiver": ["lower-receiver", "lower", "LOWER_RECEIVER_STRIPPED"], // (optional) Back-compat if anything still uses the old ids: "complete-lower": ["complete-lower"], // Lower Parts Kit (LPK) "lower-parts-kit": ["lower-parts-kit", "lower-parts"], trigger: ["trigger", "trigger-kit"], grip: ["pistol-grip", "grip"], "safety-selector": ["safety", "safety-selector"], buffer: ["buffer-kit", "buffer"], stock: ["stock"], // ===== OPTICS ===== sights: ["sight", "sights", "iron-sights"], optic: ["optic", "optics"], // ===== ACCESSORIES ===== magazine: ["magazine", "mag", "magazine-ar15", "magazine-308", "drum-magazine"], "weapon-light": [ "weapon-light", "light", "weapon-light-laser", "light-laser-combo", "laser", ], foregrip: ["vertical-grip", "angled-foregrip", "foregrip", "handstop"], bipod: ["bipod"], sling: ["sling", "sling-mount", "sling-swivel", "qd-sling-mount"], "rail-accessory": [ "rail-section", "picatinny-rail-section", "m-lok-rail-section", "keymod-rail-section", "rail-cover", "rail-panel", ], tools: [ "tool", "armorer-tool", "armorer-wrench", "cleaning-kit", "bore-snake", "vise-block", "torque-wrench", ], }; /** * Reverse lookup: backend partRole -> CategoryId. * * Implementation details: * - Stores BOTH the original role and its normalized version as keys. * - De-dupes role lists per category. */ export const PART_ROLE_TO_CATEGORY: Record = Object.entries( CATEGORY_TO_PART_ROLES ).reduce((acc, [categoryId, roles]) => { const unique = Array.from(new Set(roles ?? [])); for (const role of unique) { acc[role] = categoryId as BuilderSlotKey; acc[normalizePartRole(role)] = categoryId as BuilderSlotKey; } return acc; }, {} as Record);