feat: quiz done

This commit is contained in:
akhdanre 2025-05-05 13:48:14 +07:00
parent 93ab86e833
commit ca9e9cde7d
7 changed files with 138 additions and 2 deletions

View File

@ -7,6 +7,8 @@ class APIEndpoint {
static const String register = "/register"; static const String register = "/register";
static const String quiz = "/quiz"; static const String quiz = "/quiz";
static const String quizAnswer = "/quiz/answer";
static const String userQuiz = "/quiz/user"; static const String userQuiz = "/quiz/user";
static const String quizRecomendation = "/quiz/recomendation"; static const String quizRecomendation = "/quiz/recomendation";
static const String quizSearch = "/quiz/search"; static const String quizSearch = "/quiz/search";

View File

@ -0,0 +1,31 @@
class AnswerModel {
final int questionIndex;
final dynamic answer; // String, bool, atau int
final bool isCorrect;
final double timeSpent;
AnswerModel({
required this.questionIndex,
required this.answer,
required this.isCorrect,
required this.timeSpent,
});
factory AnswerModel.fromJson(Map<String, dynamic> json) {
return AnswerModel(
questionIndex: json['question_index'],
answer: json['answer'],
isCorrect: json['is_correct'],
timeSpent: (json['time_spent'] as num).toDouble(),
);
}
Map<String, dynamic> toJson() {
return {
'question_index': questionIndex,
'answer': answer,
'is_correct': isCorrect,
'time_spent': timeSpent,
};
}
}

View File

@ -0,0 +1,37 @@
import 'package:quiz_app/data/models/answer/answer_model.dart';
class QuizAnswerSubmissionModel {
final String sessionId;
final String quizId;
final String userId;
final DateTime answeredAt;
final List<AnswerModel> answers;
QuizAnswerSubmissionModel({
required this.sessionId,
required this.quizId,
required this.userId,
required this.answeredAt,
required this.answers,
});
factory QuizAnswerSubmissionModel.fromJson(Map<String, dynamic> json) {
return QuizAnswerSubmissionModel(
sessionId: json['session_id'],
quizId: json['quiz_id'],
userId: json['user_id'],
answeredAt: DateTime.parse(json['answered_at']),
answers: (json['answers'] as List).map((e) => AnswerModel.fromJson(e)).toList(),
);
}
Map<String, dynamic> toJson() {
return {
'session_id': sessionId,
'quiz_id': quizId,
'user_id': userId,
'answered_at': answeredAt.toIso8601String(),
'answers': answers.map((e) => e.toJson()).toList(),
};
}
}

View File

@ -1,6 +1,7 @@
import 'package:quiz_app/data/models/quiz/question/base_qustion_model.dart'; import 'package:quiz_app/data/models/quiz/question/base_qustion_model.dart';
class QuizData { class QuizData {
final String id;
final String authorId; final String authorId;
final String subjectId; final String subjectId;
final String subjectName; final String subjectName;
@ -14,6 +15,7 @@ class QuizData {
final List<BaseQuestionModel> questionListings; final List<BaseQuestionModel> questionListings;
QuizData({ QuizData({
required this.id,
required this.authorId, required this.authorId,
required this.subjectId, required this.subjectId,
required this.subjectName, required this.subjectName,
@ -29,6 +31,7 @@ class QuizData {
factory QuizData.fromJson(Map<String, dynamic> json) { factory QuizData.fromJson(Map<String, dynamic> json) {
return QuizData( return QuizData(
id: json["id"],
authorId: json['author_id'], authorId: json['author_id'],
subjectId: json['subject_id'], subjectId: json['subject_id'],
subjectName: json['subject_alias'], subjectName: json['subject_alias'],
@ -45,6 +48,7 @@ class QuizData {
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return { return {
'id': id,
'author_id': authorId, 'author_id': authorId,
'subject_id': subjectId, 'subject_id': subjectId,
'subject_alias': subjectName, 'subject_alias': subjectName,

View File

@ -0,0 +1,28 @@
import 'package:dio/dio.dart';
import 'package:get/get.dart';
import 'package:quiz_app/core/endpoint/api_endpoint.dart';
import 'package:quiz_app/core/utils/logger.dart';
import 'package:quiz_app/data/models/base/base_model.dart';
import 'package:quiz_app/data/providers/dio_client.dart';
class AnswerService extends GetxService {
late final Dio _dio;
@override
void onInit() {
_dio = Get.find<ApiClient>().dio;
super.onInit();
}
Future<BaseResponseModel?> submitQuizAnswers(Map<String, dynamic> payload) async {
try {
await _dio.post(
APIEndpoint.quizAnswer,
data: payload,
);
} on DioException catch (e) {
logC.e('Gagal mengirim jawaban: ${e.response?.data['message'] ?? e.message}');
return null;
}
}
}

View File

@ -1,9 +1,15 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:quiz_app/data/controllers/user_controller.dart';
import 'package:quiz_app/data/services/answer_service.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 QuizPlayBinding extends Bindings { class QuizPlayBinding extends Bindings {
@override @override
void dependencies() { void dependencies() {
Get.lazyPut<QuizPlayController>(() => QuizPlayController()); Get.lazyPut(() => AnswerService());
Get.lazyPut<QuizPlayController>(() => QuizPlayController(
Get.find<AnswerService>(),
Get.find<UserController>(),
));
} }
} }

View File

@ -4,13 +4,21 @@ 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/component/notification/pop_up_confirmation.dart'; import 'package:quiz_app/component/notification/pop_up_confirmation.dart';
import 'package:quiz_app/data/controllers/user_controller.dart';
import 'package:quiz_app/data/models/answer/answer_model.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/base_qustion_model.dart'; import 'package:quiz_app/data/models/quiz/question/base_qustion_model.dart';
import 'package:quiz_app/data/models/quiz/question/fill_in_the_blank_question_model.dart'; import 'package:quiz_app/data/models/quiz/question/fill_in_the_blank_question_model.dart';
import 'package:quiz_app/data/models/quiz/question/option_question_model.dart'; 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/data/models/quiz/question/true_false_question_model.dart';
import 'package:quiz_app/data/services/answer_service.dart';
class QuizPlayController extends GetxController { class QuizPlayController extends GetxController {
final AnswerService _answerService;
final UserController _userController;
QuizPlayController(this._answerService, this._userController);
late final QuizData quizData; late final QuizData quizData;
// State & UI // State & UI
@ -152,8 +160,28 @@ class QuizPlayController extends GetxController {
AppDialog.showMessage(Get.context!, "Yeay semua soal selesai"); AppDialog.showMessage(Get.context!, "Yeay semua soal selesai");
await Future.delayed(Duration(seconds: 2)); // Kirim data ke server
try {
await _answerService.submitQuizAnswers({
"session_id": "", // Sesuaikan logika session ID
"quiz_id": quizData.id,
"user_id": _userController.userData!.id, // Asumsikan ini ada di model `QuizData`
"answered_at": DateTime.now().toIso8601String(),
"answers": answeredQuestions.map((answered) {
return AnswerModel(
questionIndex: answered.questionIndex,
answer: answered.selectedAnswer,
isCorrect: answered.isCorrect,
timeSpent: answered.duration.toDouble(),
);
}).toList(),
});
} catch (e) {
AppDialog.showMessage(Get.context!, "Gagal mengirim jawaban: $e");
return;
}
await Future.delayed(const Duration(seconds: 2));
Get.offAllNamed( Get.offAllNamed(
AppRoutes.resultQuizPage, AppRoutes.resultQuizPage,