Browse Source

Merge pull request 'add: ahadith feature' (#22) from feature/hadis into develop

Reviewed-on: https://git.nwhco.ir/amirreza.chegini/hade_hoda_flutter/pulls/22
pull/24/head
amirreza.chegini 3 weeks ago
parent
commit
6d83c5e60c
  1. 2
      lib/core/routers/my_routes.dart
  2. 16
      lib/core/widgets/hadith_dialog/hadith_dialog.dart
  3. 6
      lib/features/level/data/model/level_model.dart
  4. 4
      lib/features/level/domain/entity/level_entity.dart
  5. 7
      lib/features/level/domain/entity/level_entity.g.dart
  6. 21
      lib/features/question/data/model/hadith_model.dart
  7. 25
      lib/features/question/domain/entity/hadith_entity.dart
  8. 53
      lib/features/question/domain/entity/hadith_entity.g.dart
  9. 21
      lib/features/question/presentation/bloc/question_bloc.dart
  10. 8
      lib/features/question/presentation/bloc/question_event.dart
  11. 2
      lib/features/question/presentation/ui/screens/answer_screen.dart
  12. 4
      lib/features/question/presentation/ui/screens/question_screen.dart
  13. 2
      lib/init_bindings.dart

2
lib/core/routers/my_routes.dart

@ -89,7 +89,7 @@ GoRouter get appPages => GoRouter(
builder: (context, state) => BlocProvider(
create: (context) =>
QuestionBloc(locator(), locator(), locator())
..add(GetLevelEvent(state.pathParameters['id'])),
..add(GetLevelEvent(state.pathParameters['id'], context)),
child: const QuestionPage(),
),
),

16
lib/core/widgets/hadith_dialog/hadith_dialog.dart

@ -9,18 +9,24 @@ import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart';
import 'package:hadi_hoda_flutter/core/utils/check_platform.dart';
import 'package:hadi_hoda_flutter/core/widgets/about_us_dialog/styles/background.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
import 'package:hadi_hoda_flutter/features/question/domain/entity/hadith_entity.dart';
Future<void> showHadithDialog({required BuildContext context}) async {
Future<void> showHadithDialog({
required BuildContext context,
required List<HadithEntity> hadith,
}) async {
await showDialog(
context: context,
builder: (context) => HadithDialog(),
builder: (context) => HadithDialog(hadith: hadith),
barrierColor: MyColors.purple.withValues(alpha: 0.82),
useSafeArea: false,
);
}
class HadithDialog extends StatelessWidget {
const HadithDialog({super.key});
const HadithDialog({super.key, required this.hadith});
final List<HadithEntity> hadith;
@override
Widget build(BuildContext context) {
@ -42,7 +48,7 @@ class HadithDialog extends StatelessWidget {
children: [
AboutUSDialogBackground(
child: ListView.separated(
itemCount: 3,
itemCount: hadith.length,
separatorBuilder: (context, index) => Divider(
height: 40,
thickness: 1,
@ -51,7 +57,7 @@ class HadithDialog extends StatelessWidget {
color: Color(0xFFC2BDE4),
),
itemBuilder: (context, index) => Text(
'Prophet Muhammad (PBUH) said: "Teeth, which are smooth and beautiful, become dirty as a result of chewing food, and gradually the smell of the mouth changes and causes corruption in the nasal organs. When a person brushes her teeth, the corruption disappears and the teeth become clean and pure again."',
hadith[index].hadithText ?? '',
style: Marhey.medium14.copyWith(
color: Color(0XFF494178),
),

6
lib/features/level/data/model/level_model.dart

@ -1,5 +1,7 @@
import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart';
import 'package:hadi_hoda_flutter/features/question/data/model/hadith_model.dart';
import 'package:hadi_hoda_flutter/features/question/data/model/question_model.dart';
import 'package:hadi_hoda_flutter/features/question/domain/entity/hadith_entity.dart';
import 'package:hadi_hoda_flutter/features/question/domain/entity/question_entity.dart';
class LevelModel extends LevelEntity {
@ -8,6 +10,7 @@ class LevelModel extends LevelEntity {
super.order,
super.title,
super.questions,
super.hadith,
});
factory LevelModel.fromJson(Map<String, dynamic> json) {
@ -18,6 +21,9 @@ class LevelModel extends LevelEntity {
questions: json['questions']
?.map<QuestionEntity>((e) => QuestionModel.fromJson(e))
.toList(),
hadith: json['hadiths']
?.map<HadithEntity>((e) => HadithModel.fromJson(e))
.toList(),
);
}
}

4
lib/features/level/domain/entity/level_entity.dart

@ -1,3 +1,4 @@
import 'package:hadi_hoda_flutter/features/question/domain/entity/hadith_entity.dart';
import 'package:hadi_hoda_flutter/features/question/domain/entity/question_entity.dart';
import 'package:hive/hive.dart';
@ -13,11 +14,14 @@ class LevelEntity extends HiveObject {
String? title;
@HiveField(3)
List<QuestionEntity>? questions;
@HiveField(4)
List<HadithEntity>? hadith;
LevelEntity({
this.id,
this.order,
this.title,
this.questions,
this.hadith,
});
}

7
lib/features/level/domain/entity/level_entity.g.dart

@ -21,13 +21,14 @@ class LevelEntityAdapter extends TypeAdapter<LevelEntity> {
order: fields[1] as int?,
title: fields[2] as String?,
questions: (fields[3] as List?)?.cast<QuestionEntity>(),
hadith: (fields[4] as List?)?.cast<HadithEntity>(),
);
}
@override
void write(BinaryWriter writer, LevelEntity obj) {
writer
..writeByte(4)
..writeByte(5)
..writeByte(0)
..write(obj.id)
..writeByte(1)
@ -35,7 +36,9 @@ class LevelEntityAdapter extends TypeAdapter<LevelEntity> {
..writeByte(2)
..write(obj.title)
..writeByte(3)
..write(obj.questions);
..write(obj.questions)
..writeByte(4)
..write(obj.hadith);
}
@override

21
lib/features/question/data/model/hadith_model.dart

@ -0,0 +1,21 @@
import 'package:hadi_hoda_flutter/features/question/domain/entity/hadith_entity.dart';
class HadithModel extends HadithEntity {
HadithModel({
super.id,
super.hadithText,
super.narratorName,
super.translation,
super.status,
});
factory HadithModel.fromJson(Map<String, dynamic> json) {
return HadithModel(
id: json['id'],
hadithText: json['hadith_text'],
narratorName: json['narrator_name'],
translation: json['translation'],
status: json['status'],
);
}
}

25
lib/features/question/domain/entity/hadith_entity.dart

@ -0,0 +1,25 @@
import 'package:hive/hive.dart';
part 'hadith_entity.g.dart';
@HiveType(typeId: 5)
class HadithEntity extends HiveObject {
@HiveField(0)
int? id;
@HiveField(1)
String? hadithText;
@HiveField(2)
String? narratorName;
@HiveField(3)
String? translation;
@HiveField(4)
String? status;
HadithEntity({
this.id,
this.hadithText,
this.narratorName,
this.translation,
this.status,
});
}

53
lib/features/question/domain/entity/hadith_entity.g.dart

@ -0,0 +1,53 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'hadith_entity.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class HadithEntityAdapter extends TypeAdapter<HadithEntity> {
@override
final int typeId = 5;
@override
HadithEntity read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return HadithEntity(
id: fields[0] as int?,
hadithText: fields[1] as String?,
narratorName: fields[2] as String?,
translation: fields[3] as String?,
status: fields[4] as String?,
);
}
@override
void write(BinaryWriter writer, HadithEntity obj) {
writer
..writeByte(5)
..writeByte(0)
..write(obj.id)
..writeByte(1)
..write(obj.hadithText)
..writeByte(2)
..write(obj.narratorName)
..writeByte(3)
..write(obj.translation)
..writeByte(4)
..write(obj.status);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is HadithEntityAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

21
lib/features/question/presentation/bloc/question_bloc.dart

@ -68,7 +68,11 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
}
void showHadith({required BuildContext context}) {
showHadithDialog(context: context);
if(isPlaying) return;
showHadithDialog(
context: context,
hadith: state.levelEntity?.hadith ?? [],
);
}
void goToLevelPage({required BuildContext context}) {
@ -98,13 +102,13 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
);
}
Future<void> playback() async {
Future<void> playback(BuildContext context) async {
if (isPlaying) return;
for (int i = 0; i < 4; i++) {
await Future.delayed(Duration(seconds: 1));
if (ContextProvider.context.mounted) {
if (context.mounted) {
await showAnswerDialog(
context: ContextProvider.context,
context: context,
answerEntity: state.currentQuestion?.answers?[i] ?? AnswerEntity(),
);
isPlaying = true;
@ -123,6 +127,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
id: data.id,
order: data.order,
title: data.title,
hadith: data.hadith,
questions: [
...?data.questions,
QuestionEntity(order: (data.questions?.length ?? 0) + 1)
@ -134,7 +139,9 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
currentQuestion: data.questions?.first,
));
await playVoice();
playback();
if(event.context.mounted){
playback(event.context);
}
},
(error) {
emit(state.copyWith(getQuestionStatus: BaseError(error.errorMessage)));
@ -177,7 +184,9 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
}
} else {
await playVoice();
playback();
if(event.context.mounted){
playback(event.context);
}
}
});
}

8
lib/features/question/presentation/bloc/question_event.dart

@ -1,16 +1,20 @@
import 'package:flutter/cupertino.dart';
sealed class QuestionEvent {
const QuestionEvent();
}
class GetLevelEvent extends QuestionEvent {
final String? id;
const GetLevelEvent(this.id);
final BuildContext context;
const GetLevelEvent(this.id, this.context);
}
class ChooseAnswerEvent extends QuestionEvent {
final bool chooseCorrectAnswer;
final int correctAnswer;
const ChooseAnswerEvent(this.chooseCorrectAnswer, this.correctAnswer);
final BuildContext context;
const ChooseAnswerEvent(this.chooseCorrectAnswer, this.correctAnswer, this.context);
}
class GetNextLevelEvent extends QuestionEvent {

2
lib/features/question/presentation/ui/screens/answer_screen.dart

@ -22,7 +22,7 @@ class _AnswerScreenState extends State<AnswerScreen> {
Future<void> back() async {
await Future.delayed(Duration(seconds: 2), () {
if (ContextProvider.context.mounted) {
if (context.mounted) {
Navigator.pop(ContextProvider.context);
}
});

4
lib/features/question/presentation/ui/screens/question_screen.dart

@ -99,7 +99,7 @@ class QuestionScreen extends StatelessWidget {
correctAnswer: state.currentQuestion?.correctAnswer ?? 0,
onTap: (isCorrect, correctAnswer) =>
context.read<QuestionBloc>().add(
ChooseAnswerEvent(isCorrect, correctAnswer),
ChooseAnswerEvent(isCorrect, correctAnswer, context),
),
),
),
@ -157,7 +157,7 @@ class QuestionScreen extends StatelessWidget {
),
Spacer(),
RefreshButton(
onTap: () => context.read<QuestionBloc>().playback(),
onTap: () => context.read<QuestionBloc>().playback(context),
),
],
);

2
lib/init_bindings.dart

@ -22,6 +22,7 @@ import 'package:hadi_hoda_flutter/features/question/data/datasource/question_dat
import 'package:hadi_hoda_flutter/features/question/data/repository_impl/question_repository_impl.dart';
import 'package:hadi_hoda_flutter/features/question/domain/entity/answer_entity.dart';
import 'package:hadi_hoda_flutter/features/question/domain/entity/file_entity.dart';
import 'package:hadi_hoda_flutter/features/question/domain/entity/hadith_entity.dart';
import 'package:hadi_hoda_flutter/features/question/domain/entity/question_entity.dart';
import 'package:hadi_hoda_flutter/features/question/domain/repository/question_repository.dart';
import 'package:hadi_hoda_flutter/features/question/domain/usecases/get_level_usecase.dart';
@ -78,6 +79,7 @@ Future<void> initDataBase() async {
..registerAdapter<FileEntity>(FileEntityAdapter())
..registerAdapter<AnswerEntity>(AnswerEntityAdapter())
..registerAdapter<QuestionEntity>(QuestionEntityAdapter())
..registerAdapter<HadithEntity>(HadithEntityAdapter())
..registerAdapter<LevelEntity>(LevelEntityAdapter())
..registerAdapter<TotalDataEntity>(TotalDataEntityAdapter());

Loading…
Cancel
Save