feat: done on quiz result
This commit is contained in:
parent
9797fd4a4f
commit
51182b8c7b
|
@ -0,0 +1,194 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:quiz_app/app/const/colors/app_colors.dart';
|
||||||
|
import 'package:quiz_app/app/const/enums/question_type.dart';
|
||||||
|
import 'package:quiz_app/data/models/quiz/quiestion_data_model.dart';
|
||||||
|
import 'package:quiz_app/feature/quiz_play/controller/quiz_play_controller.dart';
|
||||||
|
|
||||||
|
class QuestionContainerWidget extends StatelessWidget {
|
||||||
|
final QuestionData question;
|
||||||
|
final AnsweredQuestion? answeredQuestion;
|
||||||
|
|
||||||
|
const QuestionContainerWidget({super.key, required this.question, this.answeredQuestion});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
width: double.infinity,
|
||||||
|
margin: const EdgeInsets.only(bottom: 20),
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
border: Border.all(color: AppColors.borderLight),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.05),
|
||||||
|
blurRadius: 6,
|
||||||
|
offset: const Offset(2, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('Soal ${question.index}', style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: AppColors.darkText)),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Text(
|
||||||
|
_mapQuestionTypeToText(question.type),
|
||||||
|
style: const TextStyle(fontSize: 12, color: AppColors.softGrayText, fontStyle: FontStyle.italic),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Text(
|
||||||
|
question.question ?? '-',
|
||||||
|
style: const TextStyle(fontSize: 16, color: AppColors.darkText),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
_buildAnswerSection(question),
|
||||||
|
if (answeredQuestion != null) ...[
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
_buildAnsweredSection(answeredQuestion!),
|
||||||
|
],
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
const Text(
|
||||||
|
'Durasi: 0 detik',
|
||||||
|
style: TextStyle(fontSize: 14, color: AppColors.softGrayText),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildAnswerSection(QuestionData question) {
|
||||||
|
if (question.type == QuestionType.option && question.options != null) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: question.options!.map((option) {
|
||||||
|
bool isCorrect = question.correctAnswerIndex == option.index;
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 4),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: isCorrect ? AppColors.primaryBlue.withOpacity(0.1) : Colors.transparent,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
isCorrect ? Icons.check_circle_rounded : Icons.circle_outlined,
|
||||||
|
size: 18,
|
||||||
|
color: isCorrect ? AppColors.primaryBlue : AppColors.softGrayText,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
option.text,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: isCorrect ? FontWeight.bold : FontWeight.normal,
|
||||||
|
color: isCorrect ? AppColors.primaryBlue : AppColors.darkText,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
} else if (question.type == QuestionType.fillTheBlank) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: _buildFillTheBlankPossibilities(question.answer ?? '-'),
|
||||||
|
);
|
||||||
|
} else if (question.type == QuestionType.trueOrFalse) {
|
||||||
|
return Text(
|
||||||
|
'Jawaban: ${question.answer ?? '-'}',
|
||||||
|
style: const TextStyle(color: AppColors.softGrayText),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return const SizedBox();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildAnsweredSection(AnsweredQuestion answered) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text('Jawaban Anda:', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14, color: AppColors.darkText)),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
answered.isCorrect ? Icons.check_circle : Icons.cancel,
|
||||||
|
color: answered.isCorrect ? Colors.green : Colors.red,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
answered.selectedAnswer,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: answered.isCorrect ? Colors.green : Colors.red,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _mapQuestionTypeToText(QuestionType? type) {
|
||||||
|
switch (type) {
|
||||||
|
case QuestionType.option:
|
||||||
|
return 'Tipe: Pilihan Ganda';
|
||||||
|
case QuestionType.fillTheBlank:
|
||||||
|
return 'Tipe: Isian Kosong';
|
||||||
|
case QuestionType.trueOrFalse:
|
||||||
|
return 'Tipe: Benar / Salah';
|
||||||
|
default:
|
||||||
|
return 'Tipe: Tidak diketahui';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> _buildFillTheBlankPossibilities(String answer) {
|
||||||
|
List<String> possibilities = [
|
||||||
|
_capitalizeEachWord(answer),
|
||||||
|
answer.toLowerCase(),
|
||||||
|
_capitalizeFirstWordOnly(answer),
|
||||||
|
];
|
||||||
|
|
||||||
|
return possibilities.map((option) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.arrow_right, size: 18, color: AppColors.softGrayText),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
Text(
|
||||||
|
option,
|
||||||
|
style: const TextStyle(color: AppColors.darkText),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
String _capitalizeEachWord(String text) {
|
||||||
|
return text.split(' ').map((word) {
|
||||||
|
if (word.isEmpty) return word;
|
||||||
|
return word[0].toUpperCase() + word.substring(1).toLowerCase();
|
||||||
|
}).join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
String _capitalizeFirstWordOnly(String text) {
|
||||||
|
if (text.isEmpty) return text;
|
||||||
|
List<String> parts = text.split(' ');
|
||||||
|
parts[0] = parts[0][0].toUpperCase() + parts[0].substring(1).toLowerCase();
|
||||||
|
for (int i = 1; i < parts.length; i++) {
|
||||||
|
parts[i] = parts[i].toLowerCase();
|
||||||
|
}
|
||||||
|
return parts.join(' ');
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,6 @@ import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:quiz_app/app/routes/app_pages.dart';
|
import 'package:quiz_app/app/routes/app_pages.dart';
|
||||||
import 'package:quiz_app/core/utils/logger.dart';
|
|
||||||
import 'package:quiz_app/data/models/quiz/library_quiz_model.dart';
|
import 'package:quiz_app/data/models/quiz/library_quiz_model.dart';
|
||||||
import 'package:quiz_app/data/models/quiz/question_listings_model.dart';
|
import 'package:quiz_app/data/models/quiz/question_listings_model.dart';
|
||||||
|
|
||||||
|
@ -136,7 +135,7 @@ class QuizPlayController extends GetxController {
|
||||||
// );
|
// );
|
||||||
Get.toNamed(
|
Get.toNamed(
|
||||||
AppRoutes.resultQuizPage,
|
AppRoutes.resultQuizPage,
|
||||||
arguments: [quizData.questionListings, answeredQuestions],
|
arguments: [quizData, answeredQuestions],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:quiz_app/app/const/colors/app_colors.dart';
|
|
||||||
import 'package:quiz_app/app/const/enums/question_type.dart';
|
import 'package:quiz_app/app/const/enums/question_type.dart';
|
||||||
import 'package:quiz_app/app/routes/app_pages.dart';
|
import 'package:quiz_app/app/routes/app_pages.dart';
|
||||||
import 'package:quiz_app/core/utils/logger.dart';
|
import 'package:quiz_app/core/utils/logger.dart';
|
||||||
|
@ -106,153 +105,6 @@ class QuizPreviewController extends GetxController {
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildQuestionCard(QuestionData question) {
|
|
||||||
return Container(
|
|
||||||
width: double.infinity,
|
|
||||||
margin: const EdgeInsets.only(bottom: 20),
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.white,
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
border: Border.all(color: AppColors.borderLight),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withOpacity(0.05),
|
|
||||||
blurRadius: 6,
|
|
||||||
offset: const Offset(2, 2),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text('Soal ${question.index}', style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: AppColors.darkText)),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
Text(
|
|
||||||
_mapQuestionTypeToText(question.type),
|
|
||||||
style: const TextStyle(fontSize: 12, color: AppColors.softGrayText, fontStyle: FontStyle.italic),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
Text(
|
|
||||||
question.question ?? '-',
|
|
||||||
style: const TextStyle(fontSize: 16, color: AppColors.darkText),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
_buildAnswerSection(question),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
const Text(
|
|
||||||
'Durasi: 0 detik',
|
|
||||||
style: TextStyle(fontSize: 14, color: AppColors.softGrayText),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildAnswerSection(QuestionData question) {
|
|
||||||
if (question.type == QuestionType.option && question.options != null) {
|
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: question.options!.map((option) {
|
|
||||||
bool isCorrect = question.correctAnswerIndex == option.index;
|
|
||||||
return Container(
|
|
||||||
margin: const EdgeInsets.symmetric(vertical: 4),
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: isCorrect ? AppColors.primaryBlue.withOpacity(0.1) : Colors.transparent,
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
isCorrect ? Icons.check_circle_rounded : Icons.circle_outlined,
|
|
||||||
size: 18,
|
|
||||||
color: isCorrect ? AppColors.primaryBlue : AppColors.softGrayText,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
option.text,
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: isCorrect ? FontWeight.bold : FontWeight.normal,
|
|
||||||
color: isCorrect ? AppColors.primaryBlue : AppColors.darkText,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
);
|
|
||||||
} else if (question.type == QuestionType.fillTheBlank) {
|
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: _buildFillTheBlankPossibilities(question.answer ?? '-'),
|
|
||||||
);
|
|
||||||
} else if (question.type == QuestionType.trueOrFalse) {
|
|
||||||
return Text(
|
|
||||||
'Jawaban: ${question.answer ?? '-'}',
|
|
||||||
style: const TextStyle(color: AppColors.softGrayText),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return const SizedBox();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String _mapQuestionTypeToText(QuestionType? type) {
|
|
||||||
switch (type) {
|
|
||||||
case QuestionType.option:
|
|
||||||
return 'Tipe: Pilihan Ganda';
|
|
||||||
case QuestionType.fillTheBlank:
|
|
||||||
return 'Tipe: Isian Kosong';
|
|
||||||
case QuestionType.trueOrFalse:
|
|
||||||
return 'Tipe: Benar / Salah';
|
|
||||||
default:
|
|
||||||
return 'Tipe: Tidak diketahui';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Widget> _buildFillTheBlankPossibilities(String answer) {
|
|
||||||
List<String> possibilities = [
|
|
||||||
_capitalizeEachWord(answer),
|
|
||||||
answer.toLowerCase(),
|
|
||||||
_capitalizeFirstWordOnly(answer),
|
|
||||||
];
|
|
||||||
|
|
||||||
return possibilities.map((option) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Icons.arrow_right, size: 18, color: AppColors.softGrayText),
|
|
||||||
const SizedBox(width: 6),
|
|
||||||
Text(
|
|
||||||
option,
|
|
||||||
style: const TextStyle(color: AppColors.darkText),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
String _capitalizeEachWord(String text) {
|
|
||||||
return text.split(' ').map((word) {
|
|
||||||
if (word.isEmpty) return word;
|
|
||||||
return word[0].toUpperCase() + word.substring(1).toLowerCase();
|
|
||||||
}).join(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
String _capitalizeFirstWordOnly(String text) {
|
|
||||||
if (text.isEmpty) return text;
|
|
||||||
List<String> parts = text.split(' ');
|
|
||||||
parts[0] = parts[0][0].toUpperCase() + parts[0].substring(1).toLowerCase();
|
|
||||||
for (int i = 1; i < parts.length; i++) {
|
|
||||||
parts[i] = parts[i].toLowerCase();
|
|
||||||
}
|
|
||||||
return parts.join(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
titleController.dispose();
|
titleController.dispose();
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'package:quiz_app/app/const/colors/app_colors.dart';
|
||||||
import 'package:quiz_app/component/global_button.dart';
|
import 'package:quiz_app/component/global_button.dart';
|
||||||
import 'package:quiz_app/component/global_text_field.dart';
|
import 'package:quiz_app/component/global_text_field.dart';
|
||||||
import 'package:quiz_app/component/label_text_field.dart';
|
import 'package:quiz_app/component/label_text_field.dart';
|
||||||
|
import 'package:quiz_app/component/widget/question_container_widget.dart';
|
||||||
import 'package:quiz_app/feature/quiz_preview/controller/quiz_preview_controller.dart';
|
import 'package:quiz_app/feature/quiz_preview/controller/quiz_preview_controller.dart';
|
||||||
|
|
||||||
class QuizPreviewPage extends GetView<QuizPreviewController> {
|
class QuizPreviewPage extends GetView<QuizPreviewController> {
|
||||||
|
@ -61,7 +62,7 @@ class QuizPreviewPage extends GetView<QuizPreviewController> {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: controller.data.map((question) {
|
children: controller.data.map((question) {
|
||||||
return controller.buildQuestionCard(question);
|
return QuestionContainerWidget(question: question);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:quiz_app/app/const/enums/question_type.dart';
|
||||||
|
import 'package:quiz_app/data/models/quiz/library_quiz_model.dart';
|
||||||
import 'package:quiz_app/data/models/quiz/question_listings_model.dart';
|
import 'package:quiz_app/data/models/quiz/question_listings_model.dart';
|
||||||
|
import 'package:quiz_app/data/models/quiz/quiestion_data_model.dart';
|
||||||
import 'package:quiz_app/feature/quiz_play/controller/quiz_play_controller.dart';
|
import 'package:quiz_app/feature/quiz_play/controller/quiz_play_controller.dart';
|
||||||
|
|
||||||
class QuizResultController extends GetxController {
|
class QuizResultController extends GetxController {
|
||||||
|
late final QuizData question;
|
||||||
late final List<QuestionListing> questions;
|
late final List<QuestionListing> questions;
|
||||||
late final List<AnsweredQuestion> answers;
|
late final List<AnsweredQuestion> answers;
|
||||||
|
|
||||||
|
@ -20,7 +24,8 @@ class QuizResultController extends GetxController {
|
||||||
void loadData() {
|
void loadData() {
|
||||||
final args = Get.arguments as List<dynamic>;
|
final args = Get.arguments as List<dynamic>;
|
||||||
|
|
||||||
questions = args[0] as List<QuestionListing>;
|
question = args[0] as QuizData;
|
||||||
|
questions = question.questionListings;
|
||||||
answers = args[1] as List<AnsweredQuestion>;
|
answers = args[1] as List<AnsweredQuestion>;
|
||||||
totalQuestions.value = questions.length;
|
totalQuestions.value = questions.length;
|
||||||
}
|
}
|
||||||
|
@ -40,4 +45,49 @@ class QuizResultController extends GetxController {
|
||||||
return "Belum Lulus 😔";
|
return "Belum Lulus 😔";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QuestionData mapQuestionListingToQuestionData(QuestionListing questionListing, int index) {
|
||||||
|
// Convert type string ke enum
|
||||||
|
QuestionType? questionType;
|
||||||
|
switch (questionListing.type) {
|
||||||
|
case 'fill_the_blank':
|
||||||
|
questionType = QuestionType.fillTheBlank;
|
||||||
|
break;
|
||||||
|
case 'option':
|
||||||
|
questionType = QuestionType.option;
|
||||||
|
break;
|
||||||
|
case 'true_false':
|
||||||
|
questionType = QuestionType.trueOrFalse;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
questionType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert options ke OptionData
|
||||||
|
List<OptionData>? optionDataList;
|
||||||
|
if (questionListing.options != null) {
|
||||||
|
optionDataList = [];
|
||||||
|
for (int i = 0; i < questionListing.options!.length; i++) {
|
||||||
|
optionDataList.add(OptionData(index: i, text: questionListing.options![i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cari correctAnswerIndex kalau tipe-nya option
|
||||||
|
int? correctAnswerIndex;
|
||||||
|
if (questionType == QuestionType.option && optionDataList != null) {
|
||||||
|
correctAnswerIndex = optionDataList.indexWhere((option) => option.text == questionListing.targetAnswer);
|
||||||
|
if (correctAnswerIndex == -1) {
|
||||||
|
correctAnswerIndex = null; // Kalau tidak ketemu
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QuestionData(
|
||||||
|
index: index,
|
||||||
|
question: questionListing.question,
|
||||||
|
answer: questionListing.targetAnswer,
|
||||||
|
options: optionDataList,
|
||||||
|
correctAnswerIndex: correctAnswerIndex,
|
||||||
|
type: questionType,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:quiz_app/app/const/colors/app_colors.dart';
|
import 'package:quiz_app/app/const/colors/app_colors.dart';
|
||||||
|
import 'package:quiz_app/component/widget/question_container_widget.dart';
|
||||||
import 'package:quiz_app/feature/quiz_result/controller/quiz_result_controller.dart';
|
import 'package:quiz_app/feature/quiz_result/controller/quiz_result_controller.dart';
|
||||||
|
|
||||||
class QuizResultView extends GetView<QuizResultController> {
|
class QuizResultView extends GetView<QuizResultController> {
|
||||||
|
@ -33,7 +34,9 @@ class QuizResultView extends GetView<QuizResultController> {
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
itemCount: controller.questions.length,
|
itemCount: controller.questions.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return _buildQuestionResult(index);
|
return QuestionContainerWidget(
|
||||||
|
question: controller.mapQuestionListingToQuestionData(controller.questions[index], index),
|
||||||
|
answeredQuestion: controller.answers[index]);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -71,76 +74,76 @@ class QuizResultView extends GetView<QuizResultController> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildQuestionResult(int index) {
|
// Widget _buildQuestionResult(int index) {
|
||||||
final answered = controller.answers[index];
|
// final answered = controller.answers[index];
|
||||||
final isCorrect = answered.isCorrect;
|
// final isCorrect = answered.isCorrect;
|
||||||
|
|
||||||
return Container(
|
// return Container(
|
||||||
width: double.infinity,
|
// width: double.infinity,
|
||||||
margin: const EdgeInsets.only(bottom: 16),
|
// margin: const EdgeInsets.only(bottom: 16),
|
||||||
padding: const EdgeInsets.all(16),
|
// padding: const EdgeInsets.all(16),
|
||||||
decoration: BoxDecoration(
|
// decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
// color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(12),
|
// borderRadius: BorderRadius.circular(12),
|
||||||
border: Border.all(color: AppColors.borderLight),
|
// border: Border.all(color: AppColors.borderLight),
|
||||||
boxShadow: [
|
// boxShadow: [
|
||||||
BoxShadow(
|
// BoxShadow(
|
||||||
color: Colors.black.withOpacity(0.05),
|
// color: Colors.black.withOpacity(0.05),
|
||||||
blurRadius: 6,
|
// blurRadius: 6,
|
||||||
offset: const Offset(2, 2),
|
// offset: const Offset(2, 2),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
child: Column(
|
// child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
// children: [
|
||||||
Text('Soal ${answered.index + 1}', style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: AppColors.darkText)),
|
// Text('Soal ${answered.index + 1}', style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: AppColors.darkText)),
|
||||||
const SizedBox(height: 6),
|
// const SizedBox(height: 6),
|
||||||
Text(
|
// Text(
|
||||||
// Tidak ada tipe soal di AnsweredQuestion, jadi kalau mau kasih tipe harus pakai question[index].type
|
// // Tidak ada tipe soal di AnsweredQuestion, jadi kalau mau kasih tipe harus pakai question[index].type
|
||||||
// kalau tidak mau ribet, ini bisa dihapus saja
|
// // kalau tidak mau ribet, ini bisa dihapus saja
|
||||||
// controller.mapQuestionTypeToText(controller.questions[answered.index].type),
|
// // controller.mapQuestionTypeToText(controller.questions[answered.index].type),
|
||||||
'', // kosongkan dulu
|
// '', // kosongkan dulu
|
||||||
style: const TextStyle(fontSize: 12, color: AppColors.softGrayText, fontStyle: FontStyle.italic),
|
// style: const TextStyle(fontSize: 12, color: AppColors.softGrayText, fontStyle: FontStyle.italic),
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 12),
|
// const SizedBox(height: 12),
|
||||||
Text(
|
// Text(
|
||||||
answered.question,
|
// answered.question,
|
||||||
style: const TextStyle(fontSize: 16, color: AppColors.darkText),
|
// style: const TextStyle(fontSize: 16, color: AppColors.darkText),
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 12),
|
// const SizedBox(height: 12),
|
||||||
Row(
|
// Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
// children: [
|
||||||
const Icon(Icons.person, size: 18, color: AppColors.primaryBlue),
|
// const Icon(Icons.person, size: 18, color: AppColors.primaryBlue),
|
||||||
const SizedBox(width: 6),
|
// const SizedBox(width: 6),
|
||||||
Expanded(
|
// Expanded(
|
||||||
child: Text(
|
// child: Text(
|
||||||
"Jawaban Kamu: ${answered.selectedAnswer}",
|
// "Jawaban Kamu: ${answered.selectedAnswer}",
|
||||||
style: TextStyle(
|
// style: TextStyle(
|
||||||
color: isCorrect ? Colors.green : Colors.red,
|
// color: isCorrect ? Colors.green : Colors.red,
|
||||||
fontWeight: FontWeight.bold,
|
// fontWeight: FontWeight.bold,
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
const SizedBox(height: 4),
|
// const SizedBox(height: 4),
|
||||||
Row(
|
// Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
// children: [
|
||||||
const Icon(Icons.check, size: 18, color: AppColors.softGrayText),
|
// const Icon(Icons.check, size: 18, color: AppColors.softGrayText),
|
||||||
const SizedBox(width: 6),
|
// const SizedBox(width: 6),
|
||||||
Expanded(
|
// Expanded(
|
||||||
child: Text(
|
// child: Text(
|
||||||
"Jawaban Benar: ${answered.correctAnswer}",
|
// "Jawaban Benar: ${answered.correctAnswer}",
|
||||||
style: const TextStyle(color: AppColors.darkText),
|
// style: const TextStyle(color: AppColors.darkText),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue