Files
rocketry/src/components/Workspace.jsx
2026-03-03 20:30:29 +00:00

93 lines
3.6 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useDroppable } from '@dnd-kit/core'
import { SortableContext, rectSortingStrategy } from '@dnd-kit/sortable'
import { EQUATION_PRESETS } from '../engine/equations.js'
import { WorkspaceCard } from './VariableCard.jsx'
export function Workspace({
workspaceVarIds,
userValues,
solved,
onRemove,
onValueChange,
onAddPreset,
onClear,
getUnit,
setUnit,
sciNotation,
areaRatioBranch,
onToggleAreaRatioBranch,
}) {
const { setNodeRef, isOver } = useDroppable({ id: 'workspace' })
return (
<main className="flex flex-col flex-1 min-w-0 h-full overflow-hidden">
{/* Equation preset bar */}
<div className="flex flex-wrap gap-2 px-4 py-3 border-b border-slate-700 bg-slate-900 shrink-0">
<span className="text-xs text-slate-500 self-center mr-1 uppercase tracking-wide">Presets:</span>
{EQUATION_PRESETS.map(preset => (
<button
key={preset.id}
onClick={() => onAddPreset(preset.id)}
className="px-3 py-1 rounded-full text-xs font-medium bg-slate-700 text-slate-300 hover:bg-blue-700 hover:text-white border border-slate-600 hover:border-blue-500 transition-colors"
>
{preset.label}
</button>
))}
{workspaceVarIds.length > 0 && (
<button
onClick={onClear}
className="ml-auto px-3 py-1 rounded-full text-xs font-medium bg-slate-800 text-red-400 hover:bg-red-900 hover:text-red-200 border border-slate-600 hover:border-red-600 transition-colors"
>
Clear all
</button>
)}
</div>
{/* Drop zone */}
<div
ref={setNodeRef}
className={`flex-1 overflow-y-auto p-4 transition-colors ${isOver ? 'bg-blue-950/20' : ''}`}
>
{workspaceVarIds.length === 0 ? (
<div className={`flex flex-col items-center justify-center h-full text-center transition-colors ${isOver ? 'text-blue-400' : 'text-slate-600'}`}>
<div className="text-5xl mb-4"></div>
<div className="text-lg font-semibold mb-2">
{isOver ? 'Drop variable here' : 'Workspace is empty'}
</div>
<div className="text-sm max-w-xs">
Drag variables from the left panel, or click a preset above to get started.
Enter known values unknowns solve automatically.
</div>
</div>
) : (
<SortableContext items={workspaceVarIds} strategy={rectSortingStrategy}>
<div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-3 content-start">
{workspaceVarIds.map(varId => (
<WorkspaceCard
key={varId}
varId={varId}
userValue={userValues[varId]}
solvedInfo={solved[varId]}
onRemove={() => onRemove(varId)}
onValueChange={val => onValueChange(varId, val)}
getUnit={getUnit}
onUnitChange={unitId => setUnit(varId, unitId)}
sciNotation={sciNotation}
areaRatioBranch={areaRatioBranch}
onToggleBranch={onToggleAreaRatioBranch}
/>
))}
{/* Drop indicator card when dragging over a non-empty workspace */}
{isOver && (
<div className="rounded-xl border-2 border-dashed border-blue-500 bg-blue-950/30 p-3 flex items-center justify-center text-blue-400 text-sm min-h-[100px]">
Drop here
</div>
)}
</div>
</SortableContext>
)}
</div>
</main>
)
}