diff --git a/src/db/dev-seed-data.ts b/src/db/dev-seed-data.ts new file mode 100644 index 0000000..6e14c67 --- /dev/null +++ b/src/db/dev-seed-data.ts @@ -0,0 +1,782 @@ +// ── Dev Seed Data ────────────────────────────────────────────────── +// All seed data as typed constants for local development. +// Realistic bikepacking gear with accurate weights and prices. + +// ── Categories ───────────────────────────────────────────────────── + +export const DEV_CATEGORIES = [ + { name: "Bags", icon: "briefcase" }, + { name: "Shelter", icon: "tent" }, + { name: "Sleep System", icon: "moon" }, + { name: "Cooking", icon: "flame" }, + { name: "Lighting", icon: "flashlight" }, + { name: "Tools & Repair", icon: "wrench" }, + { name: "Clothing", icon: "shirt" }, + { name: "Water", icon: "droplets" }, + { name: "Electronics", icon: "battery" }, + { name: "Navigation", icon: "compass" }, +] as const; + +// ── Global Items ─────────────────────────────────────────────────── +// Index positions are referenced by user items, thread candidates, and tag assignments. + +export const DEV_GLOBAL_ITEMS = [ + // Bags (indices 0-5) + { + brand: "Revelate Designs", + model: "Terrapin System", + category: "bags", + weightGrams: 529, + priceCents: 18500, + description: + "Waterproof saddle bag with 14L capacity, roll-top closure, and integrated seat bag mount.", + }, + { + brand: "Apidura", + model: "Expedition Handlebar Pack", + category: "bags", + weightGrams: 300, + priceCents: 16000, + description: + "14L waterproof handlebar roll bag with internal dry bag and accessory pocket.", + }, + { + brand: "Ortlieb", + model: "Frame-Pack RC", + category: "bags", + weightGrams: 250, + priceCents: 12000, + description: + "6L waterproof roll-closure frame bag with TIZIP zipper for full-frame bikes.", + }, + { + brand: "Rockgeist", + model: "BarJam", + category: "bags", + weightGrams: 142, + priceCents: 9900, + description: + "Ultralight handlebar harness with side-loading dry bag compatibility.", + }, + { + brand: "Oveja Negra", + model: "Superwedgie", + category: "bags", + weightGrams: 170, + priceCents: 7500, + description: + "Half-frame bag with easy-access zipper and internal organization.", + }, + { + brand: "Apidura", + model: "Racing Top Tube Pack", + category: "bags", + weightGrams: 72, + priceCents: 5500, + description: + "Bolt-on 1L top tube pack for nutrition and essentials during racing.", + }, + + // Shelter (indices 6-9) + { + brand: "Zpacks", + model: "Duplex", + category: "shelter", + weightGrams: 539, + priceCents: 67900, + description: + "Dyneema Composite Fabric two-person trekking pole shelter, freestanding with optional poles.", + }, + { + brand: "Tarptent", + model: "Stratospire Li", + category: "shelter", + weightGrams: 737, + priceCents: 62500, + description: + "Two-person double-wall tent in Dyneema with dual vestibules and excellent ventilation.", + }, + { + brand: "Durston", + model: "X-Mid 1 Solid", + category: "shelter", + weightGrams: 880, + priceCents: 22000, + description: + "Single-wall silpoly trekking pole tent with symmetrical design and two vestibules.", + }, + { + brand: "Big Agnes", + model: "Copper Spur HV UL1", + category: "shelter", + weightGrams: 936, + priceCents: 42000, + description: + "Freestanding ultralight one-person tent with high-volume architecture and DAC poles.", + }, + + // Sleep System (indices 10-14) + { + brand: "Enlightened Equipment", + model: "Enigma 20F", + category: "sleep", + weightGrams: 567, + priceCents: 35500, + description: + "20F down quilt with 850FP DownTek water-resistant fill, sewn footbox option.", + }, + { + brand: "Therm-a-Rest", + model: "NeoAir XLite NXT", + category: "sleep", + weightGrams: 354, + priceCents: 21000, + description: + "R-value 4.5 ultralight inflatable sleeping pad with ThermaCapture reflective technology.", + }, + { + brand: "Nemo", + model: "Tensor Insulated Regular", + category: "sleep", + weightGrams: 425, + priceCents: 17000, + description: + "R-value 4.2 insulated sleeping pad with Spaceframe baffles for stability.", + }, + { + brand: "Sea to Summit", + model: "Aeros Premium Pillow", + category: "sleep", + weightGrams: 79, + priceCents: 4500, + description: + "Brushed 50D polyester inflatable pillow with multifunctional valve.", + }, + { + brand: "Western Mountaineering", + model: "NanoLite 22F", + category: "sleep", + weightGrams: 510, + priceCents: 46000, + description: + "Premium 850+ FP goose down mummy bag with continuous baffles and draft collar.", + }, + + // Cooking (indices 15-19) + { + brand: "BRS", + model: "BRS-3000T", + category: "cooking", + weightGrams: 25, + priceCents: 2000, + description: + "Ultralight titanium canister stove, 25g with piezo ignition, 2700W output.", + }, + { + brand: "Soto", + model: "WindMaster", + category: "cooking", + weightGrams: 67, + priceCents: 7500, + description: + "Micro-regulator stove with concave burner head for excellent wind resistance.", + }, + { + brand: "Toaks", + model: "Light Titanium 750ml", + category: "cooking", + weightGrams: 86, + priceCents: 3200, + description: + "Titanium pot with graduated measurements, lid, and folding bail handle.", + }, + { + brand: "Snow Peak", + model: "Ti-Mini Solo Combo", + category: "cooking", + weightGrams: 198, + priceCents: 5500, + description: + "Titanium cookset with 850ml pot, lid/pan, and nesting mug for solo cooking.", + }, + { + brand: "MSR", + model: "PocketRocket Deluxe", + category: "cooking", + weightGrams: 83, + priceCents: 6000, + description: + "Pressure-regulated canister stove with built-in wind clip and push-start ignition.", + }, + + // Lighting (indices 20-22) + { + brand: "Nitecore", + model: "NU25 UL", + category: "lighting", + weightGrams: 28, + priceCents: 3600, + description: + "Rechargeable ultralight headlamp with 400 lumens, red/high-CRI aux LEDs.", + }, + { + brand: "Lezyne", + model: "Lite Drive 1200+", + category: "lighting", + weightGrams: 176, + priceCents: 8500, + description: + "1200 lumen USB-C rechargeable bike light with MOR optical lens design.", + }, + { + brand: "Fenix", + model: "HL60R", + category: "lighting", + weightGrams: 134, + priceCents: 7000, + description: + "950 lumen rechargeable headlamp with neutral white LED and red light mode.", + }, + + // Tools & Repair (indices 23-25) + { + brand: "Park Tool", + model: "IB-3", + category: "tools", + weightGrams: 175, + priceCents: 3500, + description: + "Folding hex/Torx multi-tool with 3-6mm hex, T25, Phillips and flathead.", + }, + { + brand: "Lezyne", + model: "CNC Chain Breaker", + category: "tools", + weightGrams: 28, + priceCents: 2300, + description: + "CNC-machined aluminum chain tool compatible with 8-12 speed chains.", + }, + { + brand: "Gorilla Tape", + model: "Mini Duct Tape Roll", + category: "tools", + weightGrams: 30, + priceCents: 500, + description: "1-inch wide mini roll for emergency repairs, 5-yard length.", + }, + + // Clothing (indices 26-28) + { + brand: "Patagonia", + model: "R1 Air Full-Zip", + category: "clothing", + weightGrams: 266, + priceCents: 15900, + description: + "Breathable midlayer fleece with open-knit R1 Air fabric for high-output activities.", + }, + { + brand: "Frogg Toggs", + model: "Ultra-Lite2 Rain Suit", + category: "clothing", + weightGrams: 340, + priceCents: 2500, + description: + "Budget ultralight rain jacket and pants set, DriPore breathable material.", + }, + { + brand: "Buff", + model: "Merino Wool Multifunctional", + category: "clothing", + weightGrams: 43, + priceCents: 2800, + description: + "Seamless 100% merino wool neck gaiter with natural odor resistance.", + }, + + // Water (indices 29-31) + { + brand: "Sawyer", + model: "Squeeze SP129", + category: "water", + weightGrams: 85, + priceCents: 3500, + description: + "0.1 micron hollow-fiber water filter with high flow rate and backflush capability.", + }, + { + brand: "Katadyn", + model: "BeFree 1L", + category: "water", + weightGrams: 63, + priceCents: 4500, + description: + "EZ-Clean membrane filter with collapsible Hydrapak flask, 2L/min flow rate.", + }, + { + brand: "HydraPak", + model: "Seeker 2L", + category: "water", + weightGrams: 76, + priceCents: 1600, + description: + "Ultralight collapsible water storage with wide mouth and Plug-N-Play cap.", + }, + + // Electronics (indices 32-33) + { + brand: "Anker", + model: "Nano Power Bank 10000 PD", + category: "electronics", + weightGrams: 220, + priceCents: 3000, + description: + "10000mAh 30W USB-C PD power bank with built-in display and passthrough charging.", + }, + { + brand: "Garmin", + model: "inReach Mini 2", + category: "electronics", + weightGrams: 100, + priceCents: 39999, + description: + "Satellite communicator with SOS, two-way messaging, tracking, and weather forecasts.", + }, + + // Navigation (indices 34-35) + { + brand: "Wahoo", + model: "ELEMNT BOLT V2", + category: "navigation", + weightGrams: 68, + priceCents: 27999, + description: + "GPS cycling computer with color display, turn-by-turn navigation, and smart trainer integration.", + }, + { + brand: "Ortlieb", + model: "Ultimate Six Classic", + category: "navigation", + weightGrams: 500, + priceCents: 9000, + description: + "5L handlebar bag with integrated map case and magnetic closure, IP64 rated.", + }, +] as const; + +// ── Tag Assignments ──────────────────────────────────────────────── +// Maps global item index -> tag names. Tags are seeded by seedGlobalItems(). + +export const DEV_TAG_ASSIGNMENTS = [ + { globalItemIndex: 0, tagNames: ["saddlebag", "waterproof", "bikepacking"] }, + { + globalItemIndex: 1, + tagNames: ["handlebar-bag", "waterproof", "bikepacking"], + }, + { + globalItemIndex: 2, + tagNames: ["framebag", "waterproof", "bikepacking", "touring"], + }, + { + globalItemIndex: 3, + tagNames: ["handlebar-bag", "ultralight", "bikepacking"], + }, + { globalItemIndex: 4, tagNames: ["framebag", "bikepacking"] }, + { + globalItemIndex: 5, + tagNames: ["top-tube-bag", "ultralight", "bikepacking"], + }, + { + globalItemIndex: 6, + tagNames: ["tent", "ultralight", "premium", "hiking"], + }, + { globalItemIndex: 7, tagNames: ["tent", "premium", "hiking"] }, + { globalItemIndex: 8, tagNames: ["tent", "ultralight", "budget", "hiking"] }, + { globalItemIndex: 9, tagNames: ["tent", "ultralight", "hiking", "camping"] }, + { + globalItemIndex: 10, + tagNames: ["quilt", "ultralight", "premium", "hiking"], + }, + { + globalItemIndex: 11, + tagNames: ["sleeping-pad", "ultralight", "premium", "hiking"], + }, + { + globalItemIndex: 12, + tagNames: ["sleeping-pad", "hiking", "camping"], + }, + { globalItemIndex: 13, tagNames: ["pillow", "ultralight", "hiking"] }, + { + globalItemIndex: 14, + tagNames: ["sleeping-bag", "premium", "hiking", "camping"], + }, + { + globalItemIndex: 15, + tagNames: ["stove", "ultralight", "budget", "bikepacking"], + }, + { globalItemIndex: 16, tagNames: ["stove", "premium", "bikepacking"] }, + { + globalItemIndex: 17, + tagNames: ["cookware", "ultralight", "bikepacking"], + }, + { globalItemIndex: 18, tagNames: ["cookware", "camping"] }, + { globalItemIndex: 19, tagNames: ["stove", "camping", "hiking"] }, + { + globalItemIndex: 20, + tagNames: ["headlamp", "ultralight", "bikepacking", "hiking"], + }, + { globalItemIndex: 21, tagNames: ["bike-light", "bikepacking"] }, + { globalItemIndex: 22, tagNames: ["headlamp", "camping", "hiking"] }, + { globalItemIndex: 29, tagNames: ["water-filter", "ultralight", "hiking"] }, + { globalItemIndex: 30, tagNames: ["water-filter", "ultralight", "hiking"] }, + { + globalItemIndex: 31, + tagNames: ["water-bottle", "ultralight", "bikepacking"], + }, + { globalItemIndex: 32, tagNames: ["bikepacking", "touring"] }, + { globalItemIndex: 33, tagNames: ["premium", "hiking", "bikepacking"] }, + { globalItemIndex: 34, tagNames: ["bikepacking", "premium"] }, + { globalItemIndex: 35, tagNames: ["handlebar-bag", "waterproof", "touring"] }, +] as const; + +// ── Category name mapping (for FK lookups by category name) ──────── + +const CATEGORY_MAP: Record = { + bags: "Bags", + shelter: "Shelter", + sleep: "Sleep System", + cooking: "Cooking", + lighting: "Lighting", + tools: "Tools & Repair", + clothing: "Clothing", + water: "Water", + electronics: "Electronics", + navigation: "Navigation", +}; + +export function categoryDisplayName(seedCategory: string): string { + return CATEGORY_MAP[seedCategory] ?? seedCategory; +} + +// ── User Items ───────────────────────────────────────────────────── +// globalItemIndex: index into DEV_GLOBAL_ITEMS (null = standalone item) +// categoryName: matches DEV_CATEGORIES name for FK lookup + +export const DEV_USER_ITEMS = [ + // Catalog-linked items (10) + { + globalItemIndex: 0 as number | null, + categoryName: "Bags", + name: "Revelate Designs Terrapin System", + weightGrams: 529, + priceCents: 18500, + purchasePriceCents: 16200, + notes: "Bought used on r/BikeparkingMarket, great condition.", + quantity: 1, + }, + { + globalItemIndex: 2, + categoryName: "Bags", + name: "Ortlieb Frame-Pack RC", + weightGrams: 250, + priceCents: 12000, + purchasePriceCents: 12000, + notes: null, + quantity: 1, + }, + { + globalItemIndex: 5, + categoryName: "Bags", + name: "Apidura Racing Top Tube Pack", + weightGrams: 72, + priceCents: 5500, + purchasePriceCents: 4900, + notes: null, + quantity: 1, + }, + { + globalItemIndex: 8, + categoryName: "Shelter", + name: "Durston X-Mid 1 Solid", + weightGrams: 880, + priceCents: 22000, + purchasePriceCents: 22000, + notes: "Drop 2 batch, arrived March 2025.", + quantity: 1, + }, + { + globalItemIndex: 10, + categoryName: "Sleep System", + name: "Enlightened Equipment Enigma 20F", + weightGrams: 567, + priceCents: 35500, + purchasePriceCents: 31000, + notes: "Custom order: 20F, 850FP, regular/regular, teal/charcoal.", + quantity: 1, + }, + { + globalItemIndex: 11, + categoryName: "Sleep System", + name: "Therm-a-Rest NeoAir XLite NXT", + weightGrams: 354, + priceCents: 21000, + purchasePriceCents: null, + notes: null, + quantity: 1, + }, + { + globalItemIndex: 15, + categoryName: "Cooking", + name: "BRS BRS-3000T", + weightGrams: 25, + priceCents: 2000, + purchasePriceCents: 1800, + notes: null, + quantity: 1, + }, + { + globalItemIndex: 20, + categoryName: "Lighting", + name: "Nitecore NU25 UL", + weightGrams: 28, + priceCents: 3600, + purchasePriceCents: 3600, + notes: "Swapped stock strap for Litesmith strap (-5g).", + quantity: 1, + }, + { + globalItemIndex: 29, + categoryName: "Water", + name: "Sawyer Squeeze SP129", + weightGrams: 85, + priceCents: 3500, + purchasePriceCents: 3500, + notes: null, + quantity: 1, + }, + { + globalItemIndex: 34, + categoryName: "Navigation", + name: "Wahoo ELEMNT BOLT V2", + weightGrams: 68, + priceCents: 27999, + purchasePriceCents: 23999, + notes: "Refurbished from Wahoo directly.", + quantity: 1, + }, + + // Standalone items (7) - no global item link + { + globalItemIndex: null, + categoryName: "Bags", + name: "Custom Frame Bag (Wanderlust Gear Co)", + weightGrams: 145, + priceCents: 8500, + purchasePriceCents: 8500, + notes: "Custom-fitted to Surly Bridge Club 54cm frame.", + quantity: 1, + }, + { + globalItemIndex: null, + categoryName: "Cooking", + name: "Folding Titanium Spork", + weightGrams: 18, + priceCents: 1200, + purchasePriceCents: null, + notes: null, + quantity: 2, + }, + { + globalItemIndex: null, + categoryName: "Tools & Repair", + name: "Spare Inner Tubes 700x28-35", + weightGrams: 125, + priceCents: 800, + purchasePriceCents: null, + notes: "Schwalbe SV17, presta valve.", + quantity: 2, + }, + { + globalItemIndex: null, + categoryName: "Clothing", + name: "Pearl Izumi AmFIB Lobster Gloves", + weightGrams: 180, + priceCents: 6000, + purchasePriceCents: 4500, + notes: "Essential for shoulder-season rides below 5C.", + quantity: 1, + }, + { + globalItemIndex: null, + categoryName: "Electronics", + name: "USB-C to Micro-USB Adapter", + weightGrams: 3, + priceCents: 500, + purchasePriceCents: null, + notes: "For charging Garmin inReach Mini 2.", + quantity: 2, + }, + { + globalItemIndex: null, + categoryName: "Sleep System", + name: "Sea to Summit Aeros UL Pillow", + weightGrams: 60, + priceCents: 4000, + purchasePriceCents: 3800, + notes: null, + quantity: 1, + }, + { + globalItemIndex: null, + categoryName: "Water", + name: "Nalgene Wide Mouth 1L", + weightGrams: 179, + priceCents: 1200, + purchasePriceCents: null, + notes: "Backup water carry, also doubles as hot water bottle in sleep system.", + quantity: 1, + }, +] as const; + +// ── Threads ──────────────────────────────────────────────────────── + +export const DEV_THREADS = [ + { + name: "Handlebar Bag Upgrade", + status: "active", + categoryName: "Bags", + candidates: [ + { + name: "Apidura Expedition Handlebar Pack", + globalItemIndex: 1 as number | null, + weightGrams: 300, + priceCents: 16000, + status: "shortlisted", + pros: "Proven waterproof design, 14L capacity, integrated dry bag", + cons: "Heavier than competitors, price premium", + notes: "Widely used in ultra-endurance racing.", + sortOrder: 1, + }, + { + name: "Rockgeist BarJam", + globalItemIndex: 3, + weightGrams: 142, + priceCents: 9900, + status: "researching", + pros: "Ultra-light, modular, supports various dry bags", + cons: "Requires separate dry bag, less total protection", + notes: "Need to factor in dry bag weight.", + sortOrder: 2, + }, + { + name: "Oveja Negra Bootlegger 2.0", + globalItemIndex: null, + weightGrams: 200, + priceCents: 11500, + status: "researching", + pros: "Good build quality, middle-weight option", + cons: "Smaller capacity than Apidura", + notes: null, + sortOrder: 3, + }, + ], + }, + { + name: "Navigation Computer", + status: "active", + categoryName: "Navigation", + candidates: [ + { + name: "Wahoo ELEMNT ROAM V2", + globalItemIndex: null, + weightGrams: 95, + priceCents: 39999, + status: "shortlisted", + pros: "Color display, long battery, excellent navigation", + cons: "Expensive, heavier than BOLT", + notes: "Considering upgrading from BOLT V2.", + sortOrder: 1, + }, + { + name: "Hammerhead Karoo 3", + globalItemIndex: null, + weightGrams: 132, + priceCents: 49999, + status: "researching", + pros: "Touchscreen, Android-based, great mapping", + cons: "Heaviest option, most expensive, battery life concerns", + notes: null, + sortOrder: 2, + }, + ], + }, + { + name: "Camp Stove", + status: "resolved", + categoryName: "Cooking", + candidates: [ + { + name: "Soto WindMaster", + globalItemIndex: 16 as number | null, + weightGrams: 67, + priceCents: 7500, + status: "arrived", + pros: "Excellent wind performance, micro-regulator, reliable ignition", + cons: "Slightly heavier than BRS-3000T", + notes: "Winner! Ordered from REI.", + sortOrder: 1, + }, + { + name: "MSR PocketRocket Deluxe", + globalItemIndex: 19, + weightGrams: 83, + priceCents: 6000, + status: "researching", + pros: "Pressure regulator, push-start ignition", + cons: "Heaviest option, no clear wind advantage over Soto", + notes: null, + sortOrder: 2, + }, + ], + // resolvedCandidateIndex: 0 — the Soto WindMaster wins + resolvedCandidateIndex: 0, + }, +] as const; + +// ── Setups ───────────────────────────────────────────────────────── +// itemIndices: indices into DEV_USER_ITEMS for FK lookup + +export const DEV_SETUPS = [ + { + name: "Weekend Overnighter", + isPublic: true, + items: [ + { userItemIndex: 0, classification: "base" }, // Terrapin saddle bag + { userItemIndex: 3, classification: "base" }, // X-Mid 1 + { userItemIndex: 4, classification: "base" }, // EE Enigma + { userItemIndex: 5, classification: "base" }, // NeoAir XLite + { userItemIndex: 6, classification: "consumable" }, // BRS stove + { userItemIndex: 7, classification: "worn" }, // Nitecore NU25 + { userItemIndex: 8, classification: "consumable" }, // Sawyer Squeeze + { userItemIndex: 9, classification: "base" }, // Wahoo BOLT + ], + }, + { + name: "Ultra-Light Day Ride", + isPublic: false, + items: [ + { userItemIndex: 2, classification: "base" }, // Top tube pack + { userItemIndex: 7, classification: "worn" }, // Nitecore NU25 + { userItemIndex: 9, classification: "base" }, // Wahoo BOLT + { userItemIndex: 16, classification: "consumable" }, // Nalgene + ], + }, +] as const; + +// ── Settings ─────────────────────────────────────────────────────── + +export const DEV_SETTINGS = [ + { key: "weightUnit", value: "g" }, + { key: "currency", value: "EUR" }, +] as const;