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 117 118 119 120 121 122 123 124 | import { useState, useEffect, useRef } from "react";
import type { Assessment } from "../api/client";
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);
}}
style={{
padding: "4px 8px",
fontSize: 12,
cursor: "pointer",
color: "#1E293B",
background: a.id === selectedAssessmentId ? "#EFF6FF" : "#fff",
borderBottom:
i < assessments.length - 1 ? "1px solid #F1F5F9" : "none",
}}
onMouseEnter={(e) =>
(e.currentTarget.style.background = "#F8FAFC")
}
onMouseLeave={(e) =>
(e.currentTarget.style.background =
a.id === selectedAssessmentId ? "#EFF6FF" : "#fff")
}
>
{a.name}
</div>
))}
</div>
)}
</div>
);
}
|