Skip to content

Commit

Permalink
feat: integrate survey questions screen (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
markgravity committed May 17, 2021
1 parent 485d6f9 commit fac8ce9
Show file tree
Hide file tree
Showing 32 changed files with 464 additions and 98 deletions.
14 changes: 13 additions & 1 deletion lib/components/button/button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,31 @@ class Button extends StatelessWidget {
final String? title;
final VoidCallback? onPressed;
final bool isEnabled;
final double? width;
final double? height;
final BorderRadius? borderRadius;
final Widget? child;

const Button({
Key? key,
this.title,
this.onPressed,
this.isEnabled = true,
this.width,
this.height,
this.borderRadius,
this.child,
}) : super(key: key);

@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: isEnabled ? Colors.white : Colors.grey,
borderRadius: BorderRadius.circular(12.0),
borderRadius: borderRadius ?? BorderRadius.circular(12.0),
),
width: width,
height: height,
child: PlatformButton(
onPressed: isEnabled ? onPressed : null,
materialFlat: (_, __) => MaterialFlatButtonData(),
Expand All @@ -35,6 +46,7 @@ class Button extends StatelessWidget {
fontWeight: FontWeight.bold,
),
),
if (child != null) child!
],
),
),
Expand Down
15 changes: 10 additions & 5 deletions lib/components/common/progress_hud.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
import 'package:streams_provider/streams_provider.dart';
import 'package:survey/core/viper/module.dart';

Expand Down Expand Up @@ -37,10 +36,16 @@ class ProgressHUD extends StatelessWidget {
);
}

return ModalProgressHUD(
inAsyncCall: isShow,
progressIndicator: progressIndicator,
child: child,
return Stack(
children: [
child,
if (isShow)
const Opacity(
opacity: 0.3,
child: ModalBarrier(dismissible: false, color: Colors.grey),
),
if (isShow) Center(child: progressIndicator),
],
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/configs/factories.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ final Map<Type, Function> _factories = {
SurveyQuestionInfo: () => SurveyQuestionInfo(),
SurveyQuestionDisplayType: (v) => SurveyQuestionDisplayType(v as String),
SurveyQuestionPickType: (v) => SurveyQuestionPickType(v as String),
SurveyAnswerInfo: () => SurveyAnswerInfo(),
SurveyQuestionAnswerInfo: () => SurveyQuestionAnswerInfo(),
};
2 changes: 2 additions & 0 deletions lib/configs/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ final Map<String, WidgetBuilder> _routes = {
ForgotPasswordModule.routePath: (_) => ForgotPasswordModule(),
SideMenuModule.routePath: (_) => SideMenuModule(),
SurveyDetailModule.routePath: (_) => SurveyDetailModule(),
SurveyQuestionsModule.routePath: (_) => SurveyQuestionsModule(),
SurveyCompletedModule.routePath: (_) => SurveyCompletedModule(),
};
4 changes: 3 additions & 1 deletion lib/gen/configs.gen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'package:survey/gen/flavors.gen.dart';
import 'package:flutter/widgets.dart';
import 'package:survey/models/auth_token_info.dart';
import 'package:survey/models/detailed_survey_info.dart';
import 'package:survey/models/survey_answer_info.dart';
import 'package:survey/models/survey_question_answer_info.dart';
import 'package:survey/models/survey_info.dart';
import 'package:survey/models/survey_question_info.dart';
import 'package:survey/models/user_info.dart';
Expand All @@ -11,7 +11,9 @@ import 'package:survey/modules/home/home_module.dart';
import 'package:survey/modules/landing/landing_module.dart';
import 'package:survey/modules/login/login_module.dart';
import 'package:survey/modules/side_menu/side_menu_module.dart';
import 'package:survey/modules/survey_completed/survey_completed_module.dart';
import 'package:survey/modules/survey_detail/survey_detail_module.dart';
import 'package:survey/modules/survey_questions/survey_questions_module.dart';
import 'package:survey/services/api/api_service.dart';

part 'package:survey/configs/app.dart';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:object_mapper/object_mapper.dart';
import 'package:survey/models/survey_submit_answer_info.dart';

class SurveyAnswerInfo with Mappable {
class SurveyQuestionAnswerInfo with Mappable {
String? id;
String? content;
int? displayOrder;
Expand All @@ -23,4 +24,8 @@ class SurveyAnswerInfo with Mappable {
(v) => displayOrder = v as int,
);
}

SurveySubmitAnswerInfo toAnswer([String? answer]) {
return SurveySubmitAnswerInfo(id: id!, answer: answer);
}
}
6 changes: 3 additions & 3 deletions lib/models/survey_question_info.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:object_mapper/object_mapper.dart';
import 'package:survey/models/survey_answer_info.dart';
import 'package:survey/models/survey_question_answer_info.dart';

class SurveyQuestionInfo with Mappable {
String? id;
Expand All @@ -10,8 +10,8 @@ class SurveyQuestionInfo with Mappable {
bool? isMandatory;
String? coverImageUrl;
double? coverImageOpacity;
List<SurveyAnswerInfo> answers = [];
List<SurveyAnswerInfo> get orderedAnswers => answers.toList()
List<SurveyQuestionAnswerInfo> answers = [];
List<SurveyQuestionAnswerInfo> get orderedAnswers => answers.toList()
..sort((a, b) => a.displayOrder!.compareTo(b.displayOrder!));

@override
Expand Down
14 changes: 14 additions & 0 deletions lib/models/survey_submit_answer_info.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import 'package:object_mapper/object_mapper.dart';

class SurveySubmitAnswerInfo with Mappable {
SurveySubmitAnswerInfo({required this.id, this.answer});

String id;
String? answer;

@override
void mapping(Mapper map) {
map<String>("id", id, (v) => id = v as String);
map<String>("answer", answer, (v) => answer = v as String?);
}
}
18 changes: 18 additions & 0 deletions lib/models/survey_submit_question_info.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import 'package:object_mapper/object_mapper.dart';
import 'package:survey/models/survey_submit_answer_info.dart';

class SurveySubmitQuestionInfo with Mappable {
const SurveySubmitQuestionInfo({
required this.questionId,
required this.answers,
});

final String questionId;
final List<SurveySubmitAnswerInfo> answers;

@override
void mapping(Mapper map) {
map<String>("id", questionId, (v) {});
map<SurveySubmitAnswerInfo>("answers", answers, (v) {});
}
}
8 changes: 8 additions & 0 deletions lib/modules/survey_completed/survey_completed_interactor.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
part of 'survey_completed_module.dart';

abstract class SurveyCompletedInteractorDelegate {}

abstract class SurveyCompletedInteractor extends ArgumentsInteractor<
SurveyCompletedInteractorDelegate, SurveyCompletedArguments> {}

class SurveyCompletedInteractorImpl extends SurveyCompletedInteractor {}
32 changes: 32 additions & 0 deletions lib/modules/survey_completed/survey_completed_module.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:flutter/widgets.dart' hide Router;
import 'package:survey/core/viper/module.dart';
import 'package:survey/models/survey_question_info.dart';
import 'package:survey/modules/screen.dart';

part 'survey_completed_view.dart';

part 'survey_completed_interactor.dart';

part 'survey_completed_presenter.dart';

part 'survey_completed_router.dart';

class SurveyCompletedModule extends ArgumentsModule<
SurveyCompletedView,
SurveyCompletedInteractor,
SurveyCompletedPresenter,
SurveyCompletedRouter,
SurveyCompletedArguments> {
static const routePath = "survey/completed";

@override
Widget build(BuildContext context) {
return const SurveyCompletedViewImpl();
}
}

class SurveyCompletedArguments extends ModuleArguments {
SurveyCompletedArguments({required this.outro});

final SurveyQuestionInfo outro;
}
7 changes: 7 additions & 0 deletions lib/modules/survey_completed/survey_completed_presenter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
part of 'survey_completed_module.dart';

abstract class SurveyCompletedPresenter extends Presenter<SurveyCompletedView,
SurveyCompletedInteractor, SurveyCompletedRouter> {}

class SurveyCompletedPresenterImpl extends SurveyCompletedPresenter
implements SurveyCompletedViewDelegate, SurveyCompletedInteractorDelegate {}
5 changes: 5 additions & 0 deletions lib/modules/survey_completed/survey_completed_router.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
part of 'survey_completed_module.dart';

abstract class SurveyCompletedRouter extends Router {}

class SurveyCompletedRouterImpl extends SurveyCompletedRouter {}
25 changes: 25 additions & 0 deletions lib/modules/survey_completed/survey_completed_view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
part of 'survey_completed_module.dart';

abstract class SurveyCompletedViewDelegate {}

abstract class SurveyCompletedView extends View<SurveyCompletedViewDelegate> {}

class SurveyCompletedViewImpl extends StatefulWidget {
const SurveyCompletedViewImpl({Key? key}) : super(key: key);

@override
_SurveyCompletedViewImplState createState() => _SurveyCompletedViewImplState();
}

class _SurveyCompletedViewImplState
extends ViewState<SurveyCompletedViewImpl, SurveyCompletedModule, SurveyCompletedViewDelegate>
implements SurveyCompletedView {
@override
Widget build(BuildContext context) {
return const Screen(
body: Center(
child: Text("Survey Completed"),
),
);
}
}
1 change: 1 addition & 0 deletions lib/modules/survey_detail/survey_detail_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:survey/models/detailed_survey_info.dart';
import 'package:survey/models/survey_info.dart';
import 'package:survey/modules/screen.dart';
import 'package:survey/modules/survey_questions/survey_questions_module.dart';
import 'package:survey/repositories/survey_repository.dart';
import 'package:survey/services/locator/locator_service.dart';

Expand Down
7 changes: 6 additions & 1 deletion lib/modules/survey_detail/survey_detail_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,10 @@ abstract class SurveyDetailRouter extends Router {
class SurveyDetailRouterImpl extends SurveyDetailRouter {
@override
void pushToSurveyQuestionsScreen(BuildContext context,
{required DetailedSurveyInfo survey}) {}
{required DetailedSurveyInfo survey}) {
context.navigator.pushReplacementNamed(
SurveyQuestionsModule.routePath,
arguments: SurveyQuestionsArguments(survey: survey),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ class NPSAnswer extends StatefulWidget {
}) : super(key: key);

final int? score;
final List<SurveyAnswerInfo> items;
final ValueChanged<int?>? onSelect;
final List<SurveyQuestionAnswerInfo> items;
final ValueChanged<SurveyQuestionAnswerInfo?>? onSelect;

@override
_NPSAnswerState createState() => _NPSAnswerState();
Expand Down Expand Up @@ -86,7 +86,7 @@ class _NPSAnswerState extends State<NPSAnswer> {
return GestureDetector(
onTap: () {
selected.add(i);
if (widget.onSelect != null) widget.onSelect!(i + 1);
if (widget.onSelect != null) widget.onSelect!(widget.items[i]);
},
child: SizedBox(
width: 35,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class SelectAnswer extends StatefulWidget {

final bool isMultiSelection;
final List<int> selectedIndexes;
final List<SurveyAnswerInfo> options;
final ValueChanged<List<SurveyAnswerInfo>>? onSelect;
final List<SurveyQuestionAnswerInfo> options;
final ValueChanged<List<SurveyQuestionAnswerInfo>>? onSelect;

@override
_SelectAnswerState createState() => _SelectAnswerState();
Expand Down
61 changes: 36 additions & 25 deletions lib/modules/survey_questions/components/content.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,45 @@ class Content extends StatelessWidget {
final state =
context.findRootAncestorStateOfType<_SurveyQuestionsViewImplState>()!;

return Screen(
body: Stack(
children: [
StreamsSelector0<List<SurveyQuestionInfo>>.value(
stream: state._questions,
builder: (_, questions, __) => CarouselSlider.builder(
itemCount: questions.length,
itemBuilder: (_, i, __) => Slide(questions: questions, index: i),
options: CarouselOptions(
height: double.infinity,
viewportFraction: 1,
enableInfiniteScroll: false,
return StreamsSelector0<bool>.value(
stream: state.isProgressHUDShown,
builder: (_, isShown, child) => ProgressHUD(
isShow: isShown,
child: child!,
),
child: Screen(
body: Stack(
children: [
StreamsSelector0<List<SurveyQuestionInfo>>.value(
stream: state._questions,
builder: (_, questions, __) => CarouselSlider.builder(
itemCount: questions.length,
itemBuilder: (_, i, __) =>
Slide(questions: questions, index: i),
carouselController: state._carouselController,
options: CarouselOptions(
height: double.infinity,
scrollPhysics: const NeverScrollableScrollPhysics(),
viewportFraction: 1,
enableInfiniteScroll: false,
),
),
),
),
SafeArea(
child: NavigationBar(
key: state._navigationBarKey,
isBackButtonHidden: true,
leftChildren: [
PlatformButton(
onPressed: () => state.delegate?.closeButtonDidTap.add(null),
child: Assets.images.navCloseButton.svg(),
)
],
SafeArea(
child: NavigationBar(
key: state._navigationBarKey,
isBackButtonHidden: true,
leftChildren: [
PlatformButton(
onPressed: () =>
state.delegate?.closeButtonDidTap.add(null),
child: Assets.images.navCloseButton.svg(),
)
],
),
),
),
],
],
),
),
);
}
Expand Down
Loading

0 comments on commit fac8ce9

Please sign in to comment.