dragging and dropping blocks. ontaining mutiple coloumn should also show up mutiple colomuns and also they all should act as a single ebtity and moving 
"""
// App.js
import React, { useState, useCallback, useRef } from 'react';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import Header from './Header';
import WorkoutBlocks from './WorkoutBlocks';
import Graph from './Graph';
import ColumnsList from './ColumnsList';

function App() {
  const [graphBlocks, setGraphBlocks] = useState([]);
  const idRef = useRef(0); // Persistent ID counter

  // Function to add a new block to the Graph at a specific index
  const addBlockToGraph = useCallback((block, index = graphBlocks.length) => {
    if (!block || !block.type || typeof block.height !== 'number') {
      console.error('Invalid block:', block);
      return;
    }

    const newBlock = { ...block, id: idRef.current++ };
    setGraphBlocks((prevBlocks) => {
      const updatedBlocks = [...prevBlocks];
      const insertIndex =
        index >= 0 && index <= updatedBlocks.length ? index : updatedBlocks.length;
      updatedBlocks.splice(insertIndex, 0, newBlock);
      return updatedBlocks;
    });
  }, [graphBlocks.length]);

  // Function to move (rearrange) a block within the Graph
  const moveGraphBlock = useCallback((dragIndex, hoverIndex) => {
    setGraphBlocks((prevBlocks) => {
      const updatedBlocks = [...prevBlocks];
      const [removed] = updatedBlocks.splice(dragIndex, 1);
      updatedBlocks.splice(hoverIndex, 0, removed);
      return updatedBlocks;
    });
  }, []);


  return (
    <DndProvider backend={HTML5Backend}>
      <div className="justify-center min-h-screen bg-[#F8F8F8] w-full p-4">
        <Header />

        {/* Main content */}
        <div className="flex justify-between mx-6 my-3 items-start">
          {/* Workout blocks card */}
          <WorkoutBlocks />

          {/* Graph and Columns List */}
          <div className="w-full ml-6">
            <Graph
              blocks={graphBlocks}
              addBlockToGraph={addBlockToGraph}
              moveBlock={moveGraphBlock}
            />
            <ColumnsList blocks={graphBlocks} />
          </div>
        </div>
      </div>
    </DndProvider>
  );
}

export default App;
"""
"""
// Graph.js
import React from 'react';
import GraphBlock from './GraphBlock';
import { useDrop } from 'react-dnd';
import { ItemTypes } from './constants';

const Graph = ({ blocks, addBlockToGraph, moveBlock, removeBlock }) => {
  // Universal drop target for adding to empty graph or at the end
  const [{ isOver, canDrop }, drop] = useDrop({
    accept: ItemTypes.WORKOUT_BLOCK,
    drop: (item, monitor) => {
      if (!monitor.didDrop()) {
        // If dropped directly on the graph (not on a GraphBlock), add to the end
        addBlockToGraph(item, blocks.length);
      }
    },
    canDrop: (item, monitor) => {
      return true; // Allow dropping
    },
    collect: (monitor) => ({
      isOver: monitor.isOver(),
      canDrop: monitor.canDrop(),
    }),
  });

  const isActive = isOver && canDrop;

  return (
    <div
      ref={drop} // Universal drop target
      className={`graph-container relative w-full h-[300px] bg-[#EAEAEA] rounded-lg shadow-md p-4 mb-4 ${
        isActive ? 'bg-[#D3D3D3]' : ''
      }`}
    >
      {/* Bar Graph */}
      <div className="absolute inset-0 flex items-end space-x-2 px-2">
        {blocks.map((block, index) => (
          <GraphBlock
            key={block.id}
            id={block.id}
            index={index}
            block={block}
            moveBlock={moveBlock}
            removeBlock={removeBlock}
            addBlockToGraph={addBlockToGraph}
            totalBlocks={blocks.length}
          />
        ))}
      </div>

      {/* X-Axis Labels */}
      <div className="absolute bottom-0 w-full flex justify-between text-xs mt-1">
        {blocks.map((_, index) => (
          <span key={index}>{index + 1} km</span>
        ))}
      </div>

      {/* Y-Axis Labels */}
      <div className="absolute left-0 top-0 h-full flex flex-col justify-between text-xs mr-1">
        <span>100%</span>
        <span>75%</span>
        <span>50%</span>
        <span>25%</span>
        <span>0%</span>
      </div>
    </div>
  );
};

export default Graph;
"""
""
// GraphBlock.js
import React, { useRef } from 'react';
import { useDrag, useDrop } from 'react-dnd';
import { ItemTypes } from './constants';

const GraphBlock = ({
  id,
  index,
  block,
  moveBlock,
  removeBlock,
  addBlockToGraph,
  totalBlocks,
}) => {
  const ref = useRef(null);

  // useDrag setup for existing GraphBlocks
  const [{ isDragging }, drag] = useDrag({
    type: ItemTypes.GRAPH_BLOCK,
    item: { type: ItemTypes.GRAPH_BLOCK, id, index },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  });

  // useDrop setup for GraphBlocks to handle both moving and inserting
  const [, drop] = useDrop({
    accept: [ItemTypes.GRAPH_BLOCK, ItemTypes.WORKOUT_BLOCK],
    hover(item, monitor) {
      if (!ref.current) {
        return;
      }

      const dragType = item.type;

      if (dragType === ItemTypes.GRAPH_BLOCK) {
        const dragIndex = item.index;
        const hoverIndex = index;

        if (dragIndex === hoverIndex) {
          return;
        }

        // Determine rectangle on screen
        const hoverBoundingRect = ref.current.getBoundingClientRect();
        // Get horizontal middle
        const hoverMiddleX = (hoverBoundingRect.right - hoverBoundingRect.left) / 2;
        // Determine mouse position
        const clientOffset = monitor.getClientOffset();
        // Get pixels to the left
        const hoverClientX = clientOffset.x - hoverBoundingRect.left;

        // Only perform move when the mouse has crossed half of the item's width
        // When dragging to the left, only move when the cursor is less than middle
        if (dragIndex < hoverIndex && hoverClientX < hoverMiddleX) {
          return;
        }
        // When dragging to the right, only move when the cursor is more than middle
        if (dragIndex > hoverIndex && hoverClientX > hoverMiddleX) {
          return;
        }

        // Perform the move
        moveBlock(dragIndex, hoverIndex);

        // Note: we're mutating the monitor item here!
        // Generally it's better to avoid mutations,
        // but it's good here for the sake of performance to avoid expensive index searches.
        item.index = hoverIndex;
      }
    },
    drop(item, monitor) {
      if (item.type === ItemTypes.WORKOUT_BLOCK) {
        const clientOffset = monitor.getClientOffset();
        const hoverBoundingRect = ref.current.getBoundingClientRect();
        const hoverMiddleX = (hoverBoundingRect.right - hoverBoundingRect.left) / 2;
        const hoverClientX = clientOffset.x - hoverBoundingRect.left;

        const insertIndex = hoverClientX < hoverMiddleX ? index : index + 1;

        addBlockToGraph(item, insertIndex);
      }
    },
    collect: (monitor) => ({
      isOver: monitor.isOver(),
      canDrop: monitor.canDrop(),
    }),
  });

  // Connect drag and drop
  drag(drop(ref));

  const handleRemove = () => {
    removeBlock(id);
  };

  return (
    <div
      ref={ref}
      className={`relative bg-[#4339F280] rounded cursor-move flex flex-col items-center transition-all duration-200
        ${isDragging ? 'opacity-50' : 'opacity-100'}
      `}
      style={{
        width: `calc(${100 / totalBlocks}% - 8px)`, // Even width distribution
        height: `${block.height}%`,
        marginRight: index !== totalBlocks - 1 ? '8px' : '0',
        border: '', // Can add conditional border based on hover if desired
      }}
    >
      {/* Remove Button */}
      <button
        onClick={handleRemove}
        className="absolute top-1 right-1 text-red-500 hover:text-red-700 text-xs"
        title="Remove Block"
      >
        &times;
      </button>
    </div>
  );
};

export default GraphBlock;
"""
"""
// WorkoutBlocks.js
import React from 'react';
import { useDrag } from 'react-dnd';
import { FiInfo } from 'react-icons/fi';

const WorkoutBlock = ({ children, type, height }) => {
  const [{ isDragging }, drag] = useDrag({
    type: 'WORKOUT_BLOCK', // Ensure the type matches what's accepted in Graph.js and GraphBlock.js
    item: { type, height },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  });

  return (
    <div
      ref={drag}
      className={`relative bg-gray-200 rounded-lg overflow-hidden h-20 cursor-pointer ${
        isDragging ? 'opacity-50' : 'opacity-100'
      }`}
    >
      {children}
    </div>
  );
};

const WorkoutBlocks = () => {
  return (
    <div className="bg-white p-6 rounded-lg shadow-md max-w-sm w-full">
      <div className="flex justify-between items-center mb-3">
        <h2 className="text-lg font-semibold">Click or drag the blocks to build workout</h2>
        <FiInfo className="text-gray-400 text-2xl" />
      </div>

      <hr className="border-gray-300 mb-4" />

      <div className="grid grid-cols-2 gap-3">
        <WorkoutBlock type="block50" height={50}>
          <div className="absolute bottom-0 w-full h-1/2" style={{ background: '#4339F280' }}></div>
        </WorkoutBlock>

        <WorkoutBlock type="block75" height={75}>
          <div className="absolute bottom-0 w-full h-3/4" style={{ background: '#4339F280' }}></div>
        </WorkoutBlock>

        <WorkoutBlock type="block30" height={30}>
          <div className="absolute bottom-0 w-full h-1/3" style={{ background: '#4339F280' }}></div>
        </WorkoutBlock>

        {/* Single block with two columns */}
        <WorkoutBlock type="block60_40" height={60}>
          <div className="flex h-full gap-1 transform scale-y-[-1] ">
            <div className="w-1/2 h-3/5" style={{ background: '#4339F280' }}></div>
            <div className="w-1/2 h-2/5" style={{ background: '#4339F280' }}></div>
          </div>
        </WorkoutBlock>

        {/* Single block with four columns */}
        <WorkoutBlock type="block80_60_40_20" height={80}>
          <div className="flex h-full gap-1 transform scale-y-[-1]">
            <div className="w-1/4 h-1/5" style={{ background: '#4339F280' }}></div>
            <div className="w-1/4 h-2/5" style={{ background: '#4339F280' }}></div>
            <div className="w-1/4 h-3/5" style={{ background: '#4339F280' }}></div>
            <div className="w-1/4 h-4/5" style={{ background: '#4339F280' }}></div>
          </div>
        </WorkoutBlock>

        {/* Another single block with reversed four columns */}
        <WorkoutBlock type="block20_40_60_80" height={20}>
          <div className="flex h-full gap-1 transform scale-y-[-1] ">
            <div className="w-1/4 h-4/5" style={{ background: '#4339F280' }}></div>
            <div className="w-1/4 h-3/5" style={{ background: '#4339F280' }}></div>
            <div className="w-1/4 h-2/5" style={{ background: '#4339F280' }}></div>
            <div className="w-1/4 h-1/5" style={{ background: '#4339F280' }}></div>
          </div>
        </WorkoutBlock>
      </div>
    </div>
  );
};

export default WorkoutBlocks;