All files / components/Scaffold AssessmentSelect.tsx

100% Statements 17/17
100% Branches 19/19
100% Functions 9/9
100% Lines 14/14

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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116                            175x 175x     178x   175x 61x 7x       3x     61x 61x     175x     9x                                                                                                               13x     4x 4x                                      
import { useState, useEffect, useRef } from "react";
import type { Assessment } from "main/types/conceptGraph";
 
interface AssessmentSelectProps {
  assessments: Assessment[];
  selectedAssessmentId: string;
  onSelect: (id: string) => void;
}
 
export default function AssessmentSelect({
  assessments,
  selectedAssessmentId,
  onSelect,
}: AssessmentSelectProps) {
  const [isOpen, setIsOpen] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);
 
  const selectedName =
    assessments.find((a) => a.id === selectedAssessmentId)?.name ?? "";
 
  useEffect(() => {
    const handler = (e: MouseEvent) => {
      if (
        containerRef.current &&
        !containerRef.current.contains(e.target as Node)
      ) {
        setIsOpen(false);
      }
    };
    document.addEventListener("mousedown", handler, true);
    return () => document.removeEventListener("mousedown", handler, true);
  }, []);
 
  return (
    <div ref={containerRef} style={{ position: "relative", minWidth: 200 }}>
      <div
        onClick={() => setIsOpen((o) => !o)}
        style={{
          width: "100%",
          height: 28,
          padding: "0px 10px",
          fontFamily: "Helvetica, Arial, sans-serif",
          fontSize: 13,
          background: "#ffffff",
          color: selectedAssessmentId ? "#1E293B" : "#94A3B8",
          border: "1px solid #000000",
          borderRadius: 6,
          cursor: "pointer",
          boxSizing: "border-box",
          display: "flex",
          alignItems: "center",
          justifyContent: "space-between",
          userSelect: "none",
        }}
      >
        <span>{selectedName || "Select assessment…"}</span>
        <svg
          width="12"
          height="12"
          viewBox="0 0 24 24"
          fill="none"
          stroke="#94A3B8"
          strokeWidth="2"
          strokeLinecap="round"
          strokeLinejoin="round"
          style={{
            flexShrink: 0,
            transform: isOpen ? "rotate(180deg)" : "none",
            transition: "transform 0.15s",
          }}
        >
          <polyline points="6 9 12 15 18 9" />
        </svg>
      </div>
 
      {isOpen && assessments.length > 0 && (
        <div
          style={{
            position: "absolute",
            top: "calc(100% + 4px)",
            left: 0,
            right: 0,
            background: "#fff",
            border: "1px solid #E2E8F0",
            borderRadius: 6,
            boxShadow: "0 4px 16px rgba(0,0,0,0.1)",
            zIndex: 100,
            maxHeight: 260,
            overflowY: "auto",
          }}
        >
          {assessments.map((a, i) => (
            <div
              key={a.id}
              onMouseDown={() => {
                onSelect(a.id);
                setIsOpen(false);
              }}
              className={
                "dropdown-option" +
                (a.id === selectedAssessmentId ? " is-selected" : "")
              }
              style={{
                borderBottom:
                  i < assessments.length - 1 ? "1px solid #F1F5F9" : "none",
              }}
            >
              {a.name}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}