← back to Epstein Card

components/ui/enhanced-dropdown.tsx

151 lines

"use client";

import { useState, useRef, useEffect } from "react";

interface EnhancedDropdownProps {
  options: string[];
  placeholder?: string;
  onSelect: (value: string) => void;
  className?: string;
  redactedText?: string;
}

export function EnhancedDropdown({
  options,
  placeholder = "████████",
  onSelect,
  className = "",
  redactedText = placeholder
}: EnhancedDropdownProps) {
  const [isOpen, setIsOpen] = useState(false);
  const [selectedValue, setSelectedValue] = useState("");
  const [customValue, setCustomValue] = useState("");
  const [showCustomInput, setShowCustomInput] = useState(false);
  const dropdownRef = useRef<HTMLDivElement>(null);
  const customInputRef = useRef<HTMLInputElement>(null);

  // Take only first 3 options for presets
  const presetOptions = options.slice(0, 3);

  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
        setIsOpen(false);
        setShowCustomInput(false);
      }
    }
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  useEffect(() => {
    if (showCustomInput && customInputRef.current) {
      customInputRef.current.focus();
    }
  }, [showCustomInput]);

  const handleSelect = (value: string) => {
    if (value === "custom") {
      setShowCustomInput(true);
      setIsOpen(false);
    } else {
      setSelectedValue(value);
      onSelect(value);
      setIsOpen(false);
      setShowCustomInput(false);
    }
  };

  const handleCustomSubmit = () => {
    if (customValue.trim()) {
      setSelectedValue(customValue);
      onSelect(customValue);
      setShowCustomInput(false);
      setCustomValue("");
    }
  };

  const displayValue = selectedValue || redactedText;

  return (
    <div className={`relative inline-block ${className}`} ref={dropdownRef}>
      <button
        type="button"
        onClick={() => setIsOpen(!isOpen)}
        className={`
          border-b-2 border-purple-500 bg-transparent px-2 py-1
          font-mono text-xl mx-1 min-w-[120px] text-left
          hover:border-purple-400 transition-colors cursor-pointer
          ${selectedValue ? 'text-purple-400' : 'text-gray-500'}
        `}
      >
        {displayValue}
      </button>

      {isOpen && (
        <div className="absolute z-50 mt-2 w-64 rounded-lg border-2 border-purple-500 bg-black shadow-2xl">
          <div className="p-1">
            {presetOptions.map((option, index) => (
              <button
                key={option}
                type="button"
                onClick={() => handleSelect(option)}
                className="w-full text-left px-4 py-3 hover:bg-purple-900/50 text-purple-300 font-mono text-lg transition-colors rounded"
              >
                {index + 1}. {option}
              </button>
            ))}
            <div className="border-t border-purple-700 my-1"></div>
            <button
              type="button"
              onClick={() => handleSelect("custom")}
              className="w-full text-left px-4 py-3 hover:bg-purple-900/50 text-yellow-400 font-mono text-lg transition-colors rounded"
            >
              ✏️ Fill in your own...
            </button>
          </div>
        </div>
      )}

      {showCustomInput && (
        <div className="absolute z-50 mt-2 w-64 rounded-lg border-2 border-yellow-500 bg-black shadow-2xl p-4">
          <div className="text-yellow-400 font-mono text-sm mb-2">Enter custom value:</div>
          <input
            ref={customInputRef}
            type="text"
            value={customValue}
            onChange={(e) => setCustomValue(e.target.value)}
            onKeyDown={(e) => {
              if (e.key === 'Enter') handleCustomSubmit();
              if (e.key === 'Escape') {
                setShowCustomInput(false);
                setCustomValue("");
              }
            }}
            className="w-full bg-gray-900 border border-yellow-500 text-white px-3 py-2 rounded font-mono text-lg focus:outline-none focus:border-yellow-400"
            placeholder="Type here..."
          />
          <div className="flex gap-2 mt-3">
            <button
              type="button"
              onClick={handleCustomSubmit}
              className="flex-1 bg-yellow-600 hover:bg-yellow-500 text-black font-bold py-2 rounded transition-colors"
            >
              Submit
            </button>
            <button
              type="button"
              onClick={() => {
                setShowCustomInput(false);
                setCustomValue("");
              }}
              className="flex-1 bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 rounded transition-colors"
            >
              Cancel
            </button>
          </div>
        </div>
      )}
    </div>
  );
}