feat: finish implement subject on the home and search
This commit is contained in:
parent
80e6704bec
commit
cd38b79bef
|
@ -1,11 +1,18 @@
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:quiz_app/data/services/quiz_service.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';
|
import 'package:quiz_app/feature/home/controller/home_controller.dart';
|
||||||
|
|
||||||
class HomeBinding extends Bindings {
|
class HomeBinding extends Bindings {
|
||||||
@override
|
@override
|
||||||
void dependencies() {
|
void dependencies() {
|
||||||
Get.lazyPut<QuizService>(() => QuizService());
|
Get.lazyPut<QuizService>(() => QuizService());
|
||||||
Get.lazyPut<HomeController>(() => HomeController(Get.find<QuizService>()));
|
Get.lazyPut<SubjectService>(() => SubjectService());
|
||||||
|
Get.lazyPut<HomeController>(
|
||||||
|
() => HomeController(
|
||||||
|
Get.find<QuizService>(),
|
||||||
|
Get.find<SubjectService>(),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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/controllers/user_controller.dart';
|
||||||
import 'package:quiz_app/data/models/base/base_model.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/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/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 {
|
class HomeController extends GetxController {
|
||||||
final UserController _userController = Get.find<UserController>();
|
final UserController _userController = Get.find<UserController>();
|
||||||
|
|
||||||
final QuizService _quizService;
|
final QuizService _quizService;
|
||||||
HomeController(this._quizService);
|
final SubjectService _subjectService;
|
||||||
|
|
||||||
|
HomeController(
|
||||||
|
this._quizService,
|
||||||
|
this._subjectService,
|
||||||
|
);
|
||||||
|
|
||||||
Rx<String> get userName => _userController.userName;
|
Rx<String> get userName => _userController.userName;
|
||||||
Rx<String?> get userImage => _userController.userImage;
|
Rx<String?> get userImage => _userController.userImage;
|
||||||
|
|
||||||
RxList<QuizListingModel> data = <QuizListingModel>[].obs;
|
RxList<QuizListingModel> data = <QuizListingModel>[].obs;
|
||||||
|
|
||||||
|
RxList<SubjectModel> subjects = <SubjectModel>[].obs;
|
||||||
|
|
||||||
void goToQuizCreation() => Get.toNamed(AppRoutes.quizCreatePage);
|
void goToQuizCreation() => Get.toNamed(AppRoutes.quizCreatePage);
|
||||||
|
|
||||||
|
void goToSearch() {
|
||||||
|
final navController = Get.find<NavigationController>();
|
||||||
|
navController.changePage(1);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
_getRecomendationQuiz();
|
_getRecomendationQuiz();
|
||||||
|
loadSubjectData();
|
||||||
super.onInit();
|
super.onInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +47,13 @@ class HomeController extends GetxController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loadSubjectData() async {
|
||||||
|
BaseResponseModel<List<SubjectModel>>? respnse = await _subjectService.getSubject();
|
||||||
|
if (respnse != null) {
|
||||||
|
subjects.assignAll(respnse.data!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void onRecommendationTap(String quizId) => Get.toNamed(AppRoutes.detailQuizPage, arguments: quizId);
|
void onRecommendationTap(String quizId) => Get.toNamed(AppRoutes.detailQuizPage, arguments: quizId);
|
||||||
|
|
||||||
void goToListingsQuizPage() => Get.toNamed(AppRoutes.listingQuizPage);
|
void goToListingsQuizPage() => Get.toNamed(AppRoutes.listingQuizPage);
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:quiz_app/app/const/colors/app_colors.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 {
|
class SearchComponent extends StatelessWidget {
|
||||||
const SearchComponent({super.key});
|
final Function() onSearchTap;
|
||||||
|
final List<SubjectModel> subject;
|
||||||
|
|
||||||
|
const SearchComponent({
|
||||||
|
super.key,
|
||||||
|
required this.onSearchTap,
|
||||||
|
required this.subject,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -52,12 +60,18 @@ class SearchComponent extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildCategoryRow() {
|
Widget _buildCategoryRow() {
|
||||||
return Row(
|
return SizedBox(
|
||||||
children: [
|
height: 30, // Set height for horizontal ListView
|
||||||
_buildCategoryComponent("History"),
|
child: ListView.builder(
|
||||||
const SizedBox(width: 8),
|
scrollDirection: Axis.horizontal,
|
||||||
_buildCategoryComponent("Science"),
|
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,7 +94,10 @@ class SearchComponent extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildSearchInput() {
|
Widget _buildSearchInput() {
|
||||||
return Container(
|
return GestureDetector(
|
||||||
|
onTap: () => onSearchTap(),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
@ -88,16 +105,22 @@ class SearchComponent extends StatelessWidget {
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: Colors.black.withValues(alpha: 0.05),
|
color: Colors.black.withValues(alpha: 0.05),
|
||||||
blurRadius: 6,
|
blurRadius: 6,
|
||||||
offset: Offset(0, 2),
|
offset: const Offset(0, 2),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
child: const TextField(
|
child: Row(
|
||||||
decoration: InputDecoration(
|
children: const [
|
||||||
hintText: "Search for quizzes...",
|
Icon(Icons.search, color: Color(0xFF6B778C)),
|
||||||
hintStyle: TextStyle(color: Color(0xFF6B778C)),
|
SizedBox(width: 8),
|
||||||
border: InputBorder.none,
|
Text(
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
"Search for quizzes...",
|
||||||
|
style: TextStyle(
|
||||||
|
color: Color(0xFF6B778C),
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -41,7 +41,10 @@ class HomeView extends GetView<HomeController> {
|
||||||
padding: const EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
SearchComponent(),
|
Obx(() => SearchComponent(
|
||||||
|
onSearchTap: controller.goToSearch,
|
||||||
|
subject: controller.subjects.toList(),
|
||||||
|
)),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Obx(
|
Obx(
|
||||||
() => RecomendationComponent(
|
() => RecomendationComponent(
|
||||||
|
|
|
@ -154,7 +154,6 @@ class QuizPlayController extends GetxController {
|
||||||
|
|
||||||
await Future.delayed(Duration(seconds: 2));
|
await Future.delayed(Duration(seconds: 2));
|
||||||
|
|
||||||
print(quizData);
|
|
||||||
|
|
||||||
Get.offAllNamed(
|
Get.offAllNamed(
|
||||||
AppRoutes.resultQuizPage,
|
AppRoutes.resultQuizPage,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:quiz_app/data/services/quiz_service.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';
|
import 'package:quiz_app/feature/search/controller/search_controller.dart';
|
||||||
|
|
||||||
class SearchBinding extends Bindings {
|
class SearchBinding extends Bindings {
|
||||||
|
@ -8,6 +9,12 @@ class SearchBinding extends Bindings {
|
||||||
if (!Get.isRegistered<QuizService>()) {
|
if (!Get.isRegistered<QuizService>()) {
|
||||||
Get.lazyPut<QuizService>(() => QuizService());
|
Get.lazyPut<QuizService>(() => QuizService());
|
||||||
}
|
}
|
||||||
Get.lazyPut<SearchQuizController>(() => SearchQuizController(Get.find<QuizService>()));
|
|
||||||
|
if (!Get.isRegistered()) Get.lazyPut<SubjectService>(() => SubjectService());
|
||||||
|
|
||||||
|
Get.lazyPut<SearchQuizController>(() => SearchQuizController(
|
||||||
|
Get.find<QuizService>(),
|
||||||
|
Get.find<SubjectService>(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,18 @@ import 'package:get/get.dart';
|
||||||
import 'package:quiz_app/app/routes/app_pages.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/base/base_model.dart';
|
||||||
import 'package:quiz_app/data/models/quiz/quiz_listing_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/quiz_service.dart';
|
||||||
|
import 'package:quiz_app/data/services/subject_service.dart';
|
||||||
|
|
||||||
class SearchQuizController extends GetxController {
|
class SearchQuizController extends GetxController {
|
||||||
final QuizService _quizService;
|
final QuizService _quizService;
|
||||||
|
final SubjectService _subjectService;
|
||||||
|
|
||||||
SearchQuizController(this._quizService);
|
SearchQuizController(
|
||||||
|
this._quizService,
|
||||||
|
this._subjectService,
|
||||||
|
);
|
||||||
|
|
||||||
final searchController = TextEditingController();
|
final searchController = TextEditingController();
|
||||||
final searchText = ''.obs;
|
final searchText = ''.obs;
|
||||||
|
@ -16,9 +22,12 @@ class SearchQuizController extends GetxController {
|
||||||
RxList<QuizListingModel> recommendationQData = <QuizListingModel>[].obs;
|
RxList<QuizListingModel> recommendationQData = <QuizListingModel>[].obs;
|
||||||
RxList<QuizListingModel> searchQData = <QuizListingModel>[].obs;
|
RxList<QuizListingModel> searchQData = <QuizListingModel>[].obs;
|
||||||
|
|
||||||
|
RxList<SubjectModel> subjects = <SubjectModel>[].obs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
getRecomendation();
|
getRecomendation();
|
||||||
|
loadSubjectData();
|
||||||
super.onInit();
|
super.onInit();
|
||||||
searchController.addListener(() {
|
searchController.addListener(() {
|
||||||
searchText.value = searchController.text;
|
searchText.value = searchController.text;
|
||||||
|
@ -49,6 +58,15 @@ class SearchQuizController extends GetxController {
|
||||||
|
|
||||||
void goToListingsQuizPage() => Get.toNamed(AppRoutes.listingQuizPage);
|
void goToListingsQuizPage() => Get.toNamed(AppRoutes.listingQuizPage);
|
||||||
|
|
||||||
|
void loadSubjectData() async {
|
||||||
|
BaseResponseModel<List<SubjectModel>>? respnse = await _subjectService.getSubject();
|
||||||
|
if (respnse != null) {
|
||||||
|
subjects.assignAll(respnse.data!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void goToDetailQuizListing() {}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
searchController.dispose();
|
searchController.dispose();
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:quiz_app/component/quiz_container_component.dart';
|
import 'package:quiz_app/component/quiz_container_component.dart';
|
||||||
import 'package:quiz_app/component/widget/recomendation_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';
|
import 'package:quiz_app/feature/search/controller/search_controller.dart';
|
||||||
|
|
||||||
class SearchView extends GetView<SearchQuizController> {
|
class SearchView extends GetView<SearchQuizController> {
|
||||||
|
@ -21,7 +22,7 @@ class SearchView extends GetView<SearchQuizController> {
|
||||||
_buildSearchBar(),
|
_buildSearchBar(),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
if (isSearching) ...[
|
if (isSearching) ...[
|
||||||
_buildCategoryFilter(),
|
Obx(() => _buildCategoryFilter(controller.subjects.toList())),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
...controller.searchQData.map(
|
...controller.searchQData.map(
|
||||||
(e) => QuizContainerComponent(data: e, onTap: controller.goToDetailPage),
|
(e) => QuizContainerComponent(data: e, onTap: controller.goToDetailPage),
|
||||||
|
@ -78,17 +79,29 @@ class SearchView extends GetView<SearchQuizController> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildCategoryFilter() {
|
Widget _buildCategoryFilter(List<SubjectModel> data) {
|
||||||
final categories = ['Fisika', 'Matematika', 'Agama', 'English', 'Sejarah', 'Biologi'];
|
|
||||||
return Wrap(
|
return Wrap(
|
||||||
spacing: 8,
|
spacing: 6,
|
||||||
runSpacing: 8,
|
runSpacing: 1,
|
||||||
children: categories.map((cat) {
|
children: data.map((cat) {
|
||||||
return Chip(
|
return InkWell(
|
||||||
label: Text(cat),
|
onTap: () => controller.goToDetailQuizListing,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
child: Container(
|
||||||
backgroundColor: Colors.white,
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||||
side: const BorderSide(color: Colors.black12),
|
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(),
|
}).toList(),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue