changed structure, added login, signUp screen and logic
This commit is contained in:
parent
eb143d5496
commit
3a8ca71319
|
|
@ -0,0 +1,46 @@
|
|||
import 'package:adaptix/adaptix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../constants/global_variables.dart';
|
||||
import '../themes/app_theme.dart';
|
||||
|
||||
class CustomButton extends StatelessWidget {
|
||||
const CustomButton({
|
||||
Key? key,
|
||||
required this.name,
|
||||
required this.onTap,
|
||||
required this.backgroundColor,
|
||||
required this.isMain,
|
||||
}) : super(key: key);
|
||||
final String name;
|
||||
final Color backgroundColor;
|
||||
final bool isMain;
|
||||
final void Function() onTap;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: GlobalVariables.deviceHeight(context) / 15,
|
||||
width: double.infinity,
|
||||
margin: EdgeInsets.symmetric(
|
||||
vertical: 5.adaptedPx(),
|
||||
),
|
||||
child: OutlinedButton(
|
||||
onPressed: onTap,
|
||||
style: TextButton.styleFrom(
|
||||
backgroundColor: backgroundColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10.adaptedPx()),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
name,
|
||||
style: Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
|
||||
color: isMain ? AppTheme.whiteColor : AppTheme.blackColor,
|
||||
fontSize: 14.adaptedPx(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
import 'package:adaptix/adaptix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../themes/app_theme.dart';
|
||||
|
||||
class CustomTextField extends StatelessWidget {
|
||||
const CustomTextField({
|
||||
Key? key,
|
||||
required this.labelText,
|
||||
required this.controller,
|
||||
required this.hintText,
|
||||
required this.obscureText,
|
||||
required this.inputType,
|
||||
}) : super(key: key);
|
||||
|
||||
final String labelText, hintText;
|
||||
final TextEditingController controller;
|
||||
final bool obscureText;
|
||||
final TextInputType inputType;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextFormField(
|
||||
controller: controller,
|
||||
obscureText: obscureText,
|
||||
keyboardType: inputType,
|
||||
cursorColor: AppTheme.lightPrimaryColor,
|
||||
decoration: InputDecoration(
|
||||
labelText: labelText,
|
||||
hintText: hintText,
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10.adaptedPx()),
|
||||
borderSide: BorderSide(
|
||||
color: AppTheme.lightPrimaryColor,
|
||||
width: 3.adaptedPx(),
|
||||
),
|
||||
),
|
||||
errorBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10.adaptedPx()),
|
||||
borderSide: BorderSide(
|
||||
color: AppTheme.redColor,
|
||||
width: 3.adaptedPx(),
|
||||
),
|
||||
),
|
||||
labelStyle: Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
|
||||
color: AppTheme.lightTextColor,
|
||||
fontSize: 13.adaptedPx(),
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(5.adaptedPx()),
|
||||
borderSide: BorderSide(
|
||||
color: AppTheme.lightTextColor,
|
||||
width: 2.adaptedPx(),
|
||||
),
|
||||
),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Enter your $hintText';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:sapaly_shop/constants/utils.dart';
|
||||
|
||||
void httpErrorHandle({
|
||||
required http.Response response,
|
||||
required BuildContext context,
|
||||
required VoidCallback onSuccess,
|
||||
}) {
|
||||
switch (response.statusCode) {
|
||||
case 200:
|
||||
onSuccess();
|
||||
break;
|
||||
case 400:
|
||||
showSnackBar(context, 'this_user_exists');
|
||||
break;
|
||||
case 500:
|
||||
showSnackBar(context, 'error_occured');
|
||||
break;
|
||||
default:
|
||||
showSnackBar(context, 'error_occured');
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
|||
|
||||
String kBaseUrl = 'http://sapalymahabat.com.tm';
|
||||
|
||||
abstract class AppConstants {
|
||||
class GlobalVariables {
|
||||
static const kAppName = 'Sapaly Mahabat';
|
||||
|
||||
static double deviceHeight(BuildContext context) =>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
void showSnackBar(BuildContext context, String text) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(text),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
import 'package:adaptix/adaptix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sapaly_shop/common/custom_button.dart';
|
||||
import 'package:sapaly_shop/models/auth/login/login_request_model.dart';
|
||||
import 'package:sapaly_shop/features/services/page_navigator.dart';
|
||||
import 'package:sapaly_shop/themes/app_theme.dart';
|
||||
|
||||
import '../../../../common/widgets/custom_text_field.dart';
|
||||
import '../../../../constants/global_variables.dart';
|
||||
import '../../../services/auth_service.dart';
|
||||
import '../register_screen.dart';
|
||||
|
||||
class LoginScreen extends StatefulWidget {
|
||||
static const String routeName = '/login';
|
||||
LoginScreen({super.key});
|
||||
|
||||
@override
|
||||
State<LoginScreen> createState() => _LoginScreenState();
|
||||
}
|
||||
|
||||
class _LoginScreenState extends State<LoginScreen> {
|
||||
final formKey = GlobalKey<FormState>();
|
||||
TextEditingController emailController = TextEditingController();
|
||||
TextEditingController passwordController = TextEditingController();
|
||||
|
||||
final AuthService authService = AuthService();
|
||||
|
||||
void login() {
|
||||
debugPrint('EMAIL ${emailController.text}');
|
||||
authService.login(
|
||||
loginRequestModel: LoginRequestModel(
|
||||
email: emailController.text,
|
||||
password: passwordController.text,
|
||||
),
|
||||
context: context,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
emailController.dispose();
|
||||
passwordController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: Container(),
|
||||
),
|
||||
body: Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
margin: EdgeInsets.symmetric(
|
||||
vertical: GlobalVariables.verticalPadding(context) * 2,
|
||||
horizontal: GlobalVariables.horizontalPadding(context),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: GlobalVariables.verticalPadding(context) / 2,
|
||||
horizontal: GlobalVariables.horizontalPadding(context),
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10.adaptedPx()),
|
||||
border: Border.all(
|
||||
width: 2.adaptedPx(),
|
||||
color: AppTheme.blackColor.withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
height: GlobalVariables.deviceHeight(context) / 1.55,
|
||||
child: Form(
|
||||
key: formKey,
|
||||
child: ListView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: 30.adaptedPx(),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/sapalyLogo.png',
|
||||
),
|
||||
SizedBox(width: 15.adaptedPx()),
|
||||
Text(
|
||||
GlobalVariables.kAppName,
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.bodyMedium
|
||||
?.copyWith(
|
||||
color: AppTheme.blackColor,
|
||||
fontSize: 18.adaptedPx(),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 15.adaptedPx()),
|
||||
child: CustomTextField(
|
||||
controller: emailController,
|
||||
labelText: 'email',
|
||||
hintText: 'enter_your_email',
|
||||
obscureText: false,
|
||||
inputType: TextInputType.emailAddress,
|
||||
),
|
||||
),
|
||||
CustomTextField(
|
||||
controller: passwordController,
|
||||
labelText: 'password',
|
||||
hintText: 'enter_your_password',
|
||||
obscureText: true,
|
||||
inputType: TextInputType.visiblePassword,
|
||||
),
|
||||
SizedBox(height: 30.adaptedPx()),
|
||||
CustomButton(
|
||||
name: 'login',
|
||||
onTap: () {
|
||||
if (formKey.currentState!.validate()) {
|
||||
login();
|
||||
}
|
||||
},
|
||||
backgroundColor: AppTheme.lightPrimaryColor,
|
||||
isMain: true,
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
'or',
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.bodyMedium
|
||||
?.copyWith(
|
||||
fontSize: 15.adaptedPx(),
|
||||
color: AppTheme.lightTextColor),
|
||||
),
|
||||
),
|
||||
CustomButton(
|
||||
name: 'register',
|
||||
onTap: () {
|
||||
PageNavigator(ctx: context).nextPage(
|
||||
page: const RegisterScreen(),
|
||||
);
|
||||
},
|
||||
backgroundColor: AppTheme.lightTextColor.withOpacity(0.2),
|
||||
isMain: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
import 'package:adaptix/adaptix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sapaly_shop/features/screens/auth/login/login_screen.dart';
|
||||
import 'package:sapaly_shop/features/services/auth_service.dart';
|
||||
import 'package:sapaly_shop/features/services/page_navigator.dart';
|
||||
import 'package:sapaly_shop/themes/app_theme.dart';
|
||||
|
||||
import '../../../common/custom_button.dart';
|
||||
import '../../../common/widgets/custom_text_field.dart';
|
||||
import '../../../constants/global_variables.dart';
|
||||
import '../../../models/auth/register/register_request_model.dart';
|
||||
|
||||
class RegisterScreen extends StatefulWidget {
|
||||
static const String routeName = '/register';
|
||||
const RegisterScreen({super.key});
|
||||
|
||||
@override
|
||||
State<RegisterScreen> createState() => _LoginScreenState();
|
||||
}
|
||||
|
||||
class _LoginScreenState extends State<RegisterScreen> {
|
||||
final TextEditingController emailController = TextEditingController();
|
||||
final TextEditingController phoneController = TextEditingController();
|
||||
final TextEditingController passwordController = TextEditingController();
|
||||
final TextEditingController passwordConfirmationController =
|
||||
TextEditingController();
|
||||
final AuthService authService = AuthService();
|
||||
final formKey = GlobalKey<FormState>();
|
||||
|
||||
void register() {
|
||||
authService.register(
|
||||
registerRequestModel: RegisterRequestModel(
|
||||
email: emailController.text,
|
||||
password: passwordController.text,
|
||||
passwordConfirmation: passwordConfirmationController.text,
|
||||
phone: phoneController.text,
|
||||
),
|
||||
context: context,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
emailController.dispose();
|
||||
phoneController.dispose();
|
||||
passwordController.dispose();
|
||||
passwordConfirmationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: Container(),
|
||||
),
|
||||
body: Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
margin: EdgeInsets.symmetric(
|
||||
vertical: GlobalVariables.verticalPadding(context) / 2,
|
||||
horizontal: GlobalVariables.horizontalPadding(context),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: GlobalVariables.verticalPadding(context) / 2,
|
||||
horizontal: GlobalVariables.horizontalPadding(context),
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10.adaptedPx()),
|
||||
border: Border.all(
|
||||
width: 2.adaptedPx(),
|
||||
color: AppTheme.blackColor.withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
height: GlobalVariables.deviceHeight(context) / 1.5,
|
||||
child: Form(
|
||||
key: formKey,
|
||||
child: ListView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: 15.adaptedPx(),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/sapalyLogo.png',
|
||||
),
|
||||
SizedBox(width: 15.adaptedPx()),
|
||||
Text(
|
||||
GlobalVariables.kAppName,
|
||||
style: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.bodyMedium
|
||||
?.copyWith(
|
||||
color: AppTheme.blackColor,
|
||||
fontSize: 18.adaptedPx(),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 15.adaptedPx()),
|
||||
child: CustomTextField(
|
||||
controller: emailController,
|
||||
labelText: 'your_email',
|
||||
hintText: 'enter_your_email_here',
|
||||
obscureText: false,
|
||||
inputType: TextInputType.emailAddress,
|
||||
),
|
||||
),
|
||||
CustomTextField(
|
||||
controller: phoneController,
|
||||
labelText: 'your_phone_number',
|
||||
hintText: '64283513',
|
||||
obscureText: false,
|
||||
inputType: TextInputType.phone,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 15.adaptedPx()),
|
||||
child: CustomTextField(
|
||||
controller: passwordController,
|
||||
labelText: 'your_password',
|
||||
hintText: 'enter_your_password_here',
|
||||
obscureText: true,
|
||||
inputType: TextInputType.visiblePassword,
|
||||
),
|
||||
),
|
||||
CustomTextField(
|
||||
controller: passwordConfirmationController,
|
||||
labelText: 'repeat_password',
|
||||
hintText: 'repeat_password_to_confirm',
|
||||
obscureText: true,
|
||||
inputType: TextInputType.visiblePassword,
|
||||
),
|
||||
SizedBox(height: 20.adaptedPx()),
|
||||
CustomButton(
|
||||
name: 'register',
|
||||
onTap: () async {
|
||||
if (formKey.currentState!.validate()) {
|
||||
register();
|
||||
}
|
||||
},
|
||||
isMain: true,
|
||||
backgroundColor: AppTheme.lightPrimaryColor,
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
'or',
|
||||
textAlign: TextAlign.center,
|
||||
style:
|
||||
Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
|
||||
color: AppTheme.blackColor,
|
||||
fontSize: 14.adaptedPx(),
|
||||
),
|
||||
),
|
||||
),
|
||||
CustomButton(
|
||||
name: 'login',
|
||||
isMain: false,
|
||||
onTap: () {
|
||||
PageNavigator(ctx: context)
|
||||
.nextPageOnly(page: LoginScreen());
|
||||
},
|
||||
backgroundColor: AppTheme.lightTextColor.withOpacity(0.150),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,10 @@ import 'package:adaptix/adaptix.dart';
|
|||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:sapaly_shop/components/sapaly_app_bar.dart';
|
||||
import 'package:sapaly_shop/features/widgets/sapaly_app_bar.dart';
|
||||
import 'package:sapaly_shop/models/category_model.dart';
|
||||
import 'package:sapaly_shop/models/settings_model.dart';
|
||||
import 'package:sapaly_shop/services/requests.dart';
|
||||
import 'package:sapaly_shop/features/services/requests.dart';
|
||||
import 'package:sapaly_shop/themes/app_theme.dart';
|
||||
|
||||
class CategoryScreen extends StatefulWidget {
|
||||
|
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:sapaly_shop/themes/app_theme.dart';
|
||||
|
||||
import '../../services/app_constants.dart';
|
||||
import '../../../constants/global_variables.dart';
|
||||
|
||||
class Dashboard extends StatelessWidget {
|
||||
const Dashboard({super.key});
|
||||
|
|
@ -15,7 +15,7 @@ class Dashboard extends StatelessWidget {
|
|||
color: AppTheme.lightBackgroundColor,
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
height: AppConstants.deviceHeight(context) / 2,
|
||||
height: GlobalVariables.deviceHeight(context) / 2,
|
||||
margin: EdgeInsets.symmetric(horizontal: 15.adaptedPx()),
|
||||
decoration: BoxDecoration(
|
||||
color: AppTheme.whiteColor,
|
||||
|
|
@ -33,7 +33,7 @@ class Dashboard extends StatelessWidget {
|
|||
),
|
||||
SizedBox(width: 10.adaptedPx()),
|
||||
Text(
|
||||
AppConstants.kAppName,
|
||||
GlobalVariables.kAppName,
|
||||
style: GoogleFonts.poppins(
|
||||
textStyle:
|
||||
Theme.of(context).primaryTextTheme.bodyMedium!.copyWith(
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import 'package:adaptix/adaptix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:sapaly_shop/components/sapaly_app_bar.dart';
|
||||
import 'package:sapaly_shop/features/widgets/sapaly_app_bar.dart';
|
||||
import 'package:sapaly_shop/models/details_model.dart';
|
||||
import 'package:sapaly_shop/models/settings_model.dart';
|
||||
import 'package:sapaly_shop/services/requests.dart';
|
||||
import 'package:sapaly_shop/features/services/requests.dart';
|
||||
import 'package:sapaly_shop/themes/app_theme.dart';
|
||||
|
||||
class Details extends StatefulWidget {
|
||||
|
|
@ -2,15 +2,15 @@ import 'package:adaptix/adaptix.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:sapaly_shop/screens/category/category_screen.dart';
|
||||
import 'package:sapaly_shop/screens/drawer/contacts.dart';
|
||||
import 'package:sapaly_shop/screens/drawer/new_arrival.dart';
|
||||
import 'package:sapaly_shop/screens/drawer/sales.dart';
|
||||
import 'package:sapaly_shop/screens/drawer/shops.dart';
|
||||
import 'package:sapaly_shop/features/screens/category/category_screen.dart';
|
||||
import 'package:sapaly_shop/features/screens/drawer/contacts.dart';
|
||||
import 'package:sapaly_shop/features/screens/drawer/new_arrival.dart';
|
||||
import 'package:sapaly_shop/features/screens/drawer/sales.dart';
|
||||
import 'package:sapaly_shop/features/screens/drawer/shops.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
import '../../services/app_constants.dart';
|
||||
import '../../themes/app_theme.dart';
|
||||
import '../../../constants/global_variables.dart';
|
||||
import '../../../themes/app_theme.dart';
|
||||
import 'about_us.dart';
|
||||
|
||||
class SapalyDrawer extends StatelessWidget {
|
||||
|
|
@ -62,7 +62,7 @@ class SapalyDrawer extends StatelessWidget {
|
|||
),
|
||||
SizedBox(width: 10.adaptedPx()),
|
||||
Text(
|
||||
AppConstants.kAppName,
|
||||
GlobalVariables.kAppName,
|
||||
style: GoogleFonts.poppins(
|
||||
textStyle: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
|
|
@ -121,8 +121,9 @@ class SapalyDrawer extends StatelessWidget {
|
|||
return TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: AppConstants.verticalPadding(context) / 2,
|
||||
horizontal: AppConstants.horizontalPadding(context) / 2,
|
||||
vertical: GlobalVariables.verticalPadding(context) / 2,
|
||||
horizontal:
|
||||
GlobalVariables.horizontalPadding(context) / 2,
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
|
|
@ -8,14 +8,14 @@ import 'package:google_fonts/google_fonts.dart';
|
|||
import 'package:sapaly_shop/models/settings_model.dart';
|
||||
import 'package:sapaly_shop/models/sliders_model.dart';
|
||||
import 'package:sapaly_shop/models/subcategory_model.dart';
|
||||
import 'package:sapaly_shop/screens/drawer/sapaly_drawer.dart';
|
||||
import 'package:sapaly_shop/screens/home/product.dart';
|
||||
import 'package:sapaly_shop/screens/home/search.dart';
|
||||
import 'package:sapaly_shop/services/app_constants.dart';
|
||||
import 'package:sapaly_shop/services/requests.dart';
|
||||
import 'package:sapaly_shop/features/screens/drawer/sapaly_drawer.dart';
|
||||
import 'package:sapaly_shop/features/screens/home/product.dart';
|
||||
import 'package:sapaly_shop/features/screens/home/search.dart';
|
||||
import 'package:sapaly_shop/features/services/requests.dart';
|
||||
|
||||
import '../../components/sapaly_app_bar.dart';
|
||||
import '../../themes/app_theme.dart';
|
||||
import '../../widgets/sapaly_app_bar.dart';
|
||||
import '../../../constants/global_variables.dart';
|
||||
import '../../../themes/app_theme.dart';
|
||||
|
||||
class HomeScreen extends StatefulWidget {
|
||||
const HomeScreen({super.key});
|
||||
|
|
@ -92,8 +92,8 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
|||
),
|
||||
body: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: AppConstants.verticalPadding(context) / 2,
|
||||
horizontal: AppConstants.horizontalPadding(context),
|
||||
vertical: GlobalVariables.verticalPadding(context) / 2,
|
||||
horizontal: GlobalVariables.horizontalPadding(context),
|
||||
),
|
||||
child: NestedScrollView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
|
|
@ -153,7 +153,8 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
|
|||
for (int i = 0; i < sliders.length; i++)
|
||||
CachedNetworkImage(
|
||||
imageUrl: sliders[i].img,
|
||||
width: AppConstants.deviceWidth(context),
|
||||
width:
|
||||
GlobalVariables.deviceWidth(context),
|
||||
fit: BoxFit.contain,
|
||||
progressIndicatorBuilder:
|
||||
(context, url, progress) =>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:sapaly_shop/models/product_model.dart';
|
||||
|
||||
import '../../components/product_card.dart';
|
||||
import '../../widgets/product_card.dart';
|
||||
import '../../services/requests.dart';
|
||||
import '../details/details.dart';
|
||||
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import 'package:adaptix/adaptix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../components/sapaly_app_bar.dart';
|
||||
import '../../services/app_constants.dart';
|
||||
import '../../themes/app_theme.dart';
|
||||
import '../../widgets/sapaly_app_bar.dart';
|
||||
import '../../../constants/global_variables.dart';
|
||||
import '../../../themes/app_theme.dart';
|
||||
|
||||
class SearchScreen extends StatelessWidget {
|
||||
const SearchScreen({super.key});
|
||||
|
|
@ -25,12 +25,12 @@ class SearchScreen extends StatelessWidget {
|
|||
),
|
||||
body: ListView(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: AppConstants.horizontalPadding(context),
|
||||
horizontal: GlobalVariables.horizontalPadding(context),
|
||||
),
|
||||
shrinkWrap: true,
|
||||
scrollDirection: Axis.vertical,
|
||||
children: [
|
||||
SizedBox(height: AppConstants.verticalPadding(context)),
|
||||
SizedBox(height: GlobalVariables.verticalPadding(context)),
|
||||
SizedBox(height: 15.adaptedPx()),
|
||||
],
|
||||
),
|
||||
|
|
@ -2,7 +2,7 @@ import 'package:adaptix/adaptix.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:sapaly_shop/themes/app_theme.dart';
|
||||
|
||||
import '../services/app_constants.dart';
|
||||
import '../../constants/global_variables.dart';
|
||||
|
||||
class OnboardingScreen extends StatelessWidget {
|
||||
OnboardingScreen({super.key});
|
||||
|
|
@ -13,9 +13,9 @@ class OnboardingScreen extends StatelessWidget {
|
|||
body: Center(
|
||||
child: Container(
|
||||
margin: EdgeInsets.symmetric(
|
||||
horizontal: AppConstants.horizontalPadding(context),
|
||||
horizontal: GlobalVariables.horizontalPadding(context),
|
||||
),
|
||||
height: AppConstants.deviceHeight(context) / (1.7),
|
||||
height: GlobalVariables.deviceHeight(context) / (1.7),
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:sapaly_shop/constants/global_variables.dart';
|
||||
import 'package:sapaly_shop/constants/utils.dart';
|
||||
import 'package:sapaly_shop/models/auth/login/login_request_model.dart';
|
||||
import 'package:sapaly_shop/models/auth/login/login_response_model.dart';
|
||||
import 'package:sapaly_shop/models/auth/register/register_request_model.dart';
|
||||
import 'package:sapaly_shop/models/auth/register/register_response_model.dart';
|
||||
import '../../constants/error_handling.dart';
|
||||
|
||||
class AuthService {
|
||||
// Register
|
||||
Future<void> register({
|
||||
required RegisterRequestModel registerRequestModel,
|
||||
required BuildContext context,
|
||||
}) async {
|
||||
try {
|
||||
var response = await http.post(
|
||||
Uri.parse('$kBaseUrl/jwt/register'),
|
||||
body: registerRequestModel.toJson(),
|
||||
headers: {'Accept': 'application/json'},
|
||||
);
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
var data = response.body;
|
||||
var registerResponse = registerResponseModelFromJson(data);
|
||||
}
|
||||
httpErrorHandle(
|
||||
response: response,
|
||||
context: context,
|
||||
onSuccess: () {
|
||||
showSnackBar(
|
||||
context,
|
||||
'successfully_created_now_login',
|
||||
);
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
showSnackBar(context, e.toString());
|
||||
debugPrint('Register Repsponse $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> login({
|
||||
required LoginRequestModel loginRequestModel,
|
||||
required BuildContext context,
|
||||
}) async {
|
||||
try {
|
||||
var response = await http.post(Uri.parse('$kBaseUrl/jwt/login'),
|
||||
body: loginRequestModel.toMap(),
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
});
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
var data = response.body;
|
||||
var loginResponse = LoginResponseModel.fromJson(data);
|
||||
debugPrint('EMAIL ${loginResponse.user.email}');
|
||||
}
|
||||
|
||||
httpErrorHandle(
|
||||
response: response,
|
||||
context: context,
|
||||
onSuccess: () {
|
||||
showSnackBar(
|
||||
context,
|
||||
'successfully_created_now_login',
|
||||
);
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
showSnackBar(context, e.toString());
|
||||
debugPrint('Login Response ${e.toString()}');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,11 +7,11 @@ import 'package:sapaly_shop/models/category_model.dart';
|
|||
import 'package:sapaly_shop/models/details_model.dart';
|
||||
import 'package:sapaly_shop/models/settings_model.dart';
|
||||
import 'package:sapaly_shop/models/sliders_model.dart';
|
||||
import 'package:sapaly_shop/services/app_constants.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../models/product_model.dart';
|
||||
import '../models/subcategory_model.dart';
|
||||
import '../../constants/global_variables.dart';
|
||||
import '../../models/product_model.dart';
|
||||
import '../../models/subcategory_model.dart';
|
||||
|
||||
class API {
|
||||
static Future<dynamic> _getData(String path) async {
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import 'package:adaptix/adaptix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sapaly_shop/themes/app_theme.dart';
|
||||
|
||||
class EmptyWidget extends StatelessWidget {
|
||||
const EmptyWidget({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(),
|
||||
body: Center(
|
||||
child: Text(
|
||||
'This Screen is empty',
|
||||
style: Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
|
||||
fontSize: 18.adaptedPx(),
|
||||
color: AppTheme.lightTextColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
import 'package:adaptix/adaptix.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sapaly_shop/services/app_constants.dart';
|
||||
import 'package:sapaly_shop/themes/app_theme.dart';
|
||||
|
||||
import '../../constants/global_variables.dart';
|
||||
|
||||
class ProductCard extends StatelessWidget {
|
||||
final String imageUrl, price, discountPrice, description;
|
||||
final int discountPriceValue;
|
||||
|
|
@ -45,12 +46,12 @@ class ProductCard extends StatelessWidget {
|
|||
fit: BoxFit.fitWidth,
|
||||
alignment: Alignment.center,
|
||||
placeholder: (context, url) => Container(
|
||||
height: AppConstants.deviceHeight(context) / 7,
|
||||
height: GlobalVariables.deviceHeight(context) / 7,
|
||||
),
|
||||
errorWidget: (context, url, error) => Container(
|
||||
height: AppConstants.deviceHeight(context) / 7,
|
||||
height: GlobalVariables.deviceHeight(context) / 7,
|
||||
),
|
||||
height: AppConstants.deviceHeight(context) / 7,
|
||||
height: GlobalVariables.deviceHeight(context) / 7,
|
||||
width: double.infinity,
|
||||
),
|
||||
),
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import 'package:adaptix/adaptix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sapaly_shop/components/sapaly_icon.dart';
|
||||
import 'package:sapaly_shop/features/widgets/sapaly_icon.dart';
|
||||
|
||||
import '../themes/app_theme.dart';
|
||||
import '../../themes/app_theme.dart';
|
||||
|
||||
class SapalyAppBar extends StatelessWidget with PreferredSizeWidget {
|
||||
const SapalyAppBar({
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:adaptix/adaptix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../themes/app_theme.dart';
|
||||
import '../../themes/app_theme.dart';
|
||||
|
||||
class SapalyIcon extends StatelessWidget {
|
||||
const SapalyIcon({
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import 'package:adaptix/adaptix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sapaly_shop/themes/app_theme.dart';
|
||||
|
||||
class NoScreen extends StatelessWidget {
|
||||
const NoScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Text(
|
||||
'This screen does not exist',
|
||||
style: Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
|
||||
fontSize: 16.adaptedPx(),
|
||||
color: AppTheme.blackColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +1,18 @@
|
|||
import 'package:adaptix/adaptix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:sapaly_shop/screens/category/category_screen.dart';
|
||||
import 'package:sapaly_shop/screens/dashboard/dashboard.dart';
|
||||
import 'package:sapaly_shop/screens/drawer/sapaly_drawer.dart';
|
||||
import 'package:sapaly_shop/screens/home/home_screen.dart';
|
||||
import 'package:sapaly_shop/services/app_constants.dart';
|
||||
import 'package:sapaly_shop/screens/auth/login/login_screen.dart';
|
||||
import 'package:sapaly_shop/features/screens/category/category_screen.dart';
|
||||
import 'package:sapaly_shop/features/screens/dashboard/dashboard.dart';
|
||||
import 'package:sapaly_shop/features/screens/drawer/sapaly_drawer.dart';
|
||||
import 'package:sapaly_shop/features/screens/home/home_screen.dart';
|
||||
import 'package:sapaly_shop/features/screens/auth/login/login_screen.dart';
|
||||
import 'package:sapaly_shop/router.dart';
|
||||
import 'package:sapaly_shop/themes/app_theme.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'models/settings_model.dart';
|
||||
import 'constants/global_variables.dart';
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await SettingsModel.initLocalization(
|
||||
prefs.getString('language') ?? kDefaultLanguage);
|
||||
runApp(
|
||||
MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (_) => SettingsModel(prefs)),
|
||||
],
|
||||
child: const MyApp(),
|
||||
),
|
||||
);
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
|
|
@ -39,6 +27,7 @@ class MyApp extends StatelessWidget {
|
|||
theme: AppTheme.appLightTheme,
|
||||
title: 'Sapaly Mahabat',
|
||||
initialRoute: '/login',
|
||||
onGenerateRoute: (settings) => generateRoute(settings),
|
||||
routes: <String, WidgetBuilder>{
|
||||
'/': (context) => const Dashboard(),
|
||||
'/drawer': (context) => SapalyDrawer(),
|
||||
|
|
@ -46,8 +35,8 @@ class MyApp extends StatelessWidget {
|
|||
'/category': (context) => const CategoryScreen(),
|
||||
'/login': (context) => LoginScreen(),
|
||||
},
|
||||
localizationsDelegates: AppConstants.localizationsDelegate,
|
||||
supportedLocales: AppConstants.supportedLocales,
|
||||
localizationsDelegates: GlobalVariables.localizationsDelegate,
|
||||
supportedLocales: GlobalVariables.supportedLocales,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
import 'dart:convert';
|
||||
|
||||
class LoginRequestModel {
|
||||
final String email;
|
||||
final String password;
|
||||
LoginRequestModel({
|
||||
required this.email,
|
||||
required this.password,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'email': email,
|
||||
'password': password,
|
||||
};
|
||||
}
|
||||
|
||||
factory LoginRequestModel.fromMap(Map<String, dynamic> map) {
|
||||
return LoginRequestModel(
|
||||
email: map['email'] ?? '',
|
||||
password: map['password'] ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory LoginRequestModel.fromJson(String source) =>
|
||||
LoginRequestModel.fromMap(json.decode(source));
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// To parse this JSON data, do
|
||||
//
|
||||
// final userResponseModel = userResponseModelFromJson(jsonString);
|
||||
|
||||
class LoginResponseModel {
|
||||
final String token;
|
||||
final String expires;
|
||||
final User user;
|
||||
LoginResponseModel({
|
||||
required this.token,
|
||||
required this.expires,
|
||||
required this.user,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'token': token,
|
||||
'expires': expires,
|
||||
'user': user.toMap(),
|
||||
};
|
||||
}
|
||||
|
||||
factory LoginResponseModel.fromMap(Map<String, dynamic> map) {
|
||||
return LoginResponseModel(
|
||||
token: map['data']['token'] ?? '',
|
||||
expires: map['data']['expires'] ?? '',
|
||||
user: User.fromMap(map['data']['user']),
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory LoginResponseModel.fromJson(String source) =>
|
||||
LoginResponseModel.fromMap(json.decode(source));
|
||||
}
|
||||
|
||||
class User {
|
||||
final int id;
|
||||
final String email;
|
||||
final String name;
|
||||
final String lastName;
|
||||
final String middleName;
|
||||
final String phone;
|
||||
final String phoneShort;
|
||||
final bool isActivated;
|
||||
final String lastLogin;
|
||||
final int isSuperuser;
|
||||
final String createdAt;
|
||||
final String updatedAt;
|
||||
final List<String> phoneList;
|
||||
User({
|
||||
required this.id,
|
||||
required this.email,
|
||||
required this.name,
|
||||
required this.lastName,
|
||||
required this.middleName,
|
||||
required this.phone,
|
||||
required this.phoneShort,
|
||||
required this.isActivated,
|
||||
required this.lastLogin,
|
||||
required this.isSuperuser,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.phoneList,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'id': id,
|
||||
'email': email,
|
||||
'name': name,
|
||||
'lastName': lastName,
|
||||
'middleName': middleName,
|
||||
'phone': phone,
|
||||
'phoneShort': phoneShort,
|
||||
'isActivated': isActivated,
|
||||
'lastLogin': lastLogin,
|
||||
'isSuperuser': isSuperuser,
|
||||
'createdAt': createdAt,
|
||||
'updatedAt': updatedAt,
|
||||
'phone_list': phoneList,
|
||||
};
|
||||
}
|
||||
|
||||
factory User.fromMap(Map<String, dynamic> map) {
|
||||
return User(
|
||||
id: map['id'] ?? 0,
|
||||
email: map['email'] ?? '',
|
||||
name: map['name'] ?? '',
|
||||
lastName: map['lastName'] ?? '',
|
||||
middleName: map['middleName'] ?? '',
|
||||
phone: map['phone'] ?? '',
|
||||
phoneShort: map['phoneShort'] ?? '',
|
||||
isActivated: map['isActivated'] ?? false,
|
||||
lastLogin: map['lastLogin'] ?? '',
|
||||
isSuperuser: map['isSuperuser'] ?? 0,
|
||||
createdAt: map['createdAt'] ?? '',
|
||||
updatedAt: map['updatedAt'] ?? '',
|
||||
phoneList: List<String>.from(map['phone_list']),
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory User.fromJson(String source) => User.fromMap(json.decode(source));
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'dart:convert';
|
||||
|
||||
class UserRequestModel {
|
||||
String? email;
|
||||
String? password;
|
||||
UserRequestModel({
|
||||
this.email,
|
||||
this.password,
|
||||
});
|
||||
|
||||
UserRequestModel copyWith({
|
||||
String? email,
|
||||
String? password,
|
||||
}) {
|
||||
return UserRequestModel(
|
||||
email: email ?? this.email,
|
||||
password: password ?? this.password,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return <String, dynamic>{
|
||||
'email': email,
|
||||
'password': password,
|
||||
};
|
||||
}
|
||||
|
||||
factory UserRequestModel.fromMap(Map<String, dynamic> map) {
|
||||
return UserRequestModel(
|
||||
email: map['email'] != null ? map['email'] as String : null,
|
||||
password: map['password'] != null ? map['password'] as String : null,
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory UserRequestModel.fromJson(String source) =>
|
||||
UserRequestModel.fromMap(json.decode(source) as Map<String, dynamic>);
|
||||
|
||||
@override
|
||||
String toString() => 'UserRequestModel(email: $email, password: $password)';
|
||||
|
||||
@override
|
||||
bool operator ==(covariant UserRequestModel other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other.email == email && other.password == password;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => email.hashCode ^ password.hashCode;
|
||||
}
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
// To parse this JSON data, do
|
||||
//
|
||||
// final userResponseModel = userResponseModelFromJson(jsonString);
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
UserResponseModel userResponseModelFromJson(String str) =>
|
||||
UserResponseModel.fromJson(json.decode(str));
|
||||
|
||||
String userResponseModelToJson(UserResponseModel data) =>
|
||||
json.encode(data.toJson());
|
||||
|
||||
class UserResponseModel {
|
||||
UserResponseModel({
|
||||
required this.token,
|
||||
required this.expires,
|
||||
required this.user,
|
||||
});
|
||||
|
||||
final String token;
|
||||
final DateTime expires;
|
||||
final User user;
|
||||
|
||||
factory UserResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
UserResponseModel(
|
||||
token: json["token"],
|
||||
expires: DateTime.parse(json["expires"]),
|
||||
user: User.fromJson(json["user"]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"token": token,
|
||||
"expires": expires.toIso8601String(),
|
||||
"user": user.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
class User {
|
||||
User({
|
||||
required this.id,
|
||||
required this.email,
|
||||
required this.name,
|
||||
required this.lastName,
|
||||
required this.middleName,
|
||||
required this.phone,
|
||||
required this.phoneShort,
|
||||
required this.permissions,
|
||||
required this.isActivated,
|
||||
required this.activatedAt,
|
||||
required this.lastLogin,
|
||||
required this.isSuperuser,
|
||||
required this.property,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.deletedAt,
|
||||
required this.phoneList,
|
||||
});
|
||||
|
||||
final int id;
|
||||
final String email;
|
||||
final String name;
|
||||
final String lastName;
|
||||
final String middleName;
|
||||
final String phone;
|
||||
final String phoneShort;
|
||||
final dynamic permissions;
|
||||
final bool isActivated;
|
||||
final dynamic activatedAt;
|
||||
final DateTime lastLogin;
|
||||
final int isSuperuser;
|
||||
final dynamic property;
|
||||
final DateTime createdAt;
|
||||
final DateTime updatedAt;
|
||||
final dynamic deletedAt;
|
||||
final List<String> phoneList;
|
||||
|
||||
factory User.fromJson(Map<String, dynamic> json) => User(
|
||||
id: json["id"],
|
||||
email: json["email"],
|
||||
name: json["name"],
|
||||
lastName: json["last_name"],
|
||||
middleName: json["middle_name"],
|
||||
phone: json["phone"],
|
||||
phoneShort: json["phone_short"],
|
||||
permissions: json["permissions"],
|
||||
isActivated: json["is_activated"],
|
||||
activatedAt: json["activated_at"],
|
||||
lastLogin: DateTime.parse(json["last_login"]),
|
||||
isSuperuser: json["is_superuser"],
|
||||
property: json["property"],
|
||||
createdAt: DateTime.parse(json["created_at"]),
|
||||
updatedAt: DateTime.parse(json["updated_at"]),
|
||||
deletedAt: json["deleted_at"],
|
||||
phoneList: List<String>.from(json["phone_list"].map((x) => x)),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"id": id,
|
||||
"email": email,
|
||||
"name": name,
|
||||
"last_name": lastName,
|
||||
"middle_name": middleName,
|
||||
"phone": phone,
|
||||
"phone_short": phoneShort,
|
||||
"permissions": permissions,
|
||||
"is_activated": isActivated,
|
||||
"activated_at": activatedAt,
|
||||
"last_login": lastLogin.toIso8601String(),
|
||||
"is_superuser": isSuperuser,
|
||||
"property": property,
|
||||
"created_at": createdAt.toIso8601String(),
|
||||
"updated_at": updatedAt.toIso8601String(),
|
||||
"deleted_at": deletedAt,
|
||||
"phone_list": List<dynamic>.from(phoneList.map((x) => x)),
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'dart:convert';
|
||||
|
||||
class RegisterRequestModel {
|
||||
String email;
|
||||
String password;
|
||||
String passwordConfirmation;
|
||||
String phone;
|
||||
RegisterRequestModel({
|
||||
required this.email,
|
||||
required this.password,
|
||||
required this.passwordConfirmation,
|
||||
required this.phone,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'email': email,
|
||||
'password': password,
|
||||
'password_confirmation': passwordConfirmation,
|
||||
'phone': phone,
|
||||
};
|
||||
}
|
||||
|
||||
factory RegisterRequestModel.fromMap(Map<String, dynamic> map) {
|
||||
return RegisterRequestModel(
|
||||
email: map['email'] ?? '',
|
||||
password: map['password'] ?? '',
|
||||
passwordConfirmation: map['password_confirmation'] ?? '',
|
||||
phone: map['phone'] ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory RegisterRequestModel.fromJson(String source) =>
|
||||
RegisterRequestModel.fromMap(json.decode(source));
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
// To parse this JSON data, do
|
||||
//
|
||||
// final registerResponseModel = registerResponseModelFromJson(jsonString);
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
RegisterResponseModel registerResponseModelFromJson(String str) =>
|
||||
RegisterResponseModel.fromJson(json.decode(str));
|
||||
|
||||
String registerResponseModelToJson(RegisterResponseModel data) =>
|
||||
json.encode(data.toJson());
|
||||
|
||||
class RegisterResponseModel {
|
||||
RegisterResponseModel({
|
||||
required this.token,
|
||||
required this.expires,
|
||||
required this.user,
|
||||
});
|
||||
|
||||
final String token;
|
||||
final DateTime expires;
|
||||
final User user;
|
||||
|
||||
factory RegisterResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
RegisterResponseModel(
|
||||
token: json['data']["token"],
|
||||
expires: DateTime.parse(json['data']["expires"]),
|
||||
user: User.fromJson(json['data']["user"]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"token": token,
|
||||
"expires": expires.toIso8601String(),
|
||||
"user": user.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
class User {
|
||||
final int id;
|
||||
final String email;
|
||||
final String name;
|
||||
final String lastName;
|
||||
final String middleName;
|
||||
final String phone;
|
||||
final String phoneShort;
|
||||
final bool isActivated;
|
||||
final DateTime lastLogin;
|
||||
final int isSuperuser;
|
||||
final DateTime createdAt;
|
||||
final DateTime updatedAt;
|
||||
final List<String> phoneList;
|
||||
User({
|
||||
required this.id,
|
||||
required this.email,
|
||||
required this.name,
|
||||
required this.lastName,
|
||||
required this.middleName,
|
||||
required this.phone,
|
||||
required this.phoneShort,
|
||||
required this.isActivated,
|
||||
required this.lastLogin,
|
||||
required this.isSuperuser,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.phoneList,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'id': id,
|
||||
'email': email,
|
||||
'name': name,
|
||||
'lastName': lastName,
|
||||
'middleName': middleName,
|
||||
'phone': phone,
|
||||
'phoneShort': phoneShort,
|
||||
'isActivated': isActivated,
|
||||
'lastLogin': lastLogin.millisecondsSinceEpoch,
|
||||
'isSuperuser': isSuperuser,
|
||||
'createdAt': createdAt.millisecondsSinceEpoch,
|
||||
'updatedAt': updatedAt.millisecondsSinceEpoch,
|
||||
'phone_list': phoneList,
|
||||
};
|
||||
}
|
||||
|
||||
factory User.fromMap(Map<String, dynamic> map) {
|
||||
return User(
|
||||
id: map['id']?.toInt() ?? 0,
|
||||
email: map['email'] ?? '',
|
||||
name: map['name'] ?? '',
|
||||
lastName: map['lastName'] ?? '',
|
||||
middleName: map['middleName'] ?? '',
|
||||
phone: map['phone'] ?? '',
|
||||
phoneShort: map['phoneShort'] ?? '',
|
||||
isActivated: map['isActivated'] ?? false,
|
||||
lastLogin: DateTime.fromMillisecondsSinceEpoch(map['lastLogin']),
|
||||
isSuperuser: map['isSuperuser']?.toInt() ?? 0,
|
||||
createdAt: DateTime.fromMillisecondsSinceEpoch(map['createdAt']),
|
||||
updatedAt: DateTime.fromMillisecondsSinceEpoch(map['updatedAt']),
|
||||
phoneList: List<String>.from(map['phone_list']),
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory User.fromJson(String source) => User.fromMap(json.decode(source));
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import 'dart:convert';
|
||||
|
||||
class Vendor {
|
||||
final String id;
|
||||
final String password;
|
||||
final String address;
|
||||
final String token;
|
||||
Vendor({
|
||||
required this.id,
|
||||
required this.password,
|
||||
required this.address,
|
||||
required this.token,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'id': id,
|
||||
'password': password,
|
||||
'address': address,
|
||||
'token': token,
|
||||
};
|
||||
}
|
||||
|
||||
factory Vendor.fromMap(Map<String, dynamic> map) {
|
||||
return Vendor(
|
||||
id: map['id'] ?? '',
|
||||
password: map['password'] ?? '',
|
||||
address: map['address'] ?? '',
|
||||
token: map['token'] ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory Vendor.fromJson(String source) => Vendor.fromMap(json.decode(source));
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'features/screens/auth/login/login_screen.dart';
|
||||
import 'features/widgets/empty_widget.dart';
|
||||
|
||||
Route<dynamic> generateRoute(RouteSettings routeSettings) {
|
||||
switch (routeSettings.name) {
|
||||
case LoginScreen.routeName:
|
||||
return MaterialPageRoute(builder: (_) => LoginScreen());
|
||||
default:
|
||||
return MaterialPageRoute(
|
||||
settings: routeSettings,
|
||||
builder: (_) => const EmptyWidget(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,194 +0,0 @@
|
|||
import 'package:adaptix/adaptix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sapaly_shop/models/settings_model.dart';
|
||||
import 'package:sapaly_shop/services/app_constants.dart';
|
||||
import 'package:sapaly_shop/themes/app_theme.dart';
|
||||
|
||||
class LoginScreen extends StatefulWidget {
|
||||
LoginScreen({super.key});
|
||||
|
||||
@override
|
||||
State<LoginScreen> createState() => _LoginScreenState();
|
||||
}
|
||||
|
||||
class _LoginScreenState extends State<LoginScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final EdgeInsets paddingLow = EdgeInsets.symmetric(
|
||||
vertical: AppConstants.verticalPadding(context) / 2,
|
||||
horizontal: AppConstants.horizontalPadding(context),
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: Container(),
|
||||
),
|
||||
body: Container(
|
||||
margin: EdgeInsets.symmetric(
|
||||
vertical: AppConstants.verticalPadding(context) / 2,
|
||||
horizontal: AppConstants.horizontalPadding(context),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: AppConstants.verticalPadding(context) / 2,
|
||||
horizontal: AppConstants.horizontalPadding(context),
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10.adaptedPx()),
|
||||
border: Border.all(
|
||||
width: 2.adaptedPx(),
|
||||
color: AppTheme.blackColor.withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
height: AppConstants.deviceHeight(context) / 1.450,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: 30.adaptedPx(),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/sapalyLogo.png',
|
||||
),
|
||||
SizedBox(width: 15.adaptedPx()),
|
||||
Text(
|
||||
AppConstants.kAppName,
|
||||
style:
|
||||
Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
|
||||
color: AppTheme.blackColor,
|
||||
fontSize: 18.adaptedPx(),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 40.adaptedPx()),
|
||||
Text(
|
||||
'enter_your_email'.translation,
|
||||
textAlign: TextAlign.left,
|
||||
style: Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
|
||||
color: AppTheme.blackColor,
|
||||
fontSize: 15.adaptedPx(),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 15.adaptedPx()),
|
||||
TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Login',
|
||||
labelStyle:
|
||||
Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
|
||||
color: AppTheme.lightTextColor,
|
||||
fontSize: 13.adaptedPx(),
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(5.adaptedPx()),
|
||||
borderSide: BorderSide(
|
||||
color: AppTheme.lightTextColor,
|
||||
width: 2.adaptedPx(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
EdgeInsets.only(top: 30.adaptedPx(), bottom: 10.adaptedPx()),
|
||||
child: Text(
|
||||
'enter_your_password'.translation,
|
||||
textAlign: TextAlign.left,
|
||||
style: Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
|
||||
color: AppTheme.blackColor,
|
||||
fontSize: 15.adaptedPx(),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Password',
|
||||
labelStyle:
|
||||
Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
|
||||
color: AppTheme.lightTextColor,
|
||||
fontSize: 13.adaptedPx(),
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(5.adaptedPx()),
|
||||
borderSide: BorderSide(
|
||||
color: AppTheme.lightTextColor,
|
||||
width: 2.adaptedPx(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20.adaptedPx()),
|
||||
Container(
|
||||
height: AppConstants.deviceHeight(context) / 15,
|
||||
width: double.infinity,
|
||||
margin: EdgeInsets.symmetric(
|
||||
vertical: 5.adaptedPx(),
|
||||
),
|
||||
child: OutlinedButton(
|
||||
onPressed: () {},
|
||||
style: TextButton.styleFrom(
|
||||
backgroundColor: AppTheme.lightPrimaryColor,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10.adaptedPx()),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
'Login',
|
||||
style:
|
||||
Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
|
||||
color: AppTheme.whiteColor,
|
||||
fontSize: 14.adaptedPx(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
'or',
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
|
||||
color: AppTheme.blackColor,
|
||||
fontSize: 14.adaptedPx(),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
height: AppConstants.deviceHeight(context) / 15,
|
||||
width: double.infinity,
|
||||
margin: EdgeInsets.symmetric(
|
||||
vertical: 5.adaptedPx(),
|
||||
),
|
||||
child: OutlinedButton(
|
||||
onPressed: () {},
|
||||
style: TextButton.styleFrom(
|
||||
backgroundColor: AppTheme.lightTextColor.withOpacity(0.1),
|
||||
shape: RoundedRectangleBorder(
|
||||
side:
|
||||
const BorderSide(color: Colors.transparent, width: 0),
|
||||
borderRadius: BorderRadius.circular(10.adaptedPx()),
|
||||
)),
|
||||
child: Text(
|
||||
'Register',
|
||||
style:
|
||||
Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
|
||||
color: AppTheme.blackColor,
|
||||
fontSize: 14.adaptedPx(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sapaly_shop/screens/auth/login/login_screen.dart';
|
||||
import 'package:sapaly_shop/services/app_constants.dart';
|
||||
|
||||
import '../../../services/auth/login_service.dart';
|
||||
|
||||
abstract class LoginViewModel extends State<LoginScreen> {
|
||||
late final LoginService loginService;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
loginService = LoginService(
|
||||
Dio(
|
||||
BaseOptions(
|
||||
baseUrl: kBaseUrl,
|
||||
),
|
||||
),
|
||||
);
|
||||
super.initState();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
import 'dart:io';
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
import '../../models/auth/login/user_request_model.dart';
|
||||
import '../../models/auth/login/user_response_model.dart';
|
||||
|
||||
abstract class ILoginService {
|
||||
final String path = '/jwt/login';
|
||||
|
||||
ILoginService(this.dio);
|
||||
|
||||
Future<UserResponseModel?> fetchLogin(UserRequestModel model);
|
||||
final Dio dio;
|
||||
}
|
||||
|
||||
class LoginService extends ILoginService {
|
||||
LoginService(Dio dio) : super(dio);
|
||||
|
||||
@override
|
||||
Future<UserResponseModel?> fetchLogin(UserRequestModel model) async {
|
||||
final response = await dio.post(path, data: model);
|
||||
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
return UserResponseModel.fromJson(response.data);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -24,10 +24,10 @@ abstract class AppTheme {
|
|||
),
|
||||
);
|
||||
|
||||
static const Color lightBackgroundColor = Color(0xfff5f5f5);
|
||||
static const Color lightPrimaryColor = Color(0xFF5677FC);
|
||||
static const Color lightTextColor = Color(0xFF4B4B4B);
|
||||
static const Color whiteColor = Color(0xFFFFFFFF);
|
||||
static const Color redColor = Color(0xFFEE2F3D);
|
||||
static const Color blackColor = Color(0xFF151515);
|
||||
static const Color lightBackgroundColor = Color.fromRGBO(245, 245, 245, 1);
|
||||
static const Color lightPrimaryColor = Color.fromRGBO(86, 119, 252, 1);
|
||||
static const Color lightTextColor = Color.fromRGBO(75, 75, 75, 1);
|
||||
static const Color whiteColor = Color.fromRGBO(255, 255, 255, 1);
|
||||
static const Color redColor = Color.fromRGBO(238, 47, 61, 1);
|
||||
static const Color blackColor = Color.fromRGBO(21, 21, 21, 1);
|
||||
}
|
||||
|
|
|
|||
82
pubspec.lock
82
pubspec.lock
|
|
@ -146,14 +146,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
cross_file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cross_file
|
||||
sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.3+4"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -194,14 +186,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
dio:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: dio
|
||||
sha256: "3709d74615bba5e443eb141f6a7f4bcc4788f8fae6f743edadfb79c2a8e6287e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -276,14 +260,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.16"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
sha256: "4bef634684b2c7f3468c77c766c831229af829a0cd2d4ee6c1b99558bd14e5d2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.8"
|
||||
flutter_svg:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -342,46 +318,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.0"
|
||||
image_picker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker
|
||||
sha256: "22207768556b82d55ec70166824350fee32298732d5efa4d6e756f848f51f66a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.6+3"
|
||||
image_picker_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_android
|
||||
sha256: "68d067baf7f6e401b1124ee83dd6967e67847314250fd68012aab34a69beb344"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.5+7"
|
||||
image_picker_for_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_for_web
|
||||
sha256: "66fc6e3877bbde82c33d122f3588777c3784ac5bd7d1cdd79213ef7aecb85b34"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.11"
|
||||
image_picker_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_ios
|
||||
sha256: "39aa70b5f1e5e7c94585b9738632d5fdb764a5655e40cd9e7b95fbd2fc50c519"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.6+9"
|
||||
image_picker_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_platform_interface
|
||||
sha256: "1991219d9dbc42a99aff77e663af8ca51ced592cd6685c9485e3458302d3d4f8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.3"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -590,16 +526,8 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
progress_hud:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: progress_hud
|
||||
sha256: c7a79d70d278328cf3b0732c119a89ba96329825deb03b5dd64415c77dfb8ac4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
provider:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: provider
|
||||
sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
|
||||
|
|
@ -683,14 +611,6 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
snippet_coder_utils:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: snippet_coder_utils
|
||||
sha256: fb60b8a6b4cab3dddc17ce903cc073d2f5d42ebed676146dde0faba040dc4158
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.13"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -51,10 +51,6 @@ dependencies:
|
|||
shimmer: ^2.0.0
|
||||
url_launcher: ^6.1.9
|
||||
shared_preferences: ^2.0.17
|
||||
provider: ^6.0.5
|
||||
snippet_coder_utils: ^1.0.13
|
||||
progress_hud: ^1.1.0
|
||||
dio: ^5.0.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
Loading…
Reference in New Issue