diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 856453b..ebac102 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,22 +1,22 @@ PODS: - Flutter (1.0.0) - - path_provider_foundation (0.0.1): + - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS DEPENDENCIES: - Flutter (from `Flutter`) - - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) EXTERNAL SOURCES: Flutter: :path: Flutter - path_provider_foundation: - :path: ".symlinks/plugins/path_provider_foundation/darwin" + shared_preferences_foundation: + :path: ".symlinks/plugins/shared_preferences_foundation/darwin" SPEC CHECKSUMS: Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 - path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 + shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e diff --git a/lib/core/constants/my_api.dart b/lib/core/constants/my_api.dart index b1ba034..bafa090 100644 --- a/lib/core/constants/my_api.dart +++ b/lib/core/constants/my_api.dart @@ -7,5 +7,12 @@ class MyApi { static const String contentType = 'application/json'; static const String defaultError = 'An unexpected error has occurred.'; - static const String baseUrl = 'https://api.BASE_URL.com'; + static const String baseUrl = 'https://shiamind.newhorizonco.uk/backend/api'; + + /// Player Auth + static const String guestToken = '/player/guest-token/'; + static const String centrifugoToken = '/player/centrifugo-connect/'; + + /// Quiz + static const String topics = '/quiz/topics/'; } diff --git a/lib/core/error_handler/error_handler.dart b/lib/core/error_handler/error_handler.dart index db8de6e..559c9eb 100644 --- a/lib/core/error_handler/error_handler.dart +++ b/lib/core/error_handler/error_handler.dart @@ -1,6 +1,8 @@ import 'package:dio/dio.dart'; +import 'package:get/get.dart'; import 'package:shia_game_flutter/core/constants/my_api.dart'; import 'package:shia_game_flutter/core/error_handler/my_exception.dart'; +import 'package:shia_game_flutter/core/utils/my_localization.dart'; class ErrorHandler { static const ErrorHandler _i = ErrorHandler._internal(); @@ -8,22 +10,23 @@ class ErrorHandler { factory ErrorHandler() => _i; static void handleError(DioException e) { - if (e.response == null) { + if (e.type == DioExceptionType.connectionTimeout || + e.type == DioExceptionType.connectionError || + e.type == DioExceptionType.receiveTimeout || + e.type == DioExceptionType.sendTimeout) { throw MyException( - errorMessage: e.message ?? MyApi.defaultError, - statusCode: e.response?.statusCode, + errorMessage: Get.context!.translate.check_internet_connection, + statusCode: 0, ); } else { - if (e.response?.data['message'] == null) { + if (e.response?.data?['message'] == null) { throw MyException( - errorMessage: - e.response?.statusMessage ?? e.message ?? MyApi.defaultError, + errorMessage: e.response?.statusMessage ?? e.message ?? MyApi.defaultError, statusCode: e.response?.statusCode, ); } else { throw MyException( - errorMessage: - e.response?.data['message'] ?? e.message ?? MyApi.defaultError, + errorMessage: e.response?.data?['message'] ?? e.message ?? MyApi.defaultError, statusCode: e.response?.statusCode, ); } diff --git a/lib/core/network/http_request_impl.dart b/lib/core/network/http_request_impl.dart index 74cbbb2..c272f67 100644 --- a/lib/core/network/http_request_impl.dart +++ b/lib/core/network/http_request_impl.dart @@ -17,6 +17,7 @@ class HttpRequestImpl implements IHttpRequest { ), )..interceptors.addAll([ LoggingInterceptor.prettyDioLogger, + LoggingInterceptor.curlDioLogger, TokenInterceptor(), ]); diff --git a/lib/core/network/interceptors/logging_interceptor.dart b/lib/core/network/interceptors/logging_interceptor.dart index 5311e0d..81a6d8d 100644 --- a/lib/core/network/interceptors/logging_interceptor.dart +++ b/lib/core/network/interceptors/logging_interceptor.dart @@ -1,5 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:pretty_dio_logger/pretty_dio_logger.dart'; +import 'package:curl_logger_dio_interceptor/curl_logger_dio_interceptor.dart'; class LoggingInterceptor { static const LoggingInterceptor _i = LoggingInterceptor._internal(); @@ -16,4 +17,7 @@ class LoggingInterceptor { maxWidth: 90, enabled: kDebugMode, ); + + static final CurlLoggerDioInterceptor curlDioLogger = + CurlLoggerDioInterceptor(); } diff --git a/lib/core/network/interceptors/token_interceptor.dart b/lib/core/network/interceptors/token_interceptor.dart index c509284..55d7a1a 100644 --- a/lib/core/network/interceptors/token_interceptor.dart +++ b/lib/core/network/interceptors/token_interceptor.dart @@ -4,7 +4,7 @@ import 'package:shia_game_flutter/core/auth_storage/auth_storage.dart'; class TokenInterceptor extends Interceptor { @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { - options.headers['Authorization'] = 'Bearer ${AuthStorage.token}'; + options.headers['X-Player-Token'] = AuthStorage.token; handler.next(options); } } diff --git a/lib/core/params/awards_params.dart b/lib/core/params/awards_params.dart index 63bc3a0..9e1761c 100644 --- a/lib/core/params/awards_params.dart +++ b/lib/core/params/awards_params.dart @@ -2,12 +2,4 @@ class AwardsParams { int? id; AwardsParams({this.id}); - - AwardsParams copyWith({ - int? id, - }) { - return AwardsParams( - id: id ?? this.id, - ); - } } diff --git a/lib/core/params/battle_league_params.dart b/lib/core/params/battle_league_params.dart new file mode 100644 index 0000000..bd495e0 --- /dev/null +++ b/lib/core/params/battle_league_params.dart @@ -0,0 +1,5 @@ +class BattleLeagueParams { + int? id; + + BattleLeagueParams({this.id}); +} diff --git a/lib/core/params/bl_question_params.dart b/lib/core/params/bl_question_params.dart index aea905b..83a0165 100644 --- a/lib/core/params/bl_question_params.dart +++ b/lib/core/params/bl_question_params.dart @@ -2,12 +2,4 @@ class BLQuestionParams { int? id; BLQuestionParams({this.id}); - - BLQuestionParams copyWith({ - int? id, - }) { - return BLQuestionParams( - id: id ?? this.id, - ); - } } diff --git a/lib/core/params/home_params.dart b/lib/core/params/home_params.dart index 22518f3..18d1bee 100644 --- a/lib/core/params/home_params.dart +++ b/lib/core/params/home_params.dart @@ -1,13 +1,9 @@ class HomeParams { - int? id; + String? username; - HomeParams({this.id}); + HomeParams({this.username}); - HomeParams copyWith({ - int? id, - }) { - return HomeParams( - id: id ?? this.id, - ); - } + Map get toGuestJson => { + if (username != null) 'username': username, + }; } diff --git a/lib/core/params/intro_params.dart b/lib/core/params/intro_params.dart index b3875c8..de39cbb 100644 --- a/lib/core/params/intro_params.dart +++ b/lib/core/params/intro_params.dart @@ -2,12 +2,4 @@ class IntroParams { int? id; IntroParams({this.id}); - - IntroParams copyWith({ - int? id, - }) { - return IntroParams( - id: id ?? this.id, - ); - } } diff --git a/lib/core/params/master_params.dart b/lib/core/params/master_params.dart index 62509d2..93bbcc3 100644 --- a/lib/core/params/master_params.dart +++ b/lib/core/params/master_params.dart @@ -2,12 +2,4 @@ class MasterParams { int? id; MasterParams({this.id}); - - MasterParams copyWith({ - int? id, - }) { - return MasterParams( - id: id ?? this.id, - ); - } } diff --git a/lib/core/params/profile_params.dart b/lib/core/params/profile_params.dart index 9c62c23..06d6c59 100644 --- a/lib/core/params/profile_params.dart +++ b/lib/core/params/profile_params.dart @@ -2,12 +2,4 @@ class ProfileParams { int? id; ProfileParams({this.id}); - - ProfileParams copyWith({ - int? id, - }) { - return ProfileParams( - id: id ?? this.id, - ); - } } diff --git a/lib/core/params/sample_params.dart b/lib/core/params/sample_params.dart index 8a21fab..3a22f0b 100644 --- a/lib/core/params/sample_params.dart +++ b/lib/core/params/sample_params.dart @@ -2,12 +2,4 @@ class SampleParams { int? id; SampleParams({this.id}); - - SampleParams copyWith({ - int? id, - }) { - return SampleParams( - id: id ?? this.id, - ); - } } diff --git a/lib/core/params/shop_params.dart b/lib/core/params/shop_params.dart index 6d3537b..011c914 100644 --- a/lib/core/params/shop_params.dart +++ b/lib/core/params/shop_params.dart @@ -2,12 +2,4 @@ class ShopParams { int? id; ShopParams({this.id}); - - ShopParams copyWith({ - int? id, - }) { - return ShopParams( - id: id ?? this.id, - ); - } } diff --git a/lib/core/params/topic_params.dart b/lib/core/params/topic_params.dart deleted file mode 100644 index edf044f..0000000 --- a/lib/core/params/topic_params.dart +++ /dev/null @@ -1,13 +0,0 @@ -class TopicParams { - int? id; - - TopicParams({this.id}); - - TopicParams copyWith({ - int? id, - }) { - return TopicParams( - id: id ?? this.id, - ); - } -} diff --git a/lib/core/status/base_status.dart b/lib/core/status/base_status.dart index c44ba27..5f2b749 100644 --- a/lib/core/status/base_status.dart +++ b/lib/core/status/base_status.dart @@ -18,14 +18,11 @@ class BaseNotAuth extends BaseStatus { const BaseNotAuth(); } -class BaseComplete extends BaseStatus { - final T data; - - const BaseComplete(this.data); +class BaseComplete extends BaseStatus { + const BaseComplete(); } class BaseError extends BaseStatus { final String errorMessage; - - const BaseError(this.errorMessage); + const BaseError({required this.errorMessage}); } diff --git a/lib/core/utils/local_storage.dart b/lib/core/utils/local_storage.dart index c650581..704715f 100644 --- a/lib/core/utils/local_storage.dart +++ b/lib/core/utils/local_storage.dart @@ -1,18 +1,22 @@ -import 'package:get_storage/get_storage.dart'; +import 'package:shared_preferences/shared_preferences.dart'; class LocalStorage { static const LocalStorage _i = LocalStorage._internal(); const LocalStorage._internal(); factory LocalStorage() => _i; - static final GetStorage _box = GetStorage(); + static late final SharedPreferences _box; - static Future saveData({required String key, required dynamic value}) async { - await _box.write(key, value); + static Future init() async { + _box = await SharedPreferences.getInstance(); + } + + static Future saveData({required String key, required String value}) async { + await _box.setString(key, value); } static String? readData({required String key}) { - return _box.read(key); + return _box.getString(key); } static Future deleteData({required String key}) async { @@ -20,6 +24,6 @@ class LocalStorage { } static Future clearAll() async { - await _box.erase(); + await _box.clear(); } -} +} \ No newline at end of file diff --git a/lib/core/widgets/container/my_container.dart b/lib/core/widgets/container/my_container.dart index b40dba0..e7b1130 100644 --- a/lib/core/widgets/container/my_container.dart +++ b/lib/core/widgets/container/my_container.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:shia_game_flutter/common_ui/theme/my_theme.dart'; +import 'package:shia_game_flutter/core/widgets/loading/my_loading.dart'; class MyContainer extends StatelessWidget { const MyContainer({ @@ -7,6 +8,7 @@ class MyContainer extends StatelessWidget { this.width, this.height, this.padding, + this.margin, this.boxShape, this.borderGradient, this.borderRadius, @@ -17,12 +19,13 @@ class MyContainer extends StatelessWidget { this.gradient, this.borderColor, this.onTap, - this.inset, + this.loading = false, }); final double? width; final double? height; final EdgeInsetsGeometry? padding; + final EdgeInsetsGeometry? margin; final BoxShape? boxShape; final Gradient? borderGradient; final Gradient? gradient; @@ -33,44 +36,47 @@ class MyContainer extends StatelessWidget { final Widget? child; final DecorationImage? image; final VoidCallback? onTap; - final bool? inset; + final bool loading; @override Widget build(BuildContext context) { - return Material( - color: context.noColor, - borderRadius: boxShape == BoxShape.circle - ? const BorderRadius.all(Radius.circular(100)) - : borderRadius, - shadowColor: boxShadow?.first.color, - elevation: boxShadow?.first.blurRadius ?? 0, - child: InkWell( - onTap: onTap, - customBorder: RoundedRectangleBorder( - borderRadius: boxShape == BoxShape.circle - ? const BorderRadius.all(Radius.circular(100)) - : borderRadius ?? BorderRadius.zero, - ), - child: Ink( - padding: const EdgeInsets.all(1), - width: width, - height: height, - decoration: BoxDecoration( - shape: boxShape ?? BoxShape.rectangle, - gradient: borderGradient, - borderRadius: borderRadius, - color: borderColor, + return Padding( + padding: margin ?? EdgeInsets.zero, + child: Material( + color: context.noColor, + borderRadius: boxShape == BoxShape.circle + ? const BorderRadius.all(Radius.circular(100)) + : borderRadius, + shadowColor: boxShadow?.first.color, + elevation: boxShadow?.first.blurRadius ?? 0, + child: InkWell( + onTap: loading ? null : onTap, + customBorder: RoundedRectangleBorder( + borderRadius: boxShape == BoxShape.circle + ? const BorderRadius.all(Radius.circular(100)) + : borderRadius ?? BorderRadius.zero, ), child: Ink( - padding: padding, + padding: const EdgeInsets.all(1), + width: width, + height: height, decoration: BoxDecoration( shape: boxShape ?? BoxShape.rectangle, - gradient: gradient, + gradient: borderGradient, borderRadius: borderRadius, - color: color, - image: image, + color: borderColor, + ), + child: Ink( + padding: padding, + decoration: BoxDecoration( + shape: boxShape ?? BoxShape.rectangle, + gradient: gradient, + borderRadius: borderRadius, + color: color, + image: image, + ), + child: Center(child: loading ? const MyLoading() : child), ), - child: Center(child: child), ), ), ), diff --git a/lib/core/widgets/input/my_input.dart b/lib/core/widgets/input/my_input.dart index 713fe3c..db78391 100644 --- a/lib/core/widgets/input/my_input.dart +++ b/lib/core/widgets/input/my_input.dart @@ -14,7 +14,7 @@ class MyInput extends StatelessWidget { this.validator, this.onChanged, this.onTap, - this.onEditingComplete, + this.onFieldSubmitted, this.onTapOutside, this.enabled, this.readOnly, @@ -28,11 +28,11 @@ class MyInput extends StatelessWidget { final bool? obscureText; final TextInputType? keyboardType; final TextInputAction? action; - final String? Function(String?)? validator; - final void Function(String)? onChanged; + final String? Function(String? value)? validator; + final void Function(String value)? onChanged; final void Function()? onTap; - final void Function()? onEditingComplete; - final void Function(PointerDownEvent)? onTapOutside; + final void Function(String value)? onFieldSubmitted; + final void Function(PointerDownEvent event)? onTapOutside; final bool? enabled; final bool? readOnly; final int? maxLines; @@ -52,16 +52,16 @@ class MyInput extends StatelessWidget { TextFormField( controller: controller, obscureText: obscureText ?? false, - keyboardType: keyboardType, - textInputAction: action, + keyboardType: keyboardType ?? TextInputType.text, + textInputAction: action ?? TextInputAction.done, validator: validator, onChanged: onChanged, onTap: onTap, - onEditingComplete: onEditingComplete, + onFieldSubmitted: onFieldSubmitted, enabled: enabled, readOnly: readOnly ?? false, - maxLines: maxLines, - minLines: minLines, + maxLines: maxLines ?? 1, + minLines: minLines ?? 1, style: Lexend.extraBold.copyWith(fontSize: 12), cursorColor: context.primaryColor, decoration: InputDecoration( diff --git a/lib/core/widgets/loading/my_loading.dart b/lib/core/widgets/loading/my_loading.dart new file mode 100644 index 0000000..57a12ad --- /dev/null +++ b/lib/core/widgets/loading/my_loading.dart @@ -0,0 +1,13 @@ +import 'package:flutter/cupertino.dart'; +import 'package:shia_game_flutter/common_ui/resources/my_colors.dart'; + +class MyLoading extends StatelessWidget { + const MyLoading({super.key}); + + @override + Widget build(BuildContext context) { + return const Center( + child: CupertinoActivityIndicator(color: MyColors.white), + ); + } +} diff --git a/lib/features/battle_league/first_part/data/datasource/battle_league_datasource.dart b/lib/features/battle_league/first_part/data/datasource/battle_league_datasource.dart index 3e47fc6..719a20e 100644 --- a/lib/features/battle_league/first_part/data/datasource/battle_league_datasource.dart +++ b/lib/features/battle_league/first_part/data/datasource/battle_league_datasource.dart @@ -1,12 +1,12 @@ import 'package:shia_game_flutter/core/constants/my_api.dart'; import 'package:shia_game_flutter/core/network/http_request.dart'; -import 'package:shia_game_flutter/core/params/sample_params.dart'; +import 'package:shia_game_flutter/core/params/battle_league_params.dart'; import 'package:shia_game_flutter/core/response/base_response.dart'; -import 'package:shia_game_flutter/features/battle_league/first_part/data/model/battle_league_model.dart'; -import 'package:shia_game_flutter/features/battle_league/first_part/domain/entity/battle_league_entity.dart'; +import 'package:shia_game_flutter/features/battle_league/first_part/data/model/topics_model.dart'; +import 'package:shia_game_flutter/features/battle_league/first_part/domain/entity/topics_entity.dart'; abstract class IBattleLeagueDatasource { - Future getData({required SampleParams params}); + Future> getTopics({required BattleLeagueParams params}); } class BattleLeagueDatasourceImpl implements IBattleLeagueDatasource { @@ -15,15 +15,14 @@ class BattleLeagueDatasourceImpl implements IBattleLeagueDatasource { const BattleLeagueDatasourceImpl(this.httpRequest); @override - Future getData({required SampleParams params}) async { - final response = await httpRequest.get( - path: MyApi.baseUrl, - ); + Future> getTopics({ + required BattleLeagueParams params, + }) async { + final response = await httpRequest.get(path: MyApi.topics); - return BaseResponse.getData( - response?['data'], - (json) => BattleLeagueModel.fromJson(json), + return BaseResponse.getDataList( + response?['results'], + (json) => TopicsModel.fromJson(json), ); } } - diff --git a/lib/features/battle_league/first_part/data/model/topics_model.dart b/lib/features/battle_league/first_part/data/model/topics_model.dart new file mode 100644 index 0000000..08c604c --- /dev/null +++ b/lib/features/battle_league/first_part/data/model/topics_model.dart @@ -0,0 +1,41 @@ +import 'package:shia_game_flutter/features/battle_league/first_part/domain/entity/topics_entity.dart'; + +class TopicsModel extends TopicsEntity { + const TopicsModel({ + super.id, + super.slug, + super.title, + super.description, + super.icon, + super.iconUrl, + super.order, + super.isActive, + super.difficultyLevel, + super.difficultyDisplay, + super.questionsCount, + super.createdAt, + super.updatedAt, + }); + + factory TopicsModel.fromJson(Map json) { + return TopicsModel( + id: json['id'], + slug: json['slug'], + title: json['title'], + description: json['description'], + icon: json['icon'], + iconUrl: json['icon_url'], + order: json['order'], + isActive: json['is_active'], + difficultyLevel: json['difficulty_level'], + difficultyDisplay: json['difficulty_display'], + questionsCount: json['questions_count'], + createdAt: json['created_at'] == null + ? null + : DateTime.parse(json['created_at']), + updatedAt: json['updated_at'] == null + ? null + : DateTime.parse(json['updated_at']), + ); + } +} diff --git a/lib/features/battle_league/first_part/data/repository_impl/battle_league_repository_impl.dart b/lib/features/battle_league/first_part/data/repository_impl/battle_league_repository_impl.dart index 36d681f..5eea715 100644 --- a/lib/features/battle_league/first_part/data/repository_impl/battle_league_repository_impl.dart +++ b/lib/features/battle_league/first_part/data/repository_impl/battle_league_repository_impl.dart @@ -1,9 +1,9 @@ import 'package:flutter/foundation.dart'; import 'package:shia_game_flutter/core/error_handler/my_exception.dart'; -import 'package:shia_game_flutter/core/params/sample_params.dart'; +import 'package:shia_game_flutter/core/params/battle_league_params.dart'; import 'package:shia_game_flutter/core/utils/data_state.dart'; import 'package:shia_game_flutter/features/battle_league/first_part/data/datasource/battle_league_datasource.dart'; -import 'package:shia_game_flutter/features/battle_league/first_part/domain/entity/battle_league_entity.dart'; +import 'package:shia_game_flutter/features/battle_league/first_part/domain/entity/topics_entity.dart'; import 'package:shia_game_flutter/features/battle_league/first_part/domain/repository/battle_league_repository.dart'; class BattleLeagueRepositoryImpl implements IBattleLeagueRepository { @@ -12,9 +12,13 @@ class BattleLeagueRepositoryImpl implements IBattleLeagueRepository { const BattleLeagueRepositoryImpl(this.datasource); @override - Future> getData({required SampleParams params}) async { + Future, MyException>> getTopics({ + required BattleLeagueParams params, + }) async { try { - final BattleLeagueEntity response = await datasource.getData(params: params); + final List response = await datasource.getTopics( + params: params, + ); return DataState.success(response); } on MyException catch (e) { return DataState.error(e); @@ -27,4 +31,3 @@ class BattleLeagueRepositoryImpl implements IBattleLeagueRepository { } } } - diff --git a/lib/features/battle_league/first_part/domain/entity/topics_entity.dart b/lib/features/battle_league/first_part/domain/entity/topics_entity.dart new file mode 100644 index 0000000..b65c328 --- /dev/null +++ b/lib/features/battle_league/first_part/domain/entity/topics_entity.dart @@ -0,0 +1,50 @@ +import 'package:equatable/equatable.dart'; + +class TopicsEntity extends Equatable { + final int? id; + final String? slug; + final String? title; + final String? description; + final String? icon; + final String? iconUrl; + final int? order; + final bool? isActive; + final String? difficultyLevel; + final String? difficultyDisplay; + final int? questionsCount; + final DateTime? createdAt; + final DateTime? updatedAt; + + const TopicsEntity({ + this.id, + this.slug, + this.title, + this.description, + this.icon, + this.iconUrl, + this.order, + this.isActive, + this.difficultyLevel, + this.difficultyDisplay, + this.questionsCount, + this.createdAt, + this.updatedAt, + }); + + @override + List get props => [ + id, + slug, + title, + description, + icon, + iconUrl, + order, + isActive, + difficultyLevel, + difficultyDisplay, + questionsCount, + createdAt, + updatedAt, + ]; +} diff --git a/lib/features/battle_league/first_part/domain/repository/battle_league_repository.dart b/lib/features/battle_league/first_part/domain/repository/battle_league_repository.dart index 6fde6dd..1b3a80d 100644 --- a/lib/features/battle_league/first_part/domain/repository/battle_league_repository.dart +++ b/lib/features/battle_league/first_part/domain/repository/battle_league_repository.dart @@ -1,9 +1,10 @@ import 'package:shia_game_flutter/core/error_handler/my_exception.dart'; -import 'package:shia_game_flutter/core/params/sample_params.dart'; +import 'package:shia_game_flutter/core/params/battle_league_params.dart'; import 'package:shia_game_flutter/core/utils/data_state.dart'; -import 'package:shia_game_flutter/features/battle_league/first_part/domain/entity/battle_league_entity.dart'; +import 'package:shia_game_flutter/features/battle_league/first_part/domain/entity/topics_entity.dart'; abstract class IBattleLeagueRepository { - Future> getData({required SampleParams params}); + Future, MyException>> getTopics({ + required BattleLeagueParams params, + }); } - diff --git a/lib/features/battle_league/first_part/domain/usecases/get_battle_league_usecase.dart b/lib/features/battle_league/first_part/domain/usecases/get_topics_usecase.dart similarity index 53% rename from lib/features/battle_league/first_part/domain/usecases/get_battle_league_usecase.dart rename to lib/features/battle_league/first_part/domain/usecases/get_topics_usecase.dart index 0c201a7..bb1c4d4 100644 --- a/lib/features/battle_league/first_part/domain/usecases/get_battle_league_usecase.dart +++ b/lib/features/battle_league/first_part/domain/usecases/get_topics_usecase.dart @@ -1,18 +1,18 @@ import 'package:shia_game_flutter/core/error_handler/my_exception.dart'; -import 'package:shia_game_flutter/core/params/sample_params.dart'; +import 'package:shia_game_flutter/core/params/battle_league_params.dart'; import 'package:shia_game_flutter/core/usecase/usecase.dart'; import 'package:shia_game_flutter/core/utils/data_state.dart'; -import 'package:shia_game_flutter/features/battle_league/first_part/domain/entity/battle_league_entity.dart'; +import 'package:shia_game_flutter/features/battle_league/first_part/domain/entity/topics_entity.dart'; import 'package:shia_game_flutter/features/battle_league/first_part/domain/repository/battle_league_repository.dart'; -class GetBattleLeagueUseCase implements UseCase { +class GetTopicsUseCase + implements UseCase, BattleLeagueParams> { final IBattleLeagueRepository repository; - const GetBattleLeagueUseCase(this.repository); + const GetTopicsUseCase(this.repository); @override - Future> call(SampleParams params) { - return repository.getData(params: params); + Future, MyException>> call(BattleLeagueParams params,) { + return repository.getTopics(params: params); } } - diff --git a/lib/features/battle_league/first_part/presentation/controller/battle_league_controller.dart b/lib/features/battle_league/first_part/presentation/controller/battle_league_controller.dart index 20a645b..b949ff1 100644 --- a/lib/features/battle_league/first_part/presentation/controller/battle_league_controller.dart +++ b/lib/features/battle_league/first_part/presentation/controller/battle_league_controller.dart @@ -1,20 +1,19 @@ import 'package:flutter/material.dart'; -import 'package:shia_game_flutter/core/params/sample_params.dart'; +import 'package:get/get.dart'; +import 'package:shia_game_flutter/core/params/battle_league_params.dart'; import 'package:shia_game_flutter/core/routers/my_routes.dart'; import 'package:shia_game_flutter/core/status/base_status.dart'; -import 'package:get/get.dart'; -import 'package:shia_game_flutter/features/battle_league/first_part/domain/entity/battle_league_entity.dart'; -import 'package:shia_game_flutter/features/battle_league/first_part/domain/usecases/get_battle_league_usecase.dart'; +import 'package:shia_game_flutter/features/battle_league/first_part/domain/entity/topics_entity.dart'; +import 'package:shia_game_flutter/features/battle_league/first_part/domain/usecases/get_topics_usecase.dart'; class BattleLeagueController extends GetxController with StateMixin, GetSingleTickerProviderStateMixin { /// ----- Constructor ----- - BattleLeagueController(this.getBattleLeagueUseCase); + BattleLeagueController(this._getTopicsUseCase); @override void onInit() { super.onInit(); - change('', status: RxStatus.success()); tabController = TabController(length: 2, vsync: this); } @@ -25,11 +24,11 @@ class BattleLeagueController extends GetxController } /// ----- UseCases ----- - final GetBattleLeagueUseCase getBattleLeagueUseCase; + final GetTopicsUseCase _getTopicsUseCase; /// ----- Variables ----- - final Rx battleLeagueParams = Rx(SampleParams()); - final Rx battleLeagueEntity = Rx(const BattleLeagueEntity()); + final BattleLeagueParams battleLeagueParams = BattleLeagueParams(); + final RxList topicList = RxList.empty(); /// ------ Controllers ------ final TextEditingController textEditingController = TextEditingController(); @@ -37,33 +36,35 @@ class BattleLeagueController extends GetxController /// ------ Statuses ------ final Rx getBattleLeagueStatus = Rx(const BaseInit()); + final Rx getTopicsStatus = Rx(const BaseInit()); /// ------ Functions ------ - void goToTopicPage(){ + void goToTopicPage() { + getTopics(); Get.toNamed(Routes.battleLeagueTopicPage); } - void goToFindingPage(){ + void goToFindingPage() { Get.toNamed(Routes.battleLeagueFindingPage); } - void goToFoundedPage(){ + + void goToFoundedPage() { Get.toNamed(Routes.battleLeagueFoundedPage); } /// ------ Api Calls ------ - Future getBattleLeague() async { - change('', status: RxStatus.loading()); - await getBattleLeagueUseCase(battleLeagueParams.value).then( + Future getTopics() async { + getTopicsStatus.value = const BaseLoading(); + await _getTopicsUseCase(battleLeagueParams).then( (value) => value.fold( (data) { - battleLeagueEntity.value = data; - change('', status: RxStatus.success()); + topicList.value = data; + getTopicsStatus.value = const BaseComplete(); }, (error) { - change('', status: RxStatus.error(error.errorMessage)); + getTopicsStatus.value = BaseError(errorMessage: error.errorMessage); }, ), ); } } - diff --git a/lib/features/battle_league/first_part/presentation/ui/battle_league_topic_page.dart b/lib/features/battle_league/first_part/presentation/ui/battle_league_topic_page.dart index acbb722..f4d208b 100644 --- a/lib/features/battle_league/first_part/presentation/ui/battle_league_topic_page.dart +++ b/lib/features/battle_league/first_part/presentation/ui/battle_league_topic_page.dart @@ -3,11 +3,13 @@ import 'package:get/get.dart'; import 'package:shia_game_flutter/common_ui/resources/my_assets.dart'; import 'package:shia_game_flutter/common_ui/resources/my_colors.dart'; import 'package:shia_game_flutter/common_ui/resources/my_text_style.dart'; +import 'package:shia_game_flutter/core/status/base_status.dart'; import 'package:shia_game_flutter/core/utils/gap.dart'; import 'package:shia_game_flutter/core/utils/my_localization.dart'; import 'package:shia_game_flutter/core/utils/screen_size.dart'; import 'package:shia_game_flutter/core/widgets/app_bar/enums/app_bar_type.dart'; import 'package:shia_game_flutter/core/widgets/app_bar/my_app_bar.dart'; +import 'package:shia_game_flutter/core/widgets/loading/my_loading.dart'; import 'package:shia_game_flutter/features/battle_league/first_part/presentation/controller/battle_league_controller.dart'; import 'package:shia_game_flutter/features/battle_league/first_part/presentation/ui/widgets/button/battle_golden_button.dart'; import 'package:shia_game_flutter/features/battle_league/first_part/presentation/ui/widgets/button/battle_grey_button.dart'; @@ -26,18 +28,32 @@ class BattleLeagueTopicPage extends GetView { title: context.translate.choose_3_topics, ), body: SafeArea( - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - 20.h.gapHeight, - _title(context), - 27.h.gapHeight, - _topicList(context), - 20.h.gapHeight, - _randomButton(context), - const Spacer(), - _startButton(context), - ], + child: Obx( + () { + if(controller.getTopicsStatus.value is BaseComplete){ + return Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + 20.h.gapHeight, + _title(context), + 27.h.gapHeight, + _topicList(context), + 20.h.gapHeight, + _randomButton(context), + const Spacer(), + _startButton(context), + ], + ); + } + if(controller.getTopicsStatus.value is BaseLoading){ + return const MyLoading(); + } + if(controller.getTopicsStatus.value is BaseError){ + return Text( + (controller.getTopicsStatus.value as BaseError).errorMessage); + } + return const SizedBox.shrink(); + } ), ), ); @@ -73,17 +89,18 @@ class BattleLeagueTopicPage extends GetView { SizedBox _topicList(BuildContext context) { return SizedBox( width: context.widthScreen, - child: Wrap( - spacing: 20, - runSpacing: 14, - direction: Axis.horizontal, - alignment: WrapAlignment.center, - children: List.generate( - 10, - (index) => TopicWidget( - label: context.translate.art, - image: MyAssets.iconArt, - onTap: () {}, + child: Obx( + () => Wrap( + spacing: 20, + runSpacing: 14, + direction: Axis.horizontal, + alignment: WrapAlignment.center, + children: List.generate( + controller.topicList.length, + (index) => TopicWidget( + topic: controller.topicList[index], + onTap: () {}, + ), ), ), ), diff --git a/lib/features/battle_league/first_part/presentation/ui/widgets/topic_page/topic_widget.dart b/lib/features/battle_league/first_part/presentation/ui/widgets/topic_page/topic_widget.dart index 5147c91..80e50d5 100644 --- a/lib/features/battle_league/first_part/presentation/ui/widgets/topic_page/topic_widget.dart +++ b/lib/features/battle_league/first_part/presentation/ui/widgets/topic_page/topic_widget.dart @@ -3,18 +3,17 @@ import 'package:shia_game_flutter/common_ui/resources/my_text_style.dart'; import 'package:shia_game_flutter/core/utils/screen_size.dart'; import 'package:shia_game_flutter/core/widgets/container/my_container.dart'; import 'package:shia_game_flutter/core/widgets/image/my_image.dart'; +import 'package:shia_game_flutter/features/battle_league/first_part/domain/entity/topics_entity.dart'; class TopicWidget extends StatelessWidget { const TopicWidget({ super.key, this.onTap, - this.label, - this.image, + required this.topic, }); final VoidCallback? onTap; - final String? label; - final String? image; + final TopicsEntity topic; @override Widget build(BuildContext context) { @@ -51,10 +50,10 @@ class TopicWidget extends StatelessWidget { spacing: 4, children: [ MyImage( - asset: image ?? '', + asset: topic.iconUrl ?? '', ), Text( - label ?? '', + topic.title ?? '', style: Lexend.medium.copyWith(fontSize: 12), ), ], diff --git a/lib/features/home/data/datasource/home_datasource.dart b/lib/features/home/data/datasource/home_datasource.dart index 5cb70c4..15811cf 100644 --- a/lib/features/home/data/datasource/home_datasource.dart +++ b/lib/features/home/data/datasource/home_datasource.dart @@ -2,11 +2,11 @@ import 'package:shia_game_flutter/core/constants/my_api.dart'; import 'package:shia_game_flutter/core/network/http_request.dart'; import 'package:shia_game_flutter/core/params/home_params.dart'; import 'package:shia_game_flutter/core/response/base_response.dart'; -import 'package:shia_game_flutter/features/home/data/model/home_model.dart'; -import 'package:shia_game_flutter/features/home/domain/entity/home_entity.dart'; +import 'package:shia_game_flutter/features/home/data/model/guest_player_model.dart'; +import 'package:shia_game_flutter/features/home/domain/entity/guest_player_entity.dart'; abstract class IHomeDatasource { - Future getData({required HomeParams params}); + Future loginGuest({required HomeParams params}); } class HomeDatasourceImpl implements IHomeDatasource { @@ -15,14 +15,15 @@ class HomeDatasourceImpl implements IHomeDatasource { const HomeDatasourceImpl(this.httpRequest); @override - Future getData({required HomeParams params}) async { - final response = await httpRequest.get( - path: MyApi.baseUrl, + Future loginGuest({required HomeParams params}) async { + final response = await httpRequest.post( + path: MyApi.guestToken, + data: params.toGuestJson, ); - return BaseResponse.getData( - response?['data'], - (json) => HomeModel.fromJson(json), + return BaseResponse.getData( + response, + (json) => GuestPlayerModel.fromJson(json), ); } } diff --git a/lib/features/home/data/model/guest_player_model.dart b/lib/features/home/data/model/guest_player_model.dart new file mode 100644 index 0000000..41a41ce --- /dev/null +++ b/lib/features/home/data/model/guest_player_model.dart @@ -0,0 +1,23 @@ +import 'package:shia_game_flutter/features/home/domain/entity/guest_player_entity.dart'; + +class GuestPlayerModel extends GuestPlayerEntity { + const GuestPlayerModel({ + super.playerID, + super.playerToken, + super.username, + super.isGuest, + super.createdAt, + }); + + factory GuestPlayerModel.fromJson(Map json) { + return GuestPlayerModel( + playerID: json['player_id'], + playerToken: json['player_token'], + username: json['username'], + isGuest: json['is_guest'], + createdAt: json['created_at'] == null + ? null + : DateTime.parse(json['created_at']), + ); + } +} diff --git a/lib/features/home/data/model/home_model.dart b/lib/features/home/data/model/home_model.dart deleted file mode 100644 index b1d2b84..0000000 --- a/lib/features/home/data/model/home_model.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:shia_game_flutter/features/home/domain/entity/home_entity.dart'; - -class HomeModel extends HomeEntity { - const HomeModel({ - super.id, - }); - - factory HomeModel.fromJson(Map json) { - return HomeModel( - id: json['id'], - ); - } -} diff --git a/lib/features/home/data/repository_impl/home_repository_impl.dart b/lib/features/home/data/repository_impl/home_repository_impl.dart index 203d244..b9d2cf5 100644 --- a/lib/features/home/data/repository_impl/home_repository_impl.dart +++ b/lib/features/home/data/repository_impl/home_repository_impl.dart @@ -3,7 +3,7 @@ import 'package:shia_game_flutter/core/error_handler/my_exception.dart'; import 'package:shia_game_flutter/core/params/home_params.dart'; import 'package:shia_game_flutter/core/utils/data_state.dart'; import 'package:shia_game_flutter/features/home/data/datasource/home_datasource.dart'; -import 'package:shia_game_flutter/features/home/domain/entity/home_entity.dart'; +import 'package:shia_game_flutter/features/home/domain/entity/guest_player_entity.dart'; import 'package:shia_game_flutter/features/home/domain/repository/home_repository.dart'; class HomeRepositoryImpl implements IHomeRepository { @@ -12,9 +12,13 @@ class HomeRepositoryImpl implements IHomeRepository { const HomeRepositoryImpl(this.datasource); @override - Future> getData({required HomeParams params}) async { + Future> loginGuest({ + required HomeParams params, + }) async { try { - final HomeEntity response = await datasource.getData(params: params); + final GuestPlayerEntity response = await datasource.loginGuest( + params: params, + ); return DataState.success(response); } on MyException catch (e) { return DataState.error(e); diff --git a/lib/features/home/domain/entity/guest_player_entity.dart b/lib/features/home/domain/entity/guest_player_entity.dart new file mode 100644 index 0000000..6c28e70 --- /dev/null +++ b/lib/features/home/domain/entity/guest_player_entity.dart @@ -0,0 +1,26 @@ +import 'package:equatable/equatable.dart'; + +class GuestPlayerEntity extends Equatable { + final String? playerID; + final String? playerToken; + final String? username; + final bool? isGuest; + final DateTime? createdAt; + + const GuestPlayerEntity({ + this.playerID, + this.playerToken, + this.username, + this.isGuest, + this.createdAt, + }); + + @override + List get props => [ + playerID, + playerToken, + username, + isGuest, + createdAt, + ]; +} diff --git a/lib/features/home/domain/entity/home_entity.dart b/lib/features/home/domain/entity/home_entity.dart deleted file mode 100644 index 582723c..0000000 --- a/lib/features/home/domain/entity/home_entity.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:equatable/equatable.dart'; - -class HomeEntity extends Equatable { - final int? id; - - const HomeEntity({ - this.id, - }); - - @override - List get props => [ - id, - ]; -} diff --git a/lib/features/home/domain/repository/home_repository.dart b/lib/features/home/domain/repository/home_repository.dart index 71709c3..0fccd3d 100644 --- a/lib/features/home/domain/repository/home_repository.dart +++ b/lib/features/home/domain/repository/home_repository.dart @@ -1,8 +1,8 @@ import 'package:shia_game_flutter/core/error_handler/my_exception.dart'; import 'package:shia_game_flutter/core/params/home_params.dart'; import 'package:shia_game_flutter/core/utils/data_state.dart'; -import 'package:shia_game_flutter/features/home/domain/entity/home_entity.dart'; +import 'package:shia_game_flutter/features/home/domain/entity/guest_player_entity.dart'; abstract class IHomeRepository { - Future> getData({required HomeParams params}); + Future> loginGuest({required HomeParams params}); } diff --git a/lib/features/home/domain/usecases/get_home_usecase.dart b/lib/features/home/domain/usecases/login_guest_usecase.dart similarity index 54% rename from lib/features/home/domain/usecases/get_home_usecase.dart rename to lib/features/home/domain/usecases/login_guest_usecase.dart index dc2ad83..a8d1c2d 100644 --- a/lib/features/home/domain/usecases/get_home_usecase.dart +++ b/lib/features/home/domain/usecases/login_guest_usecase.dart @@ -2,16 +2,16 @@ import 'package:shia_game_flutter/core/error_handler/my_exception.dart'; import 'package:shia_game_flutter/core/params/home_params.dart'; import 'package:shia_game_flutter/core/usecase/usecase.dart'; import 'package:shia_game_flutter/core/utils/data_state.dart'; -import 'package:shia_game_flutter/features/home/domain/entity/home_entity.dart'; +import 'package:shia_game_flutter/features/home/domain/entity/guest_player_entity.dart'; import 'package:shia_game_flutter/features/home/domain/repository/home_repository.dart'; -class GetHomeUseCase implements UseCase { +class LoginGuestUseCase implements UseCase { final IHomeRepository repository; - const GetHomeUseCase(this.repository); + const LoginGuestUseCase(this.repository); @override - Future> call(HomeParams params) { - return repository.getData(params: params); + Future> call(HomeParams params) { + return repository.loginGuest(params: params); } } diff --git a/lib/features/home/presentation/controller/home_controller.dart b/lib/features/home/presentation/controller/home_controller.dart index f221868..f68a883 100644 --- a/lib/features/home/presentation/controller/home_controller.dart +++ b/lib/features/home/presentation/controller/home_controller.dart @@ -1,58 +1,76 @@ import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; +import 'package:shia_game_flutter/common_ui/resources/my_colors.dart'; +import 'package:shia_game_flutter/core/auth_storage/auth_storage.dart'; import 'package:shia_game_flutter/core/params/home_params.dart'; import 'package:shia_game_flutter/core/routers/my_routes.dart'; import 'package:shia_game_flutter/core/status/base_status.dart'; -import 'package:shia_game_flutter/features/home/domain/entity/home_entity.dart'; -import 'package:shia_game_flutter/features/home/domain/usecases/get_home_usecase.dart'; +import 'package:shia_game_flutter/features/home/presentation/pages/widgets/home_username_dialog.dart'; +import 'package:shia_game_flutter/features/home/domain/entity/guest_player_entity.dart'; +import 'package:shia_game_flutter/features/home/domain/usecases/login_guest_usecase.dart'; -class HomeController extends GetxController with StateMixin { +class HomeController extends GetxController { /// ----- Constructor ----- - HomeController(this.getHomeUseCase); + HomeController(this._loginGuestUseCase); @override void onInit() { super.onInit(); - change('', status: RxStatus.success()); + showUsernameDialog(); } @override void onClose() { - textEditingController.dispose(); + usernameController.dispose(); super.onClose(); } /// ----- UseCases ----- - final GetHomeUseCase getHomeUseCase; + final LoginGuestUseCase _loginGuestUseCase; /// ----- Variables ----- - final Rx homeParams = Rx(HomeParams()); - final Rx homeEntity = Rx(const HomeEntity()); + final HomeParams homeParams = HomeParams(); + final Rx guestEntity = Rx(const GuestPlayerEntity()); /// ------ Controllers ------ - final TextEditingController textEditingController = TextEditingController(); + final TextEditingController usernameController = TextEditingController(); /// ------ Statuses ------ - final Rx getHomeStatus = Rx(const BaseInit()); + final Rx loginGuestStatus = Rx(const BaseInit()); /// ------ Functions ------ void goToBattleLeaguePage() { Get.toNamed(Routes.battleLeaguePage); } - /// ------ Api Calls ------ - Future getHome() async { - change('', status: RxStatus.loading()); - await getHomeUseCase(homeParams.value).then( - (value) => value.fold( - (data) { - homeEntity.value = data; - change('', status: RxStatus.success()); - }, - (error) { - change('', status: RxStatus.error(error.errorMessage)); - }, - ), + Future showUsernameDialog() async { + await Future.delayed(const Duration(seconds: 1)); + Get.dialog( + const UsernameDialog(), + useSafeArea: false, + barrierColor: MyColors.black.withValues(alpha: 0.7), + barrierDismissible: false, ); } + + /// ------ Api Calls ------ + Future loginGuest() async { + if (homeParams.username?.isNotEmpty ?? false) { + loginGuestStatus.value = const BaseLoading(); + await _loginGuestUseCase(homeParams).then( + (value) => value.fold( + (data) async { + guestEntity.value = data; + await AuthStorage.saveData(newTokenParams: data.playerToken ?? ''); + Get.back(); + loginGuestStatus.value = const BaseComplete(); + }, + (error) { + loginGuestStatus.value = + BaseError(errorMessage: error.errorMessage); + }, + ), + ); + } + } } diff --git a/lib/features/home/presentation/pages/home_page.dart b/lib/features/home/presentation/pages/home_page.dart index 42aab98..dfaf39e 100644 --- a/lib/features/home/presentation/pages/home_page.dart +++ b/lib/features/home/presentation/pages/home_page.dart @@ -21,12 +21,10 @@ class HomePage extends GetView { return MyBackground( child: Column( children: [ - const MyImage(asset: MyAssets.shiaMindGroup), + _image(), 40.h.gapHeight, const HomeMembership(), - HomeBattleLeague( - onTap: controller.goToBattleLeaguePage, - ), + _homeBattleLeague(), 20.h.gapHeight, _customWidgets(context), 20.h.gapHeight, @@ -36,6 +34,16 @@ class HomePage extends GetView { ); } + MyImage _image() { + return const MyImage(asset: MyAssets.shiaMindGroup); + } + + HomeBattleLeague _homeBattleLeague() { + return HomeBattleLeague( + onTap: controller.goToBattleLeaguePage, + ); + } + Widget _customWidgets(BuildContext context) { return Row( spacing: 20, diff --git a/lib/features/home/presentation/pages/widgets/home_username_dialog.dart b/lib/features/home/presentation/pages/widgets/home_username_dialog.dart new file mode 100644 index 0000000..747f8f5 --- /dev/null +++ b/lib/features/home/presentation/pages/widgets/home_username_dialog.dart @@ -0,0 +1,80 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:shia_game_flutter/common_ui/resources/my_text_style.dart'; +import 'package:shia_game_flutter/core/status/base_status.dart'; +import 'package:shia_game_flutter/core/utils/my_localization.dart'; +import 'package:shia_game_flutter/core/utils/screen_size.dart'; +import 'package:shia_game_flutter/core/widgets/container/my_container.dart'; +import 'package:shia_game_flutter/core/widgets/input/my_input.dart'; +import 'package:shia_game_flutter/core/widgets/text/gradient_text.dart'; +import 'package:shia_game_flutter/features/home/presentation/controller/home_controller.dart'; + +class UsernameDialog extends GetView { + const UsernameDialog({super.key}); + + @override + Widget build(BuildContext context) { + return MyContainer( + padding: const EdgeInsets.only(left: 30, right: 30, bottom: 30, top: 13), + margin: EdgeInsets.symmetric(horizontal: 30.w, vertical: 290.h), + borderGradient: const LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0XFF6013DA), Color(0XFF4908B0)], + ), + gradient: const RadialGradient( + radius: 1, + colors: [Color(0XFF4F09BF), Color(0XFF350D73)], + ), + borderRadius: const BorderRadius.all(Radius.circular(40)), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + context.translate.welcome, + style: Lexend.extraBold.copyWith( + fontSize: 18, + color: const Color(0XFFBAA3DD), + ), + ), + MyInput( + controller: controller.usernameController, + labelText: context.translate.username, + onFieldSubmitted: (value) { + controller.loginGuest(); + }, + onChanged: (value) { + controller.homeParams.username = value; + }, + ), + Obx( + () => MyContainer( + onTap: controller.loginGuest, + height: 41.h, + loading: controller.loginGuestStatus.value is BaseLoading, + borderRadius: const BorderRadius.all(Radius.circular(12)), + gradient: const RadialGradient( + radius: 4, + center: Alignment(-0.3, 0), + colors: [Color(0XFF6A36BF), Color(0XFF562A9E)], + ), + borderGradient: LinearGradient( + begin: AlignmentDirectional.topStart, + end: AlignmentDirectional.bottomEnd, + colors: [ + const Color(0XFF7F4CD4), + const Color(0XFF7F4CD4).withValues(alpha: 0), + ], + ), + child: GradientText( + text: context.translate.done, + color: const Color(0XFFB69CDE), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/init_bindings.dart b/lib/init_bindings.dart index 8cf4318..e39fdd8 100644 --- a/lib/init_bindings.dart +++ b/lib/init_bindings.dart @@ -8,7 +8,7 @@ import 'package:shia_game_flutter/features/awards/domain/usecases/get_awards_use import 'package:shia_game_flutter/features/battle_league/first_part/data/datasource/battle_league_datasource.dart'; import 'package:shia_game_flutter/features/battle_league/first_part/data/repository_impl/battle_league_repository_impl.dart'; import 'package:shia_game_flutter/features/battle_league/first_part/domain/repository/battle_league_repository.dart'; -import 'package:shia_game_flutter/features/battle_league/first_part/domain/usecases/get_battle_league_usecase.dart'; +import 'package:shia_game_flutter/features/battle_league/first_part/domain/usecases/get_topics_usecase.dart'; import 'package:shia_game_flutter/features/battle_league/question_part/bl_question/data/datasource/bl_question_datasource.dart'; import 'package:shia_game_flutter/features/battle_league/question_part/bl_question/data/repository_impl/bl_question_repository_impl.dart'; import 'package:shia_game_flutter/features/battle_league/question_part/bl_question/domain/repository/bl_question_repository.dart'; @@ -16,7 +16,7 @@ import 'package:shia_game_flutter/features/battle_league/question_part/bl_questi import 'package:shia_game_flutter/features/home/data/datasource/home_datasource.dart'; import 'package:shia_game_flutter/features/home/data/repository_impl/home_repository_impl.dart'; import 'package:shia_game_flutter/features/home/domain/repository/home_repository.dart'; -import 'package:shia_game_flutter/features/home/domain/usecases/get_home_usecase.dart'; +import 'package:shia_game_flutter/features/home/domain/usecases/login_guest_usecase.dart'; import 'package:shia_game_flutter/features/intro/data/datasource/intro_datasource.dart'; import 'package:shia_game_flutter/features/intro/data/repository_impl/intro_repository_impl.dart'; import 'package:shia_game_flutter/features/intro/domain/repository/intro_repository.dart'; @@ -53,14 +53,14 @@ void initBindings() { Get.lazyPut(() => GetIntroUseCase(Get.find())); /// ----- Master Feature ----- - Get.lazyPut(() => MasterDatasourceImpl(Get.find())); - Get.lazyPut(() => MasterRepositoryImpl(Get.find())); - Get.lazyPut(() => GetMasterUseCase(Get.find())); + Get.lazyPut(() => MasterDatasourceImpl(Get.find()), fenix: true); + Get.lazyPut(() => MasterRepositoryImpl(Get.find()), fenix: true); + Get.lazyPut(() => GetMasterUseCase(Get.find()), fenix: true); /// ----- Home Feature ----- Get.lazyPut(() => HomeDatasourceImpl(Get.find()), fenix: true); Get.lazyPut(() => HomeRepositoryImpl(Get.find()), fenix: true); - Get.lazyPut(() => GetHomeUseCase(Get.find()), fenix: true); + Get.lazyPut(() => LoginGuestUseCase(Get.find()), fenix: true); /// ----- Shop Feature ----- Get.lazyPut(() => ShopDatasourceImpl(Get.find()), fenix: true); @@ -80,7 +80,7 @@ void initBindings() { /// ----- BattleLeague Feature ----- Get.lazyPut(() => BattleLeagueDatasourceImpl(Get.find()), fenix: true); Get.lazyPut(() => BattleLeagueRepositoryImpl(Get.find()), fenix: true); - Get.lazyPut(() => GetBattleLeagueUseCase(Get.find()), fenix: true); + Get.lazyPut(() => GetTopicsUseCase(Get.find()), fenix: true); /// ----- BattleLeagueQuestion Feature ----- Get.lazyPut(() => BLQuestionDatasourceImpl(Get.find()), fenix: true); diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 13ea525..11ed740 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -1,5 +1,6 @@ { "@@locale": "en", + "check_internet_connection": "Please Check your internet connection.", "loading": "Loading...", "home": "Home", "shop": "Shop", @@ -49,5 +50,7 @@ "quiz_league": "Quiz league", "your_place": "Your place", "finding_player": "Finding player ...", - "find_hint": "The fastest player to answer the question correctly gets the point." + "find_hint": "The fastest player to answer the question correctly gets the point.", + "welcome": "Welcome", + "done": "Done" } \ No newline at end of file diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index ae41b97..3b9e953 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -94,6 +94,12 @@ abstract class AppLocalizations { /// A list of this localizations delegate's supported locales. static const List supportedLocales = [Locale('en')]; + /// No description provided for @check_internet_connection. + /// + /// In en, this message translates to: + /// **'Please Check your internet connection.'** + String get check_internet_connection; + /// No description provided for @loading. /// /// In en, this message translates to: @@ -393,6 +399,18 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'The fastest player to answer the question correctly gets the point.'** String get find_hint; + + /// No description provided for @welcome. + /// + /// In en, this message translates to: + /// **'Welcome'** + String get welcome; + + /// No description provided for @done. + /// + /// In en, this message translates to: + /// **'Done'** + String get done; } class _AppLocalizationsDelegate diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 6af744c..3e60839 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -8,6 +8,10 @@ import 'app_localizations.dart'; class AppLocalizationsEn extends AppLocalizations { AppLocalizationsEn([String locale = 'en']) : super(locale); + @override + String get check_internet_connection => + 'Please Check your internet connection.'; + @override String get loading => 'Loading...'; @@ -158,4 +162,10 @@ class AppLocalizationsEn extends AppLocalizations { @override String get find_hint => 'The fastest player to answer the question correctly gets the point.'; + + @override + String get welcome => 'Welcome'; + + @override + String get done => 'Done'; } diff --git a/lib/main.dart b/lib/main.dart index 5285cf3..91e7d2f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,14 +5,14 @@ import 'package:shia_game_flutter/common_ui/theme/theme_service.dart'; import 'package:shia_game_flutter/core/auth_storage/auth_storage.dart'; import 'package:shia_game_flutter/core/routers/my_routes.dart'; import 'package:get/get.dart'; -import 'package:get_storage/get_storage.dart'; +import 'package:shia_game_flutter/core/utils/local_storage.dart'; import 'package:shia_game_flutter/init_bindings.dart'; import 'package:shia_game_flutter/l10n/app_localizations.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); await Future.wait([ - GetStorage.init(), + LocalStorage.init(), ]); AuthStorage.loadData(); runApp(const MainApp()); @@ -31,7 +31,7 @@ class MainApp extends StatelessWidget { fallbackLocale: const Locale('en', 'US'), supportedLocales: const [Locale('en', 'US')], getPages: appPages, - initialRoute: Routes.battleLeagueQuestionPage, + initialRoute: Routes.masterPage, localizationsDelegates: const [ AppLocalizations.delegate, GlobalMaterialLocalizations.delegate, diff --git a/pubspec.lock b/pubspec.lock index 88903b8..627b2cd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -25,6 +25,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + centrifuge: + dependency: "direct main" + description: + name: centrifuge + sha256: "9605036830de242cbb4b0ea1912b5b2238e588bbf639015018a5320734f97c73" + url: "https://pub.dev" + source: hosted + version: "0.17.0" change_app_package_name: dependency: "direct dev" description: @@ -57,6 +65,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.19.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" + curl_logger_dio_interceptor: + dependency: "direct main" + description: + name: curl_logger_dio_interceptor + sha256: "0702d32b8ff1b451ba1d9882d57b885061872ebc38384c18243b18b2a0db2a5b" + url: "https://pub.dev" + source: hosted + version: "1.0.1" dio: dependency: "direct main" description: @@ -105,6 +129,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" flutter: dependency: "direct main" description: flutter @@ -136,6 +176,11 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" get: dependency: "direct main" description: @@ -144,14 +189,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.7.2" - get_storage: - dependency: "direct main" - description: - name: get_storage - sha256: "39db1fffe779d0c22b3a744376e86febe4ade43bf65e06eab5af707dc84185a2" - url: "https://pub.dev" - source: hosted - version: "2.1.1" http: dependency: transitive description: @@ -256,30 +293,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" - path_provider: - dependency: transitive - description: - name: path_provider - sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.dev" - source: hosted - version: "2.1.5" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - sha256: "3b4c1fc3aa55ddc9cd4aa6759984330d5c8e66aa7702a6223c61540dc6380c37" - url: "https://pub.dev" - source: hosted - version: "2.2.19" - path_provider_foundation: - dependency: transitive - description: - name: path_provider_foundation - sha256: "16eef174aacb07e09c351502740fa6254c165757638eba1e9116b0a781201bbd" - url: "https://pub.dev" - source: hosted - version: "2.4.2" path_provider_linux: dependency: transitive description: @@ -336,6 +349,70 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + protobuf: + dependency: transitive + description: + name: protobuf + sha256: "2fcc8a202ca7ec17dab7c97d6b6d91cf03aa07fe6f65f8afbb6dfa52cc5bd902" + url: "https://pub.dev" + source: hosted + version: "5.1.0" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" + url: "https://pub.dev" + source: hosted + version: "2.5.3" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "46a46fd64659eff15f4638bbe19de43f9483f0e0bf024a9fb6b3582064bacc7b" + url: "https://pub.dev" + source: hosted + version: "2.4.17" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f" + url: "https://pub.dev" + source: hosted + version: "2.5.6" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 + url: "https://pub.dev" + source: hosted + version: "2.4.3" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" sky_engine: dependency: transitive description: flutter @@ -445,6 +522,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" xdg_directories: dependency: transitive description: @@ -463,4 +556,4 @@ packages: version: "6.6.1" sdks: dart: ">=3.9.2 <4.0.0" - flutter: ">=3.29.0" + flutter: ">=3.35.0" diff --git a/pubspec.yaml b/pubspec.yaml index 0852b32..2ebc492 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,6 +7,7 @@ environment: sdk: ^3.9.2 dependencies: + centrifuge: ^0.17.0 dio: ^5.9.0 draggable_scrollbar: ^0.1.0 equatable: ^2.0.7 @@ -16,9 +17,10 @@ dependencies: flutter_localizations: sdk: flutter get: ^4.7.2 - get_storage: ^2.1.1 intl: ^0.20.2 pretty_dio_logger: ^1.4.0 + curl_logger_dio_interceptor: ^1.0.1 + shared_preferences: ^2.5.3 vector_graphics: ^1.1.19 dev_dependencies: