added login

This commit is contained in:
komekh 2024-08-06 19:22:41 +05:00
parent 8088935aef
commit 6a6ab20eb9
21 changed files with 334 additions and 123 deletions

View File

@ -1,3 +1,4 @@
export 'bottom_navbar_cubit/bottom_navbar_cubit.dart'; export 'bottom_navbar_cubit/bottom_navbar_cubit.dart';
export 'user_bloc/user_bloc.dart';
export 'language_bloc/language_bloc.dart'; export 'language_bloc/language_bloc.dart';
export 'splash_cubit/splash_cubit.dart';
export 'user_bloc/user_bloc.dart';

View File

@ -0,0 +1,31 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../core/usecases/usecases.dart';
import '../../domain/usecases/splash/splash_usecase.dart';
// Define the states
abstract class SplashState {}
class SplashInitial extends SplashState {}
class NavigateToSplash2 extends SplashState {}
class NavigateToRoot extends SplashState {}
class SplashCubit extends Cubit<SplashState> {
final SplashUseCase _splashUseCase;
SplashCubit(this._splashUseCase) : super(SplashInitial());
Future<void> checkToken() async {
await Future.delayed(const Duration(seconds: 1)); // Simulating some loading time
try {
final result = await _splashUseCase(NoParams());
result.fold((failure) => emit(NavigateToSplash2()), (result) {
result ? emit(NavigateToRoot()) : emit(NavigateToSplash2());
});
} catch (e) {
emit(NavigateToSplash2());
}
}
}

View File

@ -14,6 +14,9 @@ class MyApp extends StatelessWidget {
return MultiBlocProvider( return MultiBlocProvider(
providers: [ providers: [
BlocProvider(create: (context) => di.sl<NavigationCubit>()), BlocProvider(create: (context) => di.sl<NavigationCubit>()),
BlocProvider(
create: (context) => di.sl<SplashCubit>()..checkToken(),
),
BlocProvider( BlocProvider(
create: (context) => di.sl<LanguageBloc>()..add(LanguageInitial()), create: (context) => di.sl<LanguageBloc>()..add(LanguageInitial()),
), ),
@ -29,7 +32,7 @@ class MyApp extends StatelessWidget {
localizationsDelegates: context.localizationDelegates, localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales, supportedLocales: context.supportedLocales,
locale: context.locale, locale: context.locale,
initialRoute: AppRouter.root, initialRoute: AppRouter.splash,
), ),
); );
} }

View File

@ -1,3 +1,3 @@
const String baseUrl = 'https://rich-jade-mackerel-kit.cyclic.app'; const String baseUrl = 'https://192.168.99.64:5001/api';
const String defaultApiKey = ''; const String defaultApiKey = '';
const String defaultSources = ''; const String defaultSources = '';

View File

@ -1,9 +1,10 @@
// App // App
const String appTitle = 'Cargo App'; const String appTitle = 'Durnukly ýol';
// Storage and Databases // Storage and Databases
const String articlesTableName = ''; const String articlesTableName = '';
const String databaseName = ''; const String databaseName = '';
// SharedPreferences // locale storage
const String activeLang = 'activeLang'; const String activeLang = 'activeLang';
// const String token = 'token';

View File

@ -9,6 +9,38 @@ sealed class AppRouter {
static const String login = '/login'; static const String login = '/login';
static const String root = '/root'; static const String root = '/root';
static const String orderDetails = '/order-details'; static const String orderDetails = '/order-details';
static Route<dynamic> onGenerateRoute(RouteSettings routeSettings) {
debugPrint('onGenerateRoute ${routeSettings.name}');
switch (routeSettings.name) {
case splash:
return MaterialPageRoute(builder: (_) => const SplashScreen());
case splash2:
return MaterialPageRoute(builder: (_) => const Splash2Screen());
case login:
return MaterialPageRoute(builder: (_) => const LoginScreen());
case root:
return MaterialPageRoute(builder: (_) => const RootScreen());
case orderDetails:
return MaterialPageRoute(builder: (_) => const OrderDetailsScreen());
default:
throw const RouteException('Route not found!');
}
}
static List<Route<dynamic>> generateInitialRoutes(String initialRoute) {
debugPrint('generateInitialRoutes $initialRoute');
return [
MaterialPageRoute(
builder: (context) => initialRoute == AppRouter.root ? const RootScreen() : const SplashScreen(),
),
];
}
}
// static const String search = '/search'; // static const String search = '/search';
// static const String filter = '/filter'; // static const String filter = '/filter';
// static const String signup = '/signup'; // static const String signup = '/signup';
@ -25,21 +57,8 @@ sealed class AppRouter {
// static const String orders = '/orders'; // static const String orders = '/orders';
// static const String notifications = '/notifications'; // static const String notifications = '/notifications';
static Route<dynamic> onGenerateRoute(RouteSettings routeSettings) {
debugPrint('onGenerateRoute ${routeSettings.name}'); // case search:
switch (routeSettings.name) {
case splash:
return MaterialPageRoute(builder: (_) => const SplashScreen());
case splash2:
return MaterialPageRoute(builder: (_) => const Splash2Screen());
case login:
return MaterialPageRoute(builder: (_) => const LoginScreen());
case root:
return MaterialPageRoute(builder: (_) => const RootScreen());
case orderDetails:
// ProductEntity product = routeSettings.arguments as ProductEntity;
return MaterialPageRoute(builder: (_) => const OrderDetailsScreen());
// case search:
// return MaterialPageRoute(builder: (_) => const SearchScreen()); // return MaterialPageRoute(builder: (_) => const SearchScreen());
// case filter: // case filter:
// return MaterialPageRoute(builder: (_) => const FilterScreen()); // return MaterialPageRoute(builder: (_) => const FilterScreen());
@ -83,20 +102,3 @@ sealed class AppRouter {
// return MaterialPageRoute(builder: (_) => const OrdersScreen()); // return MaterialPageRoute(builder: (_) => const OrdersScreen());
// case notifications: // case notifications:
// return MaterialPageRoute(builder: (_) => const NotificationsScreen()); // return MaterialPageRoute(builder: (_) => const NotificationsScreen());
default:
throw const RouteException('Route not found!');
}
}
static List<Route<dynamic>> generateInitialRoutes(String initialRoute) {
debugPrint('generateInitialRoutes $initialRoute');
return [
MaterialPageRoute(builder: (context) => const RootScreen()),
if (initialRoute != AppRouter.root)
MaterialPageRoute(
builder: (context) => const SplashScreen(),
),
];
}
}

View File

@ -1 +1,8 @@
// TODO Implement this library. class FormValidator {
static String? validateField(String? val) {
if (val == null || val.isEmpty) {
return 'This field can\'t be empty';
}
return null;
}
}

View File

@ -0,0 +1,7 @@
import 'package:flutter/material.dart';
class Keyboard {
static hide(BuildContext context) {
FocusScope.of(context).requestFocus(FocusNode());
}
}

View File

@ -1,10 +1,2 @@
export 'form_validator.dart'; export 'form_validator.dart';
export 'keyboard.dart';
class FormValidator {
static String? validateField(String? val) {
if (val == null || val.isEmpty) {
return 'This field can\'t be empty';
}
return null;
}
}

View File

@ -20,9 +20,20 @@ class UserRemoteDataSourceImpl implements UserRemoteDataSource {
Future<AuthenticationResponseModel> signIn(SignInParams params) async { Future<AuthenticationResponseModel> signIn(SignInParams params) async {
debugPrint('signIn'); debugPrint('signIn');
const data = ''' try {
final response = await client.post(Uri.parse('$baseUrl/Authentication/Authenticate'),
headers: {
'Content-Type': 'application/json',
'accept': '*/*',
},
body: json.encode({
'UserName': params.username,
'Password': '', // params.password,
}));
if (response.statusCode == 200) {
const userData = '''
{ {
"token": "exampleToken123", "token": "",
"user": { "user": {
"_id": "user123", "_id": "user123",
"firstName": "John", "firstName": "John",
@ -31,23 +42,21 @@ class UserRemoteDataSourceImpl implements UserRemoteDataSource {
} }
} }
'''; ''';
AuthenticationResponseModel user = authenticationResponseModelFromJson(userData);
return authenticationResponseModelFromJson(data); // Update the token value
/* final response = await client.post(Uri.parse('$baseUrl/authentication/local/sign-in'), AuthenticationResponseModel updatedUser = user.copyWith(token: response.body);
headers: {
'Content-Type': 'application/json', return updatedUser;
}, } else if (response.statusCode == 400 || response.statusCode == 401) {
body: json.encode({ throw CredentialFailure();
'identifier': params.username, } else {
'password': params.password, throw ServerException();
})); }
if (response.statusCode == 200) { } catch (e) {
return authenticationResponseModelFromJson(response.body); debugPrint('e $e');
} else if (response.statusCode == 400 || response.statusCode == 401) {
throw CredentialFailure();
} else {
throw ServerException(); throw ServerException();
} */ }
} }
@override @override

View File

@ -25,4 +25,14 @@ class AuthenticationResponseModel {
'token': token, 'token': token,
'user': user.toJson(), 'user': user.toJson(),
}; };
AuthenticationResponseModel copyWith({
String? token,
UserModel? user,
}) {
return AuthenticationResponseModel(
token: token ?? this.token,
user: user ?? this.user,
);
}
} }

View File

@ -1 +1,2 @@
export 'user_repository_impl.dart'; export 'user_repository_impl.dart';
export 'splash_repository_impl.dart';

View File

@ -0,0 +1,21 @@
import 'package:dartz/dartz.dart';
import '../../core/core.dart';
import '../../domain/domain.dart';
import '../data.dart';
class SplashRepositoryImpl implements SplashRepository {
final UserLocalDataSource localDataSource;
SplashRepositoryImpl({required this.localDataSource});
@override
Future<Either<Failure, bool>> isTokenAvailable() async {
try {
final isAvl = await localDataSource.isTokenAvailable();
return Right(isAvl);
} on CacheFailure {
return Left(CacheFailure());
}
}
}

View File

@ -3,6 +3,7 @@ import 'package:get_it/get_it.dart';
import 'common.dart'; import 'common.dart';
import 'cubits.dart'; import 'cubits.dart';
import 'language.dart'; import 'language.dart';
import 'splash.dart';
import 'user.dart'; import 'user.dart';
final sl = GetIt.instance; final sl = GetIt.instance;
@ -10,8 +11,11 @@ final sl = GetIt.instance;
// Main Initialization // Main Initialization
Future<void> init() async { Future<void> init() async {
// Register features // Register features
registerUserFeature(); registerUserFeature();
registerLanguageFeature(); registerLanguageFeature();
registerSplashFeature();
// registerCategoryFeature(); // registerCategoryFeature();
// registerProductFeature(); // registerProductFeature();
// registerDeliveryInfoFeature(); // registerDeliveryInfoFeature();

18
lib/di/splash.dart Normal file
View File

@ -0,0 +1,18 @@
import 'package:cargo/data/data.dart';
import 'package:cargo/domain/domain.dart';
import '../application/splash_cubit/splash_cubit.dart';
import 'di.dart';
void registerSplashFeature() {
// Splash cubit and Use Cases
sl.registerFactory(() => SplashCubit(sl()));
sl.registerLazySingleton(() => SplashUseCase(sl()));
// Splash Repository and Data Sources
sl.registerLazySingleton<SplashRepository>(
() => SplashRepositoryImpl(
localDataSource: sl(),
),
);
}

View File

@ -1 +1,2 @@
export 'user_repository.dart'; export 'user_repository.dart';
export 'splash_repository.dart';

View File

@ -0,0 +1,7 @@
import 'package:dartz/dartz.dart';
import '../../core/core.dart';
abstract class SplashRepository {
Future<Either<Failure, bool>> isTokenAvailable();
}

View File

@ -0,0 +1,14 @@
import 'package:dartz/dartz.dart';
import '../../../core/core.dart';
import '../../domain.dart';
class SplashUseCase implements UseCase<bool, NoParams> {
final SplashRepository repository;
SplashUseCase(this.repository);
@override
Future<Either<Failure, bool>> call(NoParams params) async {
return await repository.isTokenAvailable();
}
}

View File

@ -1 +1,2 @@
export 'user/user.dart'; export 'user/user.dart';
export 'splash/splash_usecase.dart';

View File

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -27,6 +29,8 @@ Future<void> main() async {
statusBarBrightness: Brightness.dark, statusBarBrightness: Brightness.dark,
)); ));
HttpOverrides.global = MyHttpOverrides();
runApp( runApp(
EasyLocalization( EasyLocalization(
supportedLocales: const [ supportedLocales: const [
@ -48,3 +52,11 @@ Future<void> main() async {
// 4 create repository implementation // 4 create repository implementation
// 5 create data source // 5 create data source
// 6 add di register // 6 add di register
class MyHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {
return super.createHttpClient(context)
..badCertificateCallback = (X509Certificate cert, String host, int port) => true;
}
}

View File

@ -1,77 +1,146 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import '../../application/application.dart';
import '../../configs/configs.dart'; import '../../configs/configs.dart';
import '../../core/core.dart'; import '../../core/core.dart';
class SplashScreen extends StatefulWidget { import 'package:flutter_bloc/flutter_bloc.dart';
class SplashScreen extends StatelessWidget {
const SplashScreen({super.key}); const SplashScreen({super.key});
@override
State<SplashScreen> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
void _nextScreen() {
Future.delayed(const Duration(seconds: 1), () {
Navigator.of(context).pushNamedAndRemoveUntil(
AppRouter.splash2,
(route) => false,
);
});
}
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_nextScreen();
});
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
App.init(context); App.init(context);
return Scaffold( return BlocListener<SplashCubit, SplashState>(
body: Container( listener: (context, state) {
decoration: const BoxDecoration( Keyboard.hide(context);
gradient: RadialGradient( if (state is NavigateToSplash2) {
center: Alignment.center, Navigator.of(context).pushNamedAndRemoveUntil(
radius: 1.0, AppRouter.splash2,
colors: [ (route) => false,
Color(0xFF5468FF), // Lighter blue in the center );
AppColors.primary, // Darker blue at the edges } else if (state is NavigateToRoot) {
], Navigator.of(context).pushNamedAndRemoveUntil(
), AppRouter.root,
), (route) => false,
child: SafeArea( );
child: Center( }
child: Column( },
mainAxisAlignment: MainAxisAlignment.center, child: Scaffold(
children: [ body: Container(
SvgPicture.asset( decoration: const BoxDecoration(
AppAssets.logo, gradient: RadialGradient(
height: AppDimensions.normalize(30), center: Alignment.center,
), radius: 1.0,
Space.yf(0.80), colors: [
Text( Color(0xFF5468FF), // Lighter blue in the center
appTitle, AppColors.primary, // Darker blue at the edges
style: AppText.h1b?.copyWith(
color: Colors.white,
),
),
Space.yf(0.30),
Text(
'Довезём всё!',
style: AppText.b1?.copyWith(
color: AppColors.yellow,
),
),
], ],
), ),
), ),
child: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
AppAssets.logo,
height: AppDimensions.normalize(30),
),
Space.yf(0.80),
Text(
appTitle,
style: AppText.h1b?.copyWith(
color: Colors.white,
),
),
Space.yf(0.30),
Text(
'Довезём всё!',
style: AppText.b1?.copyWith(
color: AppColors.yellow,
),
),
],
),
),
),
), ),
), ),
); );
} }
} }
// class SplashScreen extends StatefulWidget {
// const SplashScreen({super.key});
// @override
// State<SplashScreen> createState() => _SplashScreenState();
// }
// class _SplashScreenState extends State<SplashScreen> {
// void _nextScreen() {
// Future.delayed(const Duration(seconds: 1), () {
// Navigator.of(context).pushNamedAndRemoveUntil(
// AppRouter.splash2,
// (route) => false,
// );
// });
// }
// @override
// void initState() {
// WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
// _nextScreen();
// });
// super.initState();
// }
// @override
// Widget build(BuildContext context) {
// App.init(context);
// return Scaffold(
// body: Container(
// decoration: const BoxDecoration(
// gradient: RadialGradient(
// center: Alignment.center,
// radius: 1.0,
// colors: [
// Color(0xFF5468FF), // Lighter blue in the center
// AppColors.primary, // Darker blue at the edges
// ],
// ),
// ),
// child: SafeArea(
// child: Center(
// child: Column(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// SvgPicture.asset(
// AppAssets.logo,
// height: AppDimensions.normalize(30),
// ),
// Space.yf(0.80),
// Text(
// appTitle,
// style: AppText.h1b?.copyWith(
// color: Colors.white,
// ),
// ),
// Space.yf(0.30),
// Text(
// 'Довезём всё!',
// style: AppText.b1?.copyWith(
// color: AppColors.yellow,
// ),
// ),
// ],
// ),
// ),
// ),
// ),
// );
// }
// }