diff --git a/core/example/lib/main.dart b/core/example/lib/main.dart index fd5258a6..1cbbcf05 100644 --- a/core/example/lib/main.dart +++ b/core/example/lib/main.dart @@ -37,7 +37,10 @@ class MyHomePage extends StatelessWidget { ), // Add Survey to your widget tree with filePath parameter that accepts // a json file with parsed survey data - body: const Survey(filePath: 'assets/questions.json'), + body: const Survey( + filePath: 'assets/questions.json', + onFinish: print, + ), ); } } diff --git a/core/lib/src/presentation/survey/survey.dart b/core/lib/src/presentation/survey/survey.dart index 96e3fc84..781e64da 100644 --- a/core/lib/src/presentation/survey/survey.dart +++ b/core/lib/src/presentation/survey/survey.dart @@ -12,6 +12,7 @@ import 'package:survey_sdk/src/presentation/survey/survey_cubit.dart'; import 'package:survey_sdk/src/presentation/survey/survey_state.dart'; import 'package:survey_sdk/src/presentation/survey_error/survey_error.dart'; import 'package:survey_sdk/src/presentation/utils/callback_type.dart'; +import 'package:survey_sdk/src/presentation/utils/on_finish_callback.dart'; import 'package:survey_sdk/src/presentation/utils/utils.dart'; // TODO(dev): Maybe create two classes, where one is for filePath and the other @@ -44,6 +45,9 @@ class Survey extends StatefulWidget { /// Whether the survey should save user selected answers. final bool saveAnswer; + /// Called after the survey is finished. + final OnFinishCallback? onFinish; + /// Either [filePath] or [surveyData] must pe provided. The [controller] /// parameter is optional and can be used to provide a custom survey /// controller. @@ -51,6 +55,7 @@ class Survey extends StatefulWidget { this.filePath, this.surveyData, this.controller, + this.onFinish, this.saveAnswer = true, super.key, }) : assert( @@ -107,6 +112,7 @@ class _SurveyState extends State { index, answer, callbackType, + onFinish: widget.onFinish, saveAnswer: widget.saveAnswer, ); } @@ -177,9 +183,6 @@ class _SurveyState extends State { onGoNext: _surveyController.onNext, ), ), - DataToWidgetUtil.createEndPage( - data: data.endPage, - ), ], ), ), diff --git a/core/lib/src/presentation/survey/survey_cubit.dart b/core/lib/src/presentation/survey/survey_cubit.dart index 37fb70a2..beb6f5cb 100644 --- a/core/lib/src/presentation/survey/survey_cubit.dart +++ b/core/lib/src/presentation/survey/survey_cubit.dart @@ -2,6 +2,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:survey_sdk/src/domain/entities/question_answer.dart'; import 'package:survey_sdk/src/domain/repository_interfaces/survey_data_repository.dart'; import 'package:survey_sdk/src/presentation/survey/survey_state.dart'; +import 'package:survey_sdk/src/presentation/utils/on_finish_callback.dart'; import 'package:survey_sdk/src/presentation/utils/survey_button_callback.dart'; import 'package:survey_sdk/survey_sdk.dart'; @@ -29,6 +30,7 @@ class SurveyCubit extends Cubit { QuestionAnswer? answer, CallbackType callbackType, { required bool saveAnswer, + OnFinishCallback? onFinish, }) { if (state is SurveyLoadedState) { final loadedState = state as SurveyLoadedState; @@ -41,10 +43,16 @@ class SurveyCubit extends Cubit { callback: callback, callbackType: callbackType, surveyController: surveyController, + onFinish: onFinish, + answers: loadedState.answers, questions: loadedState.surveyData.questions, saveAnswer: () => answer == null || !saveAnswer ? null - : _saveAnswer(index: questionIndex, answer: answer), + : _saveAnswer( + index: questionIndex, + answer: answer, + onFinish: onFinish, + ), ).callbackFromType(); } } @@ -72,11 +80,18 @@ class SurveyCubit extends Cubit { } /// Saves the provided [answer] for the question at the specified [index]. - void _saveAnswer({required int index, required QuestionAnswer answer}) { + void _saveAnswer({ + required int index, + required QuestionAnswer answer, + OnFinishCallback? onFinish, + }) { final currentState = state; if (currentState is SurveyLoadedState) { final newAnswers = Map.of(currentState.answers); newAnswers[index] = answer; + if (index == currentState.surveyData.questions.length) { + onFinish?.call(newAnswers); + } emit(currentState.copyWith(answers: newAnswers)); } } diff --git a/core/lib/src/presentation/utils/on_finish_callback.dart b/core/lib/src/presentation/utils/on_finish_callback.dart new file mode 100644 index 00000000..8a4e7fa8 --- /dev/null +++ b/core/lib/src/presentation/utils/on_finish_callback.dart @@ -0,0 +1,3 @@ +import 'package:survey_sdk/src/domain/entities/question_answer.dart'; + +typedef OnFinishCallback = void Function(Map answers); diff --git a/core/lib/src/presentation/utils/survey_button_callback.dart b/core/lib/src/presentation/utils/survey_button_callback.dart index c387afe8..13c1cecd 100644 --- a/core/lib/src/presentation/utils/survey_button_callback.dart +++ b/core/lib/src/presentation/utils/survey_button_callback.dart @@ -5,16 +5,20 @@ import 'package:survey_sdk/src/domain/entities/actions/go_next_action.dart'; import 'package:survey_sdk/src/domain/entities/actions/go_to_action.dart'; import 'package:survey_sdk/src/domain/entities/actions/skip_question_action.dart'; import 'package:survey_sdk/src/domain/entities/actions/survey_action.dart'; +import 'package:survey_sdk/src/domain/entities/question_answer.dart'; import 'package:survey_sdk/src/domain/entities/question_types/question_data.dart'; import 'package:survey_sdk/src/presentation/survey/survey_controller.dart'; import 'package:survey_sdk/src/presentation/utils/callback_type.dart'; +import 'package:survey_sdk/src/presentation/utils/on_finish_callback.dart'; class SurveyButtonCallback { final SurveyAction? callback; final VoidCallback? saveAnswer; final SurveyController surveyController; final List questions; + final OnFinishCallback? onFinish; final CallbackType callbackType; + final Map? answers; SurveyButtonCallback({ required this.callback, @@ -22,7 +26,12 @@ class SurveyButtonCallback { required this.surveyController, required this.questions, required this.callbackType, - }); + this.answers, + this.onFinish, + }) : assert( + onFinish != null && answers != null || onFinish == null, + 'If onFinish != null answers should not be null either', + ); void callbackFromType() => switch (callback.runtimeType) { GoToAction => goToCallback(), @@ -33,7 +42,6 @@ class SurveyButtonCallback { _ => defaultSurveyCallback(), }; - @visibleForTesting void goToCallback() { saveAnswer?.call(); @@ -43,6 +51,7 @@ class SurveyButtonCallback { @visibleForTesting void finishSurveyCallback() { saveAnswer?.call(); + onFinish?.call(answers!); surveyController.animateTo(questions.length); }