// Grouping for nav + layout export type CategoryGroup = "lower" | "upper" | "accessories"; /** * CategoryId is the canonical identifier used throughout the UI + localStorage. * * ✅ Canonical IDs are kebab-case to match route segments and `gunbuilderParts.ts`. * * 🧯 Legacy camelCase IDs are temporarily supported to avoid breaking older * localStorage/build-state and older code paths. Prefer kebab-case going forward. */ export type CategoryId = // ===== LOWER ===== | "lower-receiver" | "complete-lower" | "lower-parts" | "trigger" | "grip" | "safety" | "buffer" | "stock" // ===== UPPER ===== | "upper-receiver" | "complete-upper" | "barrel" | "handguard" | "gas-block" | "gas-tube" | "muzzle-device" | "bcg" | "charging-handle" | "suppressor" | "sights" | "optic" // ===== ACCESSORIES ===== | "magazine" | "weapon-light" | "foregrip" | "bipod" | "sling" | "rail-accessory" | "tools" // ===== LEGACY (temporary) ===== | "completeUpper" | "gasBlock" | "gasTube" | "muzzleDevice" | "chargingHandle" | "completeLower" | "lowerParts" | "weaponLight" | "railAccessory"; export interface Category { id: CategoryId; name: string; description?: string; /** used for nav & grouping */ group?: CategoryGroup; /** optional slug override (mostly for legacy IDs) */ slug?: string; } export interface Part { id: string; name: string; brand: string; categoryId: CategoryId; price: number; affiliateUrl?: string; url?: string; imageUrl?: string; notes?: string; } /** * Route / UI slug for each CategoryId. * * - Canonical kebab-case ids map 1:1. * - Legacy camelCase ids map to the same slug. */ export const CATEGORY_SLUGS = { // LOWER "lower-receiver": "lower-receiver", "complete-lower": "complete-lower", "lower-parts": "lower-parts", trigger: "trigger", grip: "grip", safety: "safety", buffer: "buffer", stock: "stock", // UPPER "upper-receiver": "upper-receiver", "complete-upper": "complete-upper", barrel: "barrel", handguard: "handguard", "gas-block": "gas-block", "gas-tube": "gas-tube", "muzzle-device": "muzzle-device", sights: "sights", bcg: "bcg", "charging-handle": "charging-handle", suppressor: "suppressor", optic: "optic", // ACCESSORIES magazine: "magazine", "weapon-light": "weapon-light", foregrip: "foregrip", bipod: "bipod", sling: "sling", "rail-accessory": "rail-accessory", tools: "tools", // LEGACY (temporary) completeUpper: "complete-upper", gasBlock: "gas-block", gasTube: "gas-tube", muzzleDevice: "muzzle-device", chargingHandle: "charging-handle", completeLower: "complete-lower", lowerParts: "lower-parts", weaponLight: "weapon-light", railAccessory: "rail-accessory", } as const satisfies Record;