1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-12-26 04:48:51 +00:00

Can create surveys

This commit is contained in:
Pierre HUBERT 2020-04-25 11:58:45 +02:00
parent 8af4a61072
commit 4e951c6a78
4 changed files with 193 additions and 10 deletions

View File

@ -158,6 +158,11 @@ class PostsHelper {
"time-end", (post.timeEnd.millisecondsSinceEpoch / 1000).floor());
break;
case PostKind.SURVEY:
request.addString("question", post.survey.question);
request.addString("answers", post.survey.answers.join("<>"));
break;
default:
throw Exception("Unsupported post type :" + post.kind.toString());
break;

View File

@ -9,6 +9,17 @@ import 'package:meta/meta.dart';
///
/// @author Pierre HUBERT
class NewSurvey {
final String question;
final Set<String> answers;
const NewSurvey({
@required this.question,
@required this.answers,
}) : assert(question != null),
assert(answers.length > 1);
}
class NewPost {
final PostTarget target;
final int targetID;
@ -18,6 +29,7 @@ class NewPost {
final List<int> pdf;
final PostKind kind;
final DateTime timeEnd;
final NewSurvey survey;
const NewPost({
@required this.target,
@ -28,6 +40,7 @@ class NewPost {
@required this.image,
@required this.pdf,
@required this.timeEnd,
@required this.survey,
}) : assert(target != null),
assert(targetID != null),
assert(visibility != null),
@ -35,5 +48,6 @@ class NewPost {
assert(kind != PostKind.TEXT || content.length > 3),
assert(kind != PostKind.IMAGE || image != null),
assert(kind != PostKind.PDF || pdf != null),
assert(kind != PostKind.COUNTDOWN || timeEnd != null);
assert(kind != PostKind.COUNTDOWN || timeEnd != null),
assert(kind != PostKind.SURVEY || survey != null);
}

View File

@ -0,0 +1,137 @@
import 'package:comunic/models/new_post.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:flutter/material.dart';
/// Create a new survey dialog
///
/// @author Pierre Hubert
/// Show a dialog to prompt information about a new survey to create
Future<NewSurvey> showNewSurveyDialog(
{@required BuildContext context, NewSurvey initialSurvey}) async {
return await showDialog<NewSurvey>(
context: context,
builder: (c) => _SurveyDialog(
initialSurvey: initialSurvey,
));
}
class _SurveyDialog extends StatefulWidget {
final NewSurvey initialSurvey;
const _SurveyDialog({Key key, this.initialSurvey}) : super(key: key);
@override
__SurveyDialogState createState() => __SurveyDialogState();
}
class __SurveyDialogState extends State<_SurveyDialog> {
TextEditingController _questionController;
final _choiceController = TextEditingController();
var _choices = Set<String>();
bool get canConfirm =>
_questionController.text.length > 2 && _choices.length > 1;
NewSurvey get newSurvey =>
NewSurvey(question: _questionController.text, answers: _choices);
@override
void initState() {
super.initState();
_questionController = TextEditingController(
text: widget.initialSurvey == null ? "" : widget.initialSurvey.question,
);
if (widget.initialSurvey != null) _choices = widget.initialSurvey.answers;
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text(tr("New survey")),
content: _buildBody(),
actions: <Widget>[
// Cancel
MaterialButton(
onPressed: () => Navigator.of(context).pop(),
child: Text(tr("Cancel").toUpperCase()),
),
// Confirm
MaterialButton(
onPressed:
canConfirm ? () => Navigator.of(context).pop(newSurvey) : null,
child: Text(tr("Confirm").toUpperCase()),
),
],
);
}
Widget _buildBody() {
return ConstrainedBox(
constraints:
BoxConstraints(maxHeight: MediaQuery.of(context).size.height - 50),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
// Survey question
TextField(
controller: _questionController,
onChanged: (s) => setState(() {}),
decoration: InputDecoration(
alignLabelWithHint: true, labelText: tr("Question")),
),
Container(height: 30),
Text(tr("Current choices:")),
_buildCurrentChoices(),
Container(
height: 10,
),
// Add choice form
TextField(
controller: _choiceController,
onChanged: (s) => setState(() {}),
onSubmitted: (s) => _addChoice(),
decoration: InputDecoration(
hintText: tr("New choice..."),
suffixIcon: IconButton(
icon: Icon(Icons.add),
onPressed: () => _choiceController.text.length > 0
? _addChoice()
: null,
)),
),
]),
),
);
}
Widget _buildCurrentChoices() {
if (_choices.length == 0) return Text(tr("No choice yet."));
return Column(
children: _choices
.map((f) => ListTile(
title: Text(f),
dense: true,
trailing: IconButton(
icon: Icon(Icons.delete),
iconSize: 15,
onPressed: () => setState(() => _choices.remove(f)),
)))
.toList(),
);
}
void _addChoice() {
if (_choiceController.text.length == 0) return;
setState(() {
_choices.add(_choiceController.text);
_choiceController.text = "";
});
}
}

View File

@ -5,6 +5,7 @@ import 'package:comunic/enums/post_target.dart';
import 'package:comunic/enums/post_visibility_level.dart';
import 'package:comunic/helpers/posts_helper.dart';
import 'package:comunic/models/new_post.dart';
import 'package:comunic/ui/dialogs/new_survey_dialog.dart';
import 'package:comunic/utils/files_utils.dart';
import 'package:comunic/utils/intl_utils.dart';
import 'package:comunic/utils/post_utils.dart';
@ -50,6 +51,7 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
File _postImage;
List<int> _postPDF;
DateTime _timeEnd;
NewSurvey _postSurvey;
bool get hasImage => _postImage != null;
@ -57,6 +59,8 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
bool get hasTimeEnd => _timeEnd != null;
bool get hasSurvey => _postSurvey != null;
bool get canSubmitForm =>
!_isCreating && _postTextController.text.length > 5 ||
postKind != PostKind.TEXT;
@ -68,6 +72,8 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
return PostKind.PDF;
else if (hasTimeEnd)
return PostKind.COUNTDOWN;
else if (hasSurvey)
return PostKind.SURVEY;
else
return PostKind.TEXT;
}
@ -132,6 +138,13 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
selected: postKind == PostKind.COUNTDOWN,
onTap: _pickCountdownTime,
),
// Add survey
_PostOptionWidget(
icon: Icons.insert_chart,
selected: postKind == PostKind.SURVEY,
onTap: _pickSurvey,
),
],
),
),
@ -192,6 +205,7 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
_postImage = null;
_postPDF = null;
_timeEnd = null;
_postSurvey = null;
});
}
@ -262,6 +276,19 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
});
}
/// Pick a new survey for this post
Future<void> _pickSurvey() async {
final newSurvey =
await showNewSurveyDialog(context: context, initialSurvey: _postSurvey);
if (newSurvey == null) return;
_resetPostSelection();
setState(() {
_postSurvey = newSurvey;
});
}
/// Submit new post
Future<void> _submitForm() async {
if (!canSubmitForm)
@ -271,15 +298,15 @@ class _PostCreateFormWidgetState extends State<PostCreateFormWidget> {
try {
await _postHelper.createPost(NewPost(
target: widget.postTarget,
targetID: widget.targetID,
visibility: _postVisibilityLevel,
content: _postTextController.text,
kind: postKind,
image: _postImage,
pdf: _postPDF,
timeEnd: _timeEnd,
));
target: widget.postTarget,
targetID: widget.targetID,
visibility: _postVisibilityLevel,
content: _postTextController.text,
kind: postKind,
image: _postImage,
pdf: _postPDF,
timeEnd: _timeEnd,
survey: _postSurvey));
setState(() => _isCreating = false);
showSimpleSnack(context, tr("The post has been successfully created!"));