All files / src/components/Chatbot VoteProgressBar.tsx

100% Statements 58/58
100% Branches 16/16
100% Functions 1/1
100% Lines 58/58

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 831x     1x 1x     1x             1x 6x   6x 6x   6x 6x   6x 6x     6x 2x 4x 2x 2x   6x   6x 6x   6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x   6x 4x 4x 4x 4x 4x 4x   4x 4x 4x 4x 4x 4x 4x 4x 4x   4x 2x 2x 2x 2x   4x   6x   6x  
import * as Slider from '@radix-ui/react-slider';
 
// Utils
import { combineClasses } from '@shared/utils';
import { pluralize } from '@/utils';
 
// Components
import { VoteMetric } from './VoteMetric';
 
interface VoteProgressBarProps {
  likes: number;
  dislikes: number;
}
 
export const VoteProgressBar = ({ likes, dislikes }: VoteProgressBarProps) => {
  const total = likes + dislikes;
 
  const hasLikes = likes > 0;
  const hasDislikes = dislikes > 0;
 
  const isEmptyVote = !hasLikes && !hasDislikes;
  const hasBothVotes = hasLikes && hasDislikes;
 
  const isLikeOnly = hasLikes && !hasDislikes;
  const isDislikeOnly = hasDislikes && !hasLikes;
 
  // Single-sided vote → fill the bar to 100%
  const percent = isEmptyVote
    ? 0
    : hasBothVotes
      ? Math.round((likes / total) * 100)
      : 100;
 
  const rangeColorClass = isDislikeOnly ? 'bg-gray-300' : 'bg-pink-600';
 
  const rangeRadiusClass =
    isLikeOnly || isDislikeOnly ? 'rounded-xs' : 'rounded-l-xs';
 
  return (
    <div className="w-full">
      <div className="mb-2 flex items-center justify-between text-slate-700">
        <VoteMetric
          label={pluralize(likes, 'Like')}
          value={likes}
          className="items-start text-pink-300"
        />
        <VoteMetric
          label={pluralize(dislikes, 'Dislike')}
          value={dislikes}
          className="items-end text-gray-300"
        />
      </div>
 
      {!isEmptyVote && (
        <Slider.Root
          className="relative flex h-2 w-full touch-none select-none items-center"
          value={[percent]}
          max={100}
          step={1}
          disabled
        >
          <Slider.Track className="relative h-2 w-full grow rounded-xs bg-gray-300">
            <Slider.Range
              className={combineClasses(
                'absolute h-full',
                rangeRadiusClass,
                rangeColorClass,
              )}
            />
          </Slider.Track>
 
          {hasBothVotes && (
            <Slider.Thumb
              className="block h-2 w-1 bg-white shadow focus:outline-none"
              aria-hidden
            />
          )}
        </Slider.Root>
      )}
    </div>
  );
};