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 'user_bloc/user_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(
providers: [
BlocProvider(create: (context) => di.sl<NavigationCubit>()),
BlocProvider(
create: (context) => di.sl<SplashCubit>()..checkToken(),
),
BlocProvider(
create: (context) => di.sl<LanguageBloc>()..add(LanguageInitial()),
),
@ -29,7 +32,7 @@ class MyApp extends StatelessWidget {
localizationsDelegates: context.localizationDelegates,
supportedLocales: context.supportedLocales,
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 defaultSources = '';

View File

@ -1,9 +1,10 @@
// App
const String appTitle = 'Cargo App';
const String appTitle = 'Durnukly ýol';
// Storage and Databases
const String articlesTableName = '';
const String databaseName = '';
// SharedPreferences
// locale storage
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 root = '/root';
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 filter = '/filter';
// static const String signup = '/signup';
@ -25,21 +57,8 @@ sealed class AppRouter {
// static const String orders = '/orders';
// static const String notifications = '/notifications';
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:
// ProductEntity product = routeSettings.arguments as ProductEntity;
return MaterialPageRoute(builder: (_) => const OrderDetailsScreen());
// case search:
// case search:
// return MaterialPageRoute(builder: (_) => const SearchScreen());
// case filter:
// return MaterialPageRoute(builder: (_) => const FilterScreen());
@ -82,21 +101,4 @@ sealed class AppRouter {
// case orders:
// return MaterialPageRoute(builder: (_) => const OrdersScreen());
// case notifications:
// 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(),
),
];
}
}
// return MaterialPageRoute(builder: (_) => const NotificationsScreen());

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';
class FormValidator {
static String? validateField(String? val) {
if (val == null || val.isEmpty) {
return 'This field can\'t be empty';
}
return null;
}
}
export 'keyboard.dart';

View File

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

View File

@ -25,4 +25,14 @@ class AuthenticationResponseModel {
'token': token,
'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 '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 'cubits.dart';
import 'language.dart';
import 'splash.dart';
import 'user.dart';
final sl = GetIt.instance;
@ -10,8 +11,11 @@ final sl = GetIt.instance;
// Main Initialization
Future<void> init() async {
// Register features
registerUserFeature();
registerLanguageFeature();
registerSplashFeature();
// registerCategoryFeature();
// registerProductFeature();
// 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 '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 'splash/splash_usecase.dart';

View File

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@ -27,6 +29,8 @@ Future<void> main() async {
statusBarBrightness: Brightness.dark,
));
HttpOverrides.global = MyHttpOverrides();
runApp(
EasyLocalization(
supportedLocales: const [
@ -48,3 +52,11 @@ Future<void> main() async {
// 4 create repository implementation
// 5 create data source
// 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_svg/svg.dart';
import '../../application/application.dart';
import '../../configs/configs.dart';
import '../../core/core.dart';
class SplashScreen extends StatefulWidget {
import 'package:flutter_bloc/flutter_bloc.dart';
class SplashScreen extends StatelessWidget {
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,
),
),
return BlocListener<SplashCubit, SplashState>(
listener: (context, state) {
Keyboard.hide(context);
if (state is NavigateToSplash2) {
Navigator.of(context).pushNamedAndRemoveUntil(
AppRouter.splash2,
(route) => false,
);
} else if (state is NavigateToRoot) {
Navigator.of(context).pushNamedAndRemoveUntil(
AppRouter.root,
(route) => false,
);
}
},
child: 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,
),
),
],
),
),
),
),
),
);
}
}
// 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,
// ),
// ),
// ],
// ),
// ),
// ),
// ),
// );
// }
// }