1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-10-23 15:03:22 +00:00
comunicmobile/lib/ui/widgets/survey_widget.dart

217 lines
5.9 KiB
Dart

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<SurveyWidget> {
final SurveyHelper _helper = SurveyHelper();
Survey get survey => widget.survey;
Map<String, double> _buildDataMap() {
Map<String, double> 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: <Widget>[
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: <Widget>[
Flexible(
child: Text(
tr("Your response: %response%",
args: {"response": survey.userResponse!.name})!,
textAlign: TextAlign.center,
),
),
MaterialButton(
child: Text(tr("Cancel")!.toUpperCase()),
onPressed: _cancelUserResponse,
)
],
);
}
Future<void> _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<SurveyChoice>(
isExpanded: true,
hint: Text(tr("Respond to survey")!),
items: survey.choices
.map(
(f) => DropdownMenuItem<SurveyChoice>(
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<void> _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<void> _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!")!);
}
}
}