feat: done working on subject quiz listing
This commit is contained in:
parent
cd38b79bef
commit
93ab86e833
|
@ -0,0 +1 @@
|
|||
enum ListingType { recomendation, populer, subject }
|
|
@ -74,9 +74,17 @@ class QuizService extends GetxService {
|
|||
}
|
||||
}
|
||||
|
||||
Future<BaseResponseModel<List<QuizListingModel>>?> searchQuiz(String keyword) async {
|
||||
Future<BaseResponseModel<List<QuizListingModel>>?> searchQuiz(String keyword, int page, {int limit = 10, String? subjectId}) async {
|
||||
try {
|
||||
final response = await _dio.get("${APIEndpoint.quizSearch}?keyword=$keyword&page=1&limit=10");
|
||||
final queryParams = {
|
||||
"keyword": keyword,
|
||||
"page": page.toString(),
|
||||
"limit": limit.toString(),
|
||||
if (subjectId != null && subjectId.isNotEmpty) "subject_id": subjectId,
|
||||
};
|
||||
|
||||
final uri = Uri.parse(APIEndpoint.quizSearch).replace(queryParameters: queryParams);
|
||||
final response = await _dio.getUri(uri);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final parsedResponse = BaseResponseModel<List<QuizListingModel>>.fromJson(
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:get/get.dart';
|
||||
import 'package:quiz_app/app/const/enums/listing_type.dart';
|
||||
import 'package:quiz_app/app/routes/app_pages.dart';
|
||||
import 'package:quiz_app/data/controllers/user_controller.dart';
|
||||
import 'package:quiz_app/data/models/base/base_model.dart';
|
||||
|
@ -56,5 +57,8 @@ class HomeController extends GetxController {
|
|||
|
||||
void onRecommendationTap(String quizId) => Get.toNamed(AppRoutes.detailQuizPage, arguments: quizId);
|
||||
|
||||
void goToListingsQuizPage() => Get.toNamed(AppRoutes.listingQuizPage);
|
||||
void goToListingsQuizPage(ListingType page, {String? subjectId, String? subjecName}) => Get.toNamed(
|
||||
AppRoutes.listingQuizPage,
|
||||
arguments: {"page": page, "id": subjectId, "subject_name": subjecName},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,10 +4,12 @@ import 'package:quiz_app/data/models/subject/subject_model.dart';
|
|||
|
||||
class SearchComponent extends StatelessWidget {
|
||||
final Function() onSearchTap;
|
||||
final Function(String, String) onSubjectTap;
|
||||
final List<SubjectModel> subject;
|
||||
|
||||
const SearchComponent({
|
||||
super.key,
|
||||
required this.onSubjectTap,
|
||||
required this.onSearchTap,
|
||||
required this.subject,
|
||||
});
|
||||
|
@ -66,9 +68,12 @@ class SearchComponent extends StatelessWidget {
|
|||
scrollDirection: Axis.horizontal,
|
||||
itemCount: subject.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(right: index != subject.length - 1 ? 8.0 : 0),
|
||||
child: _buildCategoryComponent(subject[index].alias),
|
||||
return GestureDetector(
|
||||
onTap: () => onSubjectTap(subject[index].id, subject[index].alias),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(right: index != subject.length - 1 ? 8.0 : 0),
|
||||
child: _buildCategoryComponent(subject[index].alias),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:quiz_app/app/const/colors/app_colors.dart';
|
||||
import 'package:quiz_app/app/const/enums/listing_type.dart';
|
||||
import 'package:quiz_app/feature/home/controller/home_controller.dart';
|
||||
import 'package:quiz_app/feature/home/view/component/button_option.dart';
|
||||
import 'package:quiz_app/component/widget/recomendation_component.dart';
|
||||
|
@ -44,6 +45,7 @@ class HomeView extends GetView<HomeController> {
|
|||
Obx(() => SearchComponent(
|
||||
onSearchTap: controller.goToSearch,
|
||||
subject: controller.subjects.toList(),
|
||||
onSubjectTap: (p0, p1) => controller.goToListingsQuizPage(ListingType.subject, subjectId: p0, subjecName: p1),
|
||||
)),
|
||||
const SizedBox(height: 20),
|
||||
Obx(
|
||||
|
@ -51,7 +53,7 @@ class HomeView extends GetView<HomeController> {
|
|||
title: "Quiz Rekomendasi",
|
||||
datas: controller.data.toList(),
|
||||
itemOnTap: controller.onRecommendationTap,
|
||||
allOnTap: controller.goToListingsQuizPage,
|
||||
allOnTap: () => controller.goToListingsQuizPage(ListingType.recomendation),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:quiz_app/app/const/enums/listing_type.dart';
|
||||
import 'package:quiz_app/app/routes/app_pages.dart';
|
||||
import 'package:quiz_app/data/models/base/base_model.dart';
|
||||
import 'package:quiz_app/data/models/quiz/quiz_listing_model.dart';
|
||||
|
@ -20,13 +21,37 @@ class ListingQuizController extends GetxController {
|
|||
int currentPage = 1;
|
||||
bool hasMore = true;
|
||||
|
||||
RxString appBarTitle = "Quiz Recommendation".obs;
|
||||
bool isSearchMode = false;
|
||||
String? currentSubjectId;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
_getRecomendationQuiz();
|
||||
loadData();
|
||||
scrollController.addListener(_onScroll);
|
||||
}
|
||||
|
||||
void loadData() {
|
||||
final Map<String, dynamic> data = Get.arguments as Map<String, dynamic>;
|
||||
final pageType = data['page'] as ListingType;
|
||||
|
||||
switch (pageType) {
|
||||
case ListingType.populer:
|
||||
appBarTitle.value = "Quiz Populer";
|
||||
_loadRecommendation(resetPage: true);
|
||||
break;
|
||||
case ListingType.recomendation:
|
||||
appBarTitle.value = "Quiz Recommendation";
|
||||
_loadRecommendation(resetPage: true);
|
||||
break;
|
||||
case ListingType.subject:
|
||||
appBarTitle.value = "Quiz ${data["subject_name"]}";
|
||||
_loadBySubject(subjectId: data["id"], resetPage: true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _onScroll() {
|
||||
if (scrollController.position.pixels >= scrollController.position.maxScrollExtent - 200) {
|
||||
if (!isLoadingMore.value && hasMore) {
|
||||
|
@ -35,28 +60,60 @@ class ListingQuizController extends GetxController {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _getRecomendationQuiz() async {
|
||||
Future<void> _loadRecommendation({bool resetPage = false}) async {
|
||||
isSearchMode = false;
|
||||
currentSubjectId = null;
|
||||
if (resetPage) currentPage = 1;
|
||||
|
||||
isLoading.value = true;
|
||||
currentPage = 1;
|
||||
BaseResponseModel? response = await _quizService.recomendationQuiz(amount: amountQuiz);
|
||||
if (response != null && response.data != null) {
|
||||
final data = response.data as List<QuizListingModel>;
|
||||
quizzes.assignAll(data);
|
||||
hasMore = data.length == amountQuiz;
|
||||
}
|
||||
|
||||
final response = await _quizService.recomendationQuiz(page: currentPage, amount: amountQuiz);
|
||||
_handleResponse(response, resetPage: resetPage);
|
||||
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
Future<void> _loadBySubject({required String subjectId, bool resetPage = false}) async {
|
||||
isSearchMode = true;
|
||||
currentSubjectId = subjectId;
|
||||
if (resetPage) currentPage = 1;
|
||||
|
||||
isLoading.value = true;
|
||||
|
||||
final response = await _quizService.searchQuiz("", currentPage, subjectId: subjectId);
|
||||
_handleResponse(response, resetPage: resetPage);
|
||||
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
Future<void> loadMoreQuiz() async {
|
||||
if (!hasMore) return;
|
||||
|
||||
isLoadingMore.value = true;
|
||||
currentPage++;
|
||||
BaseResponseModel? response = await _quizService.recomendationQuiz(page: currentPage, amount: amountQuiz);
|
||||
|
||||
BaseResponseModel? response;
|
||||
if (isSearchMode && currentSubjectId != null) {
|
||||
response = await _quizService.searchQuiz("", currentPage, subjectId: currentSubjectId!);
|
||||
} else {
|
||||
response = await _quizService.recomendationQuiz(page: currentPage, amount: amountQuiz);
|
||||
}
|
||||
|
||||
_handleResponse(response, resetPage: false);
|
||||
|
||||
isLoadingMore.value = false;
|
||||
}
|
||||
|
||||
void _handleResponse(BaseResponseModel? response, {required bool resetPage}) {
|
||||
if (response != null && response.data != null) {
|
||||
final data = response.data as List<QuizListingModel>;
|
||||
quizzes.addAll(data);
|
||||
if (resetPage) {
|
||||
quizzes.assignAll(data);
|
||||
} else {
|
||||
quizzes.addAll(data);
|
||||
}
|
||||
hasMore = data.length == amountQuiz;
|
||||
}
|
||||
isLoadingMore.value = false;
|
||||
}
|
||||
|
||||
void goToDetailQuiz(String quizId) => Get.toNamed(AppRoutes.detailQuizPage, arguments: quizId);
|
||||
|
|
|
@ -13,8 +13,10 @@ class ListingsQuizView extends GetView<ListingQuizController> {
|
|||
backgroundColor: AppColors.background,
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: const Text(
|
||||
'Daftar Kuis',
|
||||
title: Obx(
|
||||
() => Text(
|
||||
controller.appBarTitle.value,
|
||||
),
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:quiz_app/app/const/enums/listing_type.dart';
|
||||
import 'package:quiz_app/app/routes/app_pages.dart';
|
||||
import 'package:quiz_app/data/models/base/base_model.dart';
|
||||
import 'package:quiz_app/data/models/quiz/quiz_listing_model.dart';
|
||||
|
@ -35,7 +36,7 @@ class SearchQuizController extends GetxController {
|
|||
debounce<String>(
|
||||
searchText,
|
||||
(value) => getSearchData(value),
|
||||
time: Duration(seconds: 2),
|
||||
time: Duration(seconds: 1),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -48,7 +49,7 @@ class SearchQuizController extends GetxController {
|
|||
|
||||
void getSearchData(String keyword) async {
|
||||
searchQData.clear();
|
||||
BaseResponseModel? response = await _quizService.searchQuiz(keyword);
|
||||
BaseResponseModel? response = await _quizService.searchQuiz(keyword, 1);
|
||||
if (response != null) {
|
||||
searchQData.assignAll(response.data);
|
||||
}
|
||||
|
@ -56,7 +57,10 @@ class SearchQuizController extends GetxController {
|
|||
|
||||
void goToDetailPage(String quizId) => Get.toNamed(AppRoutes.detailQuizPage, arguments: quizId);
|
||||
|
||||
void goToListingsQuizPage() => Get.toNamed(AppRoutes.listingQuizPage);
|
||||
void goToListingsQuizPage(ListingType page, {String? subjectId, String? subjecName}) => Get.toNamed(
|
||||
AppRoutes.listingQuizPage,
|
||||
arguments: {"page": page, "id": subjectId, "subject_name": subjecName},
|
||||
);
|
||||
|
||||
void loadSubjectData() async {
|
||||
BaseResponseModel<List<SubjectModel>>? respnse = await _subjectService.getSubject();
|
||||
|
@ -65,8 +69,6 @@ class SearchQuizController extends GetxController {
|
|||
}
|
||||
}
|
||||
|
||||
void goToDetailQuizListing() {}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
searchController.dispose();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:quiz_app/app/const/enums/listing_type.dart';
|
||||
import 'package:quiz_app/component/quiz_container_component.dart';
|
||||
import 'package:quiz_app/component/widget/recomendation_component.dart';
|
||||
import 'package:quiz_app/data/models/subject/subject_model.dart';
|
||||
|
@ -33,7 +34,7 @@ class SearchView extends GetView<SearchQuizController> {
|
|||
title: "Quiz Rekomendasi",
|
||||
datas: controller.recommendationQData.toList(),
|
||||
itemOnTap: controller.goToDetailPage,
|
||||
allOnTap: controller.goToListingsQuizPage,
|
||||
allOnTap: () => controller.goToListingsQuizPage(ListingType.recomendation),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
|
@ -42,7 +43,7 @@ class SearchView extends GetView<SearchQuizController> {
|
|||
title: "Quiz Populer",
|
||||
datas: controller.recommendationQData.toList(),
|
||||
itemOnTap: controller.goToDetailPage,
|
||||
allOnTap: controller.goToListingsQuizPage,
|
||||
allOnTap: () => controller.goToListingsQuizPage(ListingType.populer),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -85,7 +86,7 @@ class SearchView extends GetView<SearchQuizController> {
|
|||
runSpacing: 1,
|
||||
children: data.map((cat) {
|
||||
return InkWell(
|
||||
onTap: () => controller.goToDetailQuizListing,
|
||||
onTap: () => controller.goToListingsQuizPage(ListingType.subject, subjectId: cat.id, subjecName: cat.alias),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||
margin: const EdgeInsets.symmetric(vertical: 2),
|
||||
|
|
Loading…
Reference in New Issue