From cd38b79bef3f92a5fabb9d2e8b70ece3a63714d3 Mon Sep 17 00:00:00 2001 From: akhdanre Date: Mon, 5 May 2025 09:39:19 +0700 Subject: [PATCH] feat: finish implement subject on the home and search --- lib/feature/home/binding/home_binding.dart | 9 ++- .../home/controller/home_controller.dart | 26 ++++++- .../home/view/component/search_component.dart | 73 ++++++++++++------- lib/feature/home/view/home_page.dart | 5 +- .../controller/quiz_play_controller.dart | 1 - .../search/binding/search_binding.dart | 9 ++- .../search/controller/search_controller.dart | 20 ++++- lib/feature/search/view/search_view.dart | 35 ++++++--- 8 files changed, 136 insertions(+), 42 deletions(-) diff --git a/lib/feature/home/binding/home_binding.dart b/lib/feature/home/binding/home_binding.dart index 53a5d45..e1b47cc 100644 --- a/lib/feature/home/binding/home_binding.dart +++ b/lib/feature/home/binding/home_binding.dart @@ -1,11 +1,18 @@ import 'package:get/get.dart'; import 'package:quiz_app/data/services/quiz_service.dart'; +import 'package:quiz_app/data/services/subject_service.dart'; import 'package:quiz_app/feature/home/controller/home_controller.dart'; class HomeBinding extends Bindings { @override void dependencies() { Get.lazyPut(() => QuizService()); - Get.lazyPut(() => HomeController(Get.find())); + Get.lazyPut(() => SubjectService()); + Get.lazyPut( + () => HomeController( + Get.find(), + Get.find(), + ), + ); } } diff --git a/lib/feature/home/controller/home_controller.dart b/lib/feature/home/controller/home_controller.dart index c0b2d84..78afb4e 100644 --- a/lib/feature/home/controller/home_controller.dart +++ b/lib/feature/home/controller/home_controller.dart @@ -3,23 +3,40 @@ 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'; import 'package:quiz_app/data/models/quiz/quiz_listing_model.dart'; +import 'package:quiz_app/data/models/subject/subject_model.dart'; import 'package:quiz_app/data/services/quiz_service.dart'; +import 'package:quiz_app/data/services/subject_service.dart'; +import 'package:quiz_app/feature/navigation/controllers/navigation_controller.dart'; class HomeController extends GetxController { final UserController _userController = Get.find(); + final QuizService _quizService; - HomeController(this._quizService); + final SubjectService _subjectService; + + HomeController( + this._quizService, + this._subjectService, + ); Rx get userName => _userController.userName; Rx get userImage => _userController.userImage; RxList data = [].obs; + RxList subjects = [].obs; + void goToQuizCreation() => Get.toNamed(AppRoutes.quizCreatePage); + void goToSearch() { + final navController = Get.find(); + navController.changePage(1); + } + @override void onInit() { _getRecomendationQuiz(); + loadSubjectData(); super.onInit(); } @@ -30,6 +47,13 @@ class HomeController extends GetxController { } } + void loadSubjectData() async { + BaseResponseModel>? respnse = await _subjectService.getSubject(); + if (respnse != null) { + subjects.assignAll(respnse.data!); + } + } + void onRecommendationTap(String quizId) => Get.toNamed(AppRoutes.detailQuizPage, arguments: quizId); void goToListingsQuizPage() => Get.toNamed(AppRoutes.listingQuizPage); diff --git a/lib/feature/home/view/component/search_component.dart b/lib/feature/home/view/component/search_component.dart index 512b314..129d733 100644 --- a/lib/feature/home/view/component/search_component.dart +++ b/lib/feature/home/view/component/search_component.dart @@ -1,8 +1,16 @@ import 'package:flutter/material.dart'; import 'package:quiz_app/app/const/colors/app_colors.dart'; +import 'package:quiz_app/data/models/subject/subject_model.dart'; class SearchComponent extends StatelessWidget { - const SearchComponent({super.key}); + final Function() onSearchTap; + final List subject; + + const SearchComponent({ + super.key, + required this.onSearchTap, + required this.subject, + }); @override Widget build(BuildContext context) { @@ -52,12 +60,18 @@ class SearchComponent extends StatelessWidget { } Widget _buildCategoryRow() { - return Row( - children: [ - _buildCategoryComponent("History"), - const SizedBox(width: 8), - _buildCategoryComponent("Science"), - ], + return SizedBox( + height: 30, // Set height for horizontal ListView + child: ListView.builder( + 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), + ); + }, + ), ); } @@ -80,24 +94,33 @@ class SearchComponent extends StatelessWidget { } Widget _buildSearchInput() { - return Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black.withValues(alpha: 0.05), - blurRadius: 6, - offset: Offset(0, 2), - ), - ], - ), - child: const TextField( - decoration: InputDecoration( - hintText: "Search for quizzes...", - hintStyle: TextStyle(color: Color(0xFF6B778C)), - border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12), + return GestureDetector( + onTap: () => onSearchTap(), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha: 0.05), + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: Row( + children: const [ + Icon(Icons.search, color: Color(0xFF6B778C)), + SizedBox(width: 8), + Text( + "Search for quizzes...", + style: TextStyle( + color: Color(0xFF6B778C), + fontSize: 16, + ), + ), + ], ), ), ); diff --git a/lib/feature/home/view/home_page.dart b/lib/feature/home/view/home_page.dart index 7f8b84a..f220ed5 100644 --- a/lib/feature/home/view/home_page.dart +++ b/lib/feature/home/view/home_page.dart @@ -41,7 +41,10 @@ class HomeView extends GetView { padding: const EdgeInsets.all(20), child: Column( children: [ - SearchComponent(), + Obx(() => SearchComponent( + onSearchTap: controller.goToSearch, + subject: controller.subjects.toList(), + )), const SizedBox(height: 20), Obx( () => RecomendationComponent( diff --git a/lib/feature/quiz_play/controller/quiz_play_controller.dart b/lib/feature/quiz_play/controller/quiz_play_controller.dart index b1969ec..a8f02ee 100644 --- a/lib/feature/quiz_play/controller/quiz_play_controller.dart +++ b/lib/feature/quiz_play/controller/quiz_play_controller.dart @@ -154,7 +154,6 @@ class QuizPlayController extends GetxController { await Future.delayed(Duration(seconds: 2)); - print(quizData); Get.offAllNamed( AppRoutes.resultQuizPage, diff --git a/lib/feature/search/binding/search_binding.dart b/lib/feature/search/binding/search_binding.dart index 2d2c0f4..3383d06 100644 --- a/lib/feature/search/binding/search_binding.dart +++ b/lib/feature/search/binding/search_binding.dart @@ -1,5 +1,6 @@ import 'package:get/get.dart'; import 'package:quiz_app/data/services/quiz_service.dart'; +import 'package:quiz_app/data/services/subject_service.dart'; import 'package:quiz_app/feature/search/controller/search_controller.dart'; class SearchBinding extends Bindings { @@ -8,6 +9,12 @@ class SearchBinding extends Bindings { if (!Get.isRegistered()) { Get.lazyPut(() => QuizService()); } - Get.lazyPut(() => SearchQuizController(Get.find())); + + if (!Get.isRegistered()) Get.lazyPut(() => SubjectService()); + + Get.lazyPut(() => SearchQuizController( + Get.find(), + Get.find(), + )); } } diff --git a/lib/feature/search/controller/search_controller.dart b/lib/feature/search/controller/search_controller.dart index f8c932c..f03fef4 100644 --- a/lib/feature/search/controller/search_controller.dart +++ b/lib/feature/search/controller/search_controller.dart @@ -3,12 +3,18 @@ import 'package:get/get.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'; +import 'package:quiz_app/data/models/subject/subject_model.dart'; import 'package:quiz_app/data/services/quiz_service.dart'; +import 'package:quiz_app/data/services/subject_service.dart'; class SearchQuizController extends GetxController { final QuizService _quizService; + final SubjectService _subjectService; - SearchQuizController(this._quizService); + SearchQuizController( + this._quizService, + this._subjectService, + ); final searchController = TextEditingController(); final searchText = ''.obs; @@ -16,9 +22,12 @@ class SearchQuizController extends GetxController { RxList recommendationQData = [].obs; RxList searchQData = [].obs; + RxList subjects = [].obs; + @override void onInit() { getRecomendation(); + loadSubjectData(); super.onInit(); searchController.addListener(() { searchText.value = searchController.text; @@ -49,6 +58,15 @@ class SearchQuizController extends GetxController { void goToListingsQuizPage() => Get.toNamed(AppRoutes.listingQuizPage); + void loadSubjectData() async { + BaseResponseModel>? respnse = await _subjectService.getSubject(); + if (respnse != null) { + subjects.assignAll(respnse.data!); + } + } + + void goToDetailQuizListing() {} + @override void onClose() { searchController.dispose(); diff --git a/lib/feature/search/view/search_view.dart b/lib/feature/search/view/search_view.dart index a188618..51db20c 100644 --- a/lib/feature/search/view/search_view.dart +++ b/lib/feature/search/view/search_view.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:get/get.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'; import 'package:quiz_app/feature/search/controller/search_controller.dart'; class SearchView extends GetView { @@ -21,7 +22,7 @@ class SearchView extends GetView { _buildSearchBar(), const SizedBox(height: 20), if (isSearching) ...[ - _buildCategoryFilter(), + Obx(() => _buildCategoryFilter(controller.subjects.toList())), const SizedBox(height: 20), ...controller.searchQData.map( (e) => QuizContainerComponent(data: e, onTap: controller.goToDetailPage), @@ -78,17 +79,29 @@ class SearchView extends GetView { ); } - Widget _buildCategoryFilter() { - final categories = ['Fisika', 'Matematika', 'Agama', 'English', 'Sejarah', 'Biologi']; + Widget _buildCategoryFilter(List data) { return Wrap( - spacing: 8, - runSpacing: 8, - children: categories.map((cat) { - return Chip( - label: Text(cat), - padding: const EdgeInsets.symmetric(horizontal: 12), - backgroundColor: Colors.white, - side: const BorderSide(color: Colors.black12), + spacing: 6, + runSpacing: 1, + children: data.map((cat) { + return InkWell( + onTap: () => controller.goToDetailQuizListing, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + margin: const EdgeInsets.symmetric(vertical: 2), + decoration: BoxDecoration( + color: Color(0xFFD6E4FF), + borderRadius: BorderRadius.circular(15), + ), + child: Text( + cat.alias, + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: Color(0xFF0052CC), + ), + ), + ), ); }).toList(), );