mycart
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
// ignore_for_file: library_private_types_in_public_api
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grocery_app/src/ui/cart/cartview_screen.dart';
|
||||
import 'package:grocery_app/src/ui/favourite/favourite_screen.dart';
|
||||
import 'package:grocery_app/src/ui/home/home_screen.dart';
|
||||
import 'package:grocery_app/src/ui/profilepage/profile_screen.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
@@ -25,7 +27,8 @@ class _BottomBarState extends State<BottomBarWidget> {
|
||||
});
|
||||
|
||||
if (bottomWidgetPageController.hasClients) {
|
||||
bottomWidgetPageController.animateToPage(index, duration: const Duration(milliseconds: 100), curve: Curves.ease);
|
||||
bottomWidgetPageController.animateToPage(index,
|
||||
duration: const Duration(milliseconds: 100), curve: Curves.ease);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,10 +50,10 @@ class _BottomBarState extends State<BottomBarWidget> {
|
||||
body: PageView(
|
||||
controller: bottomWidgetPageController,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: const <Widget>[
|
||||
children: <Widget>[
|
||||
HomeScreen(),
|
||||
Text('1'),
|
||||
Text('2'),
|
||||
FavouriteScreen(),
|
||||
Mycart(),
|
||||
ProfileScreen(),
|
||||
],
|
||||
),
|
||||
|
||||
94
lib/src/ui/cart/cart_item.dart
Normal file
94
lib/src/ui/cart/cart_item.dart
Normal file
@@ -0,0 +1,94 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:grocery_app/src/common_widget/network_image.dart';
|
||||
import 'package:grocery_app/src/ui/widgets/custom_icon_button.dart';
|
||||
import 'package:grocery_app/utils/constants/assets_constant.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
|
||||
class CartItem extends StatelessWidget {
|
||||
// final ProductModel product;
|
||||
const CartItem({
|
||||
Key? key,
|
||||
// required this.product,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// final theme = context.theme;
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24.w),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.greenAccent.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: AppNetworkImage(
|
||||
width: 50.w,
|
||||
height: 40.h,
|
||||
imageUrl:
|
||||
'https://i.pinimg.com/originals/a5/f3/5f/a5f35fb23e942809da3df91b23718e8d.png',
|
||||
backGroundColor: APPCOLOR.bgGrey,
|
||||
radius: 10,
|
||||
),
|
||||
),
|
||||
// Image.asset(product.image, width: 50.w, height: 40.h),
|
||||
|
||||
16.horizontalSpace,
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Vegitables and Fruits",
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
|
||||
),
|
||||
5.verticalSpace,
|
||||
Text(
|
||||
'1kg, 10\$',
|
||||
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
Row(
|
||||
children: [
|
||||
CustomIconButton(
|
||||
width: 20.w,
|
||||
height: 20.h,
|
||||
onPressed: () {},
|
||||
icon: SvgPicture.asset(
|
||||
APPASSETS.removeIcon,
|
||||
fit: BoxFit.none,
|
||||
),
|
||||
backgroundColor: APPCOLOR.appGreen,
|
||||
),
|
||||
16.horizontalSpace,
|
||||
Text(
|
||||
"10",
|
||||
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
|
||||
),
|
||||
16.horizontalSpace,
|
||||
CustomIconButton(
|
||||
width: 20.w,
|
||||
height: 20.h,
|
||||
onPressed: () {},
|
||||
icon: SvgPicture.asset(
|
||||
APPASSETS.addIcon,
|
||||
fit: BoxFit.none,
|
||||
),
|
||||
backgroundColor: APPCOLOR.appGreen,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
244
lib/src/ui/cart/cartview_screen.dart
Normal file
244
lib/src/ui/cart/cartview_screen.dart
Normal file
@@ -0,0 +1,244 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_animate/flutter_animate.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:grocery_app/src/common_widget/network_image.dart';
|
||||
import 'package:grocery_app/src/ui/bestdeal/bestdeal_screen.dart';
|
||||
import 'package:grocery_app/src/ui/cart/cart_item.dart';
|
||||
import 'package:grocery_app/src/ui/widgets/custom_icon_button.dart';
|
||||
import 'package:grocery_app/utils/constants/assets_constant.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
|
||||
class Mycart extends StatefulWidget {
|
||||
const Mycart({super.key});
|
||||
|
||||
@override
|
||||
State<Mycart> createState() => _MycartState();
|
||||
}
|
||||
|
||||
class _MycartState extends State<Mycart> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
centerTitle: true,
|
||||
// leading: Center(
|
||||
// child: SizedBox(
|
||||
// height: 20,
|
||||
// width: 20,
|
||||
// child: InkWell(
|
||||
// onTap: () {
|
||||
// Navigator.of(context).pop();
|
||||
// },
|
||||
// child: SvgPicture.asset(
|
||||
// APPASSETS.back,
|
||||
// height: 20,
|
||||
// width: 20,
|
||||
// )),
|
||||
// ),
|
||||
// ),
|
||||
title: Center(
|
||||
child: const Text(
|
||||
'Cart 🛒',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
),
|
||||
// actions: [
|
||||
// InkWell(
|
||||
// onTap: () {},
|
||||
// child: Icon(
|
||||
// MdiIcons.magnify,
|
||||
// size: 35,
|
||||
// ),
|
||||
// )
|
||||
// ],
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ListView.separated(
|
||||
separatorBuilder: (_, index) => Padding(
|
||||
padding: EdgeInsets.only(top: 12.h, bottom: 24.h),
|
||||
child: const Divider(thickness: 1),
|
||||
),
|
||||
itemCount: 10,
|
||||
itemBuilder: (context, index) => CartItem(
|
||||
//product: controller.products[index],
|
||||
)
|
||||
.animate(delay: (100 * index).ms)
|
||||
.fade()
|
||||
.slideX(
|
||||
duration: 300.ms,
|
||||
begin: -1,
|
||||
curve: Curves.easeInSine,
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Best Deal",
|
||||
style: context.customExtraBold(Colors.black, 18),
|
||||
),
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return const BestDealScreen();
|
||||
},
|
||||
));
|
||||
},
|
||||
child: Text(
|
||||
"See All",
|
||||
style: context.customMedium(APPCOLOR.lightGreen, 16),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
SizedBox(
|
||||
height: 222,
|
||||
child: ListView.builder(
|
||||
itemCount: 5,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 10, bottom: 5, top: 5),
|
||||
child: Container(
|
||||
height: 215,
|
||||
width: 150,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.1),
|
||||
blurRadius: 1,
|
||||
offset: const Offset(5, 5),
|
||||
),
|
||||
]),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
height: 100,
|
||||
width: 150,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.bgGrey,
|
||||
borderRadius: BorderRadius.circular(15)),
|
||||
child: const Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
AppNetworkImage(
|
||||
height: 70,
|
||||
width: 70,
|
||||
imageUrl:
|
||||
"https://5.imimg.com/data5/SELLER/Default/2024/2/385126988/OL/DA/VW/8627346/1l-fortune-sunflower-oil.jpg",
|
||||
backGroundColor: Colors.transparent),
|
||||
Positioned(
|
||||
right: 5,
|
||||
top: 5,
|
||||
child: Icon(Icons.favorite_border))
|
||||
],
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"Fortune Arhar Dal (Toor Dal)",
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style:
|
||||
context.customMedium(APPCOLOR.balck1A1A1A, 14),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Text(
|
||||
"500 ML",
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: context.customMedium(
|
||||
Colors.grey.withOpacity(0.8), 12),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 3,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"\$12",
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: context.customSemiBold(
|
||||
Colors.black, 12),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 5,
|
||||
),
|
||||
Text(
|
||||
"\$14",
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: context
|
||||
.customMedium(
|
||||
Colors.grey.withOpacity(0.8), 12)
|
||||
.copyWith(
|
||||
decoration:
|
||||
TextDecoration.lineThrough,
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Container(
|
||||
height: 30,
|
||||
width: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.lightGreen,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Add',
|
||||
style: context.customRegular(
|
||||
Colors.white, 12),
|
||||
)),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,14 @@ import 'package:flutter_svg/svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:grocery_app/src/common_widget/textfield_widget.dart';
|
||||
import 'package:grocery_app/src/core/routes/routes.dart';
|
||||
import 'package:grocery_app/src/logic/provider/auth_provider.dart';
|
||||
import 'package:grocery_app/src/ui/bottomnavigation/bottom_bar_widget.dart';
|
||||
import 'package:grocery_app/utils/constants/assets_constant.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
import 'package:grocery_app/utils/constants/string_constant.dart';
|
||||
import 'package:grocery_app/utils/extensions/extensions.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class EnterFullNameScreen extends StatefulWidget {
|
||||
const EnterFullNameScreen({super.key});
|
||||
@@ -23,6 +25,9 @@ class _EnterFullNameScreenState extends State<EnterFullNameScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
final pageNotifier = Provider.of<AuthProvider>(context, listen: false);
|
||||
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
@@ -53,7 +58,7 @@ class _EnterFullNameScreenState extends State<EnterFullNameScreen> {
|
||||
child: Column(
|
||||
children: [
|
||||
AppTextFieldWidget(
|
||||
controller: TextEditingController(),
|
||||
controller: pageNotifier.name,
|
||||
hintText: APPSTRING.firstNameHint,
|
||||
onValidate: (value){
|
||||
if (value == null || value.isEmpty) {
|
||||
@@ -63,7 +68,7 @@ class _EnterFullNameScreenState extends State<EnterFullNameScreen> {
|
||||
},
|
||||
),
|
||||
AppTextFieldWidget(
|
||||
controller: TextEditingController(),
|
||||
controller: pageNotifier.lastName,
|
||||
hintText: APPSTRING.lastNameHint,
|
||||
onValidate: (value){
|
||||
if (value == null || value.isEmpty) {
|
||||
@@ -72,6 +77,28 @@ class _EnterFullNameScreenState extends State<EnterFullNameScreen> {
|
||||
return null;
|
||||
},
|
||||
),
|
||||
|
||||
AppTextFieldWidget(
|
||||
controller: pageNotifier.email,
|
||||
hintText: APPSTRING.emailHint,
|
||||
onValidate: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please Enter eamil-id';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
AppTextFieldWidget(
|
||||
controller: pageNotifier.address,
|
||||
hintText: APPSTRING.addressHint,
|
||||
onValidate: (value) {
|
||||
if (value == null || value.isEmpty)
|
||||
{
|
||||
return 'Please Enter address';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
@@ -88,11 +115,13 @@ class _EnterFullNameScreenState extends State<EnterFullNameScreen> {
|
||||
padding: context.bodyAllPadding.copyWith(bottom: 20),
|
||||
child: Center(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
onTap: ()
|
||||
{
|
||||
|
||||
if (_formKey.currentState?.validate() ?? false) {
|
||||
context.clearAndPush( routePath: MyRoutes.BOTTOMNAV);
|
||||
}
|
||||
if (_formKey.currentState?.validate() ?? false)
|
||||
{
|
||||
context.clearAndPush( routePath: MyRoutes.BOTTOMNAV);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
153
lib/src/ui/favourite/favourite_screen.dart
Normal file
153
lib/src/ui/favourite/favourite_screen.dart
Normal file
@@ -0,0 +1,153 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grocery_app/src/common_widget/network_image.dart';
|
||||
import 'package:grocery_app/src/data/product_model.dart';
|
||||
import 'package:grocery_app/src/ui/widgets/custom_title.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
|
||||
class FavouriteScreen extends StatefulWidget {
|
||||
@override
|
||||
_FavouriteScreenState createState() => _FavouriteScreenState();
|
||||
}
|
||||
|
||||
class _FavouriteScreenState extends State<FavouriteScreen>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _animationController;
|
||||
late Animation<double> _animation;
|
||||
|
||||
List<ProductModel> _favProducts = [
|
||||
ProductModel("", 'Bell pepper red', '7pcs', '\$4.99'),
|
||||
ProductModel("", 'Ginger', '1kg', '\$4.99'),
|
||||
ProductModel("", 'Egg pasta', '30gm', '\$15.9'),
|
||||
];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_animationController = AnimationController(
|
||||
duration: const Duration(milliseconds: 1000),
|
||||
vsync: this,
|
||||
);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_animationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
CustomTitle(title: 'Favourite'),
|
||||
Expanded(
|
||||
child: ListView.separated(
|
||||
itemCount: _favProducts.length,
|
||||
shrinkWrap: true,
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemBuilder: (_, index)
|
||||
{
|
||||
_animation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
||||
CurvedAnimation(
|
||||
parent: _animationController,
|
||||
curve: Interval(
|
||||
(0.5 / _favProducts.length) * index,
|
||||
1,
|
||||
curve: Curves.easeOut,
|
||||
),
|
||||
),
|
||||
);
|
||||
_animationController.forward(from: 0);
|
||||
|
||||
return AnimatedBuilder(
|
||||
animation: _animationController,
|
||||
builder: (_, child) {
|
||||
return FadeTransition(
|
||||
opacity: _animation,
|
||||
child: Transform(
|
||||
transform: Matrix4.translationValues(
|
||||
0.0,
|
||||
50 * (1.0 - _animation.value),
|
||||
0.0,
|
||||
),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: ListTile(
|
||||
onTap: () {},
|
||||
leading: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.greenAccent.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: AppNetworkImage(
|
||||
height: 80,
|
||||
width: 80,
|
||||
imageUrl:
|
||||
'https://i.pinimg.com/originals/a5/f3/5f/a5f35fb23e942809da3df91b23718e8d.png',
|
||||
backGroundColor: APPCOLOR.bgGrey,
|
||||
radius: 10,
|
||||
),
|
||||
),
|
||||
// Image.asset(_favProducts[index].productImage),
|
||||
title: Text(_favProducts[index].productName),
|
||||
subtitle: Text(_favProducts[index].quantity),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(_favProducts[index].amount),
|
||||
Icon(
|
||||
Icons.navigate_next_rounded,
|
||||
size: 32,
|
||||
color: APPCOLOR.gray,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (_, index) {
|
||||
_animation = Tween<double>(begin: 0.0, end: 1.0).animate(
|
||||
CurvedAnimation(
|
||||
parent: _animationController,
|
||||
curve: Interval(
|
||||
(0.5 / _favProducts.length) * index,
|
||||
1,
|
||||
curve: Curves.easeOut,
|
||||
),
|
||||
),
|
||||
);
|
||||
_animationController.forward(from: 0);
|
||||
return AnimatedBuilder(
|
||||
animation: _animationController,
|
||||
builder: (_, child) {
|
||||
return FadeTransition(
|
||||
opacity: _animation,
|
||||
child: Transform(
|
||||
transform: Matrix4.translationValues(
|
||||
0.0,
|
||||
50 * (1.0 - _animation.value),
|
||||
0.0,
|
||||
),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Divider(),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
// Padding(
|
||||
// padding:
|
||||
// const EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 78),
|
||||
// child: NectarButton(
|
||||
// onPressed: () {},
|
||||
// text: 'Add All To Cart',
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,12 @@ import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:grocery_app/src/common_widget/textfield_widget.dart';
|
||||
import 'package:grocery_app/src/core/routes/routes.dart';
|
||||
import 'package:grocery_app/src/logic/provider/auth_provider.dart';
|
||||
import 'package:grocery_app/src/ui/otp/otp_screen.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
import 'package:grocery_app/utils/constants/string_constant.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class LoginScreen extends StatefulWidget {
|
||||
const LoginScreen({super.key});
|
||||
@@ -15,6 +17,8 @@ class LoginScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _LoginScreenState extends State<LoginScreen> {
|
||||
TextEditingController phoneController = TextEditingController();
|
||||
|
||||
String? validatePhoneNumber(String? value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Phone number cannot be empty';
|
||||
@@ -27,6 +31,8 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final pageNotifier = Provider.of<AuthProvider>(context, listen: false);
|
||||
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
@@ -62,7 +68,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
key: _formKey,
|
||||
child: AppTextFieldWidget(
|
||||
length: 10,
|
||||
controller: TextEditingController(),
|
||||
controller: phoneController,
|
||||
hintText: APPSTRING.phoneNumberHint,
|
||||
onValidate: (value) => validatePhoneNumber(value),
|
||||
),
|
||||
@@ -80,18 +86,26 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
padding: context.bodyAllPadding.copyWith(bottom: 20),
|
||||
child: Center(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
print("djkhfjdgf ${_formKey.currentState?.validate()}");
|
||||
if (_formKey.currentState?.validate() ?? false)
|
||||
{
|
||||
context.push(MyRoutes.OTPSCREEN);
|
||||
onTap: () async {
|
||||
if (_formKey.currentState?.validate() ?? false) {
|
||||
final success =
|
||||
await pageNotifier.sendOtp(phoneController.text, context);
|
||||
|
||||
// Navigator.of(context).push(MaterialPageRoute(
|
||||
// builder: (context)
|
||||
// {
|
||||
// return const OtpScreen();
|
||||
// },
|
||||
// ));
|
||||
if (success) {
|
||||
context.push(MyRoutes.OTPSCREEN);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text("Failed to send OTP. Please try again."),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text("Enter a valid 10-digit phone number."),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
|
||||
@@ -32,7 +32,8 @@ class _MapScreenState extends State<MapScreen> {
|
||||
APPASSETS.back,
|
||||
height: 20,
|
||||
width: 20,
|
||||
)),
|
||||
)
|
||||
),
|
||||
),
|
||||
),
|
||||
title: const Text(
|
||||
|
||||
@@ -25,10 +25,9 @@ class _OnBoardingScreenState extends State<OnBoardingScreen> {
|
||||
_pageController.nextPage(duration: _kDuration, curve: _kCurve);
|
||||
}
|
||||
|
||||
skipFunction()
|
||||
{
|
||||
skipFunction() {
|
||||
SharedPrefUtils.setFreshInstall(isFresh: false).then(
|
||||
(value) => context.clearAndPush(routePath: MyRoutes.LOGIN, args: 0),
|
||||
(value) => context.clearAndPush(routePath: MyRoutes.BOTTOMNAV, args: 0),
|
||||
);
|
||||
|
||||
// Navigator.pushReplacement(context, MaterialPageRoute(
|
||||
@@ -79,12 +78,12 @@ class _OnBoardingScreenState extends State<OnBoardingScreen> {
|
||||
children: <Widget>[
|
||||
Stack(
|
||||
children: [
|
||||
Image.asset(APPASSETS.onBoardMan),
|
||||
Positioned(
|
||||
top: 10,
|
||||
top: 20,
|
||||
right: 0,
|
||||
child: InkWell(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
print("djfhgk");
|
||||
skipFunction();
|
||||
},
|
||||
child: Row(
|
||||
@@ -95,15 +94,14 @@ class _OnBoardingScreenState extends State<OnBoardingScreen> {
|
||||
style:
|
||||
context.customMedium(APPCOLOR.appGreen, 14),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Container(
|
||||
height: 35,
|
||||
width: 35,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.appGreen,
|
||||
borderRadius: BorderRadius.circular(90)),
|
||||
color: APPCOLOR.appGreen,
|
||||
borderRadius: BorderRadius.circular(90),
|
||||
),
|
||||
child: const Center(
|
||||
child: Icon(
|
||||
Icons.arrow_forward,
|
||||
@@ -116,7 +114,6 @@ class _OnBoardingScreenState extends State<OnBoardingScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
Image.asset(APPASSETS.onBoardMan),
|
||||
Positioned(
|
||||
bottom: 100,
|
||||
right: 0,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:grocery_app/src/logic/provider/auth_provider.dart';
|
||||
import 'package:grocery_app/src/ui/entername/enter_fullname_screen.dart';
|
||||
import 'package:grocery_app/utils/constants/assets_constant.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
@@ -9,6 +10,7 @@ import 'package:grocery_app/utils/extensions/color_ex.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
import 'package:otp_text_field/otp_text_field.dart';
|
||||
import 'package:otp_text_field/style.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../core/routes/routes.dart';
|
||||
|
||||
@@ -20,8 +22,22 @@ class OtpScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _OtpScreenState extends State<OtpScreen> {
|
||||
String maskNumber(String number) {
|
||||
// Ensure the input has at least 4 digits to avoid errors
|
||||
if (number.length < 4) {
|
||||
throw Exception('Number is too short to mask');
|
||||
}
|
||||
|
||||
// Replace all characters except the last 4 with '*'
|
||||
String maskedPart = '*' * (number.length - 4);
|
||||
String visiblePart = number.substring(number.length - 4);
|
||||
return maskedPart + visiblePart;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final pageNotifier = Provider.of<AuthProvider>(context, listen: false);
|
||||
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
@@ -49,7 +65,7 @@ class _OtpScreenState extends State<OtpScreen> {
|
||||
SizedBox(
|
||||
width: 300,
|
||||
child: Text(
|
||||
APPSTRING.enterCode,
|
||||
"Enter the 6-digit code sent to you at ${maskNumber(pageNotifier.numberwithCode)}",
|
||||
style: context.customRegular(APPCOLOR.grey666666, 16),
|
||||
),
|
||||
),
|
||||
@@ -57,16 +73,12 @@ class _OtpScreenState extends State<OtpScreen> {
|
||||
OTPTextField(
|
||||
length: 6,
|
||||
onChanged: (c) {
|
||||
if (c.length == 6)
|
||||
{
|
||||
context.push(MyRoutes.FULLNAME);
|
||||
|
||||
// Navigator.push(context, MaterialPageRoute(
|
||||
// builder: (context)
|
||||
// {
|
||||
// return const EnterFullNameScreen();
|
||||
// },
|
||||
// ));
|
||||
if (c.length == 6) {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return const EnterFullNameScreen();
|
||||
},
|
||||
));
|
||||
}
|
||||
},
|
||||
width: MediaQuery.of(context).size.width,
|
||||
@@ -77,7 +89,20 @@ class _OtpScreenState extends State<OtpScreen> {
|
||||
style: const TextStyle(fontSize: 17),
|
||||
textFieldAlignment: MainAxisAlignment.spaceBetween,
|
||||
fieldStyle: FieldStyle.box,
|
||||
onCompleted: (pin) {},
|
||||
onCompleted: (pin) async {
|
||||
final success = await pageNotifier.verifiOtp(pin, context);
|
||||
|
||||
if (success) {
|
||||
context.push(MyRoutes.FULLNAME);
|
||||
} else {
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// backgroundColor: Colors.grey,
|
||||
// content: Text("Failed to send OTP. Please try again."),
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
|
||||
43
lib/src/ui/widgets/custom_icon_button.dart
Normal file
43
lib/src/ui/widgets/custom_icon_button.dart
Normal file
@@ -0,0 +1,43 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
|
||||
class CustomIconButton extends StatelessWidget {
|
||||
final Function()? onPressed;
|
||||
final Widget? icon;
|
||||
final Color? backgroundColor;
|
||||
final Color? borderColor;
|
||||
final double? width;
|
||||
final double? height;
|
||||
const CustomIconButton({
|
||||
Key? key,
|
||||
required this.onPressed,
|
||||
required this.icon,
|
||||
this.backgroundColor,
|
||||
this.borderColor,
|
||||
this.width,
|
||||
this.height,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: width ?? 44.w,
|
||||
height: height ?? 44.h,
|
||||
child: Material(
|
||||
color: backgroundColor,
|
||||
shape: borderColor == null
|
||||
? const CircleBorder()
|
||||
: CircleBorder(
|
||||
side: BorderSide(color: borderColor!),
|
||||
),
|
||||
child: InkWell(
|
||||
onTap: onPressed,
|
||||
child: icon,
|
||||
highlightColor: Colors.red,
|
||||
customBorder: const CircleBorder(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
28
lib/src/ui/widgets/custom_title.dart
Normal file
28
lib/src/ui/widgets/custom_title.dart
Normal file
@@ -0,0 +1,28 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
|
||||
class CustomTitle extends StatelessWidget {
|
||||
final String title;
|
||||
const CustomTitle({
|
||||
Key? key,
|
||||
required this.title,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
bottom: false,
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
title,
|
||||
style: context.customExtraBold(Colors.black, 18),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Divider(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user