fix: make the quiz answer component into global

This commit is contained in:
akhdanre 2025-05-04 22:06:02 +07:00
parent 55d96c3baf
commit 1a465fd0d1
4 changed files with 154 additions and 143 deletions

View File

@ -1,156 +1,156 @@
import 'package:flutter/material.dart';
import 'package:lucide_icons/lucide_icons.dart';
import 'package:quiz_app/app/const/colors/app_colors.dart';
import 'package:quiz_app/app/const/text/text_style.dart';
import 'package:quiz_app/data/models/history/detail_quiz_history.dart';
// import 'package:flutter/material.dart';
// import 'package:lucide_icons/lucide_icons.dart';
// import 'package:quiz_app/app/const/colors/app_colors.dart';
// import 'package:quiz_app/app/const/text/text_style.dart';
// import 'package:quiz_app/data/models/history/detail_quiz_history.dart';
class QuizItemComponent extends StatelessWidget {
final QuestionAnswerItem item;
// class QuizItemComponent extends StatelessWidget {
// final QuestionAnswerItem item;
const QuizItemComponent({super.key, required this.item});
// const QuizItemComponent({super.key, required this.item});
@override
Widget build(BuildContext context) {
final bool isOptionType = item.type == 'option';
// @override
// Widget build(BuildContext context) {
// final bool isOptionType = item.type == 'option';
return Container(
width: double.infinity,
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.04),
blurRadius: 6,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildQuestionText(),
const SizedBox(height: 16),
if (isOptionType && item.options != null) _buildOptions(),
const SizedBox(height: 12),
_buildAnswerIndicator(),
const SizedBox(height: 16),
const Divider(height: 24, color: AppColors.shadowPrimary),
_buildMetadata(),
],
),
);
}
// return Container(
// width: double.infinity,
// margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
// padding: const EdgeInsets.all(20),
// decoration: BoxDecoration(
// color: Colors.white,
// borderRadius: BorderRadius.circular(16),
// boxShadow: [
// BoxShadow(
// color: Colors.black.withValues(alpha: 0.04),
// blurRadius: 6,
// offset: const Offset(0, 2),
// ),
// ],
// ),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// _buildQuestionText(),
// const SizedBox(height: 16),
// if (isOptionType && item.options != null) _buildOptions(),
// const SizedBox(height: 12),
// _buildAnswerIndicator(),
// const SizedBox(height: 16),
// const Divider(height: 24, color: AppColors.shadowPrimary),
// _buildMetadata(),
// ],
// ),
// );
// }
Widget _buildQuestionText() {
return Text(
'${item.index}. ${item.question}',
style: AppTextStyles.title.copyWith(fontSize: 16, fontWeight: FontWeight.w600),
);
}
// Widget _buildQuestionText() {
// return Text(
// '${item.index}. ${item.question}',
// style: AppTextStyles.title.copyWith(fontSize: 16, fontWeight: FontWeight.w600),
// );
// }
Widget _buildOptions() {
return Column(
children: item.options!.asMap().entries.map((entry) {
final int index = entry.key;
final String text = entry.value;
// Widget _buildOptions() {
// return Column(
// children: item.options!.asMap().entries.map((entry) {
// final int index = entry.key;
// final String text = entry.value;
final bool isCorrectAnswer = index == item.targetAnswer;
final bool isUserWrongAnswer = index == item.userAnswer && !isCorrectAnswer;
// final bool isCorrectAnswer = index == item.targetAnswer;
// final bool isUserWrongAnswer = index == item.userAnswer && !isCorrectAnswer;
Color? backgroundColor;
IconData icon = LucideIcons.circle;
Color iconColor = AppColors.shadowPrimary;
// Color? backgroundColor;
// IconData icon = LucideIcons.circle;
// Color iconColor = AppColors.shadowPrimary;
if (isCorrectAnswer) {
backgroundColor = AppColors.primaryBlue.withValues(alpha: 0.15);
icon = LucideIcons.checkCircle2;
iconColor = AppColors.primaryBlue;
} else if (isUserWrongAnswer) {
backgroundColor = Colors.red.withValues(alpha: 0.15);
icon = LucideIcons.xCircle;
iconColor = Colors.red;
}
// if (isCorrectAnswer) {
// backgroundColor = AppColors.primaryBlue.withValues(alpha: 0.15);
// icon = LucideIcons.checkCircle2;
// iconColor = AppColors.primaryBlue;
// } else if (isUserWrongAnswer) {
// backgroundColor = Colors.red.withValues(alpha: 0.15);
// icon = LucideIcons.xCircle;
// iconColor = Colors.red;
// }
return Container(
width: double.infinity,
margin: const EdgeInsets.symmetric(vertical: 6),
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 12),
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: AppColors.shadowPrimary),
),
child: Row(
children: [
Icon(icon, size: 16, color: iconColor),
const SizedBox(width: 8),
Flexible(
child: Text(text, style: AppTextStyles.optionText),
),
],
),
);
}).toList(),
);
}
// return Container(
// width: double.infinity,
// margin: const EdgeInsets.symmetric(vertical: 6),
// padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 12),
// decoration: BoxDecoration(
// color: backgroundColor,
// borderRadius: BorderRadius.circular(12),
// border: Border.all(color: AppColors.shadowPrimary),
// ),
// child: Row(
// children: [
// Icon(icon, size: 16, color: iconColor),
// const SizedBox(width: 8),
// Flexible(
// child: Text(text, style: AppTextStyles.optionText),
// ),
// ],
// ),
// );
// }).toList(),
// );
// }
Widget _buildAnswerIndicator() {
final correctIcon = item.isCorrect ? LucideIcons.checkCircle2 : LucideIcons.xCircle;
final correctColor = item.isCorrect ? AppColors.primaryBlue : Colors.red;
// Widget _buildAnswerIndicator() {
// final correctIcon = item.isCorrect ? LucideIcons.checkCircle2 : LucideIcons.xCircle;
// final correctColor = item.isCorrect ? AppColors.primaryBlue : Colors.red;
final String userAnswerText = item.type == 'option' ? item.options![item.userAnswer] : item.userAnswer.toString();
// final String userAnswerText = item.type == 'option' ? item.options![item.userAnswer] : item.userAnswer.toString();
final String correctAnswerText = item.targetAnswer.toString();
// final String correctAnswerText = item.targetAnswer.toString();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(correctIcon, color: correctColor, size: 18),
const SizedBox(width: 8),
Text(
'Jawabanmu: $userAnswerText',
style: AppTextStyles.statValue,
),
],
),
if (item.type != 'option' && !item.isCorrect) ...[
const SizedBox(height: 6),
Row(
children: [
const SizedBox(width: 26), // offset for icon + spacing
Text(
'Jawaban benar: $correctAnswerText',
style: AppTextStyles.caption,
),
],
),
],
],
);
}
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Row(
// children: [
// Icon(correctIcon, color: correctColor, size: 18),
// const SizedBox(width: 8),
// Text(
// 'Jawabanmu: $userAnswerText',
// style: AppTextStyles.statValue,
// ),
// ],
// ),
// if (item.type != 'option' && !item.isCorrect) ...[
// const SizedBox(height: 6),
// Row(
// children: [
// const SizedBox(width: 26), // offset for icon + spacing
// Text(
// 'Jawaban benar: $correctAnswerText',
// style: AppTextStyles.caption,
// ),
// ],
// ),
// ],
// ],
// );
// }
Widget _buildMetadata() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_metaItem(icon: LucideIcons.helpCircle, label: item.type),
_metaItem(icon: LucideIcons.clock3, label: '${item.timeSpent}s'),
],
);
}
// Widget _buildMetadata() {
// return Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// _metaItem(icon: LucideIcons.helpCircle, label: item.type),
// _metaItem(icon: LucideIcons.clock3, label: '${item.timeSpent}s'),
// ],
// );
// }
Widget _metaItem({required IconData icon, required String label}) {
return Row(
children: [
Icon(icon, size: 16, color: AppColors.primaryBlue),
const SizedBox(width: 6),
Text(label, style: AppTextStyles.caption),
],
);
}
}
// Widget _metaItem({required IconData icon, required String label}) {
// return Row(
// children: [
// Icon(icon, size: 16, color: AppColors.primaryBlue),
// const SizedBox(width: 6),
// Text(label, style: AppTextStyles.caption),
// ],
// );
// }
// }

View File

@ -4,8 +4,8 @@ import 'package:lucide_icons/lucide_icons.dart';
import 'package:quiz_app/app/const/colors/app_colors.dart';
import 'package:quiz_app/app/const/text/text_style.dart';
import 'package:quiz_app/component/widget/loading_widget.dart';
import 'package:quiz_app/component/widget/quiz_item_wa_component.dart';
import 'package:quiz_app/feature/history/controller/detail_history_controller.dart';
import 'package:quiz_app/feature/history/view/component/quiz_item_component.dart';
class DetailHistoryView extends GetView<DetailHistoryController> {
const DetailHistoryView({super.key});
@ -41,7 +41,18 @@ class DetailHistoryView extends GetView<DetailHistoryController> {
}
List<Widget> quizListings() {
return controller.quizAnswer.questionListings.map((e) => QuizItemComponent(item: e)).toList();
return controller.quizAnswer.questionListings
.map((e) => QuizItemWAComponent(
index: e.index,
isCorrect: e.isCorrect,
question: e.question,
targetAnswer: e.targetAnswer,
timeSpent: e.timeSpent,
type: e.type,
userAnswer: e.userAnswer,
options: e.options,
))
.toList();
}
Widget quizMetaInfo() {

View File

@ -6,7 +6,7 @@ import 'package:quiz_app/data/models/quiz/question/fill_in_the_blank_question_mo
import 'package:quiz_app/data/models/quiz/question/option_question_model.dart';
import 'package:quiz_app/data/models/quiz/question/true_false_question_model.dart';
import 'package:quiz_app/feature/quiz_result/controller/quiz_result_controller.dart';
import 'package:quiz_app/feature/quiz_result/view/component/quiz_item_wa_component.dart';
import 'package:quiz_app/component/widget/quiz_item_wa_component.dart';
class QuizResultView extends GetView<QuizResultController> {
const QuizResultView({super.key});