summaryrefslogblamecommitdiff
path: root/makima/frontend/src/components/SupervisorQuestionNotification.tsx
blob: 6a71de29182db53acae65f0304c3301965e93f95 (plain) (tree)






































































































































                                                                                                                                                                                                                        
import { useState } from "react";
import { useNavigate } from "react-router";
import { useSupervisorQuestions } from "../contexts/SupervisorQuestionsContext";
import type { PendingQuestion } from "../lib/api";

export function SupervisorQuestionNotification() {
  const navigate = useNavigate();
  const { pendingQuestions, submitAnswer } = useSupervisorQuestions();
  const [expandedQuestion, setExpandedQuestion] = useState<string | null>(null);
  const [response, setResponse] = useState("");
  const [submitting, setSubmitting] = useState(false);

  if (pendingQuestions.length === 0) {
    return null;
  }

  const handleGoToTask = (taskId: string) => {
    navigate(`/mesh/${taskId}`);
  };

  const handleExpand = (questionId: string) => {
    setExpandedQuestion(expandedQuestion === questionId ? null : questionId);
    setResponse("");
  };

  const handleSubmit = async (question: PendingQuestion) => {
    if (!response.trim()) return;

    setSubmitting(true);
    const success = await submitAnswer(question.questionId, response.trim());
    setSubmitting(false);

    if (success) {
      setExpandedQuestion(null);
      setResponse("");
    }
  };

  const handleChoiceSelect = async (question: PendingQuestion, choice: string) => {
    setSubmitting(true);
    await submitAnswer(question.questionId, choice);
    setSubmitting(false);
  };

  return (
    <div className="fixed bottom-4 right-4 z-50 max-w-md space-y-2">
      {pendingQuestions.map((question) => (
        <div
          key={question.questionId}
          className="bg-[#0d1b2d] border border-amber-500/50 rounded-lg shadow-lg overflow-hidden"
        >
          {/* Header */}
          <div className="flex items-center justify-between px-4 py-3 bg-amber-900/30">
            <div className="flex items-center gap-2">
              <span className="text-amber-400 text-lg">?</span>
              <span className="font-mono text-sm text-amber-300 uppercase">
                Supervisor Question
              </span>
            </div>
            <div className="flex items-center gap-2">
              <button
                onClick={() => handleGoToTask(question.taskId)}
                className="px-2 py-1 font-mono text-xs text-amber-400 hover:text-amber-300 transition-colors"
                title="Go to task"
              >
                View Task
              </button>
              <button
                onClick={() => handleExpand(question.questionId)}
                className="px-2 py-1 font-mono text-xs text-amber-400 border border-amber-500/30 hover:border-amber-400/50 transition-colors uppercase"
              >
                {expandedQuestion === question.questionId ? "Collapse" : "Answer"}
              </button>
            </div>
          </div>

          {/* Question preview */}
          <div className="px-4 py-3">
            {question.context && (
              <div className="text-xs text-[#8b949e] font-mono mb-1 uppercase">
                {question.context}
              </div>
            )}
            <p className="text-sm text-[#dbe7ff] font-mono">
              {question.question}
            </p>
          </div>

          {/* Expanded answer section */}
          {expandedQuestion === question.questionId && (
            <div className="px-4 pb-4 border-t border-amber-500/20 pt-3">
              {question.choices.length > 0 ? (
                // Choice buttons
                <div className="space-y-2">
                  <p className="text-xs text-[#8b949e] font-mono uppercase mb-2">
                    Select an option:
                  </p>
                  {question.choices.map((choice, idx) => (
                    <button
                      key={idx}
                      onClick={() => handleChoiceSelect(question, choice)}
                      disabled={submitting}
                      className="w-full px-3 py-2 text-left font-mono text-sm text-[#dbe7ff] bg-[#0a1628] border border-[#3f6fb3] hover:border-amber-400/50 hover:bg-amber-900/20 disabled:opacity-50 transition-colors"
                    >
                      {choice}
                    </button>
                  ))}
                </div>
              ) : (
                // Free-form text input
                <div className="space-y-2">
                  <textarea
                    value={response}
                    onChange={(e) => setResponse(e.target.value)}
                    placeholder="Type your response..."
                    rows={3}
                    className="w-full px-3 py-2 bg-[#0a1628] border border-[#3f6fb3] text-[#dbe7ff] font-mono text-sm focus:outline-none focus:border-amber-400 resize-none"
                    disabled={submitting}
                  />
                  <button
                    onClick={() => handleSubmit(question)}
                    disabled={submitting || !response.trim()}
                    className="w-full px-4 py-2 font-mono text-xs text-[#0a1628] bg-amber-500 hover:bg-amber-400 disabled:bg-amber-700 disabled:cursor-not-allowed transition-colors uppercase"
                  >
                    {submitting ? "Submitting..." : "Submit Response"}
                  </button>
                </div>
              )}
            </div>
          )}
        </div>
      ))}
    </div>
  );
}