From eeafe072bc6bb81459f7d087b48fc921afe9cc11 Mon Sep 17 00:00:00 2001 From: soryu Date: Thu, 15 Jan 2026 03:26:28 +0000 Subject: Automatically derive repo URL and add notifications for input --- .../components/SupervisorQuestionNotification.tsx | 135 +++++++++++++++++++++ .../src/components/listen/ContractPickerModal.tsx | 118 ++++++++++++++++++ .../src/components/listen/ControlPanel.tsx | 32 +++-- makima/frontend/src/components/mesh/TaskDetail.tsx | 6 +- .../src/contexts/SupervisorQuestionsContext.tsx | 94 ++++++++++++++ makima/frontend/src/lib/api.ts | 125 +++++++++++++++++++ makima/frontend/src/main.tsx | 15 ++- makima/frontend/src/routes/mesh.tsx | 9 +- 8 files changed, 512 insertions(+), 22 deletions(-) create mode 100644 makima/frontend/src/components/SupervisorQuestionNotification.tsx create mode 100644 makima/frontend/src/components/listen/ContractPickerModal.tsx create mode 100644 makima/frontend/src/contexts/SupervisorQuestionsContext.tsx (limited to 'makima/frontend/src') diff --git a/makima/frontend/src/components/SupervisorQuestionNotification.tsx b/makima/frontend/src/components/SupervisorQuestionNotification.tsx new file mode 100644 index 0000000..6a71de2 --- /dev/null +++ b/makima/frontend/src/components/SupervisorQuestionNotification.tsx @@ -0,0 +1,135 @@ +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(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 ( +
+ {pendingQuestions.map((question) => ( +
+ {/* Header */} +
+
+ ? + + Supervisor Question + +
+
+ + +
+
+ + {/* Question preview */} +
+ {question.context && ( +
+ {question.context} +
+ )} +

+ {question.question} +

+
+ + {/* Expanded answer section */} + {expandedQuestion === question.questionId && ( +
+ {question.choices.length > 0 ? ( + // Choice buttons +
+

+ Select an option: +

+ {question.choices.map((choice, idx) => ( + + ))} +
+ ) : ( + // Free-form text input +
+