updateProfile
This commit is contained in:
@@ -62,14 +62,21 @@ class _BestDealScreenState extends State<BestDealScreen> {
|
||||
],
|
||||
),
|
||||
floatingActionButton: floatingAction(),
|
||||
body: itemBestdeal());
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 100),
|
||||
child: itemBestdeal(),
|
||||
));
|
||||
}
|
||||
|
||||
Widget floatingAction() {
|
||||
return Consumer<ProductProvider>(builder: (context, provider, child) {
|
||||
if (provider.countList.isEmpty) {
|
||||
Widget floatingAction()
|
||||
{
|
||||
return Consumer<ProductProvider>(builder: (context, provider, child)
|
||||
{
|
||||
if (provider.countList.isEmpty)
|
||||
{
|
||||
return Center();
|
||||
} else {
|
||||
} else
|
||||
{
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 30),
|
||||
child: Container(
|
||||
@@ -93,7 +100,7 @@ class _BestDealScreenState extends State<BestDealScreen> {
|
||||
color: Colors.white.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
),
|
||||
const Positioned(
|
||||
Positioned(
|
||||
left: 20,
|
||||
bottom: 0,
|
||||
top: 0,
|
||||
@@ -102,7 +109,7 @@ class _BestDealScreenState extends State<BestDealScreen> {
|
||||
height: 70,
|
||||
width: 70,
|
||||
radius: 10,
|
||||
imageUrl:
|
||||
imageUrl: provider.lastImageurl ??
|
||||
"https://5.imimg.com/data5/SELLER/Default/2024/2/385126988/OL/DA/VW/8627346/1l-fortune-sunflower-oil.jpg",
|
||||
backGroundColor: Colors.white,
|
||||
),
|
||||
@@ -113,15 +120,12 @@ class _BestDealScreenState extends State<BestDealScreen> {
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
provider.countList.length.toString(),
|
||||
style: context.customRegular(Colors.white, 18),
|
||||
),
|
||||
],
|
||||
Text(
|
||||
provider.countList.length.toString(),
|
||||
style: context.customRegular(
|
||||
Colors.white,
|
||||
29,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
InkWell(
|
||||
@@ -306,8 +310,12 @@ class _BestDealScreenState extends State<BestDealScreen> {
|
||||
onTap: () async {
|
||||
if (await SharedPrefUtils.getToken() !=
|
||||
null) {
|
||||
await provider.addToWithCart(context,
|
||||
bestdealproduct.id!, bestdealproduct);
|
||||
await provider.addToWithCart(
|
||||
context,
|
||||
bestdealproduct.id!,
|
||||
bestdealproduct,
|
||||
bestdealproduct
|
||||
.productImages?.first.url);
|
||||
} else {
|
||||
context.push(MyRoutes.SIGNUP);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:grocery_app/src/logic/provider/bottom_navbar_provider.dart';
|
||||
import 'package:grocery_app/src/logic/provider/home_provider.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/header.dart';
|
||||
@@ -38,6 +39,7 @@ class _BottomBarState extends State<BottomBarWidget> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
Provider.of<BottomNavProvider>(context, listen: false).getProfile(context);
|
||||
_currentIndex = 0;
|
||||
bottomWidgetPageController = PageController(
|
||||
initialPage: 0,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
135
lib/src/ui/coupons/coupons_screen.dart
Normal file
135
lib/src/ui/coupons/coupons_screen.dart
Normal file
@@ -0,0 +1,135 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CouponsScreen extends StatelessWidget {
|
||||
final List<Map<String, String>> coupons = [
|
||||
{
|
||||
"title": "Flat 10% OFF on Standard Chartered Digismart Credit Cards",
|
||||
"description": "No Minimum Order Value",
|
||||
"code": "DIGISMART"
|
||||
},
|
||||
{
|
||||
"title": "Flat 10% OFF upto \$10 on HSBC Cashback Credit Card",
|
||||
"description": "Total Value of Items Must be \$3 or More",
|
||||
"code": "HSBC10"
|
||||
},
|
||||
{
|
||||
"title": "Get Upto 50 OFF on Your First Payment",
|
||||
"description": "Total Value of Items Must be \$10 or More",
|
||||
"code": "PAYMENT50"
|
||||
}
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
title: Text("Coupons"),
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back_ios),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
TextField(
|
||||
cursorHeight: 20,
|
||||
decoration: InputDecoration(
|
||||
hintText: "Enter Coupon Code",
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
suffixIcon: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.green,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Text("Apply"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: coupons.length,
|
||||
itemBuilder: (context, index) {
|
||||
final coupon = coupons[index];
|
||||
return Card(
|
||||
color: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
elevation: 2,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
coupon["title"]!,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
Text(
|
||||
coupon["description"]!,
|
||||
style: TextStyle(color: Colors.grey[600]),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 10, vertical: 5),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.green),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
coupon["code"]!,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.green,
|
||||
),
|
||||
),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.green,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Text("Apply"),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,19 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:grocery_app/src/common_widget/name_text_field.dart';
|
||||
import 'package:grocery_app/src/common_widget/network_image.dart';
|
||||
import 'package:grocery_app/src/logic/provider/profile_provider.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/shared_pref_utils.dart';
|
||||
import 'package:grocery_app/utils/constants/string_constant.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class EditProfileScreen extends StatefulWidget {
|
||||
const EditProfileScreen({super.key});
|
||||
@@ -15,6 +23,51 @@ class EditProfileScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _EditProfileScreenState extends State<EditProfileScreen> {
|
||||
String? name;
|
||||
String? email;
|
||||
String? profile;
|
||||
File? _image;
|
||||
final ImagePicker _picker = ImagePicker();
|
||||
|
||||
TextEditingController firstController = TextEditingController();
|
||||
TextEditingController lastController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
getUserDetails();
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
}
|
||||
|
||||
getUserDetails() async {
|
||||
firstController.text = APPSTRING.userName;
|
||||
lastController.text = APPSTRING.userLastName;
|
||||
profile = APPSTRING.userProfile;
|
||||
}
|
||||
|
||||
/// Pick image from gallery or camera
|
||||
Future<void> _pickImage() async {
|
||||
final XFile? pickedFile =
|
||||
await _picker.pickImage(source: ImageSource.gallery);
|
||||
|
||||
if (pickedFile != null) {
|
||||
setState(() {
|
||||
profile = pickedFile.path;
|
||||
_image = File(pickedFile.path);
|
||||
});
|
||||
|
||||
Provider.of<ProfileProvider>(context, listen: false)
|
||||
.uploadImage(context, _image);
|
||||
|
||||
await _saveProfileImage(pickedFile.path);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _saveProfileImage(String imagePath) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('KEY_PROFILE', imagePath);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@@ -43,40 +96,50 @@ class _EditProfileScreenState extends State<EditProfileScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: Container(
|
||||
color: Colors.transparent,
|
||||
height: 60,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Container(
|
||||
height: 50,
|
||||
decoration: BoxDecoration(color: APPCOLOR.lightGreen, borderRadius: BorderRadius.circular(10)),
|
||||
child: Center(
|
||||
child: Text(
|
||||
"Update",
|
||||
style: context.customRegular(Colors.white, 16),
|
||||
bottomNavigationBar:
|
||||
Consumer<ProfileProvider>(builder: (context, imageProvider, child) {
|
||||
return Container(
|
||||
color: Colors.transparent,
|
||||
height: 60,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
Expanded(
|
||||
child: InkWell(
|
||||
onTap: imageProvider.isImageLoading
|
||||
? () {
|
||||
imageProvider.createStore(context,
|
||||
firstController.text, lastController.text);
|
||||
}
|
||||
: null,
|
||||
child: Container(
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: imageProvider.isImageLoading
|
||||
? APPCOLOR.lightGreen
|
||||
: APPCOLOR.grey666666,
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
child: Center(
|
||||
child: Text(
|
||||
"Update",
|
||||
style: context.customRegular(Colors.white, 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
],
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
body: Padding(
|
||||
padding: context.bodyAllPadding,
|
||||
child: SingleChildScrollView(
|
||||
@@ -90,26 +153,37 @@ class _EditProfileScreenState extends State<EditProfileScreen> {
|
||||
Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
const AppNetworkImage(
|
||||
height: 80,
|
||||
width: 80,
|
||||
imageUrl: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTdQLwDqDwd2JfzifvfBTFT8I7iKFFevcedYg&s",
|
||||
radius: 90,
|
||||
backGroundColor: Colors.white,
|
||||
boxFit: BoxFit.fill,
|
||||
//
|
||||
CircleAvatar(
|
||||
radius: 40,
|
||||
backgroundColor: Colors.white,
|
||||
backgroundImage: _image != null
|
||||
? FileImage(_image!) as ImageProvider
|
||||
: (profile != null && profile!.isNotEmpty
|
||||
? NetworkImage(profile!)
|
||||
: const AssetImage("assets/default_profile.png")
|
||||
as ImageProvider),
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
height: 20,
|
||||
width: 20,
|
||||
decoration: BoxDecoration(color: APPCOLOR.lightGreen, border: Border.all(color: Colors.white), borderRadius: BorderRadius.circular(5)),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
MdiIcons.pencil,
|
||||
size: 10,
|
||||
color: Colors.white,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
_pickImage();
|
||||
},
|
||||
child: Container(
|
||||
height: 20,
|
||||
width: 20,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.lightGreen,
|
||||
border: Border.all(color: Colors.white),
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
MdiIcons.pencil,
|
||||
size: 10,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
@@ -120,34 +194,103 @@ class _EditProfileScreenState extends State<EditProfileScreen> {
|
||||
const SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
const NameTextField(
|
||||
name: "Name",
|
||||
initText: "Smith Mate",
|
||||
Container(
|
||||
height: 60,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: APPCOLOR.lightGreen),
|
||||
borderRadius: BorderRadius.circular(15)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"First Name",
|
||||
style: context.customMedium(APPCOLOR.lightGreen, 14),
|
||||
),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: firstController,
|
||||
decoration: const InputDecoration(
|
||||
border: InputBorder.none,
|
||||
isCollapsed: true,
|
||||
contentPadding: EdgeInsets.only(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 5,
|
||||
top: 5,
|
||||
)),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const NameTextField(
|
||||
name: "Email Address",
|
||||
initText: "SmithMate@example.com",
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const NameTextField(
|
||||
name: "Mobile Number",
|
||||
initText: "(205) 555-0100",
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const NameTextField(
|
||||
name: "Enter Address",
|
||||
initText: "8502 Preston Rd. inglewood, USA",
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
Container(
|
||||
height: 60,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: APPCOLOR.lightGreen),
|
||||
borderRadius: BorderRadius.circular(15)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Last Name ",
|
||||
style: context.customMedium(APPCOLOR.lightGreen, 14),
|
||||
),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: lastController,
|
||||
decoration: const InputDecoration(
|
||||
border: InputBorder.none,
|
||||
isCollapsed: true,
|
||||
contentPadding: EdgeInsets.only(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 5,
|
||||
top: 5,
|
||||
)),
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// const NameTextField(
|
||||
// name: "Last Name",
|
||||
// initText: "Smith Mate",
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
// const NameTextField(
|
||||
// name: "Email Address",
|
||||
// initText: "SmithMate@example.com",
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
// const NameTextField(
|
||||
// name: "Mobile Number",
|
||||
// initText: "(205) 555-0100",
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
// const NameTextField(
|
||||
// name: "Enter Address",
|
||||
// initText: "8502 Preston Rd. inglewood, USA",
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
],
|
||||
)),
|
||||
),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
@@ -79,10 +80,25 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
|
||||
Widget productWidget() {
|
||||
return Consumer<ProductProvider>(builder: (context, provider, child) {
|
||||
if (provider.isLoadingg) {
|
||||
if (provider.isLoadingg)
|
||||
{
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 120),
|
||||
child: CircularProgressIndicator(),
|
||||
child: Center(
|
||||
child: Container(
|
||||
width: 30,
|
||||
height: 30,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(
|
||||
color: APPCOLOR.bgGrey,
|
||||
width: 1,
|
||||
)),
|
||||
child: const Center(
|
||||
child: CupertinoActivityIndicator(),
|
||||
),
|
||||
)),
|
||||
);
|
||||
} else if (provider.products.isEmpty) {
|
||||
return Padding(
|
||||
@@ -106,8 +122,7 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
crossAxisSpacing: 10,
|
||||
mainAxisSpacing: 10,
|
||||
),
|
||||
itemBuilder: (context, index)
|
||||
{
|
||||
itemBuilder: (context, index) {
|
||||
var product = provider.products[index];
|
||||
|
||||
return InkWell(
|
||||
@@ -189,31 +204,31 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
// ),
|
||||
// ),
|
||||
|
||||
Positioned(
|
||||
right: 5,
|
||||
top: 5,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
if (await SharedPrefUtils
|
||||
.getToken() !=
|
||||
null) {
|
||||
provider.toggleWishlist(
|
||||
context, product.id!);
|
||||
} else {
|
||||
context.push(MyRoutes.SIGNUP);
|
||||
}
|
||||
},
|
||||
child: Icon(
|
||||
provider.wishlist.contains(product.id)
|
||||
? Icons.favorite
|
||||
: Icons.favorite_border,
|
||||
color: provider.wishlist
|
||||
.contains(product.id)
|
||||
? Colors.red
|
||||
: Colors.grey,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Positioned(
|
||||
// right: 5,
|
||||
// top: 5,
|
||||
// child: InkWell(
|
||||
// onTap: () async {
|
||||
// if (await SharedPrefUtils
|
||||
// .getToken() !=
|
||||
// null) {
|
||||
// provider.toggleWishlist(
|
||||
// context, product.id!);
|
||||
// } else {
|
||||
// context.push(MyRoutes.SIGNUP);
|
||||
// }
|
||||
// },
|
||||
// child: Icon(
|
||||
// provider.wishlist.contains(product.id)
|
||||
// ? Icons.favorite
|
||||
// : Icons.favorite_border,
|
||||
// color: provider.wishlist
|
||||
// .contains(product.id)
|
||||
// ? Colors.red
|
||||
// : Colors.grey,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -221,7 +236,7 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
Text(
|
||||
product.name ?? " ",
|
||||
textAlign: TextAlign.left,
|
||||
maxLines: 2,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: context.customMedium(
|
||||
APPCOLOR.balck1A1A1A, 14),
|
||||
@@ -238,6 +253,7 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
Spacer(),
|
||||
Row(
|
||||
children: [
|
||||
Column(
|
||||
@@ -281,7 +297,7 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
if (await SharedPrefUtils.getToken() !=
|
||||
null) {
|
||||
await provider.addToCart(
|
||||
context, product.id!);
|
||||
context, product.id!, 1);
|
||||
} else {
|
||||
context.push(MyRoutes.SIGNUP);
|
||||
}
|
||||
@@ -327,6 +343,8 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -348,7 +366,21 @@ class _FruitVeggieDetailState extends State<FruitVeggieDetail> {
|
||||
final activeIndexProvider = Provider.of<ProductProvider>(context);
|
||||
return Consumer<ProductProvider>(builder: (context, provider, child) {
|
||||
if (provider.iscategroyloading) {
|
||||
return Center(child: CircularProgressIndicator());
|
||||
return Center(
|
||||
child: Container(
|
||||
width: 20,
|
||||
height: 20,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.bgGrey,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(
|
||||
color: APPCOLOR.bgGrey,
|
||||
width: 1,
|
||||
)),
|
||||
child: const Center(
|
||||
child: CupertinoActivityIndicator(),
|
||||
),
|
||||
));
|
||||
} else if (provider.categoryList.isEmpty) {
|
||||
return Center(child: Text('No products available'));
|
||||
} else {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
466
lib/src/ui/map/add_locations.dart
Normal file
466
lib/src/ui/map/add_locations.dart
Normal file
@@ -0,0 +1,466 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:geocoding/geocoding.dart';
|
||||
import 'package:grocery_app/src/logic/provider/addTocart_provider.dart';
|
||||
import 'package:grocery_app/src/logic/provider/address_provider.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
const String googleApiKey = "AIzaSyAi3_Dls63iGs7Nccgdm-4FkS0rhT03-4U";
|
||||
|
||||
class AddLocationAddress extends StatefulWidget {
|
||||
@override
|
||||
_AddLocationAddressState createState() => _AddLocationAddressState();
|
||||
}
|
||||
|
||||
class _AddLocationAddressState extends State<AddLocationAddress> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
late GoogleMapController mapController;
|
||||
LatLng _selectedLocation = LatLng(20.5937, 78.9629);
|
||||
|
||||
TextEditingController _pincodeController = TextEditingController();
|
||||
TextEditingController _fullNameController = TextEditingController();
|
||||
TextEditingController _PhoneNumberController = TextEditingController();
|
||||
TextEditingController _addressTypeController = TextEditingController();
|
||||
TextEditingController _HouseNoController = TextEditingController();
|
||||
TextEditingController _RoadController = TextEditingController();
|
||||
TextEditingController _AlterNativeNumberController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_determinePosition();
|
||||
}
|
||||
|
||||
Future<void> _determinePosition() async {
|
||||
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
LocationPermission permission = await Geolocator.requestPermission();
|
||||
if (permission == LocationPermission.denied) {
|
||||
return;
|
||||
}
|
||||
|
||||
Position position = await Geolocator.getCurrentPosition(
|
||||
desiredAccuracy: LocationAccuracy.high,
|
||||
);
|
||||
LatLng currentLatLng = LatLng(position.latitude, position.longitude);
|
||||
|
||||
setState(() {
|
||||
_selectedLocation = currentLatLng;
|
||||
});
|
||||
|
||||
_getAddressFromLatLng(position.latitude, position.longitude);
|
||||
}
|
||||
|
||||
Future<void> _getAddressFromLatLng(double lat, double lng) async {
|
||||
final String url =
|
||||
"https://maps.googleapis.com/maps/api/geocode/json?latlng=$lat,$lng&key=$googleApiKey";
|
||||
|
||||
try {
|
||||
final response = await http.get(Uri.parse(url));
|
||||
if (response.statusCode == 200) {
|
||||
final data = json.decode(response.body);
|
||||
if (data["status"] == "OK") {
|
||||
var result = data["results"][0]; // First result is most accurate
|
||||
|
||||
_RoadController.text = result["formatted_address"];
|
||||
List components = result["address_components"];
|
||||
|
||||
String roadName = "";
|
||||
String colony = "";
|
||||
String buildingName = "";
|
||||
String pincode = "";
|
||||
|
||||
for (var component in components) {
|
||||
List types = component["types"];
|
||||
if (types.contains("route")) {
|
||||
roadName = component["long_name"]; // Road Name
|
||||
} else if (types.contains("sublocality_level_1") ||
|
||||
types.contains("locality")) {
|
||||
colony = component["long_name"]; // Colony Name
|
||||
} else if (types.contains("premise") ||
|
||||
types.contains("street_number")) {
|
||||
buildingName = component["long_name"]; // Building Name
|
||||
} else if (types.contains("postal_code")) {
|
||||
pincode = component["long_name"]; // Extract Pin Code
|
||||
}
|
||||
}
|
||||
|
||||
// setState(() {
|
||||
// // _address = formattedAddress;
|
||||
// _roadName = roadName;
|
||||
// _colony = colony;
|
||||
// _buildingName = buildingName;
|
||||
// });
|
||||
|
||||
_pincodeController.text = pincode;
|
||||
_RoadController.text = result["formatted_address"];
|
||||
|
||||
print(
|
||||
"Full Address: ${result["formatted_address"]} ${response.body} sdfsgd ${pincode}");
|
||||
print("Road Name: $roadName");
|
||||
print("Colony: $colony");
|
||||
print("Building Name: $buildingName");
|
||||
} else {}
|
||||
} else {}
|
||||
} catch (e) {
|
||||
print("Error fetching address: $e");
|
||||
}
|
||||
}
|
||||
|
||||
void _onMapTapped(LatLng tappedPoint) {
|
||||
setState(() {
|
||||
_selectedLocation = tappedPoint;
|
||||
});
|
||||
_getAddressFromLatLng(tappedPoint.latitude, tappedPoint.longitude);
|
||||
}
|
||||
|
||||
Future<void> _updateLocationFromPincode(String enteredPincode) async {
|
||||
if (enteredPincode.isEmpty) return;
|
||||
|
||||
try {
|
||||
List<Location> locations = await locationFromAddress(enteredPincode);
|
||||
if (locations.isNotEmpty) {
|
||||
Location location = locations.first;
|
||||
LatLng newLatLng = LatLng(location.latitude, location.longitude);
|
||||
|
||||
setState(() {
|
||||
_selectedLocation = newLatLng;
|
||||
});
|
||||
|
||||
_getAddressFromLatLng(location.latitude, location.longitude);
|
||||
mapController.animateCamera(CameraUpdate.newLatLng(newLatLng));
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error fetching location from pincode: $e");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text("Add Delivery address")),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: 200.h,
|
||||
child: GoogleMap(
|
||||
initialCameraPosition: CameraPosition(
|
||||
target: _selectedLocation,
|
||||
zoom: 14,
|
||||
),
|
||||
onMapCreated: (controller) {
|
||||
mapController = controller;
|
||||
},
|
||||
|
||||
myLocationEnabled: true, // Enable current location button
|
||||
myLocationButtonEnabled: true,
|
||||
markers: {
|
||||
Marker(
|
||||
markerId: MarkerId("selected Location"),
|
||||
position: _selectedLocation,
|
||||
)
|
||||
},
|
||||
onTap: _onMapTapped,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 10)],
|
||||
),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(height: 10),
|
||||
TextFormField(
|
||||
controller: _fullNameController,
|
||||
keyboardType: TextInputType.text,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Full Name (Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Full Name";
|
||||
}
|
||||
return null; // ✅ Valid input
|
||||
},
|
||||
|
||||
// Auto-update on enter
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextFormField(
|
||||
controller: _PhoneNumberController,
|
||||
keyboardType: TextInputType.number,
|
||||
maxLength: 10,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Phone Number (Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Phone Number ";
|
||||
}
|
||||
return null; // ✅ Valid input
|
||||
},
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: _pincodeController,
|
||||
keyboardType: TextInputType.number,
|
||||
maxLength: 6,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Enter Pincode",
|
||||
border: OutlineInputBorder(),
|
||||
counterText: ""),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Please enter a pincode";
|
||||
} else if (value.length != 6) {
|
||||
return "Pincode must be exactly 6 digits";
|
||||
} else if (!RegExp(r'^[1-9][0-9]{5}$')
|
||||
.hasMatch(value)) {
|
||||
return "Enter a valid Indian pincode";
|
||||
}
|
||||
return null; // ✅ Valid input
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
// Expanded(
|
||||
// child: TextFormField(
|
||||
// controller: _addressTypeController,
|
||||
// keyboardType: TextInputType.text,
|
||||
// decoration: InputDecoration(
|
||||
// labelText: "Address Type",
|
||||
// border: OutlineInputBorder(),
|
||||
// ),
|
||||
// validator: (value) {
|
||||
// if (value == null || value.isEmpty) {
|
||||
// return "Enter address Home or Work ";
|
||||
// }
|
||||
// return null; // ✅ Valid input
|
||||
// },
|
||||
// ),
|
||||
// ),\
|
||||
Expanded(
|
||||
child: DropdownButtonFormField<String>(
|
||||
value: _addressTypeController.text.isNotEmpty
|
||||
? _addressTypeController.text
|
||||
: null,
|
||||
items:
|
||||
["HOME", "WORK", "OTHER"].map((String type) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: type,
|
||||
child: Text(type),
|
||||
);
|
||||
}).toList(),
|
||||
decoration: InputDecoration(
|
||||
labelText: "Address Type",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {
|
||||
if (value != null) {
|
||||
_addressTypeController.text = value;
|
||||
}
|
||||
},
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Select Address Type (Home, Work, Other)";
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextFormField(
|
||||
controller: _HouseNoController,
|
||||
keyboardType: TextInputType.text,
|
||||
decoration: InputDecoration(
|
||||
labelText: "House No, Building Name (Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Enter House No, Building ";
|
||||
}
|
||||
return null; // ✅ Valid input
|
||||
},
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextFormField(
|
||||
controller: _RoadController,
|
||||
keyboardType: TextInputType.text,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Road Name, Area , Colony(Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return "Enter Road Name, Area , Colony(Required)";
|
||||
}
|
||||
return null; // ✅ Valid input
|
||||
},
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
|
||||
Consumer<AddressProvider>(
|
||||
builder: (context, addressProvider, child)
|
||||
{
|
||||
return InkWell(
|
||||
onTap: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
var status = await addressProvider.checkPin(
|
||||
context, _pincodeController.text);
|
||||
|
||||
if (status) {
|
||||
var state = await addressProvider.addAddress(
|
||||
context,
|
||||
_fullNameController.text,
|
||||
_pincodeController.text,
|
||||
_PhoneNumberController.text,
|
||||
_PhoneNumberController.text,
|
||||
_HouseNoController.text,
|
||||
_RoadController.text,
|
||||
_addressTypeController.text);
|
||||
if (state) {
|
||||
context .read<AddtocartProvider>()
|
||||
.getAddress(context);
|
||||
Fluttertoast.showToast(
|
||||
msg: "Address Added!",
|
||||
backgroundColor: Colors.lightGreen);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
} else {
|
||||
Fluttertoast.showToast(
|
||||
msg:
|
||||
"Delivery is not available for this pincode. Please try another pincode!",
|
||||
toastLength: Toast.LENGTH_SHORT,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
backgroundColor: Colors.red,
|
||||
textColor: Colors.white,
|
||||
fontSize: 14.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(
|
||||
left: 15, right: 15, top: 10, bottom: 10),
|
||||
height: 50,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.lightGreen,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
if (addressProvider.ischeckpin)
|
||||
const CircularProgressIndicator(
|
||||
color: Colors.white,
|
||||
)
|
||||
else
|
||||
Text(
|
||||
"Save Address",
|
||||
style: context.customMedium(
|
||||
Colors.white, 20),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
// InkWell(
|
||||
// onTap: () async {
|
||||
// if (_formKey.currentState!.validate()) {
|
||||
// var status = await Provider.of<AddressProvider>(
|
||||
// context,
|
||||
// listen: false)
|
||||
// .checkPin(context, _pincodeController.text);
|
||||
// if (status) {
|
||||
// // var status = await Provider.of<AddressProvider>(
|
||||
// // context,
|
||||
// // listen: false)
|
||||
// // .addAddress(context, _pincodeController.text);
|
||||
// } else {
|
||||
// // Delivery is not available for this pincode. Please try another pincode.
|
||||
|
||||
// Fluttertoast.showToast(
|
||||
// msg:
|
||||
// "Delivery is not available for this pincode. Please try another pincode!",
|
||||
// toastLength: Toast.LENGTH_SHORT,
|
||||
// gravity: ToastGravity.BOTTOM,
|
||||
// backgroundColor: Colors.red,
|
||||
// textColor: Colors.white,
|
||||
// fontSize: 14.0,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// child: Container(
|
||||
// margin: const EdgeInsets.only(
|
||||
// left: 15, right: 15, top: 10, bottom: 10),
|
||||
// height: 50,
|
||||
// width: MediaQuery.sizeOf(context).width,
|
||||
// decoration: BoxDecoration(
|
||||
// color: APPCOLOR.lightGreen,
|
||||
// borderRadius: BorderRadius.circular(10)),
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// children: [
|
||||
// const SizedBox(
|
||||
// width: 10,
|
||||
// ),
|
||||
// Text(
|
||||
// "Save Address",
|
||||
// style: context.customMedium(Colors.white, 20),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
|
||||
SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,330 +0,0 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:geocoding/geocoding.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
|
||||
const String googleApiKey = "AIzaSyAi3_Dls63iGs7Nccgdm-4FkS0rhT03-4U";
|
||||
|
||||
class MapScreen extends StatefulWidget {
|
||||
@override
|
||||
_MapScreenState createState() => _MapScreenState();
|
||||
}
|
||||
|
||||
class _MapScreenState extends State<MapScreen> {
|
||||
late GoogleMapController mapController;
|
||||
LatLng _selectedLocation = LatLng(20.5937, 78.9629);
|
||||
|
||||
TextEditingController _pincodeController = TextEditingController();
|
||||
TextEditingController _fullNameController = TextEditingController();
|
||||
TextEditingController _PhoneNumberController = TextEditingController();
|
||||
TextEditingController _addressTypeController = TextEditingController();
|
||||
TextEditingController _HouseNoController = TextEditingController();
|
||||
TextEditingController _RoadController = TextEditingController();
|
||||
TextEditingController _AlterNativeNumberController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_determinePosition();
|
||||
}
|
||||
|
||||
Future<void> _determinePosition() async {
|
||||
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
LocationPermission permission = await Geolocator.requestPermission();
|
||||
if (permission == LocationPermission.denied) {
|
||||
return;
|
||||
}
|
||||
|
||||
Position position = await Geolocator.getCurrentPosition(
|
||||
desiredAccuracy: LocationAccuracy.high,
|
||||
);
|
||||
LatLng currentLatLng = LatLng(position.latitude, position.longitude);
|
||||
|
||||
setState(() {
|
||||
_selectedLocation = currentLatLng;
|
||||
});
|
||||
|
||||
_getAddressFromLatLng(position.latitude, position.longitude);
|
||||
}
|
||||
|
||||
Future<void> _getAddressFromLatLng(double lat, double lng) async {
|
||||
final String url =
|
||||
"https://maps.googleapis.com/maps/api/geocode/json?latlng=$lat,$lng&key=$googleApiKey";
|
||||
|
||||
try {
|
||||
final response = await http.get(Uri.parse(url));
|
||||
if (response.statusCode == 200) {
|
||||
final data = json.decode(response.body);
|
||||
if (data["status"] == "OK") {
|
||||
var result = data["results"][0]; // First result is most accurate
|
||||
|
||||
_RoadController.text = result["formatted_address"];
|
||||
List components = result["address_components"];
|
||||
|
||||
String roadName = "";
|
||||
String colony = "";
|
||||
String buildingName = "";
|
||||
String pincode = "";
|
||||
|
||||
for (var component in components) {
|
||||
List types = component["types"];
|
||||
if (types.contains("route")) {
|
||||
roadName = component["long_name"]; // Road Name
|
||||
} else if (types.contains("sublocality_level_1") ||
|
||||
types.contains("locality")) {
|
||||
colony = component["long_name"]; // Colony Name
|
||||
} else if (types.contains("premise") ||
|
||||
types.contains("street_number")) {
|
||||
buildingName = component["long_name"]; // Building Name
|
||||
} else if (types.contains("postal_code")) {
|
||||
pincode = component["long_name"]; // Extract Pin Code
|
||||
}
|
||||
}
|
||||
|
||||
// setState(() {
|
||||
// // _address = formattedAddress;
|
||||
// _roadName = roadName;
|
||||
// _colony = colony;
|
||||
// _buildingName = buildingName;
|
||||
// });
|
||||
|
||||
_pincodeController.text = pincode;
|
||||
_RoadController.text = result["formatted_address"];
|
||||
|
||||
print(
|
||||
"Full Address: ${result["formatted_address"]} ${response.body} sdfsgd ${pincode}");
|
||||
print("Road Name: $roadName");
|
||||
print("Colony: $colony");
|
||||
print("Building Name: $buildingName");
|
||||
} else {}
|
||||
} else {}
|
||||
} catch (e) {
|
||||
print("Error fetching address: $e");
|
||||
}
|
||||
}
|
||||
|
||||
// On map tapped
|
||||
void _onMapTapped(LatLng tappedPoint) {
|
||||
setState(() {
|
||||
_selectedLocation = tappedPoint;
|
||||
});
|
||||
_getAddressFromLatLng(tappedPoint.latitude, tappedPoint.longitude);
|
||||
}
|
||||
|
||||
// Update location based on entered pincode
|
||||
Future<void> _updateLocationFromPincode(String enteredPincode) async {
|
||||
if (enteredPincode.isEmpty) return;
|
||||
|
||||
try {
|
||||
List<Location> locations = await locationFromAddress(enteredPincode);
|
||||
if (locations.isNotEmpty) {
|
||||
Location location = locations.first;
|
||||
LatLng newLatLng = LatLng(location.latitude, location.longitude);
|
||||
|
||||
setState(() {
|
||||
_selectedLocation = newLatLng;
|
||||
});
|
||||
|
||||
_getAddressFromLatLng(location.latitude, location.longitude);
|
||||
mapController.animateCamera(CameraUpdate.newLatLng(newLatLng));
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error fetching location from pincode: $e");
|
||||
}
|
||||
}
|
||||
|
||||
// {
|
||||
// "name": "Socket Mall",
|
||||
// "pincode": "400001",
|
||||
// "phoneNumber": "+919876543210",
|
||||
// "alternatePhoneNumber": "+919876543211",
|
||||
// "addressLine": "123, Main Street, Apartment 4B",
|
||||
// "landmark": "Near Central Park",
|
||||
// "addressType": "HOME",
|
||||
// "isDefault": false,
|
||||
// "additionalInstructions": "Please ring doorbell twice"
|
||||
// }
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text("Add Delivery address")),
|
||||
body: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: 200.h,
|
||||
child: GoogleMap(
|
||||
initialCameraPosition: CameraPosition(
|
||||
target: _selectedLocation,
|
||||
zoom: 14,
|
||||
),
|
||||
onMapCreated: (controller) {
|
||||
mapController = controller;
|
||||
},
|
||||
markers: {
|
||||
Marker(
|
||||
markerId: MarkerId("selected Location"),
|
||||
position: _selectedLocation,
|
||||
)
|
||||
},
|
||||
onTap: _onMapTapped,
|
||||
),
|
||||
),
|
||||
SingleChildScrollView(
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 10)],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Text("Selected Address:",
|
||||
// style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
|
||||
// SizedBox(height: 5),
|
||||
// Text(_address, style: TextStyle(fontSize: 16)),
|
||||
SizedBox(height: 10),
|
||||
TextField(
|
||||
controller: _fullNameController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Full Name (Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {},
|
||||
onSubmitted:
|
||||
_updateLocationFromPincode, // Auto-update on enter
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextField(
|
||||
controller: _PhoneNumberController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Phone Number (Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {},
|
||||
onSubmitted:
|
||||
_updateLocationFromPincode, // Auto-update on enter
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _pincodeController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Enter Pincode",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {},
|
||||
onSubmitted:
|
||||
_updateLocationFromPincode, // Auto-update on enter
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _addressTypeController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Address Type",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {},
|
||||
onSubmitted:
|
||||
_updateLocationFromPincode, // Auto-update on enter
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextField(
|
||||
controller: _HouseNoController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: "House No, Building Name (Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {},
|
||||
onSubmitted:
|
||||
_updateLocationFromPincode, // Auto-update on enter
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
TextField(
|
||||
controller: _RoadController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: InputDecoration(
|
||||
labelText: "Road Name, Area , Colony(Required)*",
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: (value) {},
|
||||
onSubmitted:
|
||||
_updateLocationFromPincode, // Auto-update on enter
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
// print("fjnghkjfjghj");
|
||||
// Provider.of<ProductProvider>(context, listen: false)
|
||||
// .customerLogOut(context);
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(
|
||||
left: 15, right: 15, top: 10, bottom: 10),
|
||||
height: 50,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.lightGreen,
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Text(
|
||||
"Save Address",
|
||||
style: context.customMedium(Colors.white, 20),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// ElevatedButton(
|
||||
// onPressed: () {
|
||||
// Navigator.pop(context, {
|
||||
// "location": _selectedLocation,
|
||||
// "address": _address,
|
||||
// "pincode": _pincode
|
||||
// });
|
||||
// },
|
||||
// child: Text("Confirm Location"),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import 'package:go_router/go_router.dart';
|
||||
import 'package:grocery_app/src/common_widget/network_image.dart';
|
||||
import 'package:grocery_app/src/core/routes/routes.dart';
|
||||
import 'package:grocery_app/src/data/allProduct_model.dart';
|
||||
import 'package:grocery_app/src/logic/provider/bottom_navbar_provider.dart';
|
||||
import 'package:grocery_app/src/logic/provider/home_provider.dart';
|
||||
import 'package:grocery_app/utils/constants/assets_constant.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
@@ -18,6 +19,7 @@ import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:readmore/readmore.dart';
|
||||
import 'package:shimmer/shimmer.dart';
|
||||
|
||||
class ProductDetails extends StatefulWidget {
|
||||
String id;
|
||||
@@ -95,7 +97,6 @@ class _ProductDetailsState extends State<ProductDetails> {
|
||||
prodectDtails(),
|
||||
Divider(),
|
||||
reviews(),
|
||||
Divider(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Text("Similar Products",
|
||||
@@ -110,20 +111,39 @@ class _ProductDetailsState extends State<ProductDetails> {
|
||||
),
|
||||
),
|
||||
),
|
||||
// bottomNavigationBar: bottomBar(),
|
||||
bottomNavigationBar: bottomBar(),
|
||||
);
|
||||
}
|
||||
|
||||
double calculateDiscountPercentage(double basePrice, double discountPrice) {
|
||||
print(
|
||||
"Base Price (Before Discount): $basePrice, Discount Price (After Discount): $discountPrice");
|
||||
|
||||
if (basePrice <= 0 || discountPrice <= 0 || discountPrice > basePrice) {
|
||||
print("Error: Invalid price values.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
double discountAmount = basePrice - discountPrice;
|
||||
double discountPercentage = (discountAmount / basePrice) * 100;
|
||||
|
||||
return discountPercentage;
|
||||
}
|
||||
|
||||
Widget prodectDtails() {
|
||||
return Consumer<ProductProvider>(builder: (context, provider, child) {
|
||||
if (provider.isProductLoading) {
|
||||
return Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: Colors.green,
|
||||
));
|
||||
return _buildSkeletonLoader();
|
||||
} else if (provider.productDetails.data == null) {
|
||||
return Center(child: Text('No products available'));
|
||||
} else {
|
||||
provider.setProductPrice(
|
||||
double.parse(provider.productDetails.data!.discountPrice));
|
||||
provider.productQuantity = provider.productDetails.data!.quantity;
|
||||
|
||||
if (provider.productDetails.data!.isInWishlist!) {
|
||||
provider.wishlist.contains(provider.productDetails.data!.id);
|
||||
}
|
||||
return Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
@@ -206,43 +226,13 @@ class _ProductDetailsState extends State<ProductDetails> {
|
||||
color: Colors.green,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: Text("10% OFF",
|
||||
child: Text(
|
||||
"${calculateDiscountPercentage(double.parse(provider.productDetails.data!.basePrice), double.parse(provider.productDetails.data!.discountPrice))}% OFF",
|
||||
style:
|
||||
TextStyle(color: Colors.white, fontSize: 14)),
|
||||
),
|
||||
Spacer(),
|
||||
InkWell(
|
||||
onTap: () async {
|
||||
if (await SharedPrefUtils.getToken() != null) {
|
||||
provider.toggleWishlist(
|
||||
context, provider.productDetails.data!.id!);
|
||||
} else {
|
||||
context.push(MyRoutes.SIGNUP);
|
||||
}
|
||||
},
|
||||
child: Icon(
|
||||
provider.wishlist
|
||||
.contains(provider.productDetails.data!.id)
|
||||
? Icons.favorite
|
||||
: Icons.favorite_border,
|
||||
color: provider.wishlist
|
||||
.contains(provider.productDetails.data!.id)
|
||||
? Colors.red
|
||||
: Colors.grey,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
ReadMoreText(
|
||||
provider.productDetails.data!.description ?? "",
|
||||
trimMode: TrimMode.Line,
|
||||
trimLines: 2,
|
||||
colorClickableText: APPCOLOR.appGreen,
|
||||
trimCollapsedText: 'Read More',
|
||||
trimExpandedText: 'Show less',
|
||||
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -252,262 +242,320 @@ class _ProductDetailsState extends State<ProductDetails> {
|
||||
});
|
||||
}
|
||||
|
||||
Widget reviews() {
|
||||
Widget _buildSkeletonLoader() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Reviews & Ratings",
|
||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Text("4.2",
|
||||
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold)),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
RatingStars(
|
||||
value: value,
|
||||
onValueChanged: (v) {
|
||||
//
|
||||
setState(() {
|
||||
value = v;
|
||||
});
|
||||
},
|
||||
starBuilder: (index, color) => Icon(
|
||||
Icons.star,
|
||||
color: color,
|
||||
),
|
||||
starCount: 5,
|
||||
starSize: 20,
|
||||
valueLabelColor: const Color(0xff9b9b9b),
|
||||
valueLabelTextStyle: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontStyle: FontStyle.normal,
|
||||
fontSize: 12.0),
|
||||
valueLabelRadius: 10,
|
||||
maxValue: 5,
|
||||
starSpacing: 2,
|
||||
maxValueVisibility: false,
|
||||
valueLabelVisibility: false,
|
||||
animationDuration: Duration(milliseconds: 1000),
|
||||
valueLabelPadding:
|
||||
const EdgeInsets.symmetric(vertical: 1, horizontal: 8),
|
||||
valueLabelMargin: const EdgeInsets.only(right: 8),
|
||||
starOffColor: const Color(0xffe7e8ea),
|
||||
starColor: Colors.green,
|
||||
),
|
||||
Text(
|
||||
"April 10, 2023",
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
Shimmer.fromColors(
|
||||
baseColor: Colors.grey[300]!,
|
||||
highlightColor: Colors.grey[100]!,
|
||||
child: Container(
|
||||
height: 300,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start, // Align items at the top
|
||||
children: [
|
||||
CircleAvatar(
|
||||
backgroundImage: NetworkImage('https://via.placeholder.com/50'),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
|
||||
// Column for Text and RatingStars
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween, // Proper spacing
|
||||
children: [
|
||||
Text(
|
||||
"Johnson Smith",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
RatingStars(
|
||||
value: value,
|
||||
starBuilder: (index, color) => Icon(
|
||||
Icons.star,
|
||||
color: color,
|
||||
),
|
||||
starCount: 5,
|
||||
starSize: 20,
|
||||
maxValue: 5,
|
||||
starSpacing: 2,
|
||||
maxValueVisibility: false,
|
||||
valueLabelVisibility: false,
|
||||
animationDuration: Duration(milliseconds: 1000),
|
||||
valueLabelPadding: const EdgeInsets.symmetric(
|
||||
vertical: 1, horizontal: 8),
|
||||
valueLabelMargin: const EdgeInsets.only(right: 8),
|
||||
starOffColor: const Color(0xffe7e8ea),
|
||||
starColor: Colors.green,
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
"April 10, 2023",
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
Shimmer.fromColors(
|
||||
baseColor: Colors.grey[300]!,
|
||||
highlightColor: Colors.grey[100]!,
|
||||
child: Container(
|
||||
height: 20,
|
||||
width: double.infinity,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
ReadMoreText(
|
||||
'Flutter is Google’s mobile UI open source framework to build high-quality native (super fast) interfaces for iOS and Android apps with the unified codebase.',
|
||||
trimMode: TrimMode.Line,
|
||||
trimLines: 2,
|
||||
colorClickableText: APPCOLOR.appGreen,
|
||||
trimCollapsedText: 'Read More',
|
||||
trimExpandedText: 'Show less',
|
||||
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
|
||||
Shimmer.fromColors(
|
||||
baseColor: Colors.grey[300]!,
|
||||
highlightColor: Colors.grey[100]!,
|
||||
child: Container(
|
||||
height: 20,
|
||||
width: 150,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Widget similarProducts() {
|
||||
// return 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),
|
||||
// )),
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
Widget reviews() {
|
||||
return Consumer<ProductProvider>(builder: (context, provider, child) {
|
||||
if (provider.isProductLoading) {
|
||||
return SizedBox.shrink();
|
||||
} else if (provider.productDetails.data == null) {
|
||||
return Center(child: Text('No products available'));
|
||||
} else {
|
||||
return provider.productDetails.data!.productReview!.isNotEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Reviews & Ratings",
|
||||
style: TextStyle(
|
||||
fontSize: 20, fontWeight: FontWeight.bold)),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Text("4.2",
|
||||
style: TextStyle(
|
||||
fontSize: 30, fontWeight: FontWeight.bold)),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
RatingStars(
|
||||
value: value,
|
||||
onValueChanged: (v) {
|
||||
//
|
||||
setState(() {
|
||||
value = v;
|
||||
});
|
||||
},
|
||||
starBuilder: (index, color) => Icon(
|
||||
Icons.star,
|
||||
color: color,
|
||||
),
|
||||
starCount: 5,
|
||||
starSize: 20,
|
||||
valueLabelColor: const Color(0xff9b9b9b),
|
||||
valueLabelTextStyle: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontStyle: FontStyle.normal,
|
||||
fontSize: 12.0),
|
||||
valueLabelRadius: 10,
|
||||
maxValue: 5,
|
||||
starSpacing: 2,
|
||||
maxValueVisibility: false,
|
||||
valueLabelVisibility: false,
|
||||
animationDuration: Duration(milliseconds: 1000),
|
||||
valueLabelPadding: const EdgeInsets.symmetric(
|
||||
vertical: 1, horizontal: 8),
|
||||
valueLabelMargin: const EdgeInsets.only(right: 8),
|
||||
starOffColor: const Color(0xffe7e8ea),
|
||||
starColor: Colors.green,
|
||||
),
|
||||
Text(
|
||||
"April 10, 2023",
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start, // Align items at the top
|
||||
children: [
|
||||
CircleAvatar(
|
||||
backgroundImage:
|
||||
NetworkImage('https://via.placeholder.com/50'),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
|
||||
// Column for Text and RatingStars
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment
|
||||
.spaceBetween, // Proper spacing
|
||||
children: [
|
||||
Text(
|
||||
"Johnson Smith",
|
||||
style:
|
||||
TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
RatingStars(
|
||||
value: value,
|
||||
starBuilder: (index, color) => Icon(
|
||||
Icons.star,
|
||||
color: color,
|
||||
),
|
||||
starCount: 5,
|
||||
starSize: 20,
|
||||
maxValue: 5,
|
||||
starSpacing: 2,
|
||||
maxValueVisibility: false,
|
||||
valueLabelVisibility: false,
|
||||
animationDuration:
|
||||
Duration(milliseconds: 1000),
|
||||
valueLabelPadding:
|
||||
const EdgeInsets.symmetric(
|
||||
vertical: 1, horizontal: 8),
|
||||
valueLabelMargin:
|
||||
const EdgeInsets.only(right: 8),
|
||||
starOffColor: const Color(0xffe7e8ea),
|
||||
starColor: Colors.green,
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
"April 10, 2023",
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
ReadMoreText(
|
||||
'Flutter is Google’s mobile UI open source framework to build high-quality native (super fast) interfaces for iOS and Android apps with the unified codebase.',
|
||||
trimMode: TrimMode.Line,
|
||||
trimLines: 2,
|
||||
colorClickableText: APPCOLOR.appGreen,
|
||||
trimCollapsedText: 'Read More',
|
||||
trimExpandedText: 'Show less',
|
||||
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Reviews & Ratings",
|
||||
style: TextStyle(
|
||||
fontSize: 20, fontWeight: FontWeight.bold)),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
children: [
|
||||
Text("4.2",
|
||||
style: TextStyle(
|
||||
fontSize: 30, fontWeight: FontWeight.bold)),
|
||||
SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
RatingStars(
|
||||
value: value,
|
||||
onValueChanged: (v) {
|
||||
//
|
||||
setState(() {
|
||||
value = v;
|
||||
});
|
||||
},
|
||||
starBuilder: (index, color) => Icon(
|
||||
Icons.star,
|
||||
color: color,
|
||||
),
|
||||
starCount: 5,
|
||||
starSize: 20,
|
||||
valueLabelColor: const Color(0xff9b9b9b),
|
||||
valueLabelTextStyle: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontStyle: FontStyle.normal,
|
||||
fontSize: 12.0),
|
||||
valueLabelRadius: 10,
|
||||
maxValue: 5,
|
||||
starSpacing: 2,
|
||||
maxValueVisibility: false,
|
||||
valueLabelVisibility: false,
|
||||
animationDuration: Duration(milliseconds: 1000),
|
||||
valueLabelPadding: const EdgeInsets.symmetric(
|
||||
vertical: 1, horizontal: 8),
|
||||
valueLabelMargin: const EdgeInsets.only(right: 8),
|
||||
starOffColor: const Color(0xffe7e8ea),
|
||||
starColor: Colors.green,
|
||||
),
|
||||
Text(
|
||||
"April 10, 2023",
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start, // Align items at the top
|
||||
children: [
|
||||
CircleAvatar(
|
||||
backgroundImage:
|
||||
NetworkImage('https://via.placeholder.com/50'),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
|
||||
// Column for Text and RatingStars
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment
|
||||
.spaceBetween, // Proper spacing
|
||||
children: [
|
||||
Text(
|
||||
"Johnson Smith",
|
||||
style:
|
||||
TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
RatingStars(
|
||||
value: value,
|
||||
starBuilder: (index, color) => Icon(
|
||||
Icons.star,
|
||||
color: color,
|
||||
),
|
||||
starCount: 5,
|
||||
starSize: 20,
|
||||
maxValue: 5,
|
||||
starSpacing: 2,
|
||||
maxValueVisibility: false,
|
||||
valueLabelVisibility: false,
|
||||
animationDuration:
|
||||
Duration(milliseconds: 1000),
|
||||
valueLabelPadding:
|
||||
const EdgeInsets.symmetric(
|
||||
vertical: 1, horizontal: 8),
|
||||
valueLabelMargin:
|
||||
const EdgeInsets.only(right: 8),
|
||||
starOffColor: const Color(0xffe7e8ea),
|
||||
starColor: Colors.green,
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Text(
|
||||
"April 10, 2023",
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
ReadMoreText(
|
||||
'Flutter is Google’s mobile UI open source framework to build high-quality native (super fast) interfaces for iOS and Android apps with the unified codebase.',
|
||||
trimMode: TrimMode.Line,
|
||||
trimLines: 2,
|
||||
colorClickableText: APPCOLOR.appGreen,
|
||||
trimCollapsedText: 'Read More',
|
||||
trimExpandedText: 'Show less',
|
||||
style: context.customMedium(APPCOLOR.balck1A1A1A, 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Widget bestDeal() {
|
||||
return Consumer<ProductProvider>(builder: (context, provider, child) {
|
||||
@@ -678,7 +726,7 @@ class _ProductDetailsState extends State<ProductDetails> {
|
||||
false
|
||||
? null
|
||||
: () => provider.addToCart(
|
||||
context, bestdealproduct.id!);
|
||||
context, bestdealproduct.id!, 1);
|
||||
} else {
|
||||
context.push(MyRoutes.SIGNUP);
|
||||
}
|
||||
@@ -730,71 +778,90 @@ class _ProductDetailsState extends State<ProductDetails> {
|
||||
}
|
||||
|
||||
Widget bottomBar() {
|
||||
return Consumer<ProductProvider>(
|
||||
builder: (context, cartProvider, child) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
boxShadow: [BoxShadow(color: Colors.grey.shade300, blurRadius: 10)],
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
icon: Icon(Icons.remove_circle_outline),
|
||||
onPressed: cartProvider.decreaseQuantity,
|
||||
),
|
||||
Text("${cartProvider.quantity}",
|
||||
style:
|
||||
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
IconButton(
|
||||
icon: Icon(Icons.add_circle_outline),
|
||||
onPressed: cartProvider.increaseQuantity,
|
||||
),
|
||||
],
|
||||
return Consumer<ProductProvider>(builder: (context, cartProvider, child) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
boxShadow: [BoxShadow(color: Colors.grey.shade300, blurRadius: 10)],
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
IconButton(
|
||||
icon: Icon(Icons.remove_circle_outline),
|
||||
onPressed: cartProvider.decreaseQuantity,
|
||||
),
|
||||
Text("${cartProvider.quantity}",
|
||||
style:
|
||||
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
IconButton(
|
||||
icon: Icon(Icons.add_circle_outline),
|
||||
onPressed: cartProvider.increaseQuantity,
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.lightGreen,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
Container(
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.lightGreen,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Center(
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'Add to Cart',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Container(
|
||||
width: 2, height: 50, color: APPCOLOR.whiteFBFEFB),
|
||||
SizedBox(width: 10),
|
||||
Text(
|
||||
"\$${cartProvider.totalPrice}",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Center(
|
||||
child: Row(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
cartProvider.addToCart(
|
||||
context,
|
||||
cartProvider.productDetails.data!.id!,
|
||||
cartProvider.quantity);
|
||||
},
|
||||
child: cartProvider.isLoadingCart
|
||||
? Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(left: 40, right: 40),
|
||||
child: Container(
|
||||
height: 15,
|
||||
width: 15,
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: Colors.white, strokeWidth: 2),
|
||||
),
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
'Add to Cart',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
Container(
|
||||
width: 2, height: 50, color: APPCOLOR.whiteFBFEFB),
|
||||
SizedBox(width: 10),
|
||||
Text(
|
||||
"\$${cartProvider.totalPrice}",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,16 +3,19 @@ import 'package:grocery_app/src/common_widget/network_image.dart';
|
||||
import 'package:grocery_app/src/logic/provider/home_provider.dart';
|
||||
import 'package:grocery_app/src/ui/card_checkout/card_checkout_screen.dart';
|
||||
import 'package:grocery_app/src/ui/edit_profile/edit_profile_screen.dart';
|
||||
import 'package:grocery_app/src/ui/map/google_map.dart';
|
||||
|
||||
import 'package:grocery_app/src/ui/mapscreen/map_screen.dart';
|
||||
import 'package:grocery_app/src/ui/message/message_screen.dart';
|
||||
import 'package:grocery_app/src/ui/notification/notification_screen.dart';
|
||||
import 'package:grocery_app/src/ui/rating_review/rating_review_screen.dart';
|
||||
import 'package:grocery_app/src/ui/static_page/static_page_screen.dart';
|
||||
import 'package:grocery_app/utils/constants/color_constant.dart';
|
||||
import 'package:grocery_app/utils/constants/shared_pref_utils.dart';
|
||||
import 'package:grocery_app/utils/constants/string_constant.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class ProfileScreen extends StatefulWidget {
|
||||
const ProfileScreen({super.key});
|
||||
@@ -25,7 +28,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
var top = 0.0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget build(BuildContext context)
|
||||
{
|
||||
return Scaffold(
|
||||
body: NestedScrollView(
|
||||
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
||||
@@ -69,34 +73,34 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
AppNetworkImage(
|
||||
height: top < 150 ? 30 : 50,
|
||||
width: top < 150 ? 30 : 50,
|
||||
imageUrl:
|
||||
imageUrl: "${APPSTRING.userProfile ?? ""}" ??
|
||||
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTdQLwDqDwd2JfzifvfBTFT8I7iKFFevcedYg&s",
|
||||
radius: 90,
|
||||
backGroundColor: Colors.white,
|
||||
boxFit: BoxFit.fill,
|
||||
),
|
||||
top > 100
|
||||
? Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
height: 18,
|
||||
width: 18,
|
||||
decoration: BoxDecoration(
|
||||
color: APPCOLOR.lightGreen,
|
||||
border: Border.all(
|
||||
color: Colors.white),
|
||||
borderRadius:
|
||||
BorderRadius.circular(5)),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
MdiIcons.pencil,
|
||||
size: 10,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
))
|
||||
: const SizedBox(),
|
||||
// top > 100
|
||||
// ? Positioned(
|
||||
// bottom: 0,
|
||||
// right: 0,
|
||||
// child: Container(
|
||||
// height: 18,
|
||||
// width: 18,
|
||||
// decoration: BoxDecoration(
|
||||
// color: APPCOLOR.lightGreen,
|
||||
// border: Border.all(
|
||||
// color: Colors.white),
|
||||
// borderRadius:
|
||||
// BorderRadius.circular(5)),
|
||||
// child: Center(
|
||||
// child: Icon(
|
||||
// MdiIcons.pencil,
|
||||
// size: 10,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// ),
|
||||
// ))
|
||||
// : const SizedBox(),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
@@ -108,13 +112,13 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
"Smith Mate",
|
||||
APPSTRING.userName ?? "",
|
||||
style: context.customExtraBold(
|
||||
top < 100 ? Colors.black : Colors.white,
|
||||
14),
|
||||
),
|
||||
Text(
|
||||
'smithmate@example.com',
|
||||
APPSTRING.emailName,
|
||||
style: context.customRegular(
|
||||
top < 100 ? Colors.black : Colors.white,
|
||||
10),
|
||||
@@ -196,30 +200,31 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
title: const Text('Notifications'),
|
||||
trailing: Icon(MdiIcons.chevronRight),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return const RatingReviewScreen();
|
||||
},
|
||||
));
|
||||
},
|
||||
leading: Icon(MdiIcons.starOutline),
|
||||
title: const Text('Rating & Review'),
|
||||
trailing: Icon(MdiIcons.chevronRight),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return const MessageScreen();
|
||||
},
|
||||
));
|
||||
},
|
||||
leading: Icon(MdiIcons.messageOutline),
|
||||
title: const Text('Driver Message'),
|
||||
trailing: Icon(MdiIcons.chevronRight),
|
||||
),
|
||||
// ListTile(
|
||||
// onTap: () {
|
||||
// Navigator.of(context).push(MaterialPageRoute(
|
||||
// builder: (context) {
|
||||
// return const RatingReviewScreen();
|
||||
// },
|
||||
// ));
|
||||
// },
|
||||
// leading: Icon(MdiIcons.starOutline),
|
||||
// title: const Text('Rating & Review'),
|
||||
// trailing: Icon(MdiIcons.chevronRight),
|
||||
// ),
|
||||
// ListTile(
|
||||
// onTap: () {
|
||||
// Navigator.of(context).push(MaterialPageRoute(
|
||||
// builder: (context) {
|
||||
// return const MessageScreen();
|
||||
// },
|
||||
// ));
|
||||
// },
|
||||
// leading: Icon(MdiIcons.messageOutline),
|
||||
// title: const Text('Driver Message'),
|
||||
// trailing: Icon(MdiIcons.chevronRight),
|
||||
// ),
|
||||
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
@@ -248,24 +253,12 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
title: const Text('Term & Conditions'),
|
||||
trailing: Icon(MdiIcons.chevronRight),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {},
|
||||
leading: Icon(MdiIcons.basketOutline),
|
||||
title: const Text('Grocery List'),
|
||||
trailing: Icon(MdiIcons.chevronRight),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return MapScreen();
|
||||
},
|
||||
));
|
||||
},
|
||||
leading: Icon(MdiIcons.basketOutline),
|
||||
title: const Text('Map List'),
|
||||
trailing: Icon(MdiIcons.chevronRight),
|
||||
),
|
||||
// ListTile(
|
||||
// onTap: () {},
|
||||
// leading: Icon(MdiIcons.basketOutline),
|
||||
// title: const Text('Grocery List'),
|
||||
// trailing: Icon(MdiIcons.chevronRight),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grocery_app/src/core/routes/routes.dart';
|
||||
import 'package:grocery_app/src/logic/provider/bottom_navbar_provider.dart';
|
||||
import 'package:grocery_app/src/ui/onboarding/on_boarding_screen.dart';
|
||||
import 'package:grocery_app/utils/constants/assets_constant.dart';
|
||||
import 'package:grocery_app/utils/constants/shared_pref_utils.dart';
|
||||
import 'package:grocery_app/utils/extensions/extensions.dart';
|
||||
import 'package:grocery_app/utils/extensions/uicontext.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class SplashScreen extends StatefulWidget {
|
||||
const SplashScreen({super.key});
|
||||
@@ -14,6 +16,7 @@ class SplashScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _SplashScreenState extends State<SplashScreen> {
|
||||
|
||||
couting() async {
|
||||
Future.delayed(const Duration(seconds: 3)).then((c) {
|
||||
Navigator.of(context).pushReplacement(MaterialPageRoute(
|
||||
@@ -27,6 +30,9 @@ class _SplashScreenState extends State<SplashScreen> {
|
||||
@override
|
||||
void initState() {
|
||||
Future.delayed(const Duration(seconds: 2), () async {
|
||||
|
||||
Provider.of<BottomNavProvider>(context, listen: false)
|
||||
.refreshToken(context);
|
||||
if (await SharedPrefUtils.isFreshInstall()) {
|
||||
context.clearAndPush(routePath: MyRoutes.ONBOARDING);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user