diff --git a/backend/feedback/api.py b/backend/feedback/api.py new file mode 100644 index 00000000..5d30a11e --- /dev/null +++ b/backend/feedback/api.py @@ -0,0 +1,31 @@ +from pydantic import BaseModel, Field +from fastapi import APIRouter, HTTPException +from services.supabase import DBConnection + +router = APIRouter(prefix="/feedback", tags=["feedback"]) + +class FeedbackRequest(BaseModel): + message_id: str = Field(..., description="ID of the message that is being rated") + is_good: bool = Field(..., description="True for good response, False for bad response") + feedback: str | None = Field(None, description="Optional free-form text feedback from the user") + +db = DBConnection() +@router.post("/") +async def submit_feedback(request: FeedbackRequest): + try: + client = await db.client + + feedback_data = { + 'message_id': request.message_id, + 'is_good': request.is_good, + 'feedback': request.feedback + } + + feedback_result = await client.table('feedback').insert(feedback_data).execute() + + if not feedback_result.data: + raise HTTPException(status_code=500, detail="Failed to submit feedback") + + return {"success": True} + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) diff --git a/frontend/src/components/thread/feedback-modal.tsx b/frontend/src/components/thread/feedback-modal.tsx index ccc0e58e..47e0de10 100644 --- a/frontend/src/components/thread/feedback-modal.tsx +++ b/frontend/src/components/thread/feedback-modal.tsx @@ -4,7 +4,9 @@ import { ThumbsDown, ThumbsUp } from "lucide-react"; import { useState } from "react"; import { Textarea } from "../ui/textarea"; import { toast } from "sonner"; -import { apiClient } from '@/lib/api-client'; +import { backendApi } from '@/lib/api-client'; + +type SubmitStatus = 'idle' | 'submitting' | 'success' | 'error'; interface FeedbackProps { messageId: string; @@ -14,7 +16,7 @@ export default function Feedback({ messageId }: FeedbackProps) { const [open, setOpen] = useState(false); const [responseIsGood, setResponseIsGood] = useState(null); const [feedback, setFeedback] = useState(''); - const [submitting, setSubmitting] = useState(false); + const [submitStatus, setSubmitStatus] = useState('idle'); const handleClick = (isGood: boolean) => { setResponseIsGood(isGood); @@ -23,18 +25,25 @@ export default function Feedback({ messageId }: FeedbackProps) { const handleSubmit = async () => { if (responseIsGood === null) return; - setSubmitting(true); - const { success } = await apiClient.post('/api/feedback', { - message_id: messageId, - response_is_good: responseIsGood, - comment: feedback.trim() || null, - }); - setSubmitting(false); - if (success) { - toast.success('Feedback submitted - thank you!'); - setOpen(false); - setFeedback(''); - setResponseIsGood(null); + setSubmitStatus('submitting'); + + try { + const { success } = await backendApi.post('/feedback/', { + message_id: messageId, + is_good: responseIsGood, + feedback: feedback.trim() || null, + }); + setSubmitStatus('success'); + if (success) { + toast.success('Feedback submitted - thank you!'); + setOpen(false); + setFeedback(''); + setSubmitStatus('success'); + } + } catch (error) { + console.error('Failed to submit feedback:', error); + setSubmitStatus('error'); + toast.error('Failed to submit feedback'); } }; @@ -45,7 +54,7 @@ export default function Feedback({ messageId }: FeedbackProps) { variant="ghost" onClick={() => handleClick(true)} > - + Good response - {responseIsGood ? 'Good response' : 'Bad response'} + Feedback - - {`What was ${responseIsGood === false ? 'un' : ''}satisifying about this response?`} + {`What was ${responseIsGood === false ? 'un' : ''}satisfying about this response?`}