diff --git a/lib/features/level/data/datasource/level_datasource.dart b/lib/features/level/data/datasource/level_datasource.dart index ec1f645..77abd2b 100644 --- a/lib/features/level/data/datasource/level_datasource.dart +++ b/lib/features/level/data/datasource/level_datasource.dart @@ -1,28 +1,49 @@ import 'package:hadi_hoda_flutter/core/constants/my_api.dart'; +import 'package:hadi_hoda_flutter/core/constants/my_constants.dart'; +import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; import 'package:hadi_hoda_flutter/core/network/http_request.dart'; import 'package:hadi_hoda_flutter/core/params/level_params.dart'; import 'package:hadi_hoda_flutter/core/response/base_response.dart'; import 'package:hadi_hoda_flutter/features/level/data/model/level_model.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; +import 'package:hive/hive.dart'; abstract class ILevelDatasource { - Future getData({required LevelParams params}); + Future> getLevels({required LevelParams params}); } -class LevelDatasourceImpl implements ILevelDatasource { +/// Remote +class RemoteLevelDatasourceImpl implements ILevelDatasource { final IHttpRequest httpRequest; - const LevelDatasourceImpl(this.httpRequest); + const RemoteLevelDatasourceImpl(this.httpRequest); @override - Future getData({required LevelParams params}) async { + Future> getLevels({required LevelParams params}) async { final response = await httpRequest.get( path: MyApi.baseUrl, ); - return BaseResponse.getData( + return BaseResponse.getDataList( response?['data'], (json) => LevelModel.fromJson(json), ); } } + + +/// Local +class LocalLevelDatasourceImpl implements ILevelDatasource { + + const LocalLevelDatasourceImpl(); + + @override + Future> getLevels({required LevelParams params}) async { + try { + final Box levelBox = Hive.box(MyConstants.levelBox); + return levelBox.values.toList(); + } catch (_) { + throw MyException(errorMessage: 'Operation Failed'); + } + } +} \ No newline at end of file diff --git a/lib/features/level/data/model/level_model.dart b/lib/features/level/data/model/level_model.dart index b93f39d..2400039 100644 --- a/lib/features/level/data/model/level_model.dart +++ b/lib/features/level/data/model/level_model.dart @@ -1,13 +1,23 @@ import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; +import 'package:hadi_hoda_flutter/features/question/data/model/question_model.dart'; +import 'package:hadi_hoda_flutter/features/question/domain/entity/question_entity.dart'; class LevelModel extends LevelEntity { LevelModel({ super.id, + super.order, + super.title, + super.questions, }); factory LevelModel.fromJson(Map json) { return LevelModel( id: json['id'], + order: json['order'], + title: json['title'], + questions: json['questions'] + ?.map((e) => QuestionModel.fromJson(e)) + .toList(), ); } } diff --git a/lib/features/level/data/repository_impl/level_repository_impl.dart b/lib/features/level/data/repository_impl/level_repository_impl.dart index 6673644..07d9366 100644 --- a/lib/features/level/data/repository_impl/level_repository_impl.dart +++ b/lib/features/level/data/repository_impl/level_repository_impl.dart @@ -1,6 +1,6 @@ -import 'package:hadi_hoda_flutter/core/params/level_params.dart'; import 'package:flutter/foundation.dart'; import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; +import 'package:hadi_hoda_flutter/core/params/level_params.dart'; import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; import 'package:hadi_hoda_flutter/features/level/data/datasource/level_datasource.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; @@ -12,9 +12,13 @@ class LevelRepositoryImpl implements ILevelRepository { const LevelRepositoryImpl(this.datasource); @override - Future> getData({required LevelParams params}) async { + Future, MyException>> getLevels({ + required LevelParams params, + }) async { try { - final LevelEntity response = await datasource.getData(params: params); + final List response = await datasource.getLevels( + params: params, + ); return DataState.success(response); } on MyException catch (e) { return DataState.error(e); diff --git a/lib/features/level/domain/entity/level_location.dart b/lib/features/level/domain/entity/level_location.dart index 330e984..ca2bce8 100644 --- a/lib/features/level/domain/entity/level_location.dart +++ b/lib/features/level/domain/entity/level_location.dart @@ -1,11 +1,11 @@ -class MissionLocation { +class LevelLocation { final int? index; final double? top; final double? bottom; final double? right; final double? left; - const MissionLocation({ + const LevelLocation({ this.index, this.top, this.bottom, diff --git a/lib/features/level/domain/repository/level_repository.dart b/lib/features/level/domain/repository/level_repository.dart index 8d9b560..672d6f4 100644 --- a/lib/features/level/domain/repository/level_repository.dart +++ b/lib/features/level/domain/repository/level_repository.dart @@ -4,5 +4,5 @@ import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; abstract class ILevelRepository { - Future> getData({required LevelParams params}); + Future, MyException>> getLevels({required LevelParams params}); } diff --git a/lib/features/level/domain/usecases/get_level_usecase.dart b/lib/features/level/domain/usecases/get_level_usecase.dart index 76e4caf..f141d4c 100644 --- a/lib/features/level/domain/usecases/get_level_usecase.dart +++ b/lib/features/level/domain/usecases/get_level_usecase.dart @@ -5,13 +5,13 @@ import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; import 'package:hadi_hoda_flutter/features/level/domain/repository/level_repository.dart'; -class GetLevelUseCase implements UseCase { +class GetLevelUseCase implements UseCase, LevelParams> { final ILevelRepository repository; const GetLevelUseCase(this.repository); @override - Future> call(LevelParams params) { - return repository.getData(params: params); + Future, MyException>> call(LevelParams params) { + return repository.getLevels(params: params); } } diff --git a/lib/features/level/presentation/bloc/level_bloc.dart b/lib/features/level/presentation/bloc/level_bloc.dart index b19ba7f..72a49d3 100644 --- a/lib/features/level/presentation/bloc/level_bloc.dart +++ b/lib/features/level/presentation/bloc/level_bloc.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; +import 'package:hadi_hoda_flutter/core/params/level_params.dart'; import 'package:hadi_hoda_flutter/core/status/base_status.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_location.dart'; @@ -12,56 +13,58 @@ class LevelBloc extends Bloc { LevelBloc( this._getLevelUseCase, ) : super(const LevelState()) { - on(_getLevelEvent); + on(_getLevelListEvent); } /// ------------UseCases------------ final GetLevelUseCase _getLevelUseCase; /// ------------Variables------------ - final List bottomLocationList = [ - MissionLocation(bottom: -30, left: 30, index: 1), - MissionLocation(bottom: 50, left: 100, index: 2), - MissionLocation(bottom: 150, left: 60, index: 3), - MissionLocation(bottom: 210, left: 120, index: 4), - MissionLocation(bottom: 250, right: 60, index: 5), - MissionLocation(top: 170, right: 40, index: 6), - MissionLocation(top: 70, right: 70, index: 7), - MissionLocation(top: -20, right: 70, index: 8), + final List bottomLocationList = [ + LevelLocation(bottom: -30, left: 30, index: 1), + LevelLocation(bottom: 50, left: 100, index: 2), + LevelLocation(bottom: 150, left: 60, index: 3), + LevelLocation(bottom: 210, left: 120, index: 4), + LevelLocation(bottom: 250, right: 60, index: 5), + LevelLocation(top: 170, right: 40, index: 6), + LevelLocation(top: 70, right: 70, index: 7), + LevelLocation(top: -20, right: 70, index: 8), ]; - final List topLocationList = [ - MissionLocation(bottom: 30, right: 80, index: 9), - MissionLocation(bottom: 70, left: 20, index: 10), - MissionLocation(bottom: 150, left: 50, index: 11), - MissionLocation(bottom: 180, left: 140, index: 12), - MissionLocation(bottom: 260, right: 20, index: 13), - MissionLocation(bottom: 370, right: 30, index: 14), - MissionLocation(bottom: 420, left: 40, index: 15), - MissionLocation(top: 410, left: 0, index: 16), - MissionLocation(top: 320, left: 60, index: 17), - MissionLocation(top: 220, left: 80, index: 18), - MissionLocation(top: 130, left: 20, index: 19), - MissionLocation(top: 50, left: 70, index: 20), + final List topLocationList = [ + LevelLocation(bottom: 30, right: 80, index: 9), + LevelLocation(bottom: 70, left: 20, index: 10), + LevelLocation(bottom: 150, left: 50, index: 11), + LevelLocation(bottom: 180, left: 140, index: 12), + LevelLocation(bottom: 260, right: 20, index: 13), + LevelLocation(bottom: 370, right: 30, index: 14), + LevelLocation(bottom: 420, left: 40, index: 15), + LevelLocation(top: 410, left: 0, index: 16), + LevelLocation(top: 320, left: 60, index: 17), + LevelLocation(top: 220, left: 80, index: 18), + LevelLocation(top: 130, left: 20, index: 19), + LevelLocation(top: 50, left: 70, index: 20), ]; + final List bottom8LevelList = []; + final List top12LevelList = []; + /// ------------Controllers------------ /// ------------Functions------------ /// ------------Api Calls------------ - FutureOr _getLevelEvent(event, emit) async { - await _getLevelUseCase(event.levelParams).then( - (value) { - value.fold( - (data) { - emit(state.copyWith(getLevelStatus: BaseComplete(data))); - }, - (error) { - emit(state.copyWith(getLevelStatus: BaseError(error.errorMessage))); - }, - ); - }, - ); + FutureOr _getLevelListEvent(GetLevelListEvent event, + Emitter emit) async { + await _getLevelUseCase(LevelParams()).then((value) { + value.fold( + (data) { + bottom8LevelList.addAll(data.take(8)); + top12LevelList.addAll(data.sublist(8, 20)); + emit(state.copyWith(getLevelStatus: const BaseComplete(''))); + }, + (error) {}, + ); + }); } } diff --git a/lib/features/level/presentation/bloc/level_event.dart b/lib/features/level/presentation/bloc/level_event.dart index 231b8ad..7344eb5 100644 --- a/lib/features/level/presentation/bloc/level_event.dart +++ b/lib/features/level/presentation/bloc/level_event.dart @@ -2,4 +2,4 @@ sealed class LevelEvent { const LevelEvent(); } -class GetLevelEvent extends LevelEvent {} +class GetLevelListEvent extends LevelEvent {} diff --git a/lib/features/level/presentation/ui/level_page.dart b/lib/features/level/presentation/ui/level_page.dart index 2c86672..d0bcb59 100644 --- a/lib/features/level/presentation/ui/level_page.dart +++ b/lib/features/level/presentation/ui/level_page.dart @@ -5,6 +5,7 @@ import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_bloc.dart'; +import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_state.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/bottom_path.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/hint_level_widget.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/level_widget.dart'; @@ -71,25 +72,27 @@ class LevelPage extends StatelessWidget { return Positioned( top: context.heightScreen * 0.16, left: context.widthScreen * 0.15, - child: Stack( - children: [ - TopPath( - height: 950, - width: context.widthScreen * 0.6, - ), - ...List.generate( - context.read().topLocationList.length, - (index) => Positioned( - top: context.read().topLocationList[index].top, - bottom: context.read().topLocationList[index].bottom, - right: context.read().topLocationList[index].right, - left: context.read().topLocationList[index].left, - child: LevelWidget( - index: context.read().topLocationList[index].index ?? 0, + child: BlocBuilder( + builder: (context, state) => Stack( + children: [ + TopPath( + height: 950, + width: context.widthScreen * 0.6, + ), + ...List.generate( + context.read().top12LevelList.length, + (index) => Positioned( + top: context.read().topLocationList[index].top, + bottom: context.read().topLocationList[index].bottom, + right: context.read().topLocationList[index].right, + left: context.read().topLocationList[index].left, + child: LevelWidget( + index: context.read().topLocationList[index].index ?? 0, + ), ), - ), - ), - ], + ), + ], + ), ), ); } @@ -98,26 +101,28 @@ class LevelPage extends StatelessWidget { return Positioned( bottom: context.heightScreen * 0.18, left: context.widthScreen * 0.2, - child: Stack( - clipBehavior: Clip.none, - children: [ - BottomPath( - width: context.widthScreen * 0.75, - height: context.heightScreen * 0.6, - ), - ...List.generate( - context.read().bottomLocationList.length, - (index) => Positioned( - top: context.read().bottomLocationList[index].top, - bottom: context.read().bottomLocationList[index].bottom, - right: context.read().bottomLocationList[index].right, - left: context.read().bottomLocationList[index].left, - child: LevelWidget( - index: context.read().bottomLocationList[index].index ?? 0, + child: BlocBuilder( + builder: (context, state) => Stack( + clipBehavior: Clip.none, + children: [ + BottomPath( + width: context.widthScreen * 0.75, + height: context.heightScreen * 0.6, + ), + ...List.generate( + context.read().bottom8LevelList.length, + (index) => Positioned( + top: context.read().bottomLocationList[index].top, + bottom: context.read().bottomLocationList[index].bottom, + right: context.read().bottomLocationList[index].right, + left: context.read().bottomLocationList[index].left, + child: LevelWidget( + index: context.read().bottomLocationList[index].index ?? 0, + ), ), - ), - ), - ], + ), + ], + ), ), ); }