Browse Source

Merge pull request 'feature/question' (#7) from feature/question into develop

Reviewed-on: https://git.nwhco.ir/amirreza.chegini/hade_hoda_flutter/pulls/7
pull/10/head
amirreza.chegini 1 week ago
parent
commit
f8b2e11890
  1. 10
      assets/images/bubble_chat_left.svg
  2. 3
      assets/images/bubble_chat_right.svg
  3. 17
      assets/images/correct.svg
  4. BIN
      assets/images/diamond.png
  5. 4
      assets/images/done.svg
  6. 4
      assets/images/hand_point.svg
  7. 3
      assets/images/home.svg
  8. 3
      assets/images/music.svg
  9. BIN
      assets/images/pattern.png
  10. BIN
      assets/images/persons.png
  11. 17
      assets/images/wrong.svg
  12. 11
      lib/common_ui/resources/my_assets.dart
  13. 13
      lib/core/params/question_params.dart
  14. 11
      lib/core/routers/my_routes.dart
  15. 4
      lib/core/widgets/answer_box/answer_box.dart
  16. 84
      lib/core/widgets/answer_box/styles/picture_box.dart
  17. 48
      lib/core/widgets/answer_box/styles/text_box.dart
  18. 50
      lib/core/widgets/showcase/question_showcase.dart
  19. 5
      lib/features/intro/presentation/ui/intro_page.dart
  20. 28
      lib/features/question/data/datasource/question_datasource.dart
  21. 13
      lib/features/question/data/model/question_model.dart
  22. 29
      lib/features/question/data/repository_impl/question_repository_impl.dart
  23. 14
      lib/features/question/domain/entity/question_entity.dart
  24. 8
      lib/features/question/domain/repository/question_repository.dart
  25. 17
      lib/features/question/domain/usecases/get_question_usecase.dart
  26. 52
      lib/features/question/presentation/bloc/question_bloc.dart
  27. 5
      lib/features/question/presentation/bloc/question_event.dart
  28. 15
      lib/features/question/presentation/bloc/question_state.dart
  29. 178
      lib/features/question/presentation/ui/question_page.dart
  30. 41
      lib/features/question/presentation/ui/widgets/glassy_button.dart
  31. 27
      lib/features/question/presentation/ui/widgets/left_blob.dart
  32. 102
      lib/features/question/presentation/ui/widgets/question_stepper.dart
  33. 32
      lib/features/question/presentation/ui/widgets/refresh_button.dart
  34. 27
      lib/features/question/presentation/ui/widgets/right_blob.dart
  35. 9
      lib/init_bindings.dart
  36. 3
      lib/l10n/app_en.arb
  37. 6
      lib/l10n/app_localizations.dart
  38. 3
      lib/l10n/app_localizations_en.dart
  39. 42
      pubspec.lock
  40. 2
      pubspec.yaml

10
assets/images/bubble_chat_left.svg

@ -0,0 +1,10 @@
<svg width="99" height="74" viewBox="0 0 99 74" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_6_220)">
<path d="M49.4006 68.5179C22.3902 68.5179 0.490861 54.2312 0.490861 36.6075C0.490861 18.9839 22.3902 4.6972 49.4006 4.6972C76.411 4.6972 98.3103 18.9839 98.3103 36.6075C98.3103 44.6307 93.7678 51.9701 86.2663 57.5772C86.8593 62.2087 88.8157 67.287 90.9799 71.098C91.4629 71.9459 90.5275 72.8941 89.3109 72.7483C75.5184 71.0616 73.7515 67.7951 70.1872 66.4457C65.5055 67.3801 54.2471 68.5263 49.4006 68.5179Z" fill="#2F2487"/>
</g>
<defs>
<clipPath id="clip0_6_220">
<rect width="97.8194" height="72.957" fill="white" transform="matrix(-1 0 0 1 98.3102 0.213867)"/>
</clipPath>
</defs>
</svg>

3
assets/images/bubble_chat_right.svg

@ -0,0 +1,3 @@
<svg width="98" height="69" viewBox="0 0 98 69" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M48.9351 63.8829C75.9455 63.8829 97.8448 49.5961 97.8448 31.9725C97.8448 14.3489 75.9455 0.0621948 48.9351 0.0621948C21.9247 0.0621948 0.0253601 14.3489 0.0253601 31.9725C0.0253601 39.9957 4.56785 47.3351 12.0694 52.9422C11.4763 57.5737 9.51996 62.652 7.3557 66.463C6.87272 67.3109 7.80812 68.2591 9.02475 68.1132C22.8173 66.4266 24.5841 63.1601 28.1484 61.8107C32.8302 62.745 44.0886 63.8913 48.9351 63.8829Z" fill="#2F2487"/>
</svg>

17
assets/images/correct.svg

@ -0,0 +1,17 @@
<svg width="56" height="51" viewBox="0 0 56 51" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M51.9315 40.1706C50.273 47.4826 8.41234 52.8752 4.94604 45.3438C1.79486 38.5071 4.18298 10.6119 6.86977 5.71281C10.5517 -0.941101 46.6743 3.73857 49.7259 8.96665C52.4625 13.8474 53.6729 32.6758 51.9315 40.1706Z" fill="url(#paint0_radial_498_2733)"/>
<path d="M51.8976 38.6412C50.2314 45.5766 8.42476 49.5346 4.95895 42.2723C1.80973 35.7181 4.1427 10.6451 6.84203 5.96088C10.5245 -0.411776 46.8321 4.14531 49.7314 9.08366C52.564 13.7678 53.6472 31.4697 51.8976 38.6412Z" fill="#83FF9A"/>
<path d="M51.1313 38.0099C49.4846 44.7332 9.07525 48.6218 5.71605 41.6441C2.66971 35.2661 4.95877 10.7532 7.5605 6.28314C11.1173 0.104962 46.1418 4.46602 49.0235 9.31771C51.7076 13.8423 52.8109 31.1049 51.1313 38.0099Z" fill="url(#paint1_linear_498_2733)"/>
<path d="M42.7617 10.3223L45.8039 13.8678C45.8039 13.8678 39.6579 27.7548 27.4283 35.2666L24.021 31.7743C29.745 23.0196 34.8523 18.2151 42.7617 10.3223Z" fill="white"/>
<path d="M14.4469 22.8692L18.1136 19.4287C18.1136 19.4287 23.6853 22.6213 30.7432 32.8774L27.3564 35.4214C18.7247 29.3454 19.7432 29.9525 14.4469 22.8692Z" fill="white"/>
<defs>
<radialGradient id="paint0_radial_498_2733" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(43.704 56.9891) rotate(180) scale(23.8475 33.2277)">
<stop stop-color="#83FF87"/>
<stop offset="1" stop-color="#33E04D"/>
</radialGradient>
<linearGradient id="paint1_linear_498_2733" x1="28.0944" y1="45.3329" x2="28.0944" y2="3.21222" gradientUnits="userSpaceOnUse">
<stop stop-color="#21B738"/>
<stop offset="1" stop-color="#31C747"/>
</linearGradient>
</defs>
</svg>

BIN
assets/images/diamond.png

After

Width: 46  |  Height: 38  |  Size: 2.6 KiB

4
assets/images/done.svg

@ -0,0 +1,4 @@
<svg width="13" height="11" viewBox="0 0 13 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.558 0.348633L12.7359 1.73042C12.7359 1.73042 10.3562 7.14247 5.62103 10.07L4.30176 8.70894C6.51804 5.29707 8.49556 3.42465 11.558 0.348633Z" fill="white"/>
<path d="M0.594727 5.23829L2.01443 3.89746C2.01443 3.89746 4.17176 5.14167 6.90451 9.1387L5.59316 10.1301C2.25105 7.7622 2.64541 7.99882 0.594727 5.23829Z" fill="white"/>
</svg>

4
assets/images/hand_point.svg

@ -0,0 +1,4 @@
<svg width="71" height="71" viewBox="0 0 71 71" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M29.1965 4.74414C25.7116 4.7482 22.3706 6.13436 19.9064 8.59855C17.4422 11.0627 16.0561 14.4037 16.052 17.8886H20.4335C20.4335 15.5645 21.3567 13.3356 23.0001 11.6923C24.6435 10.0489 26.8724 9.12564 29.1965 9.12564C31.5206 9.12564 33.7495 10.0489 35.3929 11.6923C37.0362 13.3356 37.9595 15.5645 37.9595 17.8886H42.341C42.3369 14.4037 40.9507 11.0627 38.4866 8.59855C36.0224 6.13436 32.6814 4.7482 29.1965 4.74414Z" fill="white"/>
<path d="M46.7231 66.0848H36.9962C34.7982 66.0842 32.6808 65.2577 31.0636 63.7692L10.9088 45.2223C10.4382 44.7921 10.0671 44.2645 9.82125 43.6762C9.57543 43.0879 9.46084 42.4531 9.48545 41.816C9.51005 41.1788 9.67328 40.5548 9.96374 39.9872C10.2542 39.4196 10.6649 38.9222 11.1673 38.5296C12.0279 37.899 13.083 37.5914 14.1477 37.6607C15.2123 37.73 16.2186 38.1718 16.9903 38.9086L24.8156 46.0548V17.8883C24.8156 16.7263 25.2773 15.6118 26.0989 14.7901C26.9206 13.9685 28.0351 13.5068 29.1971 13.5068C30.3592 13.5068 31.4736 13.9685 32.2953 14.7901C33.117 15.6118 33.5786 16.7263 33.5786 17.8883V33.2236C33.5786 32.0615 34.0402 30.9471 34.8619 30.1254C35.6836 29.3037 36.7981 28.8421 37.9601 28.8421C39.1222 28.8421 40.2366 29.3037 41.0583 30.1254C41.88 30.9471 42.3416 32.0615 42.3416 33.2236V35.4143C42.3416 34.2523 42.8032 33.1378 43.6249 32.3161C44.4466 31.4944 45.5611 31.0328 46.7231 31.0328C47.8852 31.0328 48.9996 31.4944 49.8213 32.3161C50.643 33.1378 51.1046 34.2523 51.1046 35.4143V37.6051C51.1046 36.443 51.5662 35.3286 52.3879 34.5069C53.2096 33.6852 54.3241 33.2236 55.4861 33.2236C56.6481 33.2236 57.7626 33.6852 58.5843 34.5069C59.406 35.3286 59.8676 36.443 59.8676 37.6051V52.9403C59.8676 56.4264 58.4827 59.7698 56.0177 62.2348C53.5526 64.6999 50.2092 66.0848 46.7231 66.0848Z" fill="white"/>
</svg>

3
assets/images/home.svg

@ -0,0 +1,3 @@
<svg width="21" height="22" viewBox="0 0 21 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20.2727 11.7991L17.6334 12.2735L16.3568 21.4979H13.1477C13.0442 19.4422 12.5783 14.2765 10.4907 14.4698C8.40321 14.6631 8.07547 19.0556 7.9547 21.4979H5.03916C4.20655 18.4616 3.53248 15.3825 3.02035 12.2735H0.708801C0.708801 12.2735 6.83342 0.571633 9.80082 0.308078C12.7682 0.0445223 20.2727 11.7991 20.2727 11.7991Z" fill="#E4E3F7"/>
</svg>

3
assets/images/music.svg

@ -0,0 +1,3 @@
<svg width="22" height="20" viewBox="0 0 22 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.6667 2.04697V14.4808C21.6649 15.4104 21.3367 16.3119 20.7357 17.0376C20.1347 17.7634 19.2966 18.2703 18.3587 18.4755C17.4208 18.6806 16.4386 18.5718 15.573 18.1669C14.7074 17.7619 14.0096 17.0849 13.594 16.2465C13.1784 15.4082 13.0696 14.4583 13.2854 13.5523C13.5012 12.6464 14.0288 11.8381 14.7817 11.2599C15.5347 10.6817 16.4685 10.3677 17.4301 10.3695C18.3918 10.3713 19.3243 10.6887 20.0749 11.2697V7.16617L8.9642 9.11536V15.5785C8.9642 16.3901 8.71525 17.1835 8.24882 17.8583C7.7824 18.5331 7.11945 19.0591 6.34382 19.3697C5.56818 19.6803 4.7147 19.7615 3.89129 19.6032C3.06788 19.4449 2.31153 19.054 1.71788 18.4801C1.12424 17.9062 0.71996 17.1751 0.556174 16.379C0.392388 15.583 0.476449 14.7579 0.797727 14.0081C1.11901 13.2583 1.66307 12.6174 2.36112 12.1665C3.05918 11.7156 3.87986 11.4749 4.7194 11.4749C5.69402 11.4768 6.6383 11.8028 7.39363 12.3982V4.79636C7.38186 4.08709 7.62995 3.39665 8.09402 2.84717C8.56943 2.31042 9.22143 1.94818 9.9405 1.82128L19.3852 0.149074C19.8126 0.0731542 20.254 0.138029 20.6388 0.333319C21.0236 0.528608 21.3295 0.843024 21.5076 1.22626C21.6254 1.48376 21.6805 1.76485 21.6667 2.04697Z" fill="#E4E3F7"/>
</svg>

BIN
assets/images/pattern.png

After

Width: 412  |  Height: 412  |  Size: 3.1 KiB

BIN
assets/images/persons.png

After

Width: 108  |  Height: 94  |  Size: 24 KiB

17
assets/images/wrong.svg

@ -0,0 +1,17 @@
<svg width="56" height="51" viewBox="0 0 56 51" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M51.931 40.1706C50.2725 47.4826 8.41185 52.8752 4.94555 45.3438C1.79438 38.5071 4.18249 10.6118 6.86929 5.71281C10.5512 -0.9411 46.6738 3.73857 49.7254 8.96665C52.462 13.8474 53.6724 32.6758 51.931 40.1706Z" fill="url(#paint0_radial_498_2741)"/>
<path d="M51.8971 38.6402C50.2309 45.5757 8.42427 49.5336 4.95847 42.2713C1.80925 35.7171 4.14221 10.6441 6.84155 5.9599C10.524 -0.412752 46.8316 4.14433 49.7309 9.08268C52.5635 13.7669 53.6467 31.4687 51.8971 38.6402Z" fill="#FF8385"/>
<path d="M51.1308 38.0099C49.4841 44.7332 9.07476 48.6218 5.71555 41.6441C2.66922 35.2661 4.95828 10.7532 7.56002 6.28314C11.1168 0.104962 46.1414 4.46602 49.023 9.31771C51.7071 13.8423 52.8104 31.1049 51.1308 38.0099Z" fill="url(#paint1_linear_498_2741)"/>
<path d="M36.615 10.8369L39.6572 14.3825C39.6572 14.3825 30.2869 29.6865 18.0573 37.1983L15.5018 33.853C21.2258 25.0984 28.3573 17.3243 36.615 10.8369Z" fill="white"/>
<path d="M15.6688 15.9368L19.2587 12.9521C19.2587 12.9521 35.3009 24.0095 42.3588 34.2656L38.972 36.8096C30.1099 31.1458 22.2395 24.0962 15.6688 15.9368Z" fill="white"/>
<defs>
<radialGradient id="paint0_radial_498_2741" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(43.7035 56.9891) rotate(180) scale(23.8475 33.2277)">
<stop stop-color="#FF8385"/>
<stop offset="1" stop-color="#E03336"/>
</radialGradient>
<linearGradient id="paint1_linear_498_2741" x1="28.0939" y1="45.3328" x2="28.0939" y2="3.21222" gradientUnits="userSpaceOnUse">
<stop stop-color="#C72427"/>
<stop offset="1" stop-color="#E03336"/>
</linearGradient>
</defs>
</svg>

11
lib/common_ui/resources/my_assets.dart

@ -17,4 +17,15 @@ 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/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';
static const String bubbleChatLeft = 'assets/images/bubble_chat_left.svg';
static const String bubbleChatRight = 'assets/images/bubble_chat_right.svg';
static const String diamond = 'assets/images/diamond.png';
static const String done = 'assets/images/done.svg';
static const String correct = 'assets/images/correct.svg';
static const String wrong = 'assets/images/wrong.svg';
static const String handPoint = 'assets/images/hand_point.svg';
}

13
lib/core/params/question_params.dart

@ -0,0 +1,13 @@
class QuestionParams {
int? id;
QuestionParams({this.id});
QuestionParams copyWith({
int? id,
}) {
return QuestionParams(
id: id ?? this.id,
);
}
}

11
lib/core/routers/my_routes.dart

@ -3,6 +3,8 @@ import 'package:go_router/go_router.dart';
import 'package:hadi_hoda_flutter/core/utils/context_provider.dart';
import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_bloc.dart';
import 'package:hadi_hoda_flutter/features/intro/presentation/ui/intro_page.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/bloc/question_bloc.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/ui/question_page.dart';
import 'package:hadi_hoda_flutter/init_bindings.dart';
class Routes {
@ -11,6 +13,7 @@ class Routes {
factory Routes() => _i;
static const String introPage = '/intro_page';
static const String questionPage = '/question_page';
}
GoRouter get appPages => GoRouter(
@ -25,5 +28,13 @@ GoRouter get appPages => GoRouter(
child: const IntroPage(),
),
),
GoRoute(
name: Routes.questionPage,
path: Routes.questionPage,
builder: (context, state) => BlocProvider(
create: (context) => QuestionBloc(locator()),
child: const QuestionPage(),
),
),
],
);

4
lib/core/widgets/answer_box/answer_box.dart

@ -22,7 +22,6 @@ class _AnswerBoxState extends State<AnswerBox> {
});
},
child: SizedBox(
width: 170,
child: Stack(
alignment: Alignment.bottomCenter,
clipBehavior: Clip.none,
@ -34,11 +33,8 @@ class _AnswerBoxState extends State<AnswerBox> {
left: 0,
right: 0,
bottom: -36,
child: SizedBox(
height: 60,
child: AnswerTextBox(),
),
),
],
),
),

84
lib/core/widgets/answer_box/styles/picture_box.dart

@ -1,5 +1,8 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.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/common_ui/theme/my_theme.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
class AnswerPictureBox extends StatelessWidget {
@ -14,8 +17,53 @@ class AnswerPictureBox extends StatelessWidget {
foregroundPainter: _SvgCustomPainter(selected),
child: ClipPath(
clipper: _SvgCustomClipper(),
child: Stack(
children: [
MyImage(
image: MyAssets.backgroundIntro,
fit: BoxFit.cover,
size: 170,
),
PositionedDirectional(
top: MySpaces.s12,
start: MySpaces.s12,
child: ClipPath(
clipper: _CountClipper(),
child: Container(
height: MySpaces.s32,
width: MySpaces.s32,
alignment: Alignment.center,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0XFF5732CB),
Color(0XFF322386),
],
),
),
child: Text(
'1',
style: GoogleFonts.marhey(
fontSize: 17,
fontWeight: FontWeight.w600,
color: context.primaryColor,
),
),
),
),
),
PositionedDirectional(
top: MySpaces.s14,
end: MySpaces.s12,
child: MyImage(
image: MyAssets.backgroundIntro, fit: BoxFit.cover, size: 170),
image: MyAssets.correct,
size: MySpaces.s40,
),
),
],
),
),
);
}
@ -125,3 +173,37 @@ class _SvgCustomPainter extends CustomPainter {
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
class _CountClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
// Original SVG viewBox: width=34, height=33
final sx = size.width / 34.0;
final sy = size.height / 33.0;
final p = Path()
..moveTo(33.3479 * sx, 14.8127 * sy)
..cubicTo(
33.3479 * sx, 23.7042 * sy,
27.2015 * sx, 32.9501 * sy,
17.8599 * sx, 32.9501 * sy,
)..cubicTo(
8.51818 * sx, 32.9501 * sy,
0.945251 * sx, 25.7421 * sy,
0.945251 * sx, 16.8507 * sy,
)..cubicTo(
0.945251 * sx, 7.95917 * sy,
8.51818 * sx, 0.751205 * sy,
17.8599 * sx, 0.751205 * sy,
)..cubicTo(
27.2015 * sx, 0.751205 * sy,
33.3479 * sx, 5.92127 * sy,
33.3479 * sx, 14.8127 * sy,
)..close();
return p;
}
@override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}

48
lib/core/widgets/answer_box/styles/text_box.dart

@ -1,39 +1,43 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart';
class AnswerTextBox extends StatelessWidget {
const AnswerTextBox({super.key});
@override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 480 / 149.0,
child: Stack(
alignment: Alignment.center,
children: [
Positioned.fill(
child: CustomPaint(
painter: _WavyBannerPainter(),
return ClipPath(
clipper: _WavyBannerClipper(),
child: Container(
padding: EdgeInsets.all(MySpaces.s10),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0XFFFFFFFF),
Color(0XFFCADCFF),
],
),
),
Text(
child: Text(
'We walk in the yard with a glass of juice ',
textAlign: TextAlign.center,
style: GoogleFonts.marhey(
fontSize: 12,
fontWeight: FontWeight.w600,
fontSize: 14,
fontWeight: FontWeight.w700,
color: Color(0XFF322386)
),
)
],
),
),
);
}
}
class _WavyBannerPainter extends CustomPainter {
class _WavyBannerClipper extends CustomClipper<Path> {
@override
void paint(Canvas canvas, Size size) {
Path getClip(Size size) {
final sx = size.width / 480.0;
final sy = size.height / 149.0;
@ -44,19 +48,9 @@ class _WavyBannerPainter extends CustomPainter {
..cubicTo(488.753 * sx, 118.634 * sy, 483.484 * sx, 26.7097 * sy, 459.365 * sx, 10.3813 * sy)
..cubicTo(435.246 * sx, -5.94701 * sy, 41.0302 * sx, -3.23423 * sy, 14.0623 * sx, 20.0845 * sy)
..close();
final paint = Paint()
..style = PaintingStyle.fill
..isAntiAlias = true
..shader = const LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [Color(0xFFCADCFF), Colors.white],
).createShader(Offset.zero & size);
canvas.drawPath(path, paint);
return path;
}
@override
bool shouldRepaint(covariant _WavyBannerPainter oldDelegate) => false;
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}

50
lib/core/widgets/showcase/question_showcase.dart

@ -0,0 +1,50 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.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/core/utils/screen_size.dart';
import 'package:showcaseview/showcaseview.dart';
class QuestionShowcase extends StatelessWidget {
const QuestionShowcase({
super.key,
required this.globalKey,
required this.child,
this.description,
});
final GlobalKey globalKey;
final String? description;
final Widget child;
@override
Widget build(BuildContext context) {
return Showcase(
key: globalKey,
blurValue: 10,
targetShapeBorder: CircleBorder(),
tooltipBackgroundColor: Colors.transparent,
disableMovingAnimation: true,
textColor: context.primaryColor,
descriptionTextAlign: TextAlign.center,
descTextStyle: GoogleFonts.marhey(
fontSize: 12,
fontWeight: FontWeight.w700,
color: context.primaryColor,
),
disableScaleAnimation: true,
tooltipPadding: EdgeInsets.only(top: 60),
floatingActionWidget: FloatingActionWidget(
height: 60,
width: 60,
right: context.widthScreen * 0.17,
top: context.widthScreen * 1.17,
child: MyImage(image: MyAssets.handPoint),
),
overlayColor: Color(0XFF0F0041),
description: description ?? '',
child: child,
);
}
}

5
lib/features/intro/presentation/ui/intro_page.dart

@ -1,10 +1,11 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart';
import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart';
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart';
import 'package:hadi_hoda_flutter/core/utils/check_platform.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/about_us_dialog/about_us_dialog.dart';
class IntroPage extends StatelessWidget {
const IntroPage({super.key});
@ -79,7 +80,7 @@ class IntroPage extends StatelessWidget {
size: checkSize(context: context, mobile: 90, tablet: 160),
),
onTap: () {
showAboutUsDialog(context: context);
context.goNamed(Routes.questionPage);
},
),
MyImage(

28
lib/features/question/data/datasource/question_datasource.dart

@ -0,0 +1,28 @@
import 'package:hadi_hoda_flutter/core/constants/my_api.dart';
import 'package:hadi_hoda_flutter/core/network/http_request.dart';
import 'package:hadi_hoda_flutter/core/params/question_params.dart';
import 'package:hadi_hoda_flutter/core/response/base_response.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';
abstract class IQuestionDatasource {
Future<QuestionEntity> getData({required QuestionParams params});
}
class QuestionDatasourceImpl implements IQuestionDatasource {
final IHttpRequest httpRequest;
const QuestionDatasourceImpl(this.httpRequest);
@override
Future<QuestionEntity> getData({required QuestionParams params}) async {
final response = await httpRequest.get(
path: MyApi.baseUrl,
);
return BaseResponse.getData<QuestionEntity>(
response?['data'],
(json) => QuestionModel.fromJson(json),
);
}
}

13
lib/features/question/data/model/question_model.dart

@ -0,0 +1,13 @@
import 'package:hadi_hoda_flutter/features/question/domain/entity/question_entity.dart';
class QuestionModel extends QuestionEntity {
const QuestionModel({
super.id,
});
factory QuestionModel.fromJson(Map<String, dynamic> json) {
return QuestionModel(
id: json['id'],
);
}
}

29
lib/features/question/data/repository_impl/question_repository_impl.dart

@ -0,0 +1,29 @@
import 'package:hadi_hoda_flutter/core/params/question_params.dart';
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/question/data/datasource/question_datasource.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';
class QuestionRepositoryImpl implements IQuestionRepository {
final IQuestionDatasource datasource;
const QuestionRepositoryImpl(this.datasource);
@override
Future<DataState<QuestionEntity, MyException>> getData({required QuestionParams params}) async {
try {
final QuestionEntity response = await datasource.getData(params: params);
return DataState.success(response);
} on MyException catch (e) {
return DataState.error(e);
} catch (e) {
if (kDebugMode) {
rethrow;
} else {
return DataState.error(MyException(errorMessage: '$e'));
}
}
}
}

14
lib/features/question/domain/entity/question_entity.dart

@ -0,0 +1,14 @@
import 'package:equatable/equatable.dart';
class QuestionEntity extends Equatable {
final int? id;
const QuestionEntity({
this.id,
});
@override
List<Object?> get props => [
id,
];
}

8
lib/features/question/domain/repository/question_repository.dart

@ -0,0 +1,8 @@
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart';
import 'package:hadi_hoda_flutter/core/params/question_params.dart';
import 'package:hadi_hoda_flutter/core/utils/data_state.dart';
import 'package:hadi_hoda_flutter/features/question/domain/entity/question_entity.dart';
abstract class IQuestionRepository {
Future<DataState<QuestionEntity, MyException>> getData({required QuestionParams params});
}

17
lib/features/question/domain/usecases/get_question_usecase.dart

@ -0,0 +1,17 @@
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart';
import 'package:hadi_hoda_flutter/core/params/question_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/question/domain/entity/question_entity.dart';
import 'package:hadi_hoda_flutter/features/question/domain/repository/question_repository.dart';
class GetQuestionUseCase implements UseCase<QuestionEntity, QuestionParams> {
final IQuestionRepository repository;
const GetQuestionUseCase(this.repository);
@override
Future<DataState<QuestionEntity, MyException>> call(QuestionParams params) {
return repository.getData(params: params);
}
}

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

@ -0,0 +1,52 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter/cupertino.dart';
import 'package:hadi_hoda_flutter/core/status/base_status.dart';
import 'package:hadi_hoda_flutter/features/question/domain/entity/question_entity.dart';
import 'package:hadi_hoda_flutter/features/question/domain/usecases/get_question_usecase.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/bloc/question_event.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/bloc/question_state.dart';
import 'package:showcaseview/showcaseview.dart';
class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
/// ------------constructor------------
QuestionBloc(
this._getQuestionUseCase,
) : super(const QuestionState()) {
on<GetQuestionEvent>(_getQuestionEvent);
}
/// ------------UseCases------------
final GetQuestionUseCase _getQuestionUseCase;
/// ------------Variables------------
final List<GlobalKey> keys = [
GlobalKey(),
GlobalKey(),
GlobalKey(),
GlobalKey(),
];
/// ------------Controllers------------
/// ------------Functions------------
void startShowCase({required BuildContext context}) {
ShowCaseWidget.of(context).startShowCase([keys[1]]);
}
/// ------------Api Calls------------
FutureOr<void> _getQuestionEvent(event, emit) async {
await _getQuestionUseCase(event.questionParams).then(
(value) {
value.fold(
(data) {
emit(state.copyWith(getQuestionStatus: BaseComplete<QuestionEntity>(data)));
},
(error) {
emit(state.copyWith(getQuestionStatus: BaseError(error.errorMessage)));
},
);
},
);
}
}

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

@ -0,0 +1,5 @@
sealed class QuestionEvent {
const QuestionEvent();
}
class GetQuestionEvent extends QuestionEvent {}

15
lib/features/question/presentation/bloc/question_state.dart

@ -0,0 +1,15 @@
import 'package:hadi_hoda_flutter/core/status/base_status.dart';
class QuestionState {
final BaseStatus getQuestionStatus;
const QuestionState({this.getQuestionStatus = const BaseInit()});
QuestionState copyWith({
BaseStatus? getQuestionStatus,
}) {
return QuestionState(
getQuestionStatus: getQuestionStatus ?? this.getQuestionStatus,
);
}
}

178
lib/features/question/presentation/ui/question_page.dart

@ -0,0 +1,178 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:google_fonts/google_fonts.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/gap.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.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/widgets/answer_box/answer_box.dart';
import 'package:hadi_hoda_flutter/core/widgets/showcase/question_showcase.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/bloc/question_bloc.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/ui/widgets/glassy_button.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/ui/widgets/left_blob.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/ui/widgets/question_stepper.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/ui/widgets/refresh_button.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/ui/widgets/right_blob.dart';
import 'package:showcaseview/showcaseview.dart';
class QuestionPage extends StatelessWidget {
const QuestionPage({super.key});
@override
Widget build(BuildContext context) {
return ShowCaseWidget(
builder: (context) {
return Scaffold(
body: Container(
height: context.heightScreen,
width: context.widthScreen,
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: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: MySpaces.s16),
child: Column(
children: [
MySpaces.s4.gapHeight,
_topButtons(),
MySpaces.s10.gapHeight,
QuestionStepper(),
_titles(),
MySpaces.s14.gapHeight,
_questions(),
_bottomDetail(context),
],
),
),
),
),
);
},
);
}
Widget _topButtons() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GlassyButton(image: MyAssets.home, onTap: () {}),
Text(
'Toothbrushing etiquette',
style: GoogleFonts.marhey(
fontSize: 14,
fontWeight: FontWeight.w700,
color: Colors.white,
),
),
GlassyButton(image: MyAssets.music, onTap: () {}),
],
);
}
Column _titles() {
return Column(
spacing: MySpaces.s4,
children: [
Text(
'Question 1 / 5',
style: GoogleFonts.marhey(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.white.withValues(alpha: 0.5),
shadows: [
Shadow(
offset: Offset(0, 1),
blurRadius: 1,
color: Color(0xFF000000).withValues(alpha: 0.25),
),
],
),
),
Text(
'Heda wants her teeth to be clean. Which of her actions do you think is correct?',
textAlign: TextAlign.center,
style: GoogleFonts.marhey(
fontSize: 22,
fontWeight: FontWeight.w600,
color: Colors.white,
shadows: [
Shadow(
offset: Offset(0, 1),
blurRadius: 1,
color: Color(0xFF000000).withValues(alpha: 0.25),
),
],
),
),
],
);
}
Expanded _questions() {
return Expanded(
child: GridView.builder(
itemCount: 4,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: MySpaces.s20,
mainAxisSpacing: 50,
),
itemBuilder: (context, index) => QuestionShowcase(
globalKey: context.read<QuestionBloc>().keys[index],
description: context.translate.tap_to_select,
child: AnswerBox(),
),
),
);
}
Widget _bottomDetail(BuildContext context) {
return SizedBox(
width: context.widthScreen,
child: Stack(
clipBehavior: Clip.none,
alignment: Alignment.center,
children: [
PositionedDirectional(
start: 0,
top: -10,
child: LeftBlob(),
),
Padding(
padding: const EdgeInsetsDirectional.only(end: 60),
child: MyImage(image: MyAssets.persons),
),
PositionedDirectional(
start: 210,
top: -20,
child: RightBlob(),
),
PositionedDirectional(
end: 0,
bottom: 10,
child: RefreshButton(
onTap: () {},
),
),
],
),
);
}
}

41
lib/features/question/presentation/ui/widgets/glassy_button.dart

@ -0,0 +1,41 @@
import 'package:flutter/material.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
class GlassyButton extends StatelessWidget {
const GlassyButton({super.key, required this.image, this.onTap});
final String image;
final VoidCallback? onTap;
@override
Widget build(BuildContext context) {
return Material(
color: Colors.transparent,
child: Ink(
width: 48,
height: 48,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.white.withValues(alpha: 0.3),
Color(0XFF6930DA).withValues(alpha: 0.1),
],
),
border: Border.all(color: Colors.white.withValues(alpha: 0.3)),
),
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.all(Radius.circular(100)),
child: Padding(
padding: const EdgeInsets.all(MySpaces.s12),
child: MyImage(image: image),
),
),
),
);
}
}

27
lib/features/question/presentation/ui/widgets/left_blob.dart

@ -0,0 +1,27 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
class LeftBlob extends StatelessWidget {
const LeftBlob({super.key});
@override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.center,
children: [
MyImage(image: MyAssets.bubbleChatLeft),
Text(
'Your answer\nwas not correct.',
textAlign: TextAlign.center,
style: GoogleFonts.marhey(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Color(0XFFB5AEEE),
),
),
],
);
}
}

102
lib/features/question/presentation/ui/widgets/question_stepper.dart

@ -0,0 +1,102 @@
import 'package:easy_stepper/easy_stepper.dart';
import 'package:flutter/material.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
class QuestionStepper extends StatelessWidget {
const QuestionStepper({super.key});
@override
Widget build(BuildContext context) {
return SizedBox(
height: 80,
child: EasyStepper(
activeStep: 1,
lineStyle: LineStyle(
lineLength: 20,
lineType: LineType.normal,
defaultLineColor: Color(0XFFDFDDF6),
lineThickness: 5,
finishedLineColor: Color(0XFF21B738),
),
activeStepBackgroundColor: Colors.transparent,
finishedStepBackgroundColor: Colors.transparent,
unreachedStepBackgroundColor: Colors.transparent,
internalPadding: 0,
showLoadingAnimation: false,
stepRadius: 18,
showStepBorder: false,
padding: EdgeInsets.all(0),
enableStepTapping: false,
steps: List.generate(
6,
(index) => EasyStep(
customStep: index == 5
? MyImage(image: MyAssets.diamond, size: 50)
: ClipPath(
clipper: _StepperClipper(),
child: Container(
height: 32,
width: 32,
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: Color(0XFFDFDDF6),
shape: BoxShape.circle,
),
child: ClipPath(
clipper: _StepperClipper(),
child: Container(
padding: EdgeInsets.all(6),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: index < 1
? Color(0XFF21B738)
: index == 1
? Color(0XFF847AC4)
: Colors.transparent,
),
child: index < 1 ? MyImage(image: MyAssets.done) : null,
),
),
),
),
),
),
),
);
}
}
class _StepperClipper extends CustomClipper<Path> {
@override
Path getClip(Size size) {
// Original SVG viewBox: width=34, height=33
final sx = size.width / 34.0;
final sy = size.height / 33.0;
final p = Path()
..moveTo(33.3479 * sx, 14.8127 * sy)
..cubicTo(
33.3479 * sx, 23.7042 * sy,
27.2015 * sx, 32.9501 * sy,
17.8599 * sx, 32.9501 * sy,
)..cubicTo(
8.51818 * sx, 32.9501 * sy,
0.945251 * sx, 25.7421 * sy,
0.945251 * sx, 16.8507 * sy,
)..cubicTo(
0.945251 * sx, 7.95917 * sy,
8.51818 * sx, 0.751205 * sy,
17.8599 * sx, 0.751205 * sy,
)..cubicTo(
27.2015 * sx, 0.751205 * sy,
33.3479 * sx, 5.92127 * sy,
33.3479 * sx, 14.8127 * sy,
)..close();
return p;
}
@override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}

32
lib/features/question/presentation/ui/widgets/refresh_button.dart

@ -0,0 +1,32 @@
import 'package:flutter/material.dart';
import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart';
class RefreshButton extends StatelessWidget {
const RefreshButton({super.key, this.onTap,});
final VoidCallback? onTap;
@override
Widget build(BuildContext context) {
return Material(
color: context.noColor,
child: Ink(
height: 48,
width: 48,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0XFFA393FF), Color(0XFFC6BCFB)],
),
),
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.all(Radius.circular(100)),
child: Icon(Icons.refresh, size: 40, color: Color(0XFF263AA1)),
),
),
);
}
}

27
lib/features/question/presentation/ui/widgets/right_blob.dart

@ -0,0 +1,27 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
class RightBlob extends StatelessWidget {
const RightBlob({super.key});
@override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.center,
children: [
MyImage(image: MyAssets.bubbleChatRight),
Text(
'Be more\ncareful.',
textAlign: TextAlign.center,
style: GoogleFonts.marhey(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Color(0XFFB5AEEE),
),
),
],
);
}
}

9
lib/init_bindings.dart

@ -4,6 +4,10 @@ import 'package:hadi_hoda_flutter/features/intro/data/datasource/intro_datasourc
import 'package:hadi_hoda_flutter/features/intro/data/repository_impl/intro_repository_impl.dart';
import 'package:hadi_hoda_flutter/features/intro/domain/repository/intro_repository.dart';
import 'package:hadi_hoda_flutter/features/intro/domain/usecases/get_intro_usecase.dart';
import 'package:hadi_hoda_flutter/features/question/data/datasource/question_datasource.dart';
import 'package:hadi_hoda_flutter/features/question/data/repository_impl/question_repository_impl.dart';
import 'package:hadi_hoda_flutter/features/question/domain/repository/question_repository.dart';
import 'package:hadi_hoda_flutter/features/question/domain/usecases/get_question_usecase.dart';
import 'package:hadi_hoda_flutter/features/sample/data/datasource/sample_datasource.dart';
import 'package:hadi_hoda_flutter/features/sample/data/repository_impl/sample_repository_impl.dart';
import 'package:hadi_hoda_flutter/features/sample/domain/repository/sample_repository.dart';
@ -25,4 +29,9 @@ void initBindings() {
locator.registerLazySingleton<IIntroDatasource>(() => IntroDatasourceImpl(locator()));
locator.registerLazySingleton<IIntroRepository>(() => IntroRepositoryImpl(locator()));
locator.registerLazySingleton<GetIntroUseCase>(() => GetIntroUseCase(locator()));
/// Question Feature
locator.registerLazySingleton<IQuestionDatasource>(() => QuestionDatasourceImpl(locator()));
locator.registerLazySingleton<IQuestionRepository>(() => QuestionRepositoryImpl(locator()));
locator.registerLazySingleton<GetQuestionUseCase>(() => GetQuestionUseCase(locator()));
}

3
lib/l10n/app_en.arb

@ -1,4 +1,5 @@
{
"about_us": "About us",
"about_us_desc" : "Rive combines an interactive design tool, a new stateful graphics format, a lightweight multi-platform runtime, and a blazing-fast vector renderer. \nThis end-to-end pipeline brings interfaces to life with motion. It gives designers and devs the tools to build."
"about_us_desc" : "Rive combines an interactive design tool, a new stateful graphics format, a lightweight multi-platform runtime, and a blazing-fast vector renderer. \nThis end-to-end pipeline brings interfaces to life with motion. It gives designers and devs the tools to build.",
"tap_to_select": "Tap the correct option to select."
}

6
lib/l10n/app_localizations.dart

@ -105,6 +105,12 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'Rive combines an interactive design tool, a new stateful graphics format, a lightweight multi-platform runtime, and a blazing-fast vector renderer. \nThis end-to-end pipeline brings interfaces to life with motion. It gives designers and devs the tools to build.'**
String get about_us_desc;
/// No description provided for @tap_to_select.
///
/// In en, this message translates to:
/// **'Tap the correct option to select.'**
String get tap_to_select;
}
class _AppLocalizationsDelegate

3
lib/l10n/app_localizations_en.dart

@ -14,4 +14,7 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get about_us_desc =>
'Rive combines an interactive design tool, a new stateful graphics format, a lightweight multi-platform runtime, and a blazing-fast vector renderer. \nThis end-to-end pipeline brings interfaces to life with motion. It gives designers and devs the tools to build.';
@override
String get tap_to_select => 'Tap the correct option to select.';
}

42
pubspec.lock

@ -1,6 +1,14 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
archive:
dependency: transitive
description:
name: archive
sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd"
url: "https://pub.dev"
source: hosted
version: "4.0.7"
args:
dependency: transitive
description:
@ -81,6 +89,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.1"
easy_stepper:
dependency: "direct main"
description:
name: easy_stepper
sha256: "63f66314a509ec690c8152a41288961fd96ba9e92ef184299f068a5e78bd16ad"
url: "https://pub.dev"
source: hosted
version: "0.8.5+1"
equatable:
dependency: "direct main"
description:
@ -245,6 +261,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.0"
lottie:
dependency: transitive
description:
name: lottie
sha256: "8ae0be46dbd9e19641791dc12ee480d34e1fd3f84c749adc05f3ad9342b71b95"
url: "https://pub.dev"
source: hosted
version: "3.3.2"
matcher:
dependency: transitive
description:
@ -373,6 +397,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.8"
posix:
dependency: transitive
description:
name: posix
sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61"
url: "https://pub.dev"
source: hosted
version: "6.0.3"
pretty_dio_logger:
dependency: "direct main"
description:
@ -445,6 +477,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.4.1"
showcaseview:
dependency: "direct main"
description:
name: showcaseview
sha256: "82e013ac2de1ae92cc6e652badf676606057c8e17aa3afd91e78866c4b4e85b1"
url: "https://pub.dev"
source: hosted
version: "4.0.1"
sky_engine:
dependency: transitive
description: flutter
@ -572,4 +612,4 @@ packages:
version: "6.6.1"
sdks:
dart: ">=3.9.2 <4.0.0"
flutter: ">=3.29.0"
flutter: ">=3.35.0"

2
pubspec.yaml

@ -9,6 +9,7 @@ environment:
dependencies:
bloc: ^9.0.0
dio: ^5.9.0
easy_stepper: ^0.8.5+1
equatable: ^2.0.7
flutter:
sdk: flutter
@ -22,6 +23,7 @@ dependencies:
intl: ^0.20.2
pretty_dio_logger: ^1.4.0
shared_preferences: ^2.5.3
showcaseview: ^4.0.1
dev_dependencies:
flutter_test:

Loading…
Cancel
Save