85 lines
1.8 KiB
TypeScript
85 lines
1.8 KiB
TypeScript
// types/builderSlots.ts
|
|
|
|
export type CategoryGroup = "lower" | "upper" | "accessories";
|
|
|
|
/**
|
|
* Canonical key used across UI, localStorage, and (ideally) backend part_roles.key.
|
|
* Keep these in sync with part_roles.key to avoid mapping hell.
|
|
*/
|
|
export type BuilderSlotKey =
|
|
// ===== LOWER =====
|
|
| "lower-receiver"
|
|
| "complete-lower"
|
|
| "lower-parts-kit"
|
|
| "trigger"
|
|
| "grip"
|
|
| "safety-selector"
|
|
| "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";
|
|
|
|
export interface Category {
|
|
id: BuilderSlotKey;
|
|
name: string;
|
|
description?: string;
|
|
group?: CategoryGroup;
|
|
}
|
|
|
|
export interface Part {
|
|
id: string;
|
|
name: string;
|
|
brand: string;
|
|
categoryId: BuilderSlotKey;
|
|
price: number;
|
|
affiliateUrl?: string;
|
|
url?: string;
|
|
imageUrl?: string;
|
|
notes?: string;
|
|
}
|
|
|
|
/**
|
|
* Legacy localStorage / URL keys support (read-only).
|
|
* Add/remove as needed during migration.
|
|
*/
|
|
const LEGACY_SLOT_ALIASES: Record<string, BuilderSlotKey> = {
|
|
completeUpper: "complete-upper",
|
|
gasBlock: "gas-block",
|
|
gasTube: "gas-tube",
|
|
muzzleDevice: "muzzle-device",
|
|
chargingHandle: "charging-handle",
|
|
completeLower: "complete-lower",
|
|
lowerParts: "lower-parts-kit",
|
|
weaponLight: "weapon-light",
|
|
railAccessory: "rail-accessory",
|
|
// also handle older kebab mismatches if they exist:
|
|
"lower-parts": "lower-parts-kit",
|
|
safety: "safety-selector",
|
|
};
|
|
|
|
export function normalizeSlotKey(key: string): BuilderSlotKey | null {
|
|
const k = (key ?? "").trim();
|
|
if (!k) return null;
|
|
return (LEGACY_SLOT_ALIASES[k] ?? (k as BuilderSlotKey)) || null;
|
|
} |