18 changed files with 727 additions and 141 deletions
-
10lib/core/middlewares/my_middlewares.dart
-
15lib/core/routers/my_routes.dart
-
57lib/core/widgets/answer_box/answer_box.dart
-
111lib/core/widgets/answer_box/answer_box_showcase.dart
-
6lib/core/widgets/showcase/my_showcase_widget.dart
-
33lib/features/guider/data/datasource/guider_datasource.dart
-
28lib/features/guider/data/repository_impl/guider_repository_impl.dart
-
7lib/features/guider/domain/repository/guider_repository.dart
-
17lib/features/guider/domain/usecases/get_first_level_usecase.dart
-
131lib/features/guider/presentation/bloc/guider_bloc.dart
-
8lib/features/guider/presentation/bloc/guider_event.dart
-
27lib/features/guider/presentation/bloc/guider_state.dart
-
247lib/features/guider/presentation/ui/guider_page.dart
-
4lib/features/language/presentation/ui/language_page.dart
-
70lib/features/question/presentation/bloc/question_bloc.dart
-
83lib/features/question/presentation/ui/screens/question_screen.dart
-
5lib/features/sample/presentation/ui/sample_page.dart
-
9lib/init_bindings.dart
@ -0,0 +1,111 @@ |
|||||
|
import 'package:flutter/material.dart'; |
||||
|
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_localization.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/widgets/answer_box/styles/picture_box.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/widgets/answer_box/styles/text_box.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/widgets/showcase/my_showcase_widget.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/question/domain/entity/answer_entity.dart'; |
||||
|
|
||||
|
class AnswerBoxShowCase extends StatefulWidget { |
||||
|
const AnswerBoxShowCase({ |
||||
|
super.key, |
||||
|
required this.answer, |
||||
|
required this.correctAnswer, |
||||
|
required this.index, |
||||
|
this.globalKey, |
||||
|
this.answerGlobalKey, |
||||
|
this.onTap, |
||||
|
this.onNotifTap, |
||||
|
}); |
||||
|
|
||||
|
final AnswerEntity answer; |
||||
|
final int correctAnswer; |
||||
|
final void Function(bool isCorrect, int correctAnswer)? onTap; |
||||
|
final int index; |
||||
|
final Function(AnswerEntity answer)? onNotifTap; |
||||
|
final GlobalKey? globalKey; |
||||
|
final GlobalKey? answerGlobalKey; |
||||
|
|
||||
|
@override |
||||
|
State<AnswerBoxShowCase> createState() => _AnswerBoxShowCaseState(); |
||||
|
} |
||||
|
|
||||
|
class _AnswerBoxShowCaseState extends State<AnswerBoxShowCase> { |
||||
|
bool selected = false; |
||||
|
|
||||
|
@override |
||||
|
Widget build(BuildContext context) { |
||||
|
return Hero( |
||||
|
tag: 'Hero_answer_${widget.answer.id}', |
||||
|
child: Material( |
||||
|
type: MaterialType.transparency, |
||||
|
child: GestureDetector( |
||||
|
onTap: !selected |
||||
|
? () { |
||||
|
setState(() { |
||||
|
selected = true; |
||||
|
}); |
||||
|
widget.onTap?.call( |
||||
|
widget.index == widget.correctAnswer, |
||||
|
widget.correctAnswer, |
||||
|
); |
||||
|
} |
||||
|
: null, |
||||
|
child: Stack( |
||||
|
alignment: Alignment.topCenter, |
||||
|
children: [ |
||||
|
MyShowcaseWidget( |
||||
|
globalKey: widget.answerGlobalKey, |
||||
|
description: context.translate.showcase_answer, |
||||
|
child: AnswerPictureBox( |
||||
|
selected: selected, |
||||
|
index: widget.index, |
||||
|
image: widget.answer.image ?? '', |
||||
|
correctAnswer: widget.correctAnswer, |
||||
|
onTap: () { |
||||
|
widget.onNotifTap?.call(widget.answer); |
||||
|
}, |
||||
|
), |
||||
|
), |
||||
|
Positioned( |
||||
|
left: 0, |
||||
|
right: 0, |
||||
|
bottom: 0, |
||||
|
child: AnswerTextBox(text: widget.answer.title ?? ''), |
||||
|
), |
||||
|
PositionedDirectional( |
||||
|
top: setSize( |
||||
|
context: context, |
||||
|
mobile: MySpaces.s12, |
||||
|
tablet: MySpaces.s20, |
||||
|
), |
||||
|
end: setSize( |
||||
|
context: context, |
||||
|
mobile: MySpaces.s8, |
||||
|
tablet: MySpaces.s20, |
||||
|
), |
||||
|
child: MyShowcaseWidget( |
||||
|
globalKey: widget.globalKey, |
||||
|
type: ShowcaseTooltipType.bottom, |
||||
|
description: context.translate.showcase_notif, |
||||
|
child: GestureDetector( |
||||
|
onTap: () { |
||||
|
widget.onNotifTap?.call(widget.answer); |
||||
|
}, |
||||
|
child: MyImage( |
||||
|
image: MyAssets.iconNotif, |
||||
|
size: setSize(context: context, tablet: 50), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
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/utils/local_storage.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/level/domain/entity/total_data_entity.dart'; |
||||
|
import 'package:hive/hive.dart'; |
||||
|
|
||||
|
abstract class IGuiderDatasource { |
||||
|
Future<LevelEntity> getLevel(); |
||||
|
} |
||||
|
|
||||
|
/// Local |
||||
|
class GuiderDatasourceImpl implements IGuiderDatasource { |
||||
|
const GuiderDatasourceImpl(); |
||||
|
|
||||
|
@override |
||||
|
Future<LevelEntity> getLevel() async { |
||||
|
try { |
||||
|
final String selectedLanguage = |
||||
|
LocalStorage.readData(key: MyConstants.selectLanguage) ?? |
||||
|
MyConstants.defaultLanguage; |
||||
|
final Box<TotalDataEntity> levelBox = Hive.box(MyConstants.levelBox); |
||||
|
final TotalDataEntity findData = levelBox.values.singleWhere( |
||||
|
(e) => e.code == selectedLanguage, |
||||
|
orElse: () => TotalDataEntity(), |
||||
|
); |
||||
|
final LevelEntity? findLevel = findData.levels?.first; |
||||
|
return findLevel ?? LevelEntity(); |
||||
|
} catch (e) { |
||||
|
throw MyException(errorMessage: '$e'); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
import 'package:flutter/foundation.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/guider/data/datasource/guider_datasource.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/guider/domain/repository/guider_repository.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; |
||||
|
|
||||
|
class GuiderRepositoryImpl implements IGuiderRepository { |
||||
|
final IGuiderDatasource datasource; |
||||
|
|
||||
|
const GuiderRepositoryImpl(this.datasource); |
||||
|
|
||||
|
@override |
||||
|
Future<DataState<LevelEntity, MyException>> getLevel() async { |
||||
|
try { |
||||
|
final LevelEntity response = await datasource.getLevel(); |
||||
|
return DataState.success(response); |
||||
|
} on MyException catch (e) { |
||||
|
return DataState.error(e); |
||||
|
} catch (e) { |
||||
|
if (kDebugMode) { |
||||
|
rethrow; |
||||
|
} else { |
||||
|
return DataState.error(MyException(errorMessage: '$e')); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; |
||||
|
|
||||
|
abstract class IGuiderRepository { |
||||
|
Future<DataState<LevelEntity, MyException>> getLevel(); |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/params/no_params.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/guider/domain/repository/guider_repository.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; |
||||
|
|
||||
|
class GetFirstLevelUseCase implements UseCase<LevelEntity, NoParams> { |
||||
|
final IGuiderRepository repository; |
||||
|
|
||||
|
const GetFirstLevelUseCase(this.repository); |
||||
|
|
||||
|
@override |
||||
|
Future<DataState<LevelEntity, MyException>> call(NoParams params) { |
||||
|
return repository.getLevel(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,131 @@ |
|||||
|
import 'dart:async'; |
||||
|
|
||||
|
import 'package:bloc/bloc.dart'; |
||||
|
import 'package:flutter/material.dart'; |
||||
|
import 'package:go_router/go_router.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/constants/my_constants.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/params/no_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/core/utils/local_storage.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/my_context.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/guider/domain/usecases/get_first_level_usecase.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/guider/presentation/bloc/guider_event.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/guider/presentation/bloc/guider_state.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/question/domain/entity/question_entity.dart'; |
||||
|
import 'package:showcaseview/showcaseview.dart'; |
||||
|
|
||||
|
class GuiderBloc extends Bloc<GuiderEvent, GuiderState> { |
||||
|
/// ------------constructor------------ |
||||
|
GuiderBloc(this._getFirstLevelUseCase) : super(const GuiderState()) { |
||||
|
registerShowCase(); |
||||
|
on<GetFirstLevelEvent>(_getFirstLevelEvent); |
||||
|
} |
||||
|
|
||||
|
@override |
||||
|
Future<void> close() { |
||||
|
unRegisterShowCase(); |
||||
|
animationController.dispose(); |
||||
|
return super.close(); |
||||
|
} |
||||
|
|
||||
|
/// ------------UseCases------------ |
||||
|
final GetFirstLevelUseCase _getFirstLevelUseCase; |
||||
|
|
||||
|
/// ------------Variables------------ |
||||
|
final Map<String, GlobalKey> showCaseKey = { |
||||
|
'answer_key_0': GlobalKey(), |
||||
|
'answer_key_1': GlobalKey(), |
||||
|
'answer_key_2': GlobalKey(), |
||||
|
'answer_key_3': GlobalKey(), |
||||
|
'notif_key_0': GlobalKey(), |
||||
|
'notif_key_1': GlobalKey(), |
||||
|
'notif_key_2': GlobalKey(), |
||||
|
'notif_key_3': GlobalKey(), |
||||
|
'stepper_key': GlobalKey(), |
||||
|
'hadith_key': GlobalKey(), |
||||
|
'guide_key': GlobalKey(), |
||||
|
}; |
||||
|
String? id; |
||||
|
|
||||
|
/// ------------Controllers------------ |
||||
|
late final AnimationController animationController; |
||||
|
|
||||
|
/// ------------Functions------------ |
||||
|
void registerShowCase() { |
||||
|
try { |
||||
|
ShowcaseView.register( |
||||
|
onStart: (showcaseIndex, key) { |
||||
|
LocalStorage.saveData(key: MyConstants.firstShowcase, value: 'true'); |
||||
|
}, |
||||
|
onDismiss: (onDismiss) { |
||||
|
MyContext.get.goNamed( |
||||
|
Routes.questionPage, |
||||
|
pathParameters: {'id': id ?? ''}, |
||||
|
); |
||||
|
}, |
||||
|
onFinish: () { |
||||
|
MyContext.get.goNamed( |
||||
|
Routes.questionPage, |
||||
|
pathParameters: {'id': id ?? ''}, |
||||
|
); |
||||
|
}, |
||||
|
); |
||||
|
} catch (_) {} |
||||
|
} |
||||
|
|
||||
|
void unRegisterShowCase() { |
||||
|
try { |
||||
|
ShowcaseView.get().unregister(); |
||||
|
} catch (_) {} |
||||
|
} |
||||
|
|
||||
|
void startShowcase() { |
||||
|
if (LocalStorage.readData(key: MyConstants.firstShowcase) != 'true') { |
||||
|
try { |
||||
|
ShowcaseView.get().startShowCase([ |
||||
|
showCaseKey['answer_key_1']!, |
||||
|
showCaseKey['notif_key_0']!, |
||||
|
showCaseKey['stepper_key']!, |
||||
|
showCaseKey['hadith_key']!, |
||||
|
showCaseKey['guide_key']!, |
||||
|
]); |
||||
|
} catch (_) {} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// ------------Event Calls------------ |
||||
|
|
||||
|
FutureOr<void> _getFirstLevelEvent( |
||||
|
GetFirstLevelEvent event, |
||||
|
Emitter<GuiderState> emit, |
||||
|
) async { |
||||
|
id = event.id; |
||||
|
await _getFirstLevelUseCase(NoParams()).then( |
||||
|
(value) => value.fold((data) async { |
||||
|
final LevelEntity level = LevelEntity( |
||||
|
id: data.id, |
||||
|
order: data.order, |
||||
|
title: data.title, |
||||
|
questions: [ |
||||
|
...?data.questions, |
||||
|
QuestionEntity(order: (data.questions?.length ?? 0) + 1), |
||||
|
], |
||||
|
); |
||||
|
emit( |
||||
|
state.copyWith( |
||||
|
getQuestionStatus: BaseComplete(''), |
||||
|
levelEntity: level, |
||||
|
currentQuestion: data.questions?.first, |
||||
|
), |
||||
|
); |
||||
|
await Future.delayed(Duration(milliseconds: 300), () { |
||||
|
animationController.forward().then((value) { |
||||
|
startShowcase(); |
||||
|
}); |
||||
|
}); |
||||
|
}, (error) {}), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
sealed class GuiderEvent { |
||||
|
const GuiderEvent(); |
||||
|
} |
||||
|
|
||||
|
class GetFirstLevelEvent extends GuiderEvent { |
||||
|
final String? id; |
||||
|
const GetFirstLevelEvent({this.id}); |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
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/question/domain/entity/question_entity.dart'; |
||||
|
|
||||
|
class GuiderState { |
||||
|
final BaseStatus getQuestionStatus; |
||||
|
final LevelEntity? levelEntity; |
||||
|
final QuestionEntity? currentQuestion; |
||||
|
|
||||
|
const GuiderState({ |
||||
|
this.getQuestionStatus = const BaseInit(), |
||||
|
this.levelEntity, |
||||
|
this.currentQuestion, |
||||
|
}); |
||||
|
|
||||
|
GuiderState copyWith({ |
||||
|
BaseStatus? getQuestionStatus, |
||||
|
LevelEntity? levelEntity, |
||||
|
QuestionEntity? currentQuestion, |
||||
|
}) { |
||||
|
return GuiderState( |
||||
|
getQuestionStatus: getQuestionStatus ?? this.getQuestionStatus, |
||||
|
levelEntity: levelEntity ?? this.levelEntity, |
||||
|
currentQuestion: currentQuestion ?? this.currentQuestion, |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,247 @@ |
|||||
|
import 'package:flutter/material.dart'; |
||||
|
import 'package:flutter_bloc/flutter_bloc.dart'; |
||||
|
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; |
||||
|
import 'package:hadi_hoda_flutter/common_ui/resources/my_audios.dart'; |
||||
|
import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; |
||||
|
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; |
||||
|
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/gap.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/widgets/animations/fade_anim.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/widgets/animations/slide_anim.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/widgets/animations/slide_down_fade.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/widgets/animations/slide_up_fade.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/widgets/answer_box/answer_box_showcase.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/widgets/pop_scope/my_pop_scope.dart'; |
||||
|
import 'package:hadi_hoda_flutter/core/widgets/showcase/my_showcase_widget.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/guider/presentation/bloc/guider_bloc.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/guider/presentation/bloc/guider_state.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/question/domain/entity/answer_entity.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/question/presentation/ui/widgets/glassy_button.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/question/presentation/ui/widgets/question_stepper.dart'; |
||||
|
import 'package:hadi_hoda_flutter/features/question/presentation/ui/widgets/question_title.dart'; |
||||
|
|
||||
|
class GuiderPage extends StatefulWidget { |
||||
|
const GuiderPage({super.key}); |
||||
|
|
||||
|
@override |
||||
|
State<GuiderPage> createState() => _GuiderPageState(); |
||||
|
} |
||||
|
|
||||
|
class _GuiderPageState extends State<GuiderPage> with TickerProviderStateMixin { |
||||
|
|
||||
|
@override |
||||
|
void initState() { |
||||
|
super.initState(); |
||||
|
context |
||||
|
.read<GuiderBloc>() |
||||
|
.animationController = AnimationController( |
||||
|
vsync: this, |
||||
|
duration: Duration(milliseconds: 500), |
||||
|
reverseDuration: Duration(milliseconds: 500), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
@override |
||||
|
Widget build(BuildContext context) { |
||||
|
return Scaffold( |
||||
|
body: MyPopScope( |
||||
|
child: Directionality( |
||||
|
textDirection: TextDirection.ltr, |
||||
|
child: Container( |
||||
|
height: context.heightScreen, |
||||
|
width: context.widthScreen, |
||||
|
padding: EdgeInsets.symmetric( |
||||
|
horizontal: |
||||
|
setSize( |
||||
|
context: context, |
||||
|
mobile: MySpaces.s16, |
||||
|
tablet: MySpaces.s30, |
||||
|
) ?? |
||||
|
0, |
||||
|
), |
||||
|
decoration: BoxDecoration( |
||||
|
gradient: LinearGradient( |
||||
|
begin: Alignment.topCenter, |
||||
|
end: Alignment.bottomCenter, |
||||
|
colors: [Color(0XFF6930DA), Color(0XFF263AA1)], |
||||
|
), |
||||
|
image: DecorationImage( |
||||
|
image: AssetImage(MyAssets.pattern), |
||||
|
scale: 3, |
||||
|
repeat: ImageRepeat.repeat, |
||||
|
colorFilter: ColorFilter.mode( |
||||
|
Colors.black.withValues(alpha: 0.3), |
||||
|
BlendMode.srcIn, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
child: Column( |
||||
|
children: [ |
||||
|
setPlatform<double>( |
||||
|
android: MySpaces.s20, |
||||
|
iOS: 50, |
||||
|
)?.gapHeight ?? |
||||
|
SizedBox.shrink(), |
||||
|
_topButtons(context), |
||||
|
MySpaces.s10.gapHeight, |
||||
|
Expanded( |
||||
|
child: Column( |
||||
|
children: [ |
||||
|
_stepper(context), |
||||
|
_titles(context), |
||||
|
MySpaces.s20.gapHeight, |
||||
|
Expanded(child: _answers(context)), |
||||
|
_bottom(context), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
setPlatform<double>(android: MySpaces.s20)?.gapHeight ?? |
||||
|
SizedBox.shrink(), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
Widget _topButtons(BuildContext context) { |
||||
|
return SlideDownFade( |
||||
|
child: Row( |
||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
||||
|
crossAxisAlignment: CrossAxisAlignment.center, |
||||
|
children: [ |
||||
|
GlassyButton( |
||||
|
image: MyAssets.home, |
||||
|
audio: MyAudios.back, |
||||
|
onTap: () {}, |
||||
|
), |
||||
|
BlocBuilder<GuiderBloc, GuiderState>( |
||||
|
builder: (context, state) => |
||||
|
QuestionTitle( |
||||
|
step: state.levelEntity?.order, |
||||
|
currentQuestion: state.currentQuestion?.order, |
||||
|
questionLength: state.levelEntity?.questions?.length, |
||||
|
), |
||||
|
), |
||||
|
GlassyButton(image: MyAssets.music, onTap: () {}), |
||||
|
], |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
Widget _stepper(BuildContext context) { |
||||
|
return FadeAnim( |
||||
|
child: MyShowcaseWidget( |
||||
|
globalKey: context |
||||
|
.read<GuiderBloc>() |
||||
|
.showCaseKey['stepper_key']!, |
||||
|
description: context.translate.showcase_stepper, |
||||
|
child: QuestionStepper(length: 4, currentStep: 1), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
Widget _titles(BuildContext context) { |
||||
|
return BlocBuilder<GuiderBloc, GuiderState>( |
||||
|
builder: (context, state) => |
||||
|
FadeAnim( |
||||
|
child: Text( |
||||
|
state.currentQuestion?.title ?? '', |
||||
|
textAlign: TextAlign.center, |
||||
|
maxLines: 3, |
||||
|
style: MYTextStyle.titr1.copyWith( |
||||
|
shadows: [ |
||||
|
BoxShadow( |
||||
|
offset: Offset(0, 2), |
||||
|
color: MyColors.black.withValues(alpha: 0.25), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
Widget _answers(BuildContext context) { |
||||
|
return BlocBuilder<GuiderBloc, GuiderState>( |
||||
|
builder: (context, state) => |
||||
|
GridView.builder( |
||||
|
itemCount: state.currentQuestion?.answers?.length ?? 0, |
||||
|
physics: NeverScrollableScrollPhysics(), |
||||
|
shrinkWrap: true, |
||||
|
clipBehavior: Clip.none, |
||||
|
padding: EdgeInsets.symmetric( |
||||
|
horizontal: setSize(context: context, tablet: 70) ?? 0, |
||||
|
), |
||||
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( |
||||
|
crossAxisCount: 2, |
||||
|
crossAxisSpacing: MySpaces.s20, |
||||
|
mainAxisSpacing: 20, |
||||
|
childAspectRatio: 0.75, |
||||
|
), |
||||
|
itemBuilder: (context, index) => |
||||
|
state.currentQuestion?.answers?[index].imageId == null |
||||
|
? SizedBox.shrink() |
||||
|
: SlideAnim( |
||||
|
controller: context.read<GuiderBloc>().animationController, |
||||
|
index: index, |
||||
|
child: AnswerBoxShowCase( |
||||
|
globalKey: context |
||||
|
.read<GuiderBloc>() |
||||
|
.showCaseKey['notif_key_$index']!, |
||||
|
answerGlobalKey: context |
||||
|
.read<GuiderBloc>() |
||||
|
.showCaseKey['answer_key_$index']!, |
||||
|
index: state.currentQuestion?.answers?[index].order ?? 1, |
||||
|
answer: |
||||
|
state.currentQuestion?.answers?[index] ?? AnswerEntity(), |
||||
|
correctAnswer: 0, |
||||
|
onNotifTap: (AnswerEntity answer) {}, |
||||
|
onTap: (isCorrect, correctAnswer) {}, |
||||
|
), |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
Widget _bottom(BuildContext context) { |
||||
|
return SlideUpFade( |
||||
|
child: SizedBox( |
||||
|
width: context.widthScreen, |
||||
|
child: Stack( |
||||
|
alignment: AlignmentDirectional.centerStart, |
||||
|
children: [ |
||||
|
MyShowcaseWidget( |
||||
|
globalKey: context |
||||
|
.read<GuiderBloc>() |
||||
|
.showCaseKey['guide_key']!, |
||||
|
description: context.translate.showcase_guide, |
||||
|
type: ShowcaseTooltipType.top, |
||||
|
child: MyImage( |
||||
|
image: MyAssets.globe, |
||||
|
fit: BoxFit.cover, |
||||
|
size: setSize(context: context, tablet: 120), |
||||
|
), |
||||
|
), |
||||
|
PositionedDirectional( |
||||
|
end: 0, |
||||
|
child: MyShowcaseWidget( |
||||
|
globalKey: context |
||||
|
.read<GuiderBloc>() |
||||
|
.showCaseKey['hadith_key']!, |
||||
|
type: ShowcaseTooltipType.topLeft, |
||||
|
description: context.translate.showcase_hadith, |
||||
|
child: GlassyButton(image: MyAssets.leaf, onTap: () {}), |
||||
|
), |
||||
|
), |
||||
|
], |
||||
|
), |
||||
|
), |
||||
|
); |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue