Line data Source code
1 : import 'package:amadeus_proto/constants.dart';
2 : import 'package:amadeus_proto/exercises/exercises_provider.dart';
3 : import 'package:amadeus_proto/exercises/widget/pressable_button.dart';
4 : import 'package:flutter/material.dart';
5 : import 'package:localization/localization.dart';
6 : import 'package:provider/provider.dart';
7 :
8 : class SingleChoiceExercise<T extends ExerciseProvider> extends StatefulWidget {
9 36 : const SingleChoiceExercise({super.key});
10 :
11 0 : @override
12 : State<SingleChoiceExercise<T>> createState() =>
13 0 : _SingleChoiceExerciseState<T>();
14 : }
15 :
16 : class _SingleChoiceExerciseState<T extends ExerciseProvider>
17 : extends State<SingleChoiceExercise<T>> with SingleTickerProviderStateMixin {
18 : Color answerColor = Colors.transparent;
19 : bool _isEnable = false;
20 : bool _overlayDisplayed = false;
21 : bool _isCorrectAnswer = false;
22 :
23 0 : @override
24 : void initState() {
25 0 : WidgetsBinding.instance.addPostFrameCallback((_) {
26 0 : answerColor = Theme.of(context).colorScheme.primary;
27 : });
28 0 : super.initState();
29 : }
30 :
31 0 : @override
32 : Widget build(BuildContext context) {
33 0 : final T provider = Provider.of<T>(context);
34 :
35 0 : return LayoutBuilder(
36 0 : builder: (context, constraints) => Column(
37 : mainAxisAlignment: MainAxisAlignment.spaceEvenly,
38 0 : children: [
39 0 : AnimatedCrossFade(
40 : firstCurve: Curves.easeIn,
41 : secondCurve: Curves.easeIn,
42 : reverseDuration: const Duration(milliseconds: 300),
43 : layoutBuilder:
44 0 : (topChild, topChildKey, bottomChild, bottomChildKey) {
45 0 : return Stack(
46 : clipBehavior: Clip.none,
47 : alignment: Alignment.center,
48 0 : children: <Widget>[
49 0 : Positioned(key: bottomChildKey, top: 0, child: bottomChild),
50 0 : Positioned(key: topChildKey, child: topChild)
51 : ],
52 : );
53 : },
54 : duration: const Duration(milliseconds: 300),
55 0 : firstChild: Center(
56 0 : child: Container(
57 0 : decoration: BoxDecoration(
58 0 : color: Colors.grey.withOpacity(0.1),
59 0 : border: Border.all(
60 : width: 0.3,
61 0 : color: Colors.grey.shade500,
62 : ),
63 0 : borderRadius: BorderRadius.circular(smallBorderRadius)),
64 : width: 350,
65 0 : height: constraints.maxHeight * ((_isCorrectAnswer) ? 0.25 : 0.35),
66 0 : child: Padding(
67 : padding: const EdgeInsets.symmetric(
68 : horizontal: mediumPadding, vertical: largePadding),
69 0 : child: Column(
70 : crossAxisAlignment: CrossAxisAlignment.start,
71 : mainAxisAlignment: MainAxisAlignment.center,
72 0 : children: [
73 0 : Text(
74 0 : _isCorrectAnswer
75 0 : ? "answers.right".i18n()
76 0 : : "answers.wrong".i18n(),
77 0 : style: TextStyle(
78 : fontSize: mediumTextSize,
79 : fontWeight: FontWeight.bold,
80 0 : color: answerColor),
81 : ),
82 0 : if (!_isCorrectAnswer && _overlayDisplayed)
83 0 : Text(
84 0 : "answers.correctAnswer".i18n() +
85 0 : provider.choices[provider.answer],
86 0 : style: TextStyle(
87 : fontSize: mediumTextSize,
88 : fontWeight: FontWeight.bold,
89 0 : color: answerColor),
90 : ),
91 : ]),
92 : )),
93 : ),
94 0 : crossFadeState: _overlayDisplayed
95 : ? CrossFadeState.showFirst
96 : : CrossFadeState.showSecond,
97 0 : secondChild: Container(
98 0 : decoration: BoxDecoration(
99 0 : color: Colors.grey.withOpacity(0.1),
100 0 : border: Border.all(
101 : width: 0.3,
102 0 : color: Colors.grey.shade500,
103 : ),
104 0 : borderRadius: BorderRadius.circular(smallBorderRadius)),
105 : width: 350,
106 0 : height: constraints.maxHeight * 0.7,
107 0 : child: Center(
108 0 : child: Wrap(
109 : spacing: 15.0,
110 : runSpacing: 25.0,
111 : alignment: WrapAlignment.center,
112 0 : children: [
113 0 : ...List.generate(
114 0 : provider.choices.length,
115 0 : (index) => PressableButton(
116 0 : body: Center(
117 0 : child: Text(provider.choices[index],
118 0 : style: TextStyle(
119 : fontSize: mediumTextSize,
120 : fontWeight: FontWeight.normal,
121 0 : color: provider.selectedAnswer == index
122 : ? Colors.white
123 : : Colors.black)),
124 : ),
125 : height: buttonHeight,
126 : width: buttonWidth,
127 0 : shadowColor: provider.selectedAnswer == index
128 0 : ? Theme.of(context)
129 0 : .colorScheme
130 0 : .primary
131 0 : .withOpacity(0.5)
132 0 : : Colors.grey.withOpacity(0.5),
133 0 : buttonColor: provider.selectedAnswer == index
134 0 : ? Theme.of(context).colorScheme.primary
135 0 : : Colors.grey[300],
136 : isEnable: true,
137 0 : onPressed: () {
138 0 : setState(() {
139 0 : if (_overlayDisplayed) {
140 : return;
141 : }
142 0 : provider.selectedAnswer =
143 0 : provider.selectedAnswer == index
144 : ? null
145 : : index;
146 0 : _isEnable = provider.selectedAnswer == null
147 : ? false
148 : : true;
149 : });
150 : }),
151 : ),
152 : ]),
153 : ),
154 : ),
155 : ),
156 0 : Padding(
157 : padding: const EdgeInsets.only(top: 0),
158 0 : child: PressableButton(
159 0 : body: Center(
160 0 : child: Text(
161 0 : _overlayDisplayed
162 0 : ? "buttons.next".i18n()
163 0 : : "buttons.confirm".i18n(),
164 0 : style: TextStyle(
165 : fontSize: mediumTextSize,
166 : fontWeight: FontWeight.bold,
167 0 : color: _isEnable ? Colors.white : Colors.grey),
168 : ),
169 : ),
170 0 : shadowColor: answerColor
171 0 : .withOpacity(provider.selectedAnswer != null ? 0.3 : 0),
172 0 : buttonColor: answerColor.withOpacity(0.9),
173 : height: confirmButtonHeight,
174 : width: confirmButtonWidth,
175 0 : isEnable: _isEnable,
176 0 : onPressed: () {
177 0 : setState(() {
178 0 : if (_overlayDisplayed) {
179 0 : _isEnable = false;
180 0 : provider.nextQuestion = true;
181 0 : provider.verify(provider.selectedAnswer);
182 0 : answerColor = Theme.of(context).colorScheme.primary;
183 : } else {
184 0 : _isCorrectAnswer = provider.isCorrectAnswer();
185 0 : answerColor =
186 0 : provider.isCorrectAnswer() ? Colors.green : Colors.red;
187 : }
188 0 : _overlayDisplayed = !_overlayDisplayed;
189 : });
190 : },
191 : ),
192 : ),
193 : ],
194 : ),
195 : );
196 : }
197 : }
|