Skip to content

Commit 75f57a8

Browse files
authored
Merge pull request #70 from nimblehq/feature/19-ui-survey-detail
[#19] [UI] As a logged-in user, I can see the Survey Detail screen
2 parents 0069a84 + 2463f27 commit 75f57a8

File tree

8 files changed

+165
-23
lines changed

8 files changed

+165
-23
lines changed

lib/l10n/app_en.arb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
"genericError": "Something went wrong.\nPlease try again!",
1111
"loginFailAlertTitle": "Unable to log in",
1212
"today": "Today",
13-
"errorText": "Error"
13+
"errorText": "Error",
14+
"startSurveyButton": "Start Survey"
1415
}

lib/main.dart

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ import 'package:flutter_config/flutter_config.dart';
33
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
44
import 'package:flutter_riverpod/flutter_riverpod.dart';
55
import 'package:go_router/go_router.dart';
6+
import 'package:survey_flutter/model/survey_model.dart';
7+
import 'package:survey_flutter/screens/app_route.dart';
68
import 'package:survey_flutter/screens/home/home_screen.dart';
79
import 'package:survey_flutter/screens/login/login_screen.dart';
810
import 'package:survey_flutter/screens/splash/splash_screen.dart';
11+
import 'package:survey_flutter/screens/survey/survey_screen.dart';
912
import 'package:survey_flutter/storage/survey_storage.dart';
1013
import 'package:survey_flutter/theme/app_theme.dart';
1114

@@ -20,27 +23,31 @@ void main() async {
2023
);
2124
}
2225

23-
const routePathSplashScreen = '/';
24-
2526
class App extends StatelessWidget {
2627
App({Key? key}) : super(key: key);
2728

2829
final GoRouter _router = GoRouter(
2930
routes: <GoRoute>[
3031
GoRoute(
31-
path: routePathSplashScreen,
32+
path: AppRoute.splash.path,
3233
builder: (_, __) => const SplashScreen(),
3334
),
3435
GoRoute(
35-
path: routePathLoginScreen,
36+
path: AppRoute.login.path,
3637
pageBuilder: (_, __) => const NoTransitionPage<void>(
3738
child: LoginScreen(),
3839
),
3940
),
4041
GoRoute(
41-
path: routePathHomeScreen,
42+
path: AppRoute.home.path,
4243
builder: (_, __) => const HomeScreen(),
4344
),
45+
GoRoute(
46+
path: AppRoute.survey.path,
47+
builder: (_, state) => SurveyScreen(
48+
survey: state.extra as SurveyModel,
49+
),
50+
),
4451
],
4552
);
4653

lib/screens/app_route.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
enum AppRoute {
2+
splash,
3+
login,
4+
home,
5+
survey,
6+
}
7+
8+
extension AppRoutePath on AppRoute {
9+
String get path {
10+
switch (this) {
11+
case AppRoute.splash:
12+
return '/';
13+
case AppRoute.login:
14+
return '/login';
15+
case AppRoute.home:
16+
return '/home';
17+
case AppRoute.survey:
18+
return '/survey';
19+
}
20+
}
21+
}

lib/screens/home/home_pages_widget.dart

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ class HomePagesWidget extends StatelessWidget {
1111
final List<SurveyModel> surveys;
1212
final ValueNotifier<int> currentPage;
1313
final PageController _pageController = PageController();
14+
final VoidCallback onNextButtonPressed;
1415

1516
HomePagesWidget({
1617
Key? key,
1718
required this.surveys,
1819
required this.currentPage,
20+
required this.onNextButtonPressed,
1921
}) : super(key: key);
2022

2123
@override
@@ -50,12 +52,7 @@ class HomePagesWidget extends StatelessWidget {
5052
),
5153
child: HomeFooterWidget(
5254
survey: surveys[index],
53-
onNextButtonPressed: () {
54-
if (currentPage.value < surveys.length - 1) {
55-
currentPage.value = index + 1;
56-
_pageController.jumpToPage(currentPage.value);
57-
}
58-
},
55+
onNextButtonPressed: onNextButtonPressed,
5956
),
6057
),
6158
),

lib/screens/home/home_screen.dart

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_riverpod/flutter_riverpod.dart';
3+
import 'package:go_router/go_router.dart';
34
import 'package:survey_flutter/model/survey_model.dart';
5+
import 'package:survey_flutter/screens/app_route.dart';
46
import 'package:survey_flutter/screens/home/home_header_widget.dart';
5-
import 'package:survey_flutter/screens/home/home_pages_widget.dart';
67
import 'package:survey_flutter/screens/home/home_page_indicator_widget.dart';
8+
import 'package:survey_flutter/screens/home/home_pages_widget.dart';
79
import 'package:survey_flutter/screens/home/home_shimmer_loading.dart';
810
import 'package:survey_flutter/screens/home/home_view_model.dart';
911
import 'package:survey_flutter/utils/build_context_ext.dart';
1012
import 'package:survey_flutter/widgets/alert_dialog.dart';
1113

12-
const routePathHomeScreen = '/home';
13-
1414
class HomeScreen extends ConsumerStatefulWidget {
1515
const HomeScreen({Key? key}) : super(key: key);
1616

@@ -85,6 +85,13 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
8585
HomePagesWidget(
8686
surveys: surveys,
8787
currentPage: _currentPage,
88+
onNextButtonPressed: () {
89+
final survey = surveys[_currentPage.value];
90+
context.push(
91+
AppRoute.survey.path,
92+
extra: survey,
93+
);
94+
},
8895
),
8996
const HomeHeaderWidget(),
9097
Align(

lib/screens/login/login_screen.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@ import 'package:flutter/material.dart';
44
import 'package:flutter_riverpod/flutter_riverpod.dart';
55
import 'package:go_router/go_router.dart';
66
import 'package:survey_flutter/gen/assets.gen.dart';
7-
import 'package:survey_flutter/screens/home/home_screen.dart';
7+
import 'package:survey_flutter/screens/app_route.dart';
88
import 'package:survey_flutter/screens/login/login_form.dart';
99
import 'package:survey_flutter/screens/login/login_view_model.dart';
1010
import 'package:survey_flutter/theme/app_constants.dart';
1111
import 'package:survey_flutter/uimodels/app_error.dart';
1212
import 'package:survey_flutter/utils/build_context_ext.dart';
1313
import 'package:survey_flutter/widgets/alert_dialog.dart';
1414

15-
const routePathLoginScreen = '/login';
16-
1715
class LoginScreen extends ConsumerStatefulWidget {
1816
const LoginScreen({Key? key}) : super(key: key);
1917

@@ -117,7 +115,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
117115
_setUpListener(BuildContext context) {
118116
ref.listen<AsyncValue<void>>(loginViewModelProvider, (_, next) {
119117
next.maybeWhen(
120-
data: (_) => context.go(routePathHomeScreen),
118+
data: (_) => context.go(AppRoute.home.path),
121119
error: (error, _) {
122120
showAlertDialog(
123121
context: context,

lib/screens/splash/splash_screen.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ import 'package:flutter/material.dart';
22
import 'package:flutter_riverpod/flutter_riverpod.dart';
33
import 'package:go_router/go_router.dart';
44
import 'package:survey_flutter/gen/assets.gen.dart';
5-
import 'package:survey_flutter/screens/home/home_screen.dart';
6-
import 'package:survey_flutter/screens/login/login_screen.dart';
5+
import 'package:survey_flutter/screens/app_route.dart';
76
import 'package:survey_flutter/screens/splash/splash_view_model.dart';
87

98
class SplashScreen extends ConsumerStatefulWidget {
@@ -57,9 +56,9 @@ class _SplashScreenState extends ConsumerState<SplashScreen> {
5756
child: Assets.images.splashLogoWhite.image(),
5857
onEnd: () {
5958
if (_isLoggedIn == true) {
60-
context.go(routePathHomeScreen);
59+
context.go(AppRoute.home.path);
6160
} else {
62-
context.go(routePathLoginScreen);
61+
context.go(AppRoute.login.path);
6362
}
6463
},
6564
);
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:survey_flutter/gen/assets.gen.dart';
3+
import 'package:survey_flutter/model/survey_model.dart';
4+
import 'package:survey_flutter/theme/app_constants.dart';
5+
import 'package:survey_flutter/theme/primary_button_style.dart';
6+
import 'package:survey_flutter/utils/build_context_ext.dart';
7+
8+
const _buttonHeight = 56.0;
9+
10+
class SurveyScreen extends StatelessWidget {
11+
final SurveyModel survey;
12+
SurveyScreen({
13+
super.key,
14+
required this.survey,
15+
});
16+
17+
late final _backgroundImage = FadeInImage.assetNetwork(
18+
placeholder: Assets.images.placeholder.path,
19+
image: survey.coverImageUrl,
20+
fit: BoxFit.cover,
21+
width: double.infinity,
22+
height: double.infinity,
23+
);
24+
25+
late final _gradientOverlay = Container(
26+
decoration: BoxDecoration(
27+
gradient: LinearGradient(
28+
begin: Alignment.topCenter,
29+
end: Alignment.bottomCenter,
30+
colors: [
31+
Colors.black.withOpacity(0.8),
32+
Colors.black.withOpacity(0.2),
33+
Colors.black.withOpacity(0.8),
34+
],
35+
),
36+
),
37+
);
38+
39+
Widget _buildTitle(BuildContext context) {
40+
return Text(
41+
survey.title,
42+
style: context.textTheme.titleMedium,
43+
maxLines: 2,
44+
);
45+
}
46+
47+
Widget _buildDescription(BuildContext context) {
48+
return Text(
49+
survey.description,
50+
style: context.textTheme.bodyMedium,
51+
maxLines: 2,
52+
);
53+
}
54+
55+
Widget _buildButton(BuildContext context) {
56+
return SizedBox(
57+
height: _buttonHeight,
58+
child: ElevatedButton(
59+
style: PrimaryButtonStyle(
60+
hintTextStyle: context.textTheme.labelMedium,
61+
),
62+
child: Text(
63+
context.localizations.startSurveyButton,
64+
),
65+
onPressed: () {
66+
// TODO: Start survey
67+
},
68+
),
69+
);
70+
}
71+
72+
@override
73+
Widget build(BuildContext context) {
74+
return Scaffold(
75+
appBar: AppBar(
76+
backgroundColor: Colors.transparent,
77+
elevation: 0,
78+
),
79+
extendBodyBehindAppBar: true,
80+
body: Stack(
81+
children: [
82+
_backgroundImage,
83+
_gradientOverlay,
84+
Container(
85+
padding: const EdgeInsets.only(
86+
bottom: Metrics.spacing20,
87+
left: Metrics.spacing20,
88+
right: Metrics.spacing20,
89+
),
90+
child: SafeArea(
91+
child: Column(
92+
crossAxisAlignment: CrossAxisAlignment.start,
93+
children: [
94+
_buildTitle(context),
95+
const SizedBox(height: Metrics.spacing16),
96+
_buildDescription(context),
97+
const Spacer(),
98+
Row(
99+
children: [
100+
const Spacer(),
101+
_buildButton(context),
102+
],
103+
),
104+
],
105+
),
106+
),
107+
),
108+
],
109+
),
110+
);
111+
}
112+
}

0 commit comments

Comments
 (0)