From 5a945266684eddf92ac8a92df5fb524ac0c9d70e Mon Sep 17 00:00:00 2001 From: AmirrezaChegini Date: Thu, 2 Oct 2025 11:52:39 +0330 Subject: [PATCH] add: logic to level page --- lib/common_ui/resources/my_assets.dart | 2 +- lib/core/routers/my_routes.dart | 5 +- .../level/presentation/bloc/level_bloc.dart | 18 ++++ .../level/presentation/bloc/level_event.dart | 6 ++ .../level/presentation/bloc/level_state.dart | 9 +- .../level/presentation/ui/level_page.dart | 34 +++++-- .../ui/widgets/hint_level_widget.dart | 14 ++- .../presentation/ui/widgets/level_widget.dart | 92 +++++++++++-------- 8 files changed, 126 insertions(+), 54 deletions(-) diff --git a/lib/common_ui/resources/my_assets.dart b/lib/common_ui/resources/my_assets.dart index aa38b53..041843e 100644 --- a/lib/common_ui/resources/my_assets.dart +++ b/lib/common_ui/resources/my_assets.dart @@ -17,7 +17,7 @@ class MyAssets { static const String language = 'assets/images/language.svg'; static const String newHorizon = 'assets/images/new_horizon.svg'; static const String khadijeLogo = 'assets/images/khadije_logo.png'; - static const String home = 'assets/images/level.svg'; + static const String home = 'assets/images/home.svg'; static const String music = 'assets/images/music.svg'; static const String pattern = 'assets/images/pattern.png'; static const String persons = 'assets/images/persons.png'; diff --git a/lib/core/routers/my_routes.dart b/lib/core/routers/my_routes.dart index 2a88360..9c1a3bb 100644 --- a/lib/core/routers/my_routes.dart +++ b/lib/core/routers/my_routes.dart @@ -24,7 +24,7 @@ class Routes { } GoRouter get appPages => GoRouter( - initialLocation: Routes.introPage, + initialLocation: Routes.levelPage, navigatorKey: ContextProvider.navigatorKey, routes: [ GoRoute( @@ -52,8 +52,9 @@ GoRouter get appPages => GoRouter( ), ), GoRoute( + name: Routes.questionPage, - path: Routes.questionPage, + path: '${Routes.questionPage}/:id', builder: (context, state) => BlocProvider( create: (context) => QuestionBloc(locator()), child: const QuestionPage(), diff --git a/lib/features/level/presentation/bloc/level_bloc.dart b/lib/features/level/presentation/bloc/level_bloc.dart index a92b510..20f9617 100644 --- a/lib/features/level/presentation/bloc/level_bloc.dart +++ b/lib/features/level/presentation/bloc/level_bloc.dart @@ -1,6 +1,9 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:go_router/go_router.dart'; import 'package:hadi_hoda_flutter/core/params/level_params.dart'; +import 'package:hadi_hoda_flutter/core/routers/my_routes.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'; @@ -14,6 +17,7 @@ class LevelBloc extends Bloc { this._getLevelUseCase, ) : super(const LevelState()) { on(_getLevelListEvent); + on(_chooseLevelEvent); } /// ------------UseCases------------ @@ -49,9 +53,23 @@ class LevelBloc extends Bloc { final List bottom8LevelList = []; final List top12LevelList = []; + /// ------------Controllers------------ /// ------------Functions------------ + FutureOr _chooseLevelEvent(ChooseLevelEvent event, + Emitter emit) async { + emit(state.copyWith(chooseLevel: event.level)); + } + + void goToQuestionPage(BuildContext context, LevelEntity level){ + context.pushNamed( + Routes.questionPage, + pathParameters: { + 'id': '${level.id}', + }, + ); + } /// ------------Api Calls------------ FutureOr _getLevelListEvent(GetLevelListEvent event, diff --git a/lib/features/level/presentation/bloc/level_event.dart b/lib/features/level/presentation/bloc/level_event.dart index 7344eb5..6f9020c 100644 --- a/lib/features/level/presentation/bloc/level_event.dart +++ b/lib/features/level/presentation/bloc/level_event.dart @@ -1,5 +1,11 @@ +import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; + sealed class LevelEvent { const LevelEvent(); } class GetLevelListEvent extends LevelEvent {} +class ChooseLevelEvent extends LevelEvent { + final LevelEntity level; + const ChooseLevelEvent(this.level); +} diff --git a/lib/features/level/presentation/bloc/level_state.dart b/lib/features/level/presentation/bloc/level_state.dart index 4ecb07c..adc10ed 100644 --- a/lib/features/level/presentation/bloc/level_state.dart +++ b/lib/features/level/presentation/bloc/level_state.dart @@ -1,15 +1,22 @@ import 'package:hadi_hoda_flutter/core/status/base_status.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; class LevelState { final BaseStatus getLevelStatus; + final LevelEntity? chooseLevel; - const LevelState({this.getLevelStatus = const BaseInit()}); + const LevelState({ + this.getLevelStatus = const BaseInit(), + this.chooseLevel, + }); LevelState copyWith({ BaseStatus? getLevelStatus, + LevelEntity? chooseLevel, }) { return LevelState( getLevelStatus: getLevelStatus ?? this.getLevelStatus, + chooseLevel: chooseLevel ?? chooseLevel, ); } } diff --git a/lib/features/level/presentation/ui/level_page.dart b/lib/features/level/presentation/ui/level_page.dart index d0bcb59..591d335 100644 --- a/lib/features/level/presentation/ui/level_page.dart +++ b/lib/features/level/presentation/ui/level_page.dart @@ -4,7 +4,9 @@ import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; 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/domain/entity/level_entity.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_bloc.dart'; +import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_event.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'; @@ -36,12 +38,28 @@ class LevelPage extends StatelessWidget { ); } - Positioned _hintMission(BuildContext context) { - return Positioned( - bottom: MediaQuery.viewPaddingOf(context).bottom, - right: MySpaces.s16, - left: MySpaces.s16, - child: HintLevelWidget(), + Widget _hintMission(BuildContext context) { + return BlocBuilder( + buildWhen: (previous, current) => + previous.chooseLevel?.id != current.chooseLevel?.id, + builder: (context, state) { + if (state.chooseLevel != null) { + return Positioned( + bottom: MediaQuery + .viewPaddingOf(context) + .bottom, + right: MySpaces.s16, + left: MySpaces.s16, + child: HintLevelWidget( + level: state.chooseLevel ?? LevelEntity(), + onTap: (level) => + context.read().goToQuestionPage(context, level), + ), + ); + } else { + return SizedBox.shrink(); + } + } ); } @@ -88,6 +106,8 @@ class LevelPage extends StatelessWidget { left: context.read().topLocationList[index].left, child: LevelWidget( index: context.read().topLocationList[index].index ?? 0, + level: context.read().top12LevelList[index], + onTap: (LevelEntity level) => context.read().add(ChooseLevelEvent(level)), ), ), ), @@ -118,6 +138,8 @@ class LevelPage extends StatelessWidget { left: context.read().bottomLocationList[index].left, child: LevelWidget( index: context.read().bottomLocationList[index].index ?? 0, + level: context.read().bottom8LevelList[index], + onTap: (LevelEntity level) => context.read().add(ChooseLevelEvent(level)), ), ), ), diff --git a/lib/features/level/presentation/ui/widgets/hint_level_widget.dart b/lib/features/level/presentation/ui/widgets/hint_level_widget.dart index 0ddb472..f1f1312 100644 --- a/lib/features/level/presentation/ui/widgets/hint_level_widget.dart +++ b/lib/features/level/presentation/ui/widgets/hint_level_widget.dart @@ -5,9 +5,13 @@ 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/core/widgets/answer_box/styles/text_box.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; class HintLevelWidget extends StatelessWidget { - const HintLevelWidget({super.key}); + const HintLevelWidget({super.key, required this.level, this.onTap,}); + + final LevelEntity level; + final Function(LevelEntity level)? onTap; @override Widget build(BuildContext context) { @@ -32,7 +36,7 @@ class HintLevelWidget extends StatelessWidget { spacing: MySpaces.s8, children: [ Text( - 'Step 3', + 'Step ${level.order ?? 0}', style: GoogleFonts.marhey( fontSize: 14, fontWeight: FontWeight.w700, @@ -40,7 +44,7 @@ class HintLevelWidget extends StatelessWidget { ), ), Text( - 'Toothbrushing etiquette every day', + level.title ?? '', maxLines: 3, overflow: TextOverflow.ellipsis, style: GoogleFonts.marhey( @@ -53,7 +57,9 @@ class HintLevelWidget extends StatelessWidget { ], ), ), - MyImage(image: MyAssets.play, size: 70), + InkWell( + onTap: () => onTap?.call(level), + child: MyImage(image: MyAssets.play, size: 70),), ], ), ), diff --git a/lib/features/level/presentation/ui/widgets/level_widget.dart b/lib/features/level/presentation/ui/widgets/level_widget.dart index ee6229a..ff5d9a7 100644 --- a/lib/features/level/presentation/ui/widgets/level_widget.dart +++ b/lib/features/level/presentation/ui/widgets/level_widget.dart @@ -3,6 +3,7 @@ import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; enum LevelType { unFinished, @@ -17,56 +18,67 @@ enum LevelType { } class LevelWidget extends StatelessWidget { - const LevelWidget({super.key, required this.index, this.type}); + const LevelWidget({ + super.key, + required this.index, + required this.level, + this.type, + this.onTap, + }); final int index; final LevelType? type; + final LevelEntity level; + final Function(LevelEntity level)? onTap; @override Widget build(BuildContext context) { - return Stack( - alignment: Alignment.topCenter, - clipBehavior: Clip.none, - children: [ - MyImage(image: LevelType.image[type] ?? MyAssets.level, size: 46), - Text( - '$index', - style: MyTextStyle.normal26.copyWith(color: context.primaryColor), - ), - if(type == LevelType.current) - Positioned( - top: -20, - child: MyImage( - image: MyAssets.location, - size: 26, - ), + return InkWell( + onTap: () => onTap?.call(level), + child: Stack( + alignment: Alignment.topCenter, + clipBehavior: Clip.none, + children: [ + MyImage(image: LevelType.image[type] ?? MyAssets.level, size: 46), + Text( + '$index', + style: MyTextStyle.normal26.copyWith(color: context.primaryColor), ), - if(type == LevelType.finished) - Positioned( - bottom: 0, - child: Container( - height: 17, - width: 17, - padding: EdgeInsets.all(3), - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - width: 1, - color: Color(0XFF3CFF3C), - ), - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0XFF48D336), - Color(0XFF2D7C23), - ], + if(type == LevelType.current) + Positioned( + top: -20, + child: MyImage( + image: MyAssets.location, + size: 26, + ), + ), + if(type == LevelType.finished) + Positioned( + bottom: 0, + child: Container( + height: 17, + width: 17, + padding: EdgeInsets.all(3), + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + width: 1, + color: Color(0XFF3CFF3C), + ), + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0XFF48D336), + Color(0XFF2D7C23), + ], + ), ), + child: MyImage(image: MyAssets.doneRounded), ), - child: MyImage(image: MyAssets.doneRounded), ), - ), - ], + ], + ), ); } }