develop #1
|
@ -14,6 +14,7 @@ import 'package:quiz_app/feature/listing_quiz/binding/listing_quiz_binding.dart'
|
|||
import 'package:quiz_app/feature/listing_quiz/view/listing_quiz_view.dart';
|
||||
import 'package:quiz_app/feature/login/bindings/login_binding.dart';
|
||||
import 'package:quiz_app/feature/login/view/login_page.dart';
|
||||
import 'package:quiz_app/feature/monitor_quiz/binding/monitor_quiz_binding.dart';
|
||||
import 'package:quiz_app/feature/monitor_quiz/view/monitor_quiz_view.dart';
|
||||
import 'package:quiz_app/feature/navigation/bindings/navigation_binding.dart';
|
||||
import 'package:quiz_app/feature/navigation/views/navbar_view.dart';
|
||||
|
@ -127,7 +128,7 @@ class AppPages {
|
|||
GetPage(
|
||||
name: AppRoutes.monitorQuizMPLPage,
|
||||
page: () => MonitorQuizView(),
|
||||
// binding: JoinRoomBinding(),
|
||||
binding: MonitorQuizBinding(),
|
||||
),
|
||||
GetPage(
|
||||
name: AppRoutes.playQuizMPLPage,
|
||||
|
|
|
@ -7,3 +7,5 @@ class UserModel {
|
|||
required this.name,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,12 +8,23 @@ class SocketService {
|
|||
|
||||
final _roomMessageController = StreamController<Map<String, dynamic>>.broadcast();
|
||||
final _chatMessageController = StreamController<Map<String, dynamic>>.broadcast();
|
||||
final _questionUpdateController = StreamController<Map<String, dynamic>>.broadcast();
|
||||
final _quizStartedController = StreamController<void>.broadcast();
|
||||
final _answerSubmittedController = StreamController<Map<String, dynamic>>.broadcast();
|
||||
final _scoreUpdateController = StreamController<Map<String, dynamic>>.broadcast();
|
||||
final _quizDoneController = StreamController<void>.broadcast();
|
||||
final _roomClosedController = StreamController<String>.broadcast();
|
||||
final _errorController = StreamController<String>.broadcast();
|
||||
|
||||
// Public streams
|
||||
Stream<Map<String, dynamic>> get roomMessages => _roomMessageController.stream;
|
||||
Stream<Map<String, dynamic>> get questionUpdate => _questionUpdateController.stream;
|
||||
Stream<Map<String, dynamic>> get chatMessages => _chatMessageController.stream;
|
||||
Stream<void> get quizStarted => _quizStartedController.stream;
|
||||
Stream<Map<String, dynamic>> get answerSubmitted => _answerSubmittedController.stream;
|
||||
Stream<Map<String, dynamic>> get scoreUpdates => _scoreUpdateController.stream;
|
||||
Stream<void> get quizDone => _quizDoneController.stream;
|
||||
Stream<String> get roomClosed => _roomClosedController.stream;
|
||||
Stream<String> get errors => _errorController.stream;
|
||||
|
||||
void initSocketConnection() {
|
||||
|
@ -25,48 +36,67 @@ class SocketService {
|
|||
socket.connect();
|
||||
|
||||
socket.onConnect((_) {
|
||||
logC.i('Connected: ${socket.id}');
|
||||
logC.i('✅ Connected: ${socket.id}');
|
||||
});
|
||||
|
||||
socket.onDisconnect((_) {
|
||||
logC.i('Disconnected');
|
||||
logC.i('❌ Disconnected');
|
||||
});
|
||||
|
||||
socket.on('connection_response', (data) {
|
||||
logC.i('Connection response: $data');
|
||||
logC.i('🟢 Connection response: $data');
|
||||
});
|
||||
|
||||
socket.on('room_message', (data) {
|
||||
logC.i('Room Message: $data');
|
||||
logC.i('📥 Room Message: $data');
|
||||
_roomMessageController.add(Map<String, dynamic>.from(data));
|
||||
});
|
||||
|
||||
socket.on('receive_message', (data) {
|
||||
logC.i('Message from ${data['from']}: ${data['message']}');
|
||||
logC.i('💬 Chat from ${data['from']}: ${data['message']}');
|
||||
_chatMessageController.add(Map<String, dynamic>.from(data));
|
||||
});
|
||||
|
||||
socket.on('quiz_started', (_) {
|
||||
logC.i('Quiz has started!');
|
||||
logC.i('🚀 Quiz Started!');
|
||||
_quizStartedController.add(null);
|
||||
});
|
||||
socket.on('quiz_question', (data) {
|
||||
logC.i('🚀 question getted!');
|
||||
_questionUpdateController.add(Map<String, dynamic>.from(data));
|
||||
});
|
||||
|
||||
socket.on('answer_submitted', (data) {
|
||||
logC.i('✅ Answer Submitted: $data');
|
||||
_answerSubmittedController.add(Map<String, dynamic>.from(data));
|
||||
});
|
||||
|
||||
socket.on('score_update', (data) {
|
||||
logC.i('📊 Score Update: $data');
|
||||
_scoreUpdateController.add(Map<String, dynamic>.from(data));
|
||||
});
|
||||
|
||||
socket.on('quiz_done', (_) {
|
||||
logC.i('🏁 Quiz Finished!');
|
||||
_quizDoneController.add(null);
|
||||
});
|
||||
|
||||
socket.on('room_closed', (data) {
|
||||
logC.i('🔒 Room Closed: $data');
|
||||
_roomClosedController.add(data['room'].toString());
|
||||
});
|
||||
|
||||
socket.on('error', (data) {
|
||||
logC.i('Socket error: $data');
|
||||
logC.e('⚠️ Socket Error: $data');
|
||||
_errorController.add(data.toString());
|
||||
});
|
||||
}
|
||||
|
||||
void joinRoom({required String sessionCode, required String userId}) {
|
||||
var data = {
|
||||
socket.emit('join_room', {
|
||||
'session_code': sessionCode,
|
||||
'user_id': userId,
|
||||
};
|
||||
print(data);
|
||||
socket.emit(
|
||||
'join_room',
|
||||
data,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void leaveRoom({required String sessionId, required String userId, String username = "anonymous"}) {
|
||||
|
@ -89,14 +119,12 @@ class SocketService {
|
|||
});
|
||||
}
|
||||
|
||||
/// Emit when admin starts the quiz
|
||||
void startQuiz({required String sessionCode}) {
|
||||
socket.emit('start_quiz', {
|
||||
'session_code': sessionCode,
|
||||
});
|
||||
}
|
||||
|
||||
/// Emit user's answer during quiz
|
||||
void sendAnswer({
|
||||
required String sessionId,
|
||||
required String userId,
|
||||
|
@ -111,12 +139,8 @@ class SocketService {
|
|||
});
|
||||
}
|
||||
|
||||
/// Emit when user finishes the quiz
|
||||
void doneQuiz({
|
||||
required String sessionId,
|
||||
required String userId,
|
||||
}) {
|
||||
socket.emit('quiz_done', {
|
||||
void endSession({required String sessionId, required String userId}) {
|
||||
socket.emit('end_session', {
|
||||
'session_id': sessionId,
|
||||
'user_id': userId,
|
||||
});
|
||||
|
@ -127,6 +151,10 @@ class SocketService {
|
|||
_roomMessageController.close();
|
||||
_chatMessageController.close();
|
||||
_quizStartedController.close();
|
||||
_answerSubmittedController.close();
|
||||
_scoreUpdateController.close();
|
||||
_quizDoneController.close();
|
||||
_roomClosedController.close();
|
||||
_errorController.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
import 'package:get/get.dart';
|
||||
import 'package:quiz_app/data/services/socket_service.dart';
|
||||
import 'package:quiz_app/feature/monitor_quiz/controller/monitor_quiz_controller.dart';
|
||||
|
||||
class MonitorQuizBinding extends Bindings {
|
||||
@override
|
||||
void dependencies() {
|
||||
Get.lazyPut<MonitorQuizController>(() => MonitorQuizController(Get.find<SocketService>()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
import 'package:get/get.dart';
|
||||
import 'package:quiz_app/core/utils/logger.dart';
|
||||
import 'package:quiz_app/data/models/user/user_model.dart';
|
||||
import 'package:quiz_app/data/services/socket_service.dart';
|
||||
|
||||
class MonitorQuizController extends GetxController {
|
||||
final SocketService _socketService;
|
||||
|
||||
MonitorQuizController(this._socketService);
|
||||
|
||||
String sessionCode = "";
|
||||
String sessionId = "";
|
||||
|
||||
RxString currentQuestion = "".obs;
|
||||
RxList<ParticipantAnswerPoint> participan = <ParticipantAnswerPoint>[].obs;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
loadData();
|
||||
registerListener();
|
||||
super.onInit();
|
||||
}
|
||||
|
||||
void loadData() {
|
||||
final args = Get.arguments;
|
||||
sessionCode = args["session_code"] ?? "";
|
||||
sessionId = args["session_id"] ?? "";
|
||||
|
||||
final List<UserModel> userList = (args["list_participan"] as List<dynamic>).map((e) => e as UserModel).toList();
|
||||
participan.assignAll(
|
||||
userList.map(
|
||||
(user) => ParticipantAnswerPoint(
|
||||
id: user.id,
|
||||
name: user.name,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void registerListener() {
|
||||
_socketService.questionUpdate.listen((data) {
|
||||
logC.i(data);
|
||||
currentQuestion.value = data["question"];
|
||||
});
|
||||
|
||||
_socketService.scoreUpdates.listen((data) {
|
||||
logC.i("📊 Score Update Received: $data");
|
||||
|
||||
final Map<String, dynamic> scoreMap = Map<String, dynamic>.from(data);
|
||||
|
||||
scoreMap.forEach((userId, scoreData) {
|
||||
final index = participan.indexWhere((p) => p.id == userId);
|
||||
|
||||
if (index != -1) {
|
||||
// Participant found, update their scores
|
||||
final participant = participan[index];
|
||||
final correct = scoreData["correct"] ?? 0;
|
||||
final incorrect = scoreData["incorrect"] ?? 0;
|
||||
|
||||
participant.correct.value = correct;
|
||||
participant.wrong.value = incorrect;
|
||||
} else {
|
||||
// Participant not found, optionally add new participant
|
||||
participan.add(
|
||||
ParticipantAnswerPoint(
|
||||
id: userId,
|
||||
name: "Unknown", // Or fetch proper name if available
|
||||
correct: (scoreData["correct"] ?? 0).obs,
|
||||
wrong: (scoreData["incorrect"] ?? 0).obs,
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Notify observers if needed (optional)
|
||||
participan.refresh();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class ParticipantAnswerPoint {
|
||||
final String id;
|
||||
final String name;
|
||||
final RxInt correct;
|
||||
final RxInt wrong;
|
||||
|
||||
ParticipantAnswerPoint({
|
||||
required this.id,
|
||||
required this.name,
|
||||
RxInt? correct,
|
||||
RxInt? wrong,
|
||||
}) : correct = correct ?? 0.obs,
|
||||
wrong = wrong ?? 0.obs;
|
||||
}
|
|
@ -1,10 +1,164 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:lucide_icons/lucide_icons.dart';
|
||||
import 'package:quiz_app/feature/monitor_quiz/controller/monitor_quiz_controller.dart';
|
||||
|
||||
class MonitorQuizView extends GetView<MonitorQuizController> {
|
||||
const MonitorQuizView({super.key});
|
||||
|
||||
class MonitorQuizView extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Text("monitor quiz admin"),
|
||||
appBar: AppBar(title: const Text('Monitor Quiz')),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Obx(
|
||||
() => _buildCurrentQuestion(questionText: controller.currentQuestion.value),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const Text(
|
||||
'Daftar Peserta:',
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Obx(
|
||||
() => ListView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: controller.participan.length,
|
||||
itemBuilder: (context, index) => _buildUserRow(
|
||||
name: controller.participan[index].name,
|
||||
totalBenar: controller.participan[index].correct.value,
|
||||
totalSalah: controller.participan[index].wrong.value,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCurrentQuestion({required String questionText}) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue.shade50,
|
||||
border: Border.all(color: Colors.blue),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"pertanyaan sekarang",
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
const Icon(
|
||||
LucideIcons.helpCircle,
|
||||
color: Colors.blue,
|
||||
size: 24,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
questionText,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildUserRow({
|
||||
required String name,
|
||||
required int totalBenar,
|
||||
required int totalSalah,
|
||||
}) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey.shade300),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.grey.shade300,
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.person,
|
||||
size: 30,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
name,
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
const Icon(
|
||||
LucideIcons.checkCircle,
|
||||
color: Colors.green,
|
||||
size: 18,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'Benar: $totalBenar',
|
||||
style: const TextStyle(color: Colors.green),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
const Icon(
|
||||
LucideIcons.xCircle,
|
||||
color: Colors.red,
|
||||
size: 18,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'Salah: $totalSalah',
|
||||
style: const TextStyle(color: Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:quiz_app/component/global_button.dart';
|
||||
import 'package:quiz_app/data/controllers/user_controller.dart';
|
||||
import 'package:quiz_app/data/services/socket_service.dart';
|
||||
|
||||
|
@ -9,59 +10,71 @@ class PlayQuizMultiplayerController extends GetxController {
|
|||
|
||||
PlayQuizMultiplayerController(this._socketService, this._userController);
|
||||
|
||||
final questions = <MultiplayerQuestionModel>[].obs;
|
||||
// final questions = <MultiplayerQuestionModel>[].obs;
|
||||
final Rxn<MultiplayerQuestionModel> currentQuestion = Rxn<MultiplayerQuestionModel>();
|
||||
final currentQuestionIndex = 0.obs;
|
||||
final selectedAnswer = Rxn<String>();
|
||||
final isDone = false.obs;
|
||||
|
||||
final Rx<ButtonType> buttonType = ButtonType.disabled.obs;
|
||||
|
||||
final fillInAnswerController = TextEditingController();
|
||||
bool? selectedTOFAns;
|
||||
|
||||
late final String sessionCode;
|
||||
late final bool isAdmin;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
_loadData();
|
||||
_registerListener();
|
||||
super.onInit();
|
||||
}
|
||||
|
||||
_loadData() {
|
||||
final args = Get.arguments as Map<String, dynamic>;
|
||||
sessionCode = args["session_code"];
|
||||
isAdmin = args["is_admin"];
|
||||
|
||||
_socketService.socket.on("quiz_question", (data) {
|
||||
final model = MultiplayerQuestionModel.fromJson(Map<String, dynamic>.from(data));
|
||||
currentQuestion.value = model;
|
||||
questions.add(model);
|
||||
fillInAnswerController.clear(); // reset tiap soal baru
|
||||
});
|
||||
|
||||
_socketService.socket.on("quiz_done", (_) {
|
||||
isDone.value = true;
|
||||
});
|
||||
}
|
||||
|
||||
bool isAnswerSelected() {
|
||||
final type = currentQuestion.value?.type;
|
||||
if (type == 'fill_in_the_blank') {
|
||||
return fillInAnswerController.text.trim().isNotEmpty;
|
||||
}
|
||||
return selectedAnswer.value != null;
|
||||
_registerListener() {
|
||||
fillInAnswerController.addListener(() {
|
||||
final text = fillInAnswerController.text;
|
||||
|
||||
if (text.isNotEmpty) {
|
||||
buttonType.value = ButtonType.primary;
|
||||
} else {
|
||||
buttonType.value = ButtonType.disabled;
|
||||
}
|
||||
});
|
||||
|
||||
_socketService.questionUpdate.listen((data) {
|
||||
buttonType.value = ButtonType.disabled;
|
||||
fillInAnswerController.clear();
|
||||
|
||||
final model = MultiplayerQuestionModel.fromJson(Map<String, dynamic>.from(data));
|
||||
currentQuestion.value = model;
|
||||
// questions.add(model);
|
||||
fillInAnswerController.clear(); // reset tiap soal baru
|
||||
});
|
||||
}
|
||||
|
||||
void selectOptionAnswer(String option) {
|
||||
selectedAnswer.value = option;
|
||||
buttonType.value = ButtonType.primary;
|
||||
}
|
||||
|
||||
void selectTrueFalseAnswer(bool value) {
|
||||
selectedAnswer.value = value.toString();
|
||||
buttonType.value = ButtonType.primary;
|
||||
}
|
||||
|
||||
void submitAnswer() {
|
||||
final question = questions[currentQuestionIndex.value];
|
||||
final question = currentQuestion.value!;
|
||||
final type = question.type;
|
||||
|
||||
String? answer;
|
||||
if (type == 'fill_in_the_blank') {
|
||||
if (type == 'fill_the_blank') {
|
||||
answer = fillInAnswerController.text.trim();
|
||||
} else {
|
||||
answer = selectedAnswer.value;
|
||||
|
@ -75,18 +88,6 @@ class PlayQuizMultiplayerController extends GetxController {
|
|||
answer: answer,
|
||||
);
|
||||
}
|
||||
|
||||
if (currentQuestionIndex.value < questions.length - 1) {
|
||||
currentQuestionIndex.value++;
|
||||
selectedAnswer.value = null;
|
||||
fillInAnswerController.clear();
|
||||
} else {
|
||||
isDone.value = true;
|
||||
_socketService.doneQuiz(
|
||||
sessionId: sessionCode,
|
||||
userId: _userController.userData!.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -100,21 +101,24 @@ class MultiplayerQuestionModel {
|
|||
final int questionIndex;
|
||||
final String question;
|
||||
final String type; // 'option', 'true_false', 'fill_in_the_blank'
|
||||
final List<String> options;
|
||||
final int duration;
|
||||
final List<String>? options;
|
||||
|
||||
MultiplayerQuestionModel({
|
||||
required this.questionIndex,
|
||||
required this.question,
|
||||
required this.type,
|
||||
required this.options,
|
||||
required this.duration,
|
||||
this.options,
|
||||
});
|
||||
|
||||
factory MultiplayerQuestionModel.fromJson(Map<String, dynamic> json) {
|
||||
return MultiplayerQuestionModel(
|
||||
questionIndex: json['question_index'],
|
||||
questionIndex: json['index'],
|
||||
question: json['question'],
|
||||
type: json['type'],
|
||||
options: List<String>.from(json['options']),
|
||||
duration: json['duration'],
|
||||
options: json['options'] != null ? List<String>.from(json['options']) : null,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:quiz_app/component/global_button.dart';
|
||||
import 'package:quiz_app/component/global_text_field.dart';
|
||||
import 'package:quiz_app/feature/play_quiz_multiplayer/controller/play_quiz_controller.dart';
|
||||
|
||||
|
@ -12,25 +13,17 @@ class PlayQuizMultiplayerView extends GetView<PlayQuizMultiplayerController> {
|
|||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
centerTitle: true,
|
||||
title: Obx(() {
|
||||
if (controller.questions.isEmpty) {
|
||||
return const Text(
|
||||
"Loading...",
|
||||
style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
|
||||
);
|
||||
}
|
||||
return Text(
|
||||
"Soal ${controller.currentQuestionIndex.value + 1}/${controller.questions.length}",
|
||||
style: const TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
|
||||
);
|
||||
}),
|
||||
title: Text(
|
||||
"Soal ${(controller.currentQuestion.value?.questionIndex ?? 0) + 1}/10",
|
||||
style: const TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
body: Obx(() {
|
||||
if (controller.isDone.value) {
|
||||
return _buildDoneView();
|
||||
}
|
||||
|
||||
if (controller.questions.isEmpty) {
|
||||
if (controller.currentQuestion.value == null) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
|
@ -52,25 +45,16 @@ class PlayQuizMultiplayerView extends GetView<PlayQuizMultiplayerController> {
|
|||
),
|
||||
const SizedBox(height: 20),
|
||||
if (question.type == 'option') _buildOptionQuestion(),
|
||||
if (question.type == 'fill_in_the_blank') _buildFillInBlankQuestion(),
|
||||
if (question.type == 'fill_the_blank') _buildFillInBlankQuestion(),
|
||||
if (question.type == 'true_false') _buildTrueFalseQuestion(),
|
||||
const Spacer(),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: controller.isAnswerSelected() ? controller.submitAnswer : null,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: controller.isAnswerSelected() ? const Color(0xFF2563EB) : Colors.grey,
|
||||
foregroundColor: Colors.white,
|
||||
minimumSize: const Size(double.infinity, 50),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
),
|
||||
child: const Text(
|
||||
"Kirim Jawaban",
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Obx(
|
||||
() => GlobalButton(
|
||||
text: "Kirim jawaban",
|
||||
onPressed: controller.submitAnswer,
|
||||
type: controller.buttonType.value,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -79,7 +63,7 @@ class PlayQuizMultiplayerView extends GetView<PlayQuizMultiplayerController> {
|
|||
Widget _buildOptionQuestion() {
|
||||
final options = controller.currentQuestion.value!.options;
|
||||
return Column(
|
||||
children: List.generate(options.length, (index) {
|
||||
children: List.generate(options!.length, (index) {
|
||||
final option = options[index];
|
||||
final isSelected = controller.selectedAnswer.value == option;
|
||||
|
||||
|
@ -121,7 +105,7 @@ class PlayQuizMultiplayerView extends GetView<PlayQuizMultiplayerController> {
|
|||
}
|
||||
|
||||
Widget _buildTrueFalseButton(String label, bool value) {
|
||||
final isSelected = controller.selectedAnswer.value == value.toString();
|
||||
final isSelected = controller.selectedTOFAns = value;
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
|
|
|
@ -71,12 +71,7 @@ class WaitingRoomController extends GetxController {
|
|||
_socketService.quizStarted.listen((_) {
|
||||
isQuizStarted.value = true;
|
||||
Get.snackbar("Info", "Kuis telah dimulai");
|
||||
if (isAdmin.value) {
|
||||
Get.offAllNamed(AppRoutes.monitorQuizMPLPage, arguments: {
|
||||
"session_code": sessionCode.value,
|
||||
"is_admin": isAdmin.value,
|
||||
});
|
||||
} else {
|
||||
if (!isAdmin.value) {
|
||||
Get.offAllNamed(AppRoutes.playQuizMPLPage, arguments: {
|
||||
"session_code": sessionCode.value,
|
||||
"is_admin": isAdmin.value,
|
||||
|
@ -98,6 +93,11 @@ class WaitingRoomController extends GetxController {
|
|||
|
||||
void startQuiz() {
|
||||
_socketService.startQuiz(sessionCode: sessionCode.value);
|
||||
Get.offAllNamed(AppRoutes.monitorQuizMPLPage, arguments: {
|
||||
"session_code": sessionCode.value,
|
||||
"is_admin": isAdmin.value,
|
||||
"list_participan": joinedUsers.toList(),
|
||||
});
|
||||
}
|
||||
|
||||
void leaveRoom() async {
|
||||
|
|
Loading…
Reference in New Issue