updateProfile

This commit is contained in:
2025-02-03 01:29:42 +05:30
parent 42aaa7cdad
commit 1f7254ecaa
48 changed files with 6088 additions and 2473 deletions

View File

@@ -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);
}

View File

@@ -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

View 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"),
)
],
)
],
),
),
);
},
),
),
],
),
),
);
}
}

View File

@@ -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

View File

@@ -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

View 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),
],
),
),
),
],
),
),
),
);
}
}

View File

@@ -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"),
// ),
],
),
),
),
],
),
);
}
}

View File

@@ -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 Googles 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 Googles 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 Googles 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),
),
],
),
),
)
],
),
);
},
);
),
)
],
),
);
});
}
}

View File

@@ -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),
// ),
],
),
),

View File

@@ -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 {