import 'package:comunic/helpers/survey_helper.dart'; import 'package:comunic/models/survey.dart'; import 'package:comunic/models/survey_choice.dart'; import 'package:comunic/ui/widgets/safe_state.dart'; import 'package:comunic/utils/intl_utils.dart'; import 'package:comunic/utils/ui_utils.dart'; import 'package:flutter/material.dart'; import 'package:pie_chart/pie_chart.dart'; /// Survey widget /// /// @author Pierre HUBERT class SurveyWidget extends StatefulWidget { final Survey survey; final Function(Survey) onUpdated; const SurveyWidget({ Key? key, required this.survey, required this.onUpdated, }) : assert(survey != null), assert(onUpdated != null), super(key: key); @override _SurveyWidgetState createState() => _SurveyWidgetState(); } class _SurveyWidgetState extends SafeState { final SurveyHelper _helper = SurveyHelper(); Survey get survey => widget.survey; Map _buildDataMap() { Map data = Map(); widget.survey.choices.forEach((e) => data.putIfAbsent( e.name + " (" + e.responses.toString() + ")", () => 1.0 * e.responses)); return data; } @override Widget build(BuildContext context) { return Column( children: [ Text( widget.survey.question, style: TextStyle(fontWeight: FontWeight.bold), ), _buildUserResponse(), // Offer the user to create a new choice on the survey, if possible survey.allowNewChoicesCreation ? _buildNewChoiceLink() : Container(), // Offer to block the creation of new responses, if possible survey.canBlockNewChoicesCreation ? _buildBlockNewResponsesLink() : Container(), survey.hasResponses ? _buildChart() : _buildNoResponseNotice(), ], ); } Widget _buildUserResponse() { if (survey.hasResponded) return _buildUserRespondedWidget(); return _buildUserResponseFormWidget(); } Widget _buildUserRespondedWidget() { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Flexible( child: Text( tr("Your response: %response%", args: {"response": survey.userResponse!.name})!, textAlign: TextAlign.center, ), ), MaterialButton( child: Text(tr("Cancel")!.toUpperCase()), onPressed: _cancelUserResponse, ) ], ); } Future _cancelUserResponse() async { if (!await showConfirmDialog( context: context, title: tr("Cancel response to survey"), message: tr("Do you really want to cancel your response to this survey ?"), )) return; if (!await _helper.cancelResponse(survey)) { showSimpleSnack( context, tr("Could not cancel your response to the survey !")!); return; } setState(() { survey.cancelUserResponse(); }); } Widget _buildUserResponseFormWidget() { return ConstrainedBox( constraints: BoxConstraints(maxWidth: 300), child: DropdownButton( isExpanded: true, hint: Text(tr("Respond to survey")!), items: survey.choices .map( (f) => DropdownMenuItem( value: f, child: Text(f.name), ), ) .toList(), onChanged: _respondToSurvey, ), ); } Widget _buildNewChoiceLink() => Padding( padding: const EdgeInsets.all(8.0), child: InkWell( onTap: _createNewChoices, child: Text(tr("Create a new choice")!), ), ); Widget _buildBlockNewResponsesLink() => Padding( padding: const EdgeInsets.all(8.0), child: InkWell( onTap: _blockNewChoices, child: Text(tr("Block the creation of new responses")!), ), ); Widget _buildChart() { return PieChart( dataMap: _buildDataMap(), ); } Widget _buildNoResponseNotice() { return Padding( padding: const EdgeInsets.all(16.0), child: Text(tr("No response yet to this survey.")!), ); } /// Respond to survey Future _respondToSurvey(SurveyChoice? choice) async { // Send the response to the server if (!await _helper.respondToSurvey(survey: survey, choice: choice!)) return showSimpleSnack( context, tr("Could not send your response to the survey!")!); setState(() { survey.setUserResponse(choice); }); } /// Reload survey information /// /// Throws in case of failure Future _reloadSurvey() async { final newSurvey = await SurveyHelper.getSurveyInfo(widget.survey.postID); widget.onUpdated(newSurvey); } /// Create a new choice void _createNewChoices() async { try { final newChoice = await askUserString( context: context, title: tr("New choice")!, message: tr("Please specify the new choice for the survey")!, defaultValue: "", hint: tr("New choice...")!, maxLength: 50, ); if (newChoice == null || newChoice.isEmpty) return; await SurveyHelper.createNewChoice(survey.postID, newChoice); await _reloadSurvey(); } catch (e, s) { print("Could not create new survey choice! $e\n$s"); showSimpleSnack( context, tr("Could not create a new choice for this survey!")!); } } /// Block the creation of new choices on this survey void _blockNewChoices() async { try { if (!await showConfirmDialog( context: context, message: tr("Do you really want to block new choices creation?"))) return; await SurveyHelper.blockNewChoicesCreation(survey.postID); setState(() => survey.allowNewChoicesCreation = false); } catch (e, s) { print("Could not block the creation of new choices! $e\n$s"); showSimpleSnack( context, tr("Could not block the creation of new choices!")!); } } }