Files
GearBox/src/db/dev-seed-data.ts
Jean-Luc Makiola 3f3c08c512
Some checks failed
CI / ci (push) Failing after 12s
CI / e2e (push) Has been skipped
fix: format phase 22 worktree files that were committed unformatted
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:49:09 +02:00

745 lines
20 KiB
TypeScript

// ── 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", "bike-bag"] },
{ globalItemIndex: 1, tagNames: ["handlebar-bag", "bike-bag"] },
{ globalItemIndex: 2, tagNames: ["framebag", "bike-bag"] },
{ globalItemIndex: 3, tagNames: ["handlebar-bag", "bike-bag"] },
{ globalItemIndex: 4, tagNames: ["framebag", "bike-bag"] },
{ globalItemIndex: 5, tagNames: ["top-tube-bag", "bike-bag"] },
{ globalItemIndex: 6, tagNames: ["tent"] },
{ globalItemIndex: 7, tagNames: ["tent"] },
{ globalItemIndex: 8, tagNames: ["tent"] },
{ globalItemIndex: 9, tagNames: ["tent"] },
{ globalItemIndex: 10, tagNames: ["quilt"] },
{ globalItemIndex: 11, tagNames: ["sleeping-pad"] },
{ globalItemIndex: 12, tagNames: ["sleeping-pad"] },
{ globalItemIndex: 13, tagNames: ["pillow"] },
{ globalItemIndex: 14, tagNames: ["sleeping-bag"] },
{ globalItemIndex: 15, tagNames: ["stove"] },
{ globalItemIndex: 16, tagNames: ["stove"] },
{ globalItemIndex: 17, tagNames: ["cookware", "mug"] },
{ globalItemIndex: 18, tagNames: ["cookware"] },
{ globalItemIndex: 19, tagNames: ["stove"] },
{ globalItemIndex: 20, tagNames: ["headlamp"] },
{ globalItemIndex: 21, tagNames: ["bike-light"] },
{ globalItemIndex: 22, tagNames: ["headlamp"] },
{ globalItemIndex: 29, tagNames: ["water-filter"] },
{ globalItemIndex: 30, tagNames: ["water-filter"] },
{ globalItemIndex: 31, tagNames: ["water-bottle"] },
{ globalItemIndex: 32, tagNames: ["multi-tool", "repair-kit"] },
{ globalItemIndex: 33, tagNames: ["rain-jacket"] },
{ globalItemIndex: 34, tagNames: ["bike-computer", "gps"] },
{ globalItemIndex: 35, tagNames: ["handlebar-bag", "bike-bag", "dry-bag"] },
] as const;
// ── Category name mapping (for FK lookups by category name) ────────
const CATEGORY_MAP: Record<string, string> = {
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: "researching",
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: "researching",
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;