import { useState, useMemo } from 'react' import { SUBSTANCES, COMBINATIONS } from '../engine/knowledgebaseData.js' // ── Helpers ────────────────────────────────────────────────────────────────── const ROLE_FILTERS = ['All', 'Fuels', 'Oxidisers', 'Monopropellants'] const SUBCATEGORY_FILTERS = ['Cryogenic', 'Storable', 'Hypergolic', 'Green', 'Solid', 'Hybrid'] function roleBadgeClass(role) { if (role === 'fuel') return 'bg-blue-900 text-blue-200 border border-blue-700' if (role === 'oxidiser') return 'bg-orange-900 text-orange-200 border border-orange-700' return 'bg-yellow-900 text-yellow-200 border border-yellow-700' } function roleLabel(role) { if (role === 'fuel') return 'FUEL' if (role === 'oxidiser') return 'OXIDISER' return 'MONOPROPELLANT' } function subcategoryBadgeClass(sub) { const map = { Cryogenic: 'bg-cyan-900 text-cyan-200 border border-cyan-700', Storable: 'bg-slate-700 text-slate-200 border border-slate-500', Hypergolic: 'bg-red-900 text-red-200 border border-red-700', Green: 'bg-green-900 text-green-200 border border-green-700', Solid: 'bg-amber-900 text-amber-200 border border-amber-700', Hybrid: 'bg-purple-900 text-purple-200 border border-purple-700', } return map[sub] ?? 'bg-slate-700 text-slate-200 border border-slate-500' } function PropRow({ label, value }) { if (value === null || value === undefined) return null return (
{label} {value}
) } // ── Main page ──────────────────────────────────────────────────────────────── export default function KnowledgebaseFuelsPage() { const [search, setSearch] = useState('') const [roleFilter, setRoleFilter] = useState('All') const [subcatFilter, setSubcatFilter] = useState(null) const [selectedId, setSelectedId] = useState(SUBSTANCES[0].id) // Filtered list const filtered = useMemo(() => { const q = search.toLowerCase() return SUBSTANCES.filter(s => { if (q && !s.name.toLowerCase().includes(q) && !s.symbol.toLowerCase().includes(q) && !s.formula.toLowerCase().includes(q)) return false if (roleFilter === 'Fuels' && s.role !== 'fuel') return false if (roleFilter === 'Oxidisers' && s.role !== 'oxidiser') return false if (roleFilter === 'Monopropellants' && s.role !== 'monopropellant') return false if (subcatFilter && s.subcategory !== subcatFilter) return false return true }) }, [search, roleFilter, subcatFilter]) const selected = SUBSTANCES.find(s => s.id === selectedId) ?? SUBSTANCES[0] // Combinations for the selected substance const combinations = useMemo(() => { if (selected.role === 'monopropellant') return [] return COMBINATIONS.filter(c => (selected.role === 'fuel' && c.fuelId === selected.id) || (selected.role === 'oxidiser' && c.oxidiserId === selected.id) ) }, [selected]) // Get partner substance for each combination function getPartner(combo) { const partnerId = selected.role === 'fuel' ? combo.oxidiserId : combo.fuelId return SUBSTANCES.find(s => s.id === partnerId) } // Ensure selected item is still in filtered list; if not, show first filtered const effectiveSelected = filtered.find(s => s.id === selectedId) ? selected : (filtered[0] ?? selected) return (
{/* ── Left panel ────────────────────────────────────────────────────── */}
{/* Search */}
setSearch(e.target.value)} className="w-full px-3 py-1.5 rounded-md bg-slate-800 border border-slate-600 text-sm text-slate-100 placeholder-slate-500 focus:outline-none focus:border-blue-500" />
{/* Role filter pills */}
{ROLE_FILTERS.map(r => ( ))}
{/* Subcategory filter pills */}
{SUBCATEGORY_FILTERS.map(sc => ( ))}
{/* Substance list */}
{filtered.length === 0 && (

No substances match your filters.

)} {filtered.map(s => ( ))}
{/* ── Right panel ───────────────────────────────────────────────────── */}
) } // ── Substance detail view ──────────────────────────────────────────────────── function SubstanceDetail({ substance: s, combinations, getPartner }) { return (
{/* Header */}

{s.name}

{s.symbol}
{roleLabel(s.role)} {s.subcategory}
{/* Description */}

{s.description}

{/* Technical specs */}

Technical Specifications

{s.catalyticIsp != null && ( )}
{/* Engine examples */} {s.engineExamples?.length > 0 && (

Engine / Motor Examples

{s.engineExamples.join(', ')}

)} {/* Combinations */} {s.role !== 'monopropellant' && (

Bipropellant Combinations

{combinations.length === 0 ? (

No combination data available for this substance.

) : (
{combinations.map((combo, i) => { const partner = getPartner(combo) const partnerLabel = s.role === 'fuel' ? `with ${partner?.name ?? combo.oxidiserId} (oxidiser)` : `with ${partner?.name ?? combo.fuelId} (fuel)` return (
{partnerLabel} {combo.energeticCategory} {combo.isHypergolic && ( Hypergolic )}
{combo.notes && (

{combo.notes}

)} {combo.engines?.length > 0 && (

Engines: {combo.engines.join(', ')}

)}
) })}
)}
)}
) } function Stat({ label, value }) { return (
{label}
{value}
) }