mad cleanup.
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
// 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;
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
// 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<CategoryId, string>;
|
||||
Reference in New Issue
Block a user