Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ class _MyAppState extends State<MyApp> {
title: 'When was your last holiday?',
answerFormat: DateAnswerFormat(
minDate: DateTime.utc(1970),
maxDate: DateTime.now(),
defaultDate: DateTime.now(),
maxDate: DateTime.now(),
),
),
CompletionStep(
Expand Down
15 changes: 14 additions & 1 deletion lib/src/answer_format/date_answer_format.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import 'package:survey_kit/src/answer_format/answer_format.dart';

class DateAnswerFormat implements AnswerFormat {
/// Default date which will be preselected on datepicker opening
final DateTime? defaultDate;

/// Lowest date which can be selected via the datepicker
final DateTime? minDate;

/// Highest date which can be selected via the datepicker
final DateTime? maxDate;

DateAnswerFormat({
this.defaultDate,
this.minDate,
this.maxDate,
});
}) : assert(minDate == null || maxDate == null || minDate.isBefore(maxDate)),
assert(defaultDate == null ||
minDate == null ||
defaultDate.isAtSameMomentAs(minDate) ||
defaultDate.isAfter(minDate)),
assert(defaultDate == null ||
maxDate == null ||
defaultDate.isAtSameMomentAs(maxDate) ||
defaultDate.isBefore(maxDate));
}
41 changes: 25 additions & 16 deletions lib/src/views/date_answer_view.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
Expand All @@ -11,7 +9,10 @@ import 'package:survey_kit/src/steps/predefined_steps/question_step.dart';
import 'package:survey_kit/src/views/widget/step_view.dart';

class DateAnswerView extends StatefulWidget {
/// [QuestionStep] which includes the [DateAnswerFormat]
final QuestionStep questionStep;

/// [DateQuestionResult] which boxes the result
final DateQuestionResult? result;

const DateAnswerView({
Expand All @@ -27,14 +28,16 @@ class DateAnswerView extends StatefulWidget {
class _DateAnswerViewState extends State<DateAnswerView> {
final DateFormat _dateFormat = DateFormat('E, MMM d');
final DateTime _startDate = DateTime.now();
late final DateAnswerFormat _dateAnswerFormat;
late DateAnswerFormat _dateAnswerFormat;
DateTime? _result;

@override
void initState() {
super.initState();
_dateAnswerFormat = widget.questionStep.answerFormat as DateAnswerFormat;
_result = widget.result?.result ?? DateTime.now();
_result = widget.result?.result ??
_dateAnswerFormat.defaultDate ??
DateTime.now();
}

void _handleDateChanged(DateTime date) {
Expand All @@ -43,6 +46,7 @@ class _DateAnswerViewState extends State<DateAnswerView> {

@override
Widget build(BuildContext context) {
final platform = Theme.of(context).platform;
return StepView(
step: widget.questionStep,
controller: SurveyController(
Expand Down Expand Up @@ -73,7 +77,9 @@ class _DateAnswerViewState extends State<DateAnswerView> {
textAlign: TextAlign.center,
),
),
Platform.isAndroid ? _androidDatePicker() : _iosDatePicker(),
platform == TargetPlatform.iOS
? _iosDatePicker()
: _androidDatePicker(),
],
),
);
Expand All @@ -96,7 +102,7 @@ class _DateAnswerViewState extends State<DateAnswerView> {
left: 8.0,
bottom: 8.0,
child: Text(
_result != null ? _dateFormat.format(_result!) : '',
_dateFormat.format(_result!),
style: TextStyle(
fontSize: 28.0,
color: Colors.white,
Expand All @@ -110,14 +116,14 @@ class _DateAnswerViewState extends State<DateAnswerView> {
width: double.infinity,
height: 300.0,
child: CalendarDatePicker(
firstDate: _dateAnswerFormat.minDate ??
DateTime.now().add(Duration(days: 365 * DateTime.now().year)),
lastDate: _dateAnswerFormat.maxDate ??
DateTime.now().add(Duration(days: 365 * 100)),
initialDate: _result ??
_dateAnswerFormat.defaultDate ??
_dateAnswerFormat.maxDate ??
DateTime.now(),
firstDate: _dateAnswerFormat.minDate ?? DateTime.utc(1900),
lastDate: _dateAnswerFormat.maxDate?.add(
Duration(hours: 1),
) ??
DateTime.now().add(
Duration(hours: 1),
),
initialDate: _result ?? DateTime.now(),
currentDate: _result,
onDateChanged: (DateTime value) => _handleDateChanged(value),
),
Expand All @@ -135,8 +141,11 @@ class _DateAnswerViewState extends State<DateAnswerView> {
minimumDate: _dateAnswerFormat.minDate,
//We have to add an hour to to met the assert maxDate > initDate
maximumDate: _dateAnswerFormat.maxDate?.add(
Duration(hours: 1),
),
Duration(hours: 1),
) ??
DateTime.now().add(
Duration(hours: 1),
),
initialDateTime: _dateAnswerFormat.defaultDate,
onDateTimeChanged: (DateTime value) {
setState(() {
Expand Down
70 changes: 70 additions & 0 deletions test/date_answer_view_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:survey_kit/src/answer_format/date_answer_format.dart';
import 'package:survey_kit/src/steps/predefined_steps/question_step.dart';
import 'package:survey_kit/src/views/date_answer_view.dart';

void main() {
DateAnswerView _validDateAnswerView() => DateAnswerView(
questionStep: QuestionStep(
answerFormat: DateAnswerFormat(
minDate: DateTime.now().subtract(const Duration(days: 365 * 70)),
maxDate: DateTime.now().subtract(const Duration(days: 365 * 15)),
defaultDate:
DateTime.now().subtract(const Duration(days: 365 * 20)),
),
),
result: null,
);

testWidgets('Detects iOS platform and displays correct widget',
(WidgetTester tester) async {
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
await tester.pumpWidget(
CupertinoApp(
home: _validDateAnswerView(),
),
);
await tester.pumpAndSettle();
expect(find.byType(CupertinoDatePicker), findsOneWidget);
debugDefaultTargetPlatformOverride = null;
});

testWidgets('Detects Android platform and displays correct widget',
(WidgetTester tester) async {
debugDefaultTargetPlatformOverride = TargetPlatform.android;
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: _validDateAnswerView(),
),
),
);
await tester.pumpAndSettle();
expect(find.byType(CalendarDatePicker), findsOneWidget);
debugDefaultTargetPlatformOverride = null;
});

testWidgets('Initial date in between first and last date',
(WidgetTester tester) async {
debugDefaultTargetPlatformOverride = TargetPlatform.android;
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: DateAnswerView(
questionStep: QuestionStep(
title: 'Your Birthday?',
answerFormat: DateAnswerFormat(),
),
result: null,
),
),
),
);
await tester.pumpAndSettle();
expect(find.byType(CalendarDatePicker), findsOneWidget);
debugDefaultTargetPlatformOverride = null;
});
}