import { useState, useMemo } from 'react'; import { usePileCapStore } from '../../store/pileCapStore'; import { calculatePileReactions } from '../../calculations/pileReactions'; import { calculateLoadCombinations, calculateServiceCombinations } from '../../calculations/loadCombinations'; import { DraggableLabel } from './DraggableLabel'; // import type { LoadCombinationResult } from '../../types/pileCap'; export const PileReactionsDiagram = () => { const geometry = usePileCapStore(state => state.geometry); const loads = usePileCapStore(state => state.loads); const design = usePileCapStore(state => state.design); // Global Diagram State const isLocked = usePileCapStore(state => state.diagramState.isLocked); const labelPositions = usePileCapStore(state => state.diagramState.labelPositions); const setDiagramLocked = usePileCapStore(state => state.setDiagramLocked); const updateLabelPosition = usePileCapStore(state => state.updateLabelPosition); const getLabelPos = (id: string, defaultX: number, defaultY: number) => { return labelPositions[id] || { x: defaultX, y: defaultY }; }; const [combType, setCombType] = useState<'service' | 'factored'>('service'); const [selectedCombName, setSelectedCombName] = useState(''); // Calculate combinations based on type const combinations = useMemo(() => { return combType === 'service' ? calculateServiceCombinations(loads.cases) : calculateLoadCombinations(loads.cases); }, [loads.cases, combType]); // Select default combination if none selected or invalid useMemo(() => { if (combinations.length > 0) { const exists = combinations.find(c => c.combinationName === selectedCombName); if (!exists) { setSelectedCombName(combinations[0].combinationName); } } }, [combinations, selectedCombName]); const activeCombination = combinations.find(c => c.combinationName === selectedCombName) || combinations[0]; // Calculate reactions for active combination const pileReactions = useMemo(() => { if (!activeCombination) return []; return calculatePileReactions(geometry, activeCombination, design); }, [geometry, activeCombination, design]); const maxReaction = Math.max(...pileReactions.map(p => p.reaction), 0); // const minReaction = Math.min(...pileReactions.map(p => p.reaction), 0); // --- Drawing Logic --- const scale = 35; const padding = 60; // Plan View Dimensions const planWidth = geometry.length * scale; const planHeight = geometry.width * scale; // Elevation View Dimensions const elevHeight = (geometry.depth / 12 + 4) * scale; // Cap + piles // Total SVG Size const svgWidth = planWidth + 2 * padding + 100; // Extra for legend/labels const svgHeight = planHeight + elevHeight + 3 * padding; const planOriginX = padding + 50; const planOriginY = padding + elevHeight + 20; const elevOriginX = planOriginX; const elevOriginY = padding; // Helper for pile color const getPileColor = (reaction: number) => { if (reaction < 0) return '#ffcccc'; // Uplift const ratio = maxReaction > 0 ? reaction / maxReaction : 0; const opacity = 0.1 + (ratio * 0.9); return `rgba(255, 165, 0, ${opacity})`; // Orange base to match user image }; return (
{/* Controls */}
{/* Diagram */}
{/* --- Elevation View --- */} {/* Cap */} {/* Column */} {/* Piles (Projected) */} {Array.from({ length: geometry.pileColumns }).map((_, col) => { const x = ((geometry.length - (geometry.pileColumns - 1) * geometry.pileSpacingX) / 2 + col * geometry.pileSpacingX) * scale; const w = (geometry.pileSize / 12) * scale; return ( ); })} {/* Dimensions */} {/* Depth */} {/* Column Height above cap (arbitrary 3ft in user image) */} {/* --- Plan View --- */} {/* Cap Outline */} {/* Centerlines */} {/* Column */} {/* Piles & Reactions */} {pileReactions.map((p, i) => { // Transform coordinates relative to top-left of cap // p.x is from left edge, p.y is from bottom edge (standard math coords) // But SVG y is from top. // Wait, PileReaction definition: y: number; // ft from bottom edge // So SVG y = height - p.y * scale // Let's verify startY calculation in pileReactions.ts // startY = (width - ...)/2. This is from "bottom" if we assume standard grid generation. // Let's assume p.y is from bottom. const px = p.x * scale; const py = (geometry.width - p.y) * scale; // Flip Y for SVG const pileRadius = (geometry.pileSize / 12 / 2) * scale; return ( ); })} {/* Dimensions */} {/* Width */} {/* Length */}
); };