From 4430f388890a85e956df457dffc3ea63b54fac81 Mon Sep 17 00:00:00 2001 From: Priyanshu Verma Date: Sun, 27 Oct 2024 15:01:01 +0000 Subject: [PATCH] feat: Option to Comment on chatbot --- app/api_routes.py | 32 +++++++- app/models.py | 17 ++++ client/src/lib/queries.ts | 9 ++- client/src/pages/ChatbotView.tsx | 130 +++++++++++++++++++++++++++++-- client/src/types/types.d.ts | 7 ++ 5 files changed, 184 insertions(+), 11 deletions(-) diff --git a/app/api_routes.py b/app/api_routes.py index 0097d1d..ba0623d 100644 --- a/app/api_routes.py +++ b/app/api_routes.py @@ -9,7 +9,7 @@ import re from sqlalchemy import func -from .models import User, Chatbot, Chat, Image +from .models import User, Chatbot, Chat, Image, Comment from sqlalchemy.exc import IntegrityError from flask_login import login_user from typing import Union, List, Optional, Dict @@ -642,12 +642,13 @@ def api_get_chatbot_data(chatbot_id: str): chatbot: Chatbot = Chatbot.query.get(chatbot_id) if chatbot == None: return jsonify({"success": False, "message": "Chatbot not found"}), 404 - + comments: List[Comment] = Comment.query.filter_by(chatbot_id=chatbot_id).all() return ( jsonify( { "success": True, "bot": chatbot.to_dict(), + "comments": [comment.to_dict() for comment in comments], } ), 200, @@ -655,3 +656,30 @@ def api_get_chatbot_data(chatbot_id: str): except Exception as e: return jsonify({"success": False, "message": str(e)}), 500 + + +@api_bp.route("/api/chatbot/comment", methods=["POST"]) +@jwt_required() +def api_comment_chatbot(): + try: + data = request.get_json() + chatbot_id = data.get("chatbotId") + name = data.get("name") + message = data.get("message") + chatbot: Chatbot = Chatbot.query.get(chatbot_id) + if chatbot == None: + return jsonify({"success": False, "message": "Chatbot not found"}), 404 + comment: Comment = Comment( + name=name, + chatbot_id=chatbot_id, + message=message, + ) + db.session.add(comment) + user = get_current_user() + if user: + user.contribution_score += 3 + db.session.commit() + return jsonify({"success": True, "message": "Comment saved"}), 200 + + except Exception as e: + return jsonify({"success": False, "message": str(e)}), 500 diff --git a/app/models.py b/app/models.py index 0bc4053..43a8f41 100644 --- a/app/models.py +++ b/app/models.py @@ -112,3 +112,20 @@ def to_dict(self) -> dict: "likes": self.likes, "reports": self.reports, } + + +class Comment(db.Model): + __tablename__ = "comments" + + id: int = db.Column(db.Integer, primary_key=True) + name: str = db.Column(db.Text, nullable=False) + message: str = db.Column(db.Text, nullable=False) + chatbot_id: int = db.Column(db.Integer, nullable=False) + + def to_dict(self) -> dict: + return { + "id": self.id, + "name": self.name, + "message": self.message, + "chatbot_id": self.chatbot_id, + } diff --git a/client/src/lib/queries.ts b/client/src/lib/queries.ts index 38bc3f9..6d73dd1 100644 --- a/client/src/lib/queries.ts +++ b/client/src/lib/queries.ts @@ -34,11 +34,16 @@ export const fetchChatbotData = async ( }); return data; }; -export const fetchChatbotViewData = async (id: string): Promise => { +export const fetchChatbotViewData = async ( + id: string +): Promise<{ + bot: Chatbot; + comments: ChatbotComment[]; +}> => { const { data } = await axios.get(`${SERVER_URL}/api/chatbot_data/${id}`, { headers: authHeaders, }); - return data.bot; + return data; }; export const fetchImagesData = async (): Promise => { diff --git a/client/src/pages/ChatbotView.tsx b/client/src/pages/ChatbotView.tsx index 56cef8a..0f077bb 100644 --- a/client/src/pages/ChatbotView.tsx +++ b/client/src/pages/ChatbotView.tsx @@ -6,24 +6,69 @@ import { Card, CardContent, CardDescription, + CardFooter, CardHeader, CardTitle, } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; import { Skeleton } from "@/components/ui/skeleton"; -import { fetchChatbotViewData } from "@/lib/queries"; -import { useQuery } from "@tanstack/react-query"; -import { MessageCircle } from "lucide-react"; +import { Textarea } from "@/components/ui/textarea"; +import { authHeaders, fetchChatbotViewData } from "@/lib/queries"; +import { SERVER_URL } from "@/lib/utils"; +import { useQuery, useQueryClient } from "@tanstack/react-query"; +import axios from "axios"; +import { MessageCircle, Send, ThumbsUp } from "lucide-react"; +import { useState } from "react"; +import toast from "react-hot-toast"; import { Link, useNavigate, useParams } from "react-router-dom"; export default function ChatbotViewPage() { const { chatbotId } = useParams(); const navigate = useNavigate(); + const [name, setName] = useState(""); + const [comment, setComment] = useState(""); + const qc = useQueryClient(); if (!chatbotId) return null; - - const { data: bot, isLoading } = useQuery({ + const { data, isLoading } = useQuery({ queryKey: ["chatbot_view", chatbotId], queryFn: () => fetchChatbotViewData(chatbotId), }); + const handleSubmitComment = async (e: React.FormEvent) => { + e.preventDefault(); + + if (!name || !comment) { + toast.error("Please fill in both fields"); + return; + } + + try { + const response = await axios.post( + `${SERVER_URL}/api/chatbot/comment`, + { + name, + message: comment, + chatbotId: chatbotId, + }, + { headers: { ...authHeaders } } + ); + + if (response.status == 200) { + toast.success("Comment submitted successfully!"); + // Optionally, clear the form inputs + setName(""); + setComment(""); + // Refresh the comments list here (re-fetch data) + qc.invalidateQueries({ + queryKey: ["chatbot_view", chatbotId], + }); + } else { + toast.error("Failed to submit comment. Please try again."); + } + } catch (error) { + console.error("Error submitting comment:", error); + toast.error("An error occurred while submitting the comment."); + } + }; if (isLoading) { return ( @@ -39,7 +84,7 @@ export default function ChatbotViewPage() { ); } - if (!bot) { + if (!data) { return (

No Chatbot data available.

@@ -47,7 +92,7 @@ export default function ChatbotViewPage() {
); } - + const { bot, comments } = data; return ( <> @@ -83,6 +128,77 @@ export default function ChatbotViewPage() { +

Comments

+
+ {comments.map((c) => ( + + +
+ + + {c.name.at(0)} + {c.name.at(1)} + + + {c.name} +
+
+ +

{c.message}

+
+
+ ))} +
+ + + + Leave a Comment + + +
+
+ + setName(e.target.value)} + /> +
+
+ +