init
This commit is contained in:
85
src/components/Workspace.jsx
Normal file
85
src/components/Workspace.jsx
Normal file
@@ -0,0 +1,85 @@
|
||||
import { useDroppable } from '@dnd-kit/core'
|
||||
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,
|
||||
}) {
|
||||
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>
|
||||
) : (
|
||||
<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}
|
||||
/>
|
||||
))}
|
||||
{/* 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>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user