develop #1
|
@ -138,6 +138,18 @@
|
|||
},
|
||||
|
||||
"get_ready": "Get Ready",
|
||||
"quiz_starting_soon" : "Quiz Starting Soon"
|
||||
"quiz_starting_soon": "Quiz Starting Soon",
|
||||
|
||||
"waiting_room": {
|
||||
"title": "Waiting Room",
|
||||
"participants_joined": "Participants Joined:",
|
||||
"leave_room": "Leave Room",
|
||||
"session_code": "Session Code:",
|
||||
"copy_code": "Copy Code",
|
||||
"quiz_info": "Quiz Information:",
|
||||
"quiz_title": "Title",
|
||||
"quiz_description": "Description",
|
||||
"quiz_total_question": "Total Questions",
|
||||
"quiz_duration": "Duration"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,5 +122,17 @@
|
|||
},
|
||||
|
||||
"get_ready": "Bersiaplah",
|
||||
"quiz_starting_soon": "Kuis akan segera dimulai"
|
||||
"quiz_starting_soon": "Kuis akan segera dimulai",
|
||||
"waiting_room": {
|
||||
"title": "Ruang Tunggu",
|
||||
"participants_joined": "Peserta Bergabung:",
|
||||
"leave_room": "Keluar dari Ruangan",
|
||||
"session_code": "Kode Sesi:",
|
||||
"copy_code": "Salin Kode",
|
||||
"quiz_info": "Informasi Kuis:",
|
||||
"quiz_title": "Judul",
|
||||
"quiz_description": "Deskripsi",
|
||||
"quiz_total_question": "Total Pertanyaan",
|
||||
"quiz_duration": "Durasi"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,5 +124,17 @@
|
|||
},
|
||||
|
||||
"get_ready": "Bersedia",
|
||||
"quiz_starting_soon": "Kuiz akan bermula sebentar lagi"
|
||||
"quiz_starting_soon": "Kuiz akan bermula sebentar lagi",
|
||||
"waiting_room": {
|
||||
"title": "Bilik Menunggu",
|
||||
"participants_joined": "Peserta Telah Sertai:",
|
||||
"leave_room": "Tinggalkan Bilik",
|
||||
"session_code": "Kod Sesi:",
|
||||
"copy_code": "Salin Kod",
|
||||
"quiz_info": "Maklumat Kuiz:",
|
||||
"quiz_title": "Tajuk",
|
||||
"quiz_description": "Penerangan",
|
||||
"quiz_total_question": "Jumlah Soalan",
|
||||
"quiz_duration": "Tempoh"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
extension StringCasingExtension on String {
|
||||
String toTitleCase() {
|
||||
return split(' ').map((word) => word.isNotEmpty ? '${word[0].toUpperCase()}${word.substring(1).toLowerCase()}' : '').join(' ');
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ import 'package:quiz_app/data/models/user/user_model.dart';
|
|||
class SessionInfo {
|
||||
final String id;
|
||||
final String sessionCode;
|
||||
final String roomName;
|
||||
final String quizId;
|
||||
final String hostId;
|
||||
final DateTime createdAt;
|
||||
|
@ -16,6 +17,7 @@ class SessionInfo {
|
|||
SessionInfo({
|
||||
required this.id,
|
||||
required this.sessionCode,
|
||||
required this.roomName,
|
||||
required this.quizId,
|
||||
required this.hostId,
|
||||
required this.createdAt,
|
||||
|
@ -31,6 +33,7 @@ class SessionInfo {
|
|||
return SessionInfo(
|
||||
id: json['id'],
|
||||
sessionCode: json['session_code'],
|
||||
roomName: json["room_name"],
|
||||
quizId: json['quiz_id'],
|
||||
hostId: json['host_id'],
|
||||
createdAt: DateTime.parse(json['created_at']),
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
class SessionRequestModel {
|
||||
final String quizId;
|
||||
final String hostId;
|
||||
final String roomName;
|
||||
final int limitParticipan;
|
||||
|
||||
SessionRequestModel({
|
||||
required this.quizId,
|
||||
required this.hostId,
|
||||
required this.roomName,
|
||||
required this.limitParticipan,
|
||||
});
|
||||
|
||||
|
@ -13,6 +15,7 @@ class SessionRequestModel {
|
|||
return SessionRequestModel(
|
||||
quizId: json['quiz_id'],
|
||||
hostId: json['host_id'],
|
||||
roomName: json['room_name'],
|
||||
limitParticipan: json['limit_participan'],
|
||||
);
|
||||
}
|
||||
|
@ -21,6 +24,7 @@ class SessionRequestModel {
|
|||
return {
|
||||
'quiz_id': quizId,
|
||||
'host_id': hostId,
|
||||
'room_name': roomName,
|
||||
'limit_participan': limitParticipan,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -17,11 +17,7 @@ class SessionService extends GetxService {
|
|||
|
||||
Future<BaseResponseModel<SessionResponseModel>?> createSession(SessionRequestModel data) async {
|
||||
try {
|
||||
final response = await _dio.post(APIEndpoint.session, data: {
|
||||
'quiz_id': data.quizId,
|
||||
'host_id': data.hostId,
|
||||
'limit_participan': data.limitParticipan,
|
||||
});
|
||||
final response = await _dio.post(APIEndpoint.session, data: data.toJson());
|
||||
if (response.statusCode != 201) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -33,32 +33,32 @@ class JoinRoomView extends GetView<JoinRoomController> {
|
|||
children: [
|
||||
const SizedBox(height: 20),
|
||||
|
||||
TweenAnimationBuilder<double>(
|
||||
duration: const Duration(seconds: 1),
|
||||
tween: Tween(begin: 0.0, end: 1.0),
|
||||
builder: (context, value, child) {
|
||||
return Transform.scale(
|
||||
scale: value,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(22),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.primaryBlue.withValues(alpha: 0.05),
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: AppColors.primaryBlue.withValues(alpha: 0.15),
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
child: Icon(
|
||||
LucideIcons.trophy,
|
||||
size: 70,
|
||||
color: AppColors.primaryBlue,
|
||||
),
|
||||
),
|
||||
),
|
||||
// TweenAnimationBuilder<double>(
|
||||
// duration: const Duration(seconds: 1),
|
||||
// tween: Tween(begin: 0.0, end: 1.0),
|
||||
// builder: (context, value, child) {
|
||||
// return Transform.scale(
|
||||
// scale: value,
|
||||
// child: child,
|
||||
// );
|
||||
// },
|
||||
// child: Container(
|
||||
// padding: EdgeInsets.all(22),
|
||||
// decoration: BoxDecoration(
|
||||
// color: AppColors.primaryBlue.withValues(alpha: 0.05),
|
||||
// shape: BoxShape.circle,
|
||||
// border: Border.all(
|
||||
// color: AppColors.primaryBlue.withValues(alpha: 0.15),
|
||||
// width: 2,
|
||||
// ),
|
||||
// ),
|
||||
// child: Icon(
|
||||
// LucideIcons.trophy,
|
||||
// size: 70,
|
||||
// color: AppColors.primaryBlue,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
|
||||
const SizedBox(height: 30),
|
||||
|
||||
|
|
|
@ -103,6 +103,7 @@ class RoomMakerController extends GetxController {
|
|||
SessionRequestModel(
|
||||
quizId: quiz.quizId,
|
||||
hostId: _userController.userData!.id,
|
||||
roomName: nameTC.text,
|
||||
limitParticipan: int.parse(maxPlayerTC.text),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -16,6 +16,7 @@ class WaitingRoomController extends GetxController {
|
|||
WaitingRoomController(this._socketService, this._userController);
|
||||
|
||||
final sessionCode = ''.obs;
|
||||
final roomName = "".obs;
|
||||
String sessionId = '';
|
||||
final quizMeta = Rx<QuizInfo?>(null);
|
||||
final joinedUsers = <UserModel>[].obs;
|
||||
|
@ -42,6 +43,7 @@ class WaitingRoomController extends GetxController {
|
|||
sessionId = roomData!.sessionId;
|
||||
|
||||
quizMeta.value = data.quizInfo;
|
||||
roomName.value = data.sessionInfo.roomName;
|
||||
|
||||
joinedUsers.assignAll(data.sessionInfo.participants);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:quiz_app/app/const/text/string_extension.dart';
|
||||
import 'package:quiz_app/app/const/text/text_style.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';
|
||||
|
@ -11,7 +14,9 @@ class WaitingRoomView extends GetView<WaitingRoomController> {
|
|||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.background,
|
||||
appBar: AppBar(title: const Text("Waiting Room")),
|
||||
appBar: AppBar(
|
||||
title: Text(tr("waiting_room.title"), style: AppTextStyles.title),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Obx(() {
|
||||
|
@ -22,25 +27,39 @@ class WaitingRoomView extends GetView<WaitingRoomController> {
|
|||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 20),
|
||||
Center(
|
||||
child: Obx(() => Text(
|
||||
controller.roomName.value.toTitleCase(),
|
||||
style: AppTextStyles.title,
|
||||
)),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
_buildQuizMeta(quiz!),
|
||||
const SizedBox(height: 20),
|
||||
_buildSessionCode(context, session),
|
||||
const SizedBox(height: 20),
|
||||
const Text("Peserta yang Bergabung:", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
||||
Text(
|
||||
tr("waiting_room.participants_joined"),
|
||||
style: AppTextStyles.subtitle.copyWith(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColors.darkText,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Expanded(child: Obx(() => _buildUserList(users.toList()))),
|
||||
const SizedBox(height: 16),
|
||||
if (controller.isAdmin.value)
|
||||
GlobalButton(
|
||||
text: "Mulai Kuis",
|
||||
onPressed: controller.startQuiz,
|
||||
)
|
||||
else
|
||||
GlobalButton(
|
||||
text: "Tinggalkan Ruangan",
|
||||
onPressed: controller.leaveRoom,
|
||||
baseColor: const Color.fromARGB(255, 204, 14, 0),
|
||||
)
|
||||
controller.isAdmin.value
|
||||
? GlobalButton(
|
||||
text: tr("start_quiz"),
|
||||
onPressed: controller.startQuiz,
|
||||
)
|
||||
: GlobalButton(
|
||||
text: tr("waiting_room.leave_room"),
|
||||
onPressed: controller.leaveRoom,
|
||||
baseColor: const Color.fromARGB(255, 204, 14, 0),
|
||||
)
|
||||
],
|
||||
);
|
||||
}),
|
||||
|
@ -52,18 +71,19 @@ class WaitingRoomView extends GetView<WaitingRoomController> {
|
|||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.primaryBlue.withValues(alpha: 0.05),
|
||||
color: AppColors.accentBlue.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColors.primaryBlue),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Text("Session Code: ", style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
SelectableText(code, style: const TextStyle(fontSize: 16)),
|
||||
Text(tr("waiting_room.session_code"), style: AppTextStyles.statValue),
|
||||
const SizedBox(width: 4),
|
||||
SelectableText(code, style: AppTextStyles.body.copyWith(fontSize: 16)),
|
||||
const Spacer(),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.copy),
|
||||
tooltip: 'Salin Kode',
|
||||
tooltip: tr("waiting_room.copy_code"),
|
||||
onPressed: () => controller.copySessionCode(context),
|
||||
),
|
||||
],
|
||||
|
@ -72,7 +92,6 @@ class WaitingRoomView extends GetView<WaitingRoomController> {
|
|||
}
|
||||
|
||||
Widget _buildQuizMeta(QuizInfo quiz) {
|
||||
// if (quiz == null) return const SizedBox.shrink();
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
width: double.infinity,
|
||||
|
@ -84,12 +103,12 @@ class WaitingRoomView extends GetView<WaitingRoomController> {
|
|||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text("Informasi Kuis:", style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
Text(tr("waiting_room.quiz_info"), style: AppTextStyles.subtitle.copyWith(fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 8),
|
||||
Text("Judul: ${quiz.title}"),
|
||||
Text("Deskripsi: ${quiz.description}"),
|
||||
Text("Jumlah Soal: ${quiz.totalQuiz}"),
|
||||
Text("Durasi: ${quiz.limitDuration ~/ 60} menit"),
|
||||
Text("${tr("waiting_room.quiz_title")}: ${quiz.title}", style: AppTextStyles.body),
|
||||
Text("${tr("waiting_room.quiz_description")}: ${quiz.description}", style: AppTextStyles.body),
|
||||
Text("${tr("waiting_room.quiz_total_question")}: ${quiz.totalQuiz}", style: AppTextStyles.body),
|
||||
Text("${tr("waiting_room.quiz_duration")}: ${quiz.limitDuration ~/ 60} min", style: AppTextStyles.body),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -110,9 +129,9 @@ class WaitingRoomView extends GetView<WaitingRoomController> {
|
|||
),
|
||||
child: Row(
|
||||
children: [
|
||||
CircleAvatar(child: Text(user.username[0])),
|
||||
CircleAvatar(child: Text(user.username[0].toUpperCase())),
|
||||
const SizedBox(width: 12),
|
||||
Text(user.username, style: const TextStyle(fontSize: 16)),
|
||||
Text(user.username, style: AppTextStyles.body.copyWith(fontSize: 16)),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue