fix: join system
This commit is contained in:
parent
1cce1aba2c
commit
81d900878f
|
@ -1,8 +1,17 @@
|
|||
import 'package:quiz_app/data/models/quiz/quiz_info_model.dart';
|
||||
import 'package:quiz_app/data/models/session/session_info_model.dart';
|
||||
import 'package:quiz_app/data/models/session/session_response_model.dart';
|
||||
|
||||
class WaitingRoomDTO {
|
||||
final bool isAdmin;
|
||||
final SessionResponseModel data;
|
||||
final SessionInfo sessionInfo;
|
||||
final QuizInfo quizInfo;
|
||||
|
||||
WaitingRoomDTO(this.isAdmin, this.data);
|
||||
WaitingRoomDTO({
|
||||
required this.isAdmin,
|
||||
required this.data,
|
||||
required this.sessionInfo,
|
||||
required this.quizInfo,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
class QuizInfo {
|
||||
final String title;
|
||||
final String description;
|
||||
final int totalQuiz;
|
||||
final int limitDuration;
|
||||
|
||||
QuizInfo({
|
||||
required this.title,
|
||||
required this.description,
|
||||
required this.totalQuiz,
|
||||
required this.limitDuration,
|
||||
});
|
||||
|
||||
factory QuizInfo.fromJson(Map<String, dynamic> json) {
|
||||
return QuizInfo(
|
||||
title: json['title'],
|
||||
description: json['description'],
|
||||
totalQuiz: json['total_quiz'],
|
||||
limitDuration: json['limit_duration'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'title': title,
|
||||
'description': description,
|
||||
'question_count': totalQuiz,
|
||||
'limit_duration': limitDuration,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
import 'package:quiz_app/data/models/user/user_model.dart';
|
||||
|
||||
class SessionInfo {
|
||||
final String id;
|
||||
final String sessionCode;
|
||||
final String quizId;
|
||||
final String hostId;
|
||||
final DateTime createdAt;
|
||||
final DateTime? startedAt;
|
||||
final DateTime? endedAt;
|
||||
final bool isActive;
|
||||
final int participantLimit;
|
||||
final List<UserModel> participants;
|
||||
final int currentQuestionIndex;
|
||||
|
||||
SessionInfo({
|
||||
required this.id,
|
||||
required this.sessionCode,
|
||||
required this.quizId,
|
||||
required this.hostId,
|
||||
required this.createdAt,
|
||||
this.startedAt,
|
||||
this.endedAt,
|
||||
required this.isActive,
|
||||
required this.participantLimit,
|
||||
required this.participants,
|
||||
required this.currentQuestionIndex,
|
||||
});
|
||||
|
||||
factory SessionInfo.fromJson(Map<String, dynamic> json) {
|
||||
return SessionInfo(
|
||||
id: json['id'],
|
||||
sessionCode: json['session_code'],
|
||||
quizId: json['quiz_id'],
|
||||
hostId: json['host_id'],
|
||||
createdAt: DateTime.parse(json['created_at']),
|
||||
startedAt: json['started_at'] != null ? DateTime.parse(json['started_at']) : null,
|
||||
endedAt: json['ended_at'] != null ? DateTime.parse(json['ended_at']) : null,
|
||||
isActive: json['is_active'],
|
||||
participantLimit: json['participan_limit'],
|
||||
participants: (json['participants'] as List<dynamic>?)?.map((e) => UserModel.fromJson(e as Map<String, dynamic>)).toList() ?? [],
|
||||
currentQuestionIndex: json['current_question_index'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'session_code': sessionCode,
|
||||
'quiz_id': quizId,
|
||||
'host_id': hostId,
|
||||
'created_at': createdAt.toIso8601String(),
|
||||
'started_at': startedAt?.toIso8601String(),
|
||||
'ended_at': endedAt?.toIso8601String(),
|
||||
'is_active': isActive,
|
||||
'participant_limit': participantLimit,
|
||||
'participants': participants,
|
||||
'current_question_index': currentQuestionIndex,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,11 +1,22 @@
|
|||
class UserModel {
|
||||
final String id;
|
||||
final String name;
|
||||
final String username;
|
||||
final String userPic;
|
||||
final DateTime joinedAt;
|
||||
|
||||
UserModel({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.username,
|
||||
required this.userPic,
|
||||
required this.joinedAt,
|
||||
});
|
||||
|
||||
factory UserModel.fromJson(Map<String, dynamic> json) {
|
||||
return UserModel(
|
||||
id: json['id'],
|
||||
username: json['username'],
|
||||
userPic: json['user_pic'] ?? "",
|
||||
joinedAt: DateTime.parse(json['joined_at']),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:quiz_app/app/routes/app_pages.dart';
|
||||
import 'package:quiz_app/core/utils/logger.dart';
|
||||
import 'package:quiz_app/data/controllers/user_controller.dart';
|
||||
import 'package:quiz_app/data/dto/waiting_room_dto.dart';
|
||||
import 'package:quiz_app/data/models/quiz/quiz_info_model.dart';
|
||||
import 'package:quiz_app/data/models/session/session_info_model.dart';
|
||||
import 'package:quiz_app/data/models/session/session_response_model.dart';
|
||||
import 'package:quiz_app/data/services/socket_service.dart';
|
||||
|
||||
|
@ -27,9 +30,32 @@ class JoinRoomController extends GetxController {
|
|||
return;
|
||||
}
|
||||
_socketService.initSocketConnection();
|
||||
|
||||
|
||||
_socketService.joinRoom(sessionCode: code, userId: _userController.userData!.id);
|
||||
Get.toNamed(AppRoutes.waitRoomPage, arguments: WaitingRoomDTO(false, SessionResponseModel(sessionId: "", sessionCode: code)));
|
||||
_socketService.errors.listen((error) {
|
||||
logC.i(error);
|
||||
});
|
||||
|
||||
_socketService.roomMessages.listen((data) {
|
||||
if (data["type"] == "join") {
|
||||
final Map<String, dynamic> dataPayload = data["data"];
|
||||
final Map<String, dynamic> sessionInfoJson = dataPayload["session_info"];
|
||||
final Map<String, dynamic> quizInfoJson = dataPayload["quiz_info"];
|
||||
|
||||
Get.toNamed(
|
||||
AppRoutes.waitRoomPage,
|
||||
arguments: WaitingRoomDTO(
|
||||
isAdmin: false,
|
||||
data: SessionResponseModel(
|
||||
sessionId: sessionInfoJson["id"],
|
||||
sessionCode: sessionInfoJson["session_code"],
|
||||
),
|
||||
sessionInfo: SessionInfo.fromJson(sessionInfoJson),
|
||||
quizInfo: QuizInfo.fromJson(quizInfoJson),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -31,7 +31,7 @@ class MonitorQuizController extends GetxController {
|
|||
userList.map(
|
||||
(user) => ParticipantAnswerPoint(
|
||||
id: user.id,
|
||||
name: user.name,
|
||||
name: user.username,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -4,8 +4,11 @@ import 'package:quiz_app/app/routes/app_pages.dart';
|
|||
import 'package:quiz_app/data/controllers/user_controller.dart';
|
||||
import 'package:quiz_app/data/dto/waiting_room_dto.dart';
|
||||
import 'package:quiz_app/data/models/base/base_model.dart';
|
||||
import 'package:quiz_app/data/models/quiz/quiz_info_model.dart';
|
||||
import 'package:quiz_app/data/models/quiz/quiz_listing_model.dart';
|
||||
import 'package:quiz_app/data/models/session/session_info_model.dart';
|
||||
import 'package:quiz_app/data/models/session/session_request_model.dart';
|
||||
import 'package:quiz_app/data/models/session/session_response_model.dart';
|
||||
import 'package:quiz_app/data/services/quiz_service.dart';
|
||||
import 'package:quiz_app/data/services/session_service.dart';
|
||||
import 'package:quiz_app/data/services/socket_service.dart';
|
||||
|
@ -66,7 +69,26 @@ class RoomMakerController extends GetxController {
|
|||
_socketService.initSocketConnection();
|
||||
_socketService.joinRoom(sessionCode: response.data!.sessionCode, userId: _userController.userData!.id);
|
||||
|
||||
Get.toNamed(AppRoutes.waitRoomPage, arguments: WaitingRoomDTO(true, response.data!));
|
||||
_socketService.roomMessages.listen((data) {
|
||||
if (data["type"] == "join") {
|
||||
final Map<String, dynamic> dataPayload = data["data"];
|
||||
final Map<String, dynamic> sessionInfoJson = dataPayload["session_info"];
|
||||
final Map<String, dynamic> quizInfoJson = dataPayload["quiz_info"];
|
||||
|
||||
Get.toNamed(
|
||||
AppRoutes.waitRoomPage,
|
||||
arguments: WaitingRoomDTO(
|
||||
isAdmin: true,
|
||||
data: SessionResponseModel(
|
||||
sessionId: sessionInfoJson["id"],
|
||||
sessionCode: sessionInfoJson["session_code"],
|
||||
),
|
||||
sessionInfo: SessionInfo.fromJson(sessionInfoJson),
|
||||
quizInfo: QuizInfo.fromJson(quizInfoJson),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import 'package:quiz_app/app/routes/app_pages.dart';
|
|||
import 'package:quiz_app/core/utils/custom_notification.dart';
|
||||
import 'package:quiz_app/data/controllers/user_controller.dart';
|
||||
import 'package:quiz_app/data/dto/waiting_room_dto.dart';
|
||||
import 'package:quiz_app/data/models/quiz/quiz_listing_model.dart';
|
||||
import 'package:quiz_app/data/models/quiz/quiz_info_model.dart';
|
||||
import 'package:quiz_app/data/models/session/session_response_model.dart';
|
||||
import 'package:quiz_app/data/models/user/user_model.dart';
|
||||
import 'package:quiz_app/data/services/socket_service.dart';
|
||||
|
@ -16,7 +16,7 @@ class WaitingRoomController extends GetxController {
|
|||
WaitingRoomController(this._socketService, this._userController);
|
||||
|
||||
final sessionCode = ''.obs;
|
||||
final quizMeta = Rx<QuizListingModel?>(null);
|
||||
final quizMeta = Rx<QuizInfo?>(null);
|
||||
final joinedUsers = <UserModel>[].obs;
|
||||
final isAdmin = true.obs;
|
||||
|
||||
|
@ -39,32 +39,44 @@ class WaitingRoomController extends GetxController {
|
|||
|
||||
sessionCode.value = roomData!.sessionCode;
|
||||
|
||||
quizMeta.value = QuizListingModel(
|
||||
quizId: "q123",
|
||||
authorId: "a123",
|
||||
authorName: "Admin",
|
||||
title: "Uji Coba Kuis",
|
||||
description: "Kuis untuk testing",
|
||||
date: DateTime.now().toIso8601String(),
|
||||
totalQuiz: 5,
|
||||
duration: 900,
|
||||
);
|
||||
quizMeta.value = data.quizInfo;
|
||||
|
||||
joinedUsers.assignAll(data.sessionInfo.participants);
|
||||
}
|
||||
|
||||
void _registerSocketListeners() {
|
||||
_socketService.roomMessages.listen((data) {
|
||||
if (data["type"] == "join") {
|
||||
final user = data["data"];
|
||||
if (user != null) {
|
||||
joinedUsers.assign(UserModel(id: user['user_id'], name: user['username']));
|
||||
CustomNotification.success(title: "Participan Joined", message: "${user['username']} has joined to room");
|
||||
if (data["type"] == "participan_join" || data["type"] == "participan_leave") {
|
||||
joinedUsers.clear();
|
||||
|
||||
final dataPayload = data["data"];
|
||||
final participants = dataPayload["participants"] as List<dynamic>?;
|
||||
|
||||
if (participants != null && participants.isNotEmpty) {
|
||||
final users = participants.map((e) => UserModel.fromJson(e as Map<String, dynamic>)).toList();
|
||||
|
||||
joinedUsers.addAll(users);
|
||||
|
||||
if (data["type"] == "participan_join") {
|
||||
CustomNotification.success(
|
||||
title: "Participant Joined",
|
||||
message: data["message"] ?? "A participant has joined the room.",
|
||||
);
|
||||
} else if (data["type"] == "participan_leave") {
|
||||
CustomNotification.warning(
|
||||
title: "Participant Left",
|
||||
message: data["message"] ?? "A participant has left the room.",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data["type"] == "leave") {
|
||||
final userId = data["data"];
|
||||
CustomNotification.warning(title: "Participan Leave", message: "participan leave the room");
|
||||
joinedUsers.removeWhere((e) => e.id == userId);
|
||||
CustomNotification.warning(
|
||||
title: "Participant Leave",
|
||||
message: "Participant left the room",
|
||||
);
|
||||
// joinedUsers.removeWhere((e) => e.id == userId);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -101,7 +113,11 @@ class WaitingRoomController extends GetxController {
|
|||
}
|
||||
|
||||
void leaveRoom() async {
|
||||
_socketService.leaveRoom(sessionId: roomData!.sessionId, userId: _userController.userData!.id);
|
||||
_socketService.leaveRoom(
|
||||
sessionId: roomData!.sessionId,
|
||||
userId: _userController.userData!.id,
|
||||
username: _userController.userName.value,
|
||||
);
|
||||
Get.offAllNamed(AppRoutes.mainPage);
|
||||
|
||||
await Future.delayed(Duration(seconds: 2));
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:quiz_app/component/global_button.dart';
|
||||
import 'package:quiz_app/data/models/quiz/quiz_info_model.dart';
|
||||
import 'package:quiz_app/data/models/user/user_model.dart';
|
||||
import 'package:quiz_app/feature/waiting_room/controller/waiting_room_controller.dart';
|
||||
import 'package:quiz_app/app/const/colors/app_colors.dart';
|
||||
|
@ -21,7 +22,7 @@ class WaitingRoomView extends GetView<WaitingRoomController> {
|
|||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildQuizMeta(quiz),
|
||||
_buildQuizMeta(quiz!),
|
||||
const SizedBox(height: 20),
|
||||
_buildSessionCode(context, session),
|
||||
const SizedBox(height: 20),
|
||||
|
@ -70,8 +71,8 @@ class WaitingRoomView extends GetView<WaitingRoomController> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget _buildQuizMeta(dynamic quiz) {
|
||||
if (quiz == null) return const SizedBox.shrink();
|
||||
Widget _buildQuizMeta(QuizInfo quiz) {
|
||||
// if (quiz == null) return const SizedBox.shrink();
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
width: double.infinity,
|
||||
|
@ -88,7 +89,7 @@ class WaitingRoomView extends GetView<WaitingRoomController> {
|
|||
Text("Judul: ${quiz.title}"),
|
||||
Text("Deskripsi: ${quiz.description}"),
|
||||
Text("Jumlah Soal: ${quiz.totalQuiz}"),
|
||||
Text("Durasi: ${quiz.duration ~/ 60} menit"),
|
||||
Text("Durasi: ${quiz.limitDuration ~/ 60} menit"),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -109,9 +110,9 @@ class WaitingRoomView extends GetView<WaitingRoomController> {
|
|||
),
|
||||
child: Row(
|
||||
children: [
|
||||
CircleAvatar(child: Text(user.name[0])),
|
||||
CircleAvatar(child: Text(user.username[0])),
|
||||
const SizedBox(width: 12),
|
||||
Text(user.name, style: const TextStyle(fontSize: 16)),
|
||||
Text(user.username, style: const TextStyle(fontSize: 16)),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue