Spaces:
Build error
Build error
| /* | |
| 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}); | |
| _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, | |
| }); | |
| }); | |
| } | |
| } | |
| 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, | |
| )), | |
| ), | |
| ) | |
| ], | |
| ), | |
| ), | |
| ) | |
| ], | |
| ), | |
| ); | |
| } | |
| } | |