init
This commit is contained in:
173
src/pages/Solver.jsx
Normal file
173
src/pages/Solver.jsx
Normal file
@@ -0,0 +1,173 @@
|
||||
import { DndContext, DragOverlay, PointerSensor, useSensor, useSensors } from '@dnd-kit/core'
|
||||
import { useState } from 'react'
|
||||
import { VariablePalette } from '../components/VariablePalette.jsx'
|
||||
import { Workspace } from '../components/Workspace.jsx'
|
||||
import { ResultsPanel } from '../components/ResultsPanel.jsx'
|
||||
import { PaletteCard } from '../components/VariableCard.jsx'
|
||||
import { PropellantModal } from '../components/PropellantModal.jsx'
|
||||
import { EquationBrowser } from '../components/EquationBrowser.jsx'
|
||||
import { useSolver } from '../hooks/useSolver.js'
|
||||
import { EQUATIONS } from '../engine/equations.js'
|
||||
import { buildExportData, exportJSON, parseImport, downloadBlob } from '../engine/exportImport.js'
|
||||
import { generateOdt } from '../engine/exportOdt.js'
|
||||
|
||||
export default function Solver() {
|
||||
const {
|
||||
workspaceVarIds,
|
||||
userValues,
|
||||
solved,
|
||||
missingReport,
|
||||
allKnown,
|
||||
unitSelections,
|
||||
getUnit,
|
||||
setUnit,
|
||||
sciNotation,
|
||||
toggleSciNotation,
|
||||
addVariable,
|
||||
addVariables,
|
||||
removeVariable,
|
||||
setValue,
|
||||
addPreset,
|
||||
applyPropellant,
|
||||
clearWorkspace,
|
||||
importWorkspace,
|
||||
} = useSolver()
|
||||
|
||||
const [activeVarId, setActiveVarId] = useState(null)
|
||||
const [showPropellants, setShowPropellants] = useState(false)
|
||||
const [showEquations, setShowEquations] = useState(false)
|
||||
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor, { activationConstraint: { distance: 6 } })
|
||||
)
|
||||
|
||||
function handleDragStart(event) {
|
||||
const { varId } = event.active.data.current ?? {}
|
||||
if (varId) setActiveVarId(varId)
|
||||
}
|
||||
|
||||
function handleDragEnd(event) {
|
||||
const { over, active } = event
|
||||
if (over?.id === 'workspace') {
|
||||
const { varId } = active.data.current ?? {}
|
||||
if (varId) addVariable(varId)
|
||||
}
|
||||
setActiveVarId(null)
|
||||
}
|
||||
|
||||
async function handleExportOdt() {
|
||||
const data = buildExportData(workspaceVarIds, userValues, solved, unitSelections, getUnit, sciNotation)
|
||||
const blob = await generateOdt(data)
|
||||
downloadBlob(blob, 'rocketry-workspace.odt')
|
||||
}
|
||||
|
||||
function handleExportJSON() {
|
||||
const data = buildExportData(workspaceVarIds, userValues, solved, unitSelections, getUnit, sciNotation)
|
||||
const blob = exportJSON(data, workspaceVarIds, userValues, unitSelections)
|
||||
downloadBlob(blob, 'rocketry-workspace.json')
|
||||
}
|
||||
|
||||
function handleImportJSON(jsonString) {
|
||||
try {
|
||||
const workspace = parseImport(jsonString)
|
||||
importWorkspace(workspace)
|
||||
} catch (err) {
|
||||
alert(`Import failed: ${err.message}`)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<DndContext sensors={sensors} onDragStart={handleDragStart} onDragEnd={handleDragEnd}>
|
||||
<div className="flex flex-1 min-h-0 overflow-hidden flex-col">
|
||||
{/* Solver sub-header */}
|
||||
<div className="flex items-center gap-2 px-5 py-2 border-b border-slate-700 bg-slate-900 shrink-0">
|
||||
<p className="text-xs text-slate-400">
|
||||
Add variables, enter known values, and unknowns solve automatically.
|
||||
</p>
|
||||
<div className="ml-auto flex items-center gap-2">
|
||||
<button
|
||||
onClick={toggleSciNotation}
|
||||
title="Toggle scientific notation"
|
||||
className={`flex items-center gap-1.5 px-3 py-2 rounded-lg border text-sm font-medium transition-colors ${
|
||||
sciNotation
|
||||
? 'bg-blue-700 border-blue-500 text-white'
|
||||
: 'bg-slate-700 border-slate-600 text-slate-300 hover:bg-slate-600 hover:border-slate-500'
|
||||
}`}
|
||||
>
|
||||
10ˣ
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShowEquations(true)}
|
||||
className="flex items-center gap-2 px-4 py-2 rounded-lg bg-slate-700 hover:bg-slate-600 border border-slate-600 hover:border-slate-500 text-sm text-slate-200 font-medium transition-colors"
|
||||
>
|
||||
<span>∑</span> Equations
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShowPropellants(true)}
|
||||
className="flex items-center gap-2 px-4 py-2 rounded-lg bg-slate-700 hover:bg-slate-600 border border-slate-600 hover:border-slate-500 text-sm text-slate-200 font-medium transition-colors"
|
||||
>
|
||||
<span>⛽</span> Propellants
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Three-panel layout */}
|
||||
<div className="flex flex-1 min-h-0 overflow-hidden">
|
||||
<VariablePalette
|
||||
workspaceVarIds={workspaceVarIds}
|
||||
onAddVariable={addVariable}
|
||||
/>
|
||||
<Workspace
|
||||
workspaceVarIds={workspaceVarIds}
|
||||
userValues={userValues}
|
||||
solved={solved}
|
||||
onRemove={removeVariable}
|
||||
onValueChange={setValue}
|
||||
onAddPreset={addPreset}
|
||||
onClear={clearWorkspace}
|
||||
getUnit={getUnit}
|
||||
setUnit={setUnit}
|
||||
sciNotation={sciNotation}
|
||||
/>
|
||||
<ResultsPanel
|
||||
workspaceVarIds={workspaceVarIds}
|
||||
userValues={userValues}
|
||||
solved={solved}
|
||||
missingReport={missingReport}
|
||||
getUnit={getUnit}
|
||||
sciNotation={sciNotation}
|
||||
onExportOdt={handleExportOdt}
|
||||
onExportJSON={handleExportJSON}
|
||||
onImportJSON={handleImportJSON}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{showPropellants && (
|
||||
<PropellantModal
|
||||
onClose={() => setShowPropellants(false)}
|
||||
onApply={applyPropellant}
|
||||
existingVarIds={workspaceVarIds}
|
||||
/>
|
||||
)}
|
||||
|
||||
{showEquations && (
|
||||
<EquationBrowser
|
||||
equations={EQUATIONS}
|
||||
allKnown={allKnown}
|
||||
workspaceVarIds={workspaceVarIds}
|
||||
onAddVariables={varIds => addVariables(varIds)}
|
||||
onClose={() => setShowEquations(false)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<DragOverlay dropAnimation={null}>
|
||||
{activeVarId ? (
|
||||
<div className="opacity-90 rotate-2 scale-105">
|
||||
<PaletteCard varId={activeVarId} isInWorkspace={false} />
|
||||
</div>
|
||||
) : null}
|
||||
</DragOverlay>
|
||||
</DndContext>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user