llminators / webapp /lib /chatbot.dart
hugging2021's picture
Upload folder using huggingface_hub
6e97887 verified
/*
Right Vote - A web app for election prediction and manifesto comparison with machine learning and NLP.
Nilakna Warushavithana, September 2024
*/
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class ChatBotPanelGenerator extends StatefulWidget {
const ChatBotPanelGenerator({super.key});
@override
_ChatBotPanelState createState() => _ChatBotPanelState();
}
class _ChatBotPanelState extends State<ChatBotPanelGenerator> {
final TextEditingController _chatController = TextEditingController();
final ScrollController _scrollController = ScrollController();
List<Map<String, dynamic>> _chatHistory = [];
void getAnswer() async {
final url = "https://85a9-35-196-250-8.ngrok-free.app/ask";
final uri = Uri.parse(url);
try {
final response = await http.post(
uri,
headers: {"Content-Type": "application/json"},
body: jsonEncode(<String, String>{
"question": _chatController.text
}), //send the question to the server
);
//for debugging the http request and reponse
// print("Request Body: ${jsonEncode(<String, String>{
// 'question': _chatController.text
// })}");
// print("Response Body: ${response.body}");
if (response.statusCode == 200) {
final data = json.decode(response.body);
setState(() {
_chatHistory.add({
"time": DateTime.now(),
"message": data["answer"],
"isSender": false,
}); //update chat history with the answer
});
// Ensure scrolling happens after the state has been updated
WidgetsBinding.instance.addPostFrameCallback((_) {
if (_scrollController.hasClients) {
_scrollController.animateTo(
_scrollController.position.maxScrollExtent,
duration: const Duration(milliseconds: 300),
curve: Curves.easeOut,
);
}
});
} else {
// print("Error: ${response.statusCode}"); //debugging
// print(response.body); //debugging
setState(() {
_chatHistory.add({
"time": DateTime.now(),
"message": "Error: ${response.statusCode}",
"isSender": false,
});
});
}
} catch (e) {
// print("Exception: $e"); //debugging
setState(() {
_chatHistory.add({
"time": DateTime.now(),
"message": "Exception: $e",
"isSender": false,
});
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
"Chat",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
body: Stack(
children: [
Container(
//get max height
height: MediaQuery.of(context).size.height - 160,
child: ListView.builder(
itemCount: _chatHistory.length,
// shrinkWrap: false,
controller: _scrollController,
padding: const EdgeInsets.only(top: 10, bottom: 10),
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) {
return Container(
padding:
EdgeInsets.only(left: 14, right: 14, top: 10, bottom: 10),
child: Align(
alignment: (_chatHistory[index]["isSender"]
? Alignment.topRight
: Alignment.topLeft),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 2,
blurRadius: 5,
offset: const Offset(0, 3),
),
],
color: (_chatHistory[index]["isSender"]
? Colors.blue[100]
: Colors.white),
),
padding: EdgeInsets.all(16),
child: Text(_chatHistory[index]["message"],
style: TextStyle(
fontSize: 15,
color: _chatHistory[index]["isSender"]
? Colors.black
: Colors.black)),
),
),
);
},
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
padding:
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
height: 60,
width: double.infinity,
color: Colors.white,
child: Row(
children: [
Expanded(
child: Container(
decoration: const BoxDecoration(),
child: Padding(
padding: const EdgeInsets.all(4.0),
child: TextField(
decoration: const InputDecoration(
hintText: "Type a message",
border: InputBorder.none,
contentPadding: EdgeInsets.all(8.0),
),
controller: _chatController,
),
),
),
),
const SizedBox(
width: 4.0,
),
MaterialButton(
onPressed: () {
setState(() {
if (_chatController.text.isNotEmpty) {
_chatHistory.add({
"time": DateTime.now(),
"message": _chatController.text,
"isSender": true,
});
getAnswer();
_chatController.clear();
}
});
_scrollController.jumpTo(
_scrollController.position.maxScrollExtent,
);
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(80.0)),
padding: const EdgeInsets.all(0.0),
child: Ink(
decoration: const BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(50.0)),
),
child: Container(
constraints: const BoxConstraints(
minWidth: 88.0,
minHeight:
36.0), // min sizes for Material buttons
alignment: Alignment.center,
child: const Icon(
Icons.send,
color: Colors.white,
)),
),
)
],
),
),
)
],
),
);
}
}