add a clear button the graph comppoent card on top right which clears the graph and make it good 
""
import React from 'react';
import { useDrop } from 'react-dnd';
import GraphBlock from './GraphBlock';
import { ItemTypes } from './constants';

const Graph = ({ blocks, addBlockToGraph, moveBlock, removeBlock }) => {
  const [{ isOver, canDrop }, drop] = useDrop({
    accept: [ItemTypes.WORKOUT_BLOCK, ItemTypes.GRAPH_BLOCK],
    drop: (item, monitor) => {
      if (monitor.didDrop()) {
        return;
      }
      addBlockToGraph(item, blocks.length);
      return { dropped: true };
    },
    collect: (monitor) => ({
      isOver: monitor.isOver({ shallow: true }),
      canDrop: monitor.canDrop(),
    }),
  });

  const dropZoneStyle = isOver && canDrop
    ? 'bg-gray-100 border-2 border-dashed border-indigo-300'
    : 'bg-gray-50 border-2 border-dashed border-gray-200';

  // Calculate cumulative distances for x-axis labels
  const getBlockDistance = (blockType) => {
    switch (blockType) {
      case 'block50':
      case 'block75':
      case 'block30':
        return 3;
      case 'block60_40':
        return 4;
      case 'block80_60_40_20':
      case 'block20_40_60_80':
        return 5;
      default:
        return 3;
    }
  };

  const cumulativeDistances = blocks.reduce((acc, block, index) => {
    const previousDistance = index > 0 ? acc[index - 1] : 0;
    acc[index] = previousDistance + getBlockDistance(block.type);
    return acc;
  }, []);

  return (
    <div className="relative w-full h-[300px] p-6">
      <div
        ref={drop}
        className={`absolute inset-0 rounded-lg transition-colors duration-200 ${dropZoneStyle}`}
      >
        <div className="absolute inset-x-20 inset-y-10 flex items-end">
          {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>

        {/* Y-Axis Labels */}
        <div className="absolute left-4 top-10 bottom-10 flex flex-col justify-between text-sm text-gray-600">
          {[100, 75, 50, 25, 0].map((value) => (
            <div key={value} className="flex items-center justify-end w-12">
              {value}%
            </div>
          ))}
        </div>

        {/* X-Axis Labels */}
        <div className="absolute bottom-4 left-20 right-10">
        <div className="flex justify-between text-sm text-gray-600">
          <div className="text-center">0</div>
          {blocks.length > 0 && cumulativeDistances.map((distance, index) => (
            <div
              key={index}
              className="text-center"
              style={{
                position: 'absolute',
                // Calculate the position based on the cumulative distance
                left: `${(cumulativeDistances[index] / Math.max(1, cumulativeDistances[blocks.length - 1])) * 100}%`,
                transform: 'translateX(-50%)' 
              }}

              >
                {distance}
              </div>
            ))}
          </div>
        </div>

        {/* Empty State Message */}
        {blocks.length === 0 && (
          <div className="absolute inset-0 flex items-center justify-center">
            <div className={`text-center ${isOver && canDrop ? 'text-indigo-500' : 'text-gray-400'}`}>
              <p className="text-lg font-medium">Drop workout blocks here</p>
              <p className="text-sm mt-2">Drag a block from the left to start building your workout</p>
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

export default Graph;
"""
"""
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);

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

  const [{ isOver, canDrop }, drop] = useDrop({
    accept: [ItemTypes.GRAPH_BLOCK, ItemTypes.WORKOUT_BLOCK],
    hover: (item, monitor) => {
      if (!ref.current) {
        return;
      }

      const dragIndex = item.index;
      const hoverIndex = index;

      // Don't replace items with themselves
      if (item.type === ItemTypes.GRAPH_BLOCK && dragIndex === hoverIndex) {
        return;
      }

      // Get the bounds and mouse position
      const hoverBoundingRect = ref.current.getBoundingClientRect();
      const hoverMiddleX = (hoverBoundingRect.right - hoverBoundingRect.left) / 2;
      const clientOffset = monitor.getClientOffset();
      const hoverClientX = clientOffset.x - hoverBoundingRect.left;

      // Determine if we're on the left or right half of the block
      const isOverLeftHalf = hoverClientX < hoverMiddleX;

      if (item.type === ItemTypes.GRAPH_BLOCK) {
        const newIndex = isOverLeftHalf ? hoverIndex : hoverIndex + 1;
        moveBlock(dragIndex, newIndex);
        item.index = newIndex;
      }
    },
    drop: (item, monitor) => {
      if (!ref.current) {
        return;
      }

      const hoverBoundingRect = ref.current.getBoundingClientRect();
      const hoverMiddleX = (hoverBoundingRect.right - hoverBoundingRect.left) / 2;
      const clientOffset = monitor.getClientOffset();
      const hoverClientX = clientOffset.x - hoverBoundingRect.left;

      const isOverLeftHalf = hoverClientX < hoverMiddleX;

      if (item.type === ItemTypes.WORKOUT_BLOCK) {
        addBlockToGraph(item, isOverLeftHalf ? index : index + 1);
        return { dropped: true };
      }

      return { dropped: true };
    },
    collect: (monitor) => ({
      isOver: !!monitor.isOver(),
      canDrop: !!monitor.canDrop(),
    }),
  });

  drag(drop(ref));

  const opacity = isDragging ? 0.4 : 1;

  return (
    <div
      ref={ref}
      className={`relative flex items-end transition-all duration-200`}
      style={{
        opacity,
        flex: '1 1 0', // Ensures equal width distribution
        height: '100%',
        minWidth: '40px', // Optional: set a minimum width for better visibility
      }}
    >
      {/* Drop indicators */}
      {isOver && canDrop && (
        <>
          <div className="absolute left-0 top-0 bottom-0 w-1 bg-indigo-500" />
          <div className="absolute right-0 top-0 bottom-0 w-1 bg-indigo-500" />
        </>
      )}

      <div className="flex w-full h-full cursor-move space-x-1 px-1">
        {block.columns.map((height, colIndex) => (
          <div
            key={colIndex}
            className="flex-1 flex flex-col justify-end"
          >
            <div
              className="bg-indigo-500 bg-opacity-70 w-full transition-all duration-200 rounded"
              style={{ height: `${height}%` }}
            ></div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default GraphBlock;
import React from 'react';
import { useDrag } from 'react-dnd';
import { FiInfo } from 'react-icons/fi';
import { ItemTypes } from './constants';

const WorkoutBlock = ({ children, type, columns }) => {
  const [{ isDragging }, drag] = useDrag({
    type: ItemTypes.WORKOUT_BLOCK,
    item: { type, columns },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
    }),
  });

  return (
    <div
      ref={drag}
      className={`relative bg-gray-200 rounded-lg overflow-hidden h-20 cursor-move ${
        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-3 gap-3">
        <WorkoutBlock type="warm up" columns={[50]}>
          <div className="absolute bottom-0 w-full bg-indigo-500 bg-opacity-50" style={{ height: '50%' }}></div>
        </WorkoutBlock>

        <WorkoutBlock type="active" columns={[75]}>
          <div className="absolute bottom-0 w-full bg-indigo-500 bg-opacity-50" style={{ height: '75%' }}></div>
        </WorkoutBlock>

        <WorkoutBlock type="running" columns={[30]}>
          <div className="absolute bottom-0 w-full bg-indigo-500 bg-opacity-50" style={{ height: '30%' }}></div>
        </WorkoutBlock>

        <WorkoutBlock type="two step" columns={[60, 40]}>
          <div className="absolute bottom-0 w-full h-full flex gap-1 transform rotate-180">
            {[60, 40].map((height, i) => (
              <div
                key={i}
                className="flex-1 bg-indigo-500 bg-opacity-50"
                style={{ height: `${height}%` }}
              ></div>
            ))}
          </div>
        </WorkoutBlock>

        <WorkoutBlock type="ramp up" columns={[20, 40, 60, 80]}>
          <div className="absolute bottom-0 w-full h-full flex gap-1 transform rotate-180">
            {[20, 40, 60, 80].map((height, i) => (
              <div
                key={i}
                className="flex-1 bg-indigo-500 bg-opacity-50"
                style={{ height: `${height}%` }}
              ></div>
            ))}
          </div>
        </WorkoutBlock>

        <WorkoutBlock type="ramp down" columns={[80, 60, 40, 20]}>
          <div className="absolute bottom-0 w-full h-full flex gap-1 transform rotate-180">
            {[80, 60, 40, 20].map((height, i) => (
              <div
                key={i}
                className="flex-1 bg-indigo-500 bg-opacity-50"
                style={{ height: `${height}%` }}
              ></div>
            ))}
          </div>
        </WorkoutBlock>
      </div>
    </div>
  );
};

export default WorkoutBlocks;
// 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);

  const addBlockToGraph = useCallback((block, index = graphBlocks.length) => {
    if (
      !block ||
      !block.type ||
      !Array.isArray(block.columns) ||
      block.columns.some(
        (col) => typeof col !== 'number' || col < 0 || col > 100
      )
    ) {
      console.error('Invalid block:', block);
      return;
    }

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

  const moveGraphBlock = useCallback((dragIndex, hoverIndex) => {
    setGraphBlocks((prevBlocks) => {
      const updatedBlocks = [...prevBlocks];
      const [draggedBlock] = updatedBlocks.splice(dragIndex, 1);
      updatedBlocks.splice(hoverIndex, 0, draggedBlock);
      return updatedBlocks;
    });
  }, []);

  const removeBlock = useCallback((id) => {
    setGraphBlocks((prevBlocks) => prevBlocks.filter(block => block.id !== id));
  }, []);

  return (
    <DndProvider backend={HTML5Backend}>
      <div className="justify-center min-h-screen bg-[#F8F8F8] w-screen p-4">
        <div className='w-[94.5vw]'>
          <Header />
        </div>
        <div className="flex justify-between mx-6 my-3 items-start">
          <WorkoutBlocks />
          <div className="w-full bg-white p-6 rounded-lg shadow-md ml-6 overflow-hidden">
            <Graph
              blocks={graphBlocks}
              addBlockToGraph={addBlockToGraph}
              moveBlock={moveGraphBlock}
              removeBlock={removeBlock}
            />
            <ColumnsList blocks={graphBlocks} />
          </div>
        </div>
      </div>
    </DndProvider>
  );
}

export default App;