Initial commit
This commit is contained in:
459
app_code/lib/screens/address/address_new_or_update.dart
Normal file
459
app_code/lib/screens/address/address_new_or_update.dart
Normal file
@@ -0,0 +1,459 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/input_decorations.dart';
|
||||
import 'package:grostore/custom_ui/toast_ui.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/models/city_response.dart';
|
||||
import 'package:grostore/models/country_response.dart';
|
||||
import 'package:grostore/models/state_response.dart';
|
||||
import 'package:grostore/presenters/address_presenter.dart';
|
||||
import 'package:grostore/screens/address/addresses.dart';
|
||||
import 'package:grostore/screens/profile.dart';
|
||||
|
||||
class AddressNewOrUpdate extends StatefulWidget {
|
||||
int? addressId;
|
||||
|
||||
AddressNewOrUpdate({super.key, this.addressId});
|
||||
|
||||
@override
|
||||
State<AddressNewOrUpdate> createState() => _AddressNewOrUpdateState();
|
||||
}
|
||||
|
||||
class _AddressNewOrUpdateState extends State<AddressNewOrUpdate> {
|
||||
AddressPresenter addressPresenter = AddressPresenter();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
if (widget.addressId != null) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
addressPresenter.getEditAddressData(widget.addressId, context);
|
||||
});
|
||||
}else{
|
||||
addressPresenter.getCountries();
|
||||
}
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CommonAppbar.show(
|
||||
title: widget.addressId == null
|
||||
? AppLang.local(context).add_new_address_ucf
|
||||
: AppLang.local(context).update_address,
|
||||
context: context),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(StyleConfig.padding),
|
||||
child: ListenableBuilder(
|
||||
listenable: addressPresenter,
|
||||
builder: (context, child) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
//buildLabelText(AppLang.local(context).country),
|
||||
space(size: 10),
|
||||
// buildButton(AppLang.local(context).select_country,
|
||||
// addressPresenter.selectedCountry?.name ?? "", () {
|
||||
// showCountryDialog();
|
||||
// }),
|
||||
countryDropDown(),
|
||||
space(),
|
||||
//buildLabelText(AppLang.local(context).state),
|
||||
//space(size: 10),
|
||||
// buildButton(AppLang.local(context).select_state,
|
||||
// addressPresenter.selectedState?.name ?? '', () {
|
||||
// if (addressPresenter.selectedCountry != null) {
|
||||
// showStateDialog();
|
||||
// } else {
|
||||
// ToastUi.show(context,
|
||||
// AppLang.local(context).please_select_a_country);
|
||||
// }
|
||||
// }),
|
||||
stateDropDown(),
|
||||
space(),
|
||||
// buildLabelText(AppLang.local(context).city),
|
||||
// space(size: 10),
|
||||
// buildButton(AppLang.local(context).select_city,
|
||||
// addressPresenter.selectedCity?.name ?? '', () {
|
||||
// if (addressPresenter.selectedState != null) {
|
||||
// showCityDialog();
|
||||
// } else {
|
||||
// ToastUi.show(context,
|
||||
// AppLang.local(context).please_select_a_state);
|
||||
// }
|
||||
// }),
|
||||
cityDropDown(),
|
||||
space(),
|
||||
isDefaultDropDown(),
|
||||
space(),
|
||||
Container(
|
||||
height: 100,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10, vertical: 10),
|
||||
decoration: BoxDecorations.customRadius(
|
||||
radius: BorderRadius.circular(8))
|
||||
.copyWith(
|
||||
border: Border.all(color: ThemeConfig.grey)),
|
||||
child: TextField(
|
||||
controller: addressPresenter.addressController,
|
||||
decoration: const InputDecoration.collapsed(
|
||||
hintText: "2/5 Elephant Road, New Town"),
|
||||
),
|
||||
),
|
||||
space(),
|
||||
Button(
|
||||
onPressed: () {
|
||||
if (widget.addressId != null) {
|
||||
addressPresenter.updateAddress(context,
|
||||
id: widget.addressId!,
|
||||
countryInfo: addressPresenter.selectedCountry,
|
||||
stateInfo: addressPresenter.selectedState,
|
||||
cityInfo: addressPresenter.selectedCity,
|
||||
fullAddress: addressPresenter.addressController.text.trim(),
|
||||
isDefault:
|
||||
addressPresenter.defaultAddress == "No"
|
||||
? 0
|
||||
: 1);
|
||||
} else {
|
||||
addressPresenter.addAddress(context,
|
||||
countryInfo: addressPresenter.selectedCountry,
|
||||
stateInfo: addressPresenter.selectedState,
|
||||
cityInfo: addressPresenter.selectedCity,
|
||||
fullAddress: addressPresenter
|
||||
.addressController.text
|
||||
.trim(),
|
||||
isDefault:
|
||||
addressPresenter.defaultAddress == "No"
|
||||
? 0
|
||||
: 1);
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
shape: StyleConfig.buttonRadius(8),
|
||||
color: ThemeConfig.red,
|
||||
minWidth: getWidth(context),
|
||||
minHeight: 40.0,
|
||||
child: Text(
|
||||
AppLang.local(context).save,
|
||||
style: StyleConfig.fs14cWhitefwBold,
|
||||
))
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Text buildLabelText(String text) => Text(
|
||||
text,
|
||||
style: StyleConfig.fs14fwBold,
|
||||
);
|
||||
|
||||
Widget space({size = 24}) {
|
||||
return SizedBox(
|
||||
height: size.toDouble(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Button buildButton(String title, value, onPress) {
|
||||
return Button(
|
||||
onPressed: () => onPress(),
|
||||
color: ThemeConfig.grey,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.only(
|
||||
bottomLeft: Radius.circular(8), topLeft: Radius.circular(8))),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: 120,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
|
||||
decoration: BoxDecorations.customRadius(
|
||||
radius: const BorderRadius.only(
|
||||
bottomLeft: Radius.circular(8),
|
||||
topLeft: Radius.circular(8)),
|
||||
color: ThemeConfig.secondaryColor),
|
||||
child: Text(
|
||||
title,
|
||||
style: StyleConfig.fs14cWhitefwNormal,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
constraints: BoxConstraints(maxWidth: getWidth(context) * 0.5),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
||||
//decoration: BoxDecorations.customRadius(radius: BorderRadius.only(bottomRight: Radius.circular(8),topRight: Radius.circular(8)),color: ThemeConfig.grey),
|
||||
child: Text(
|
||||
value,
|
||||
style: StyleConfig.fs14cWhitefwNormal,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const Icon(Icons.arrow_drop_down_outlined)
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
Widget countryDropDown(){
|
||||
return DropdownButtonFormField<CountryInfo>(
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLang.local(context).select_country,
|
||||
border: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: ThemeConfig.accentColor)
|
||||
),
|
||||
),
|
||||
value: addressPresenter.selectedCountry,
|
||||
onChanged: (CountryInfo? country) {
|
||||
if(country!=null){
|
||||
addressPresenter.setSelectedCountry(country);
|
||||
}
|
||||
},
|
||||
dropdownColor: Colors.white,
|
||||
items:addressPresenter.countries.map<DropdownMenuItem<CountryInfo>>((e) =>DropdownMenuItem(
|
||||
value: e,
|
||||
child: Text(e.name,style: StyleConfig.fs14fwNormal,),
|
||||
) ).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget stateDropDown(){
|
||||
return DropdownButtonFormField<StateInfo>(
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLang.local(context).select_state,
|
||||
border: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: ThemeConfig.accentColor)
|
||||
),
|
||||
),
|
||||
value: addressPresenter.selectedState,
|
||||
onChanged: (StateInfo? state) {
|
||||
if(state!=null) {
|
||||
addressPresenter.setSelectedState(state);
|
||||
}
|
||||
},
|
||||
dropdownColor: Colors.white,
|
||||
items:addressPresenter.states.map<DropdownMenuItem<StateInfo>>((e) =>DropdownMenuItem(
|
||||
value: e,
|
||||
child: Text(e.name,style: StyleConfig.fs14fwNormal,),
|
||||
) ).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget cityDropDown(){
|
||||
return DropdownButtonFormField<CityInfo>(
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLang.local(context).select_city,
|
||||
border: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: ThemeConfig.accentColor)
|
||||
),
|
||||
),
|
||||
value: addressPresenter.selectedCity,
|
||||
onChanged: (CityInfo? city) {
|
||||
if(city!=null) {
|
||||
addressPresenter.setSelectedCity(city);
|
||||
}
|
||||
},
|
||||
dropdownColor: Colors.white,
|
||||
items:addressPresenter.cities.map<DropdownMenuItem<CityInfo>>((e) =>DropdownMenuItem(
|
||||
value: e,
|
||||
child: Text(e.name,style: StyleConfig.fs14fwNormal,),
|
||||
) ).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget isDefaultDropDown(){
|
||||
return DropdownButtonFormField<String>(
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLang.local(context).default_address,
|
||||
border: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: ThemeConfig.accentColor)
|
||||
),
|
||||
),
|
||||
onChanged: (String? value) {
|
||||
if(value!=null) {
|
||||
addressPresenter.setDefaultAddress(value);
|
||||
}
|
||||
},
|
||||
value: addressPresenter.defaultAddress,
|
||||
dropdownColor: Colors.white,
|
||||
items:["No", "Set Default"].map<DropdownMenuItem<String>>((e) =>DropdownMenuItem(
|
||||
value: e,
|
||||
child: Text(e,style: StyleConfig.fs14fwNormal,),
|
||||
) ).toList(),
|
||||
);
|
||||
}
|
||||
/*
|
||||
|
||||
showCountryDialog() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => ListenableBuilder(
|
||||
listenable: addressPresenter,
|
||||
builder: (context, child) {
|
||||
return AlertDialog(
|
||||
title: TextField(
|
||||
onChanged: (text) {
|
||||
print(text);
|
||||
addressPresenter.filterCountry(text);
|
||||
},
|
||||
decoration: InputDecorations.basic(hint_text: "search...")),
|
||||
content: Container(
|
||||
height: 250,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: List.generate(
|
||||
addressPresenter.filteredCountries.length,
|
||||
(index) => Button(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
|
||||
},
|
||||
child: Container(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: getWidth(context)),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10, vertical: 10),
|
||||
margin: EdgeInsets.only(bottom: 10),
|
||||
decoration: BoxDecorations.basic(),
|
||||
child: Text(
|
||||
addressPresenter
|
||||
.filteredCountries[index].name,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
)),
|
||||
))),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
Button(
|
||||
color: ThemeConfig.grey,
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
AppLang.local(context).close,
|
||||
style: StyleConfig.fs14cWhitefwNormal,
|
||||
))
|
||||
],
|
||||
);
|
||||
}));
|
||||
}
|
||||
showStateDialog() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => ListenableBuilder(
|
||||
listenable: addressPresenter,
|
||||
builder: (context, child) {
|
||||
return AlertDialog(
|
||||
title: TextField(
|
||||
onChanged: (text) {
|
||||
addressPresenter.filterState(text);
|
||||
},
|
||||
decoration: InputDecorations.basic(hint_text: "search...")),
|
||||
content: Container(
|
||||
height: 250,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: List.generate(
|
||||
addressPresenter.filteredStates.length,
|
||||
(index) => Button(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
addressPresenter.setSelectedState(
|
||||
addressPresenter.filteredStates[index]);
|
||||
},
|
||||
child: Container(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: getWidth(context)),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10, vertical: 10),
|
||||
margin: EdgeInsets.only(bottom: 10),
|
||||
decoration: BoxDecorations.basic(),
|
||||
child: Text(
|
||||
addressPresenter
|
||||
.filteredStates[index].name,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
)),
|
||||
))),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
Button(
|
||||
color: ThemeConfig.grey,
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
AppLang.local(context).close,
|
||||
style: StyleConfig.fs14cWhitefwNormal,
|
||||
))
|
||||
],
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
showCityDialog() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => ListenableBuilder(
|
||||
listenable: addressPresenter,
|
||||
builder: (context, child) {
|
||||
return AlertDialog(
|
||||
title: TextField(
|
||||
onChanged: (text) {
|
||||
addressPresenter.filterCity(text);
|
||||
},
|
||||
decoration: InputDecorations.basic(hint_text: "search...")),
|
||||
content: Container(
|
||||
height: 250,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: List.generate(
|
||||
addressPresenter.filteredCities.length,
|
||||
(index) => Button(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
addressPresenter.setSelectedCity(
|
||||
addressPresenter.filteredCities[index]);
|
||||
},
|
||||
child: Container(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: getWidth(context)),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10, vertical: 10),
|
||||
margin: EdgeInsets.only(bottom: 10),
|
||||
decoration: BoxDecorations.basic(),
|
||||
child: Text(
|
||||
addressPresenter
|
||||
.filteredCities[index].name,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
)),
|
||||
))),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
Button(
|
||||
color: ThemeConfig.grey,
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
AppLang.local(context).close,
|
||||
style: StyleConfig.fs14cWhitefwNormal,
|
||||
))
|
||||
],
|
||||
);
|
||||
}));
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
202
app_code/lib/screens/address/addresses.dart
Normal file
202
app_code/lib/screens/address/addresses.dart
Normal file
@@ -0,0 +1,202 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/Boxdecorations.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/filter_dropdown.dart';
|
||||
import 'package:grostore/custom_ui/shimmers.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/presenters/address_presenter.dart';
|
||||
import 'package:grostore/presenters/user_presenter.dart';
|
||||
import 'package:grostore/screens/address/address_new_or_update.dart';
|
||||
import 'package:grostore/screens/check_out.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class Addresses extends StatefulWidget {
|
||||
const Addresses({super.key});
|
||||
|
||||
@override
|
||||
State<Addresses> createState() => _AddressesState();
|
||||
}
|
||||
|
||||
class _AddressesState extends State<Addresses> {
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
Provider.of<AddressPresenter>(context, listen: false).initState();
|
||||
});
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CommonAppbar.show(
|
||||
title: AppLang.local(context).address,
|
||||
context: context,
|
||||
bottom: PreferredSize(
|
||||
preferredSize: Size(getWidth(context), 40),
|
||||
child: Button(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
|
||||
minWidth: getWidth(context) - (StyleConfig.padding * 2),
|
||||
shape: StyleConfig.buttonRadius(2)
|
||||
.copyWith(side: BorderSide(color: ThemeConfig.extraDarkGrey)),
|
||||
onPressed: () {
|
||||
MakeRoute.go(context, AddressNewOrUpdate());
|
||||
},
|
||||
child: Text(
|
||||
AppLang.local(context).add_new_address_ucf,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
body: Consumer<AddressPresenter>(builder: (context, data, child) {
|
||||
return addresses(data);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Widget addresses(AddressPresenter data) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: data.onRefresh,
|
||||
child: Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
//color: Colors.red,
|
||||
|
||||
width: getWidth(context),
|
||||
child: data.isFetchAddress
|
||||
? ListView.separated(
|
||||
itemCount: data.addresses.length,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding, vertical: 10),
|
||||
scrollDirection: Axis.vertical,
|
||||
itemBuilder: (context, index) {
|
||||
return Material(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
child: InkWell(
|
||||
onTap: (){
|
||||
MakeRoute.goAndRemoveAll(context,const CheckOut());
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
width: getWidth(context),
|
||||
decoration: BoxDecorations.shadow(radius: 8).copyWith(
|
||||
border: Border.all(width: 2, color: ThemeConfig.grey)),
|
||||
child: Stack(
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
data.addresses[index].address,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
maxLines: 1,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).city}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
data.addresses[index].cityName,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).state}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
data.addresses[index].stateName,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).country}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
data.addresses[index].countryName,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
top: 0,
|
||||
right: 0,
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 25,
|
||||
width: 25,
|
||||
child: Button(
|
||||
onPressed: (){
|
||||
MakeRoute.go(context, AddressNewOrUpdate(addressId:data.addresses[index].id ,));
|
||||
},
|
||||
padding: EdgeInsets.zero,
|
||||
minWidth: 10.0,
|
||||
minHeight: 10.0,
|
||||
child:const Icon(Icons.edit,),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15,),
|
||||
SizedBox(
|
||||
height: 25,
|
||||
width: 25,
|
||||
child: Button(
|
||||
onPressed: (){
|
||||
data.deleteAddress(data.addresses[index].id , context);
|
||||
},
|
||||
padding: EdgeInsets.zero,
|
||||
minWidth: 10.0,
|
||||
minHeight: 10.0,
|
||||
child:const Icon(Icons.delete,),
|
||||
),
|
||||
),
|
||||
],
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return const SizedBox(
|
||||
height: 10,
|
||||
);
|
||||
},
|
||||
)
|
||||
: Shimmers.list(10, getWidth(context) * 0.5, 100),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
300
app_code/lib/screens/auth/login.dart
Normal file
300
app_code/lib/screens/auth/login.dart
Normal file
@@ -0,0 +1,300 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/auth_ui.dart';
|
||||
import 'package:grostore/custom_ui/input_decorations.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/presenters/auth/auth_presenter.dart';
|
||||
import 'package:grostore/screens/auth/password_forget.dart';
|
||||
import 'package:grostore/screens/auth/registration.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../custom_ui/BoxDecorations.dart';
|
||||
|
||||
class Login extends StatefulWidget {
|
||||
const Login({super.key});
|
||||
|
||||
@override
|
||||
_LoginState createState() => _LoginState();
|
||||
}
|
||||
|
||||
class _LoginState extends State<Login> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Provider.of<AuthPresenter>(context, listen: false).setContext(context);
|
||||
return AuthScreen.buildScreen(
|
||||
context, buildBody(context, getWidth(context))
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildBody(BuildContext context, double screenWidth) {
|
||||
return Consumer<AuthPresenter>(builder: (context, data, child) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
width: screenWidth * (3 / 4),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: getWidth(context),
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).welcome_to_back,
|
||||
style: StyleConfig.fs24fwBold,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).phone,
|
||||
style: TextStyle(
|
||||
color: ThemeConfig.fontColor, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
|
||||
/// #Country change
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Container(
|
||||
decoration: BoxDecorations.basic(
|
||||
|
||||
),
|
||||
height: 36,
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14.0),
|
||||
child: Icon(
|
||||
Icons.phone,
|
||||
size: 18,
|
||||
color: ThemeConfig.mediumGrey,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"+998",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
// Button(
|
||||
// minWidth: 80,
|
||||
// onPressed: () {
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (context) {
|
||||
// return buildFilterDialog(data);
|
||||
// });
|
||||
// },
|
||||
// child: Row(
|
||||
// children: [
|
||||
// Image.asset(
|
||||
// "${getAssetFlag(data.regCountry.code.toLowerCase())}.png"),
|
||||
//
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
width: getWidth(context) - 200,
|
||||
child: TextField(
|
||||
keyboardType: TextInputType.number,
|
||||
textInputAction: TextInputAction.next,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
decoration: const InputDecoration.collapsed(
|
||||
hintText: "XX XXX XXX"),
|
||||
controller: data.loginPhoneNumberController,
|
||||
),
|
||||
)
|
||||
],
|
||||
)),
|
||||
),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.only(bottom: 8.0),
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.end,
|
||||
// children: [
|
||||
// SizedBox(
|
||||
// height: 36,
|
||||
// child: TextField(
|
||||
// controller: data.loginEmailController,
|
||||
// autofocus: false,
|
||||
// decoration: InputDecorations.basic(
|
||||
// prefixIcon: Icon(
|
||||
// Icons.email_outlined,
|
||||
// size: 18,
|
||||
// color: ThemeConfig.mediumGrey,
|
||||
// ),
|
||||
// hint_text: "user@example.com"),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
|
||||
// #Password
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).password,
|
||||
style: TextStyle(
|
||||
color: ThemeConfig.fontColor, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 36,
|
||||
child: TextField(
|
||||
textInputAction: TextInputAction.search,
|
||||
controller: data.loginPasswordController,
|
||||
autofocus: false,
|
||||
obscureText: true,
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
decoration: InputDecorations.basic(
|
||||
prefixIcon: Icon(
|
||||
Icons.lock,
|
||||
size: 18,
|
||||
color: ThemeConfig.mediumGrey,
|
||||
),
|
||||
hint_text: "• • • • • • • •"),
|
||||
),
|
||||
),
|
||||
Button(
|
||||
minWidth: 50,
|
||||
padding: EdgeInsets.zero,
|
||||
child: Text(
|
||||
AppLang.local(context).forgot_password_q_ucf,
|
||||
style: TextStyle(
|
||||
color: ThemeConfig.blue,
|
||||
fontStyle: FontStyle.italic),
|
||||
|
||||
),
|
||||
onPressed: (){
|
||||
MakeRoute.go(context, PasswordForget());
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// #login Button
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 30.0),
|
||||
child: Container(
|
||||
height: 45,
|
||||
child: Button.minSize(
|
||||
width: getWidth(context),
|
||||
height: 50,
|
||||
color: ThemeConfig.red,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(6.0))),
|
||||
child: Text(
|
||||
AppLang.local(context).login,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
onPressed: () {
|
||||
data.onPressedLogin();
|
||||
}),
|
||||
),
|
||||
),
|
||||
|
||||
// #register route text
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 20.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Center(
|
||||
child: Text(
|
||||
AppLang.local(context).not_a_member,
|
||||
style:
|
||||
TextStyle(color: ThemeConfig.fontColor, fontSize: 12),
|
||||
)),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Button(
|
||||
minWidth: 20,
|
||||
child: Text(
|
||||
AppLang.local(context).register_now_ucf,
|
||||
style: TextStyle(
|
||||
color: ThemeConfig.red,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.push(context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return Registration();
|
||||
}));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Country country = Country(name:"Uzbekistan" , dial_code: "+998", code: "+998");
|
||||
|
||||
// AlertDialog buildFilterDialog(AuthPresenter data) {
|
||||
// return AlertDialog(
|
||||
// title: const Text('Search Country'),
|
||||
// content: Container(
|
||||
// height: 300,
|
||||
// child: Column(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: <Widget>[
|
||||
// TextField(
|
||||
// onChanged: data.filterCountry,
|
||||
// decoration: const InputDecoration(
|
||||
// hintText: 'Search',
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(height: 16.0),
|
||||
// Expanded(
|
||||
// child: SingleChildScrollView(
|
||||
// child: Consumer<AuthPresenter>(
|
||||
// builder: (context, filterData, child) {
|
||||
// return Column(
|
||||
// children: List.generate(filterData.filteredCountry.length,
|
||||
// (index) {
|
||||
// country = filterData.filteredCountry[index];
|
||||
// return ListTile(
|
||||
// leading: Image.asset(
|
||||
// getAssetFlag("${country.code.toLowerCase()}.png"),
|
||||
// height: 30,
|
||||
// width: 30,
|
||||
// ),
|
||||
// title: Text(country.name),
|
||||
// onTap: () {
|
||||
// data.onChangeCountry(country);
|
||||
// Navigator.of(context).pop();
|
||||
// filterData.filteredCountry = filterData.country;
|
||||
// },
|
||||
// );
|
||||
// }),
|
||||
// );
|
||||
// }),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
}
|
||||
148
app_code/lib/screens/auth/password_forget.dart
Normal file
148
app_code/lib/screens/auth/password_forget.dart
Normal file
@@ -0,0 +1,148 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/auth_ui.dart';
|
||||
import 'package:grostore/custom_ui/input_decorations.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/presenters/auth/auth_presenter.dart';
|
||||
import 'package:grostore/screens/auth/password_otp.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../custom_ui/Boxdecorations.dart';
|
||||
|
||||
|
||||
class PasswordForget extends StatefulWidget {
|
||||
const PasswordForget({super.key});
|
||||
|
||||
@override
|
||||
_PasswordForgetState createState() => _PasswordForgetState();
|
||||
}
|
||||
|
||||
class _PasswordForgetState extends State<PasswordForget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AuthScreen.buildScreen(context, buildBody(getWidth(context), context));
|
||||
}
|
||||
|
||||
Widget buildBody(double screenWidth, BuildContext context) {
|
||||
return Consumer<AuthPresenter>(builder: (context, data, child) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
|
||||
width: screenWidth * (3 / 4),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: getWidth(context),
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).forgot_password_ucf,
|
||||
style: StyleConfig.fs24fwBold,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).please_enter_phone,
|
||||
style: TextStyle(
|
||||
color: ThemeConfig.fontColor, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 45,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Container(
|
||||
decoration: BoxDecorations.basic(),
|
||||
height: 36,
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14.0),
|
||||
child: Icon(
|
||||
Icons.phone,
|
||||
size: 18,
|
||||
color: ThemeConfig.mediumGrey,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"+998",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
// Button(
|
||||
// minWidth: 80,
|
||||
// onPressed: () {
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (context) {
|
||||
// return buildFilterDialog(data);
|
||||
// });
|
||||
// },
|
||||
// child: Row(
|
||||
// children: [
|
||||
// Image.asset(
|
||||
// "${getAssetFlag(data.regCountry.code.toLowerCase())}.png"),
|
||||
//
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
width: getWidth(context) - 200,
|
||||
child: TextField(
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
decoration: const InputDecoration.collapsed(
|
||||
hintText: "XX XXX XXX"),
|
||||
controller: data.forgetPhoneNumberController,
|
||||
),
|
||||
)
|
||||
],
|
||||
)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 30.0),
|
||||
child: SizedBox(
|
||||
height: 45,
|
||||
child: Button.minSize(
|
||||
width: getWidth(context),
|
||||
height: 50,
|
||||
color: ThemeConfig.red,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(6.0))),
|
||||
child: Text(
|
||||
AppLang.local(context).send,
|
||||
style:const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
onPressed: () {
|
||||
data.onPressSendCode();
|
||||
// MakeRoute.go(context, PasswordOtp(phone_num:data.loginPhoneNumberController.text,));
|
||||
|
||||
}),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
189
app_code/lib/screens/auth/password_otp.dart
Normal file
189
app_code/lib/screens/auth/password_otp.dart
Normal file
@@ -0,0 +1,189 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/auth_ui.dart';
|
||||
import 'package:grostore/custom_ui/input_decorations.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/presenters/auth/auth_presenter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class PasswordOtp extends StatefulWidget {
|
||||
PasswordOtp({super.key,this.verify_by = "phone",this.phone_num});
|
||||
|
||||
String? verify_by;
|
||||
String? phone_num;
|
||||
|
||||
@override
|
||||
_PasswordOtpState createState() => _PasswordOtpState();
|
||||
}
|
||||
|
||||
class _PasswordOtpState extends State<PasswordOtp> {
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AuthScreen.buildScreen(context, buildBody(context, getWidth(context)));
|
||||
}
|
||||
|
||||
|
||||
Widget buildBody(BuildContext context, double screenWidth) {
|
||||
return Consumer<AuthPresenter>(builder: (context, data, child) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
width: screenWidth * (3 / 4),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: getWidth(context),
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).otp_all_cap,
|
||||
style: StyleConfig.fs24fwBold,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).otp_all_cap,
|
||||
style: TextStyle(
|
||||
color: ThemeConfig.fontColor, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 36,
|
||||
child: TextField(
|
||||
controller: data.otpCodeController,
|
||||
autofocus: false,
|
||||
decoration: InputDecorations.basic(
|
||||
prefixIcon: Icon(
|
||||
Icons.pin,
|
||||
size: 18,
|
||||
color: ThemeConfig.fontColor,
|
||||
),
|
||||
hint_text: "XXX XXX"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.only(bottom: 4.0),
|
||||
// child: Text(
|
||||
// AppLang.local(context).new_password_ucf,
|
||||
// style: TextStyle(
|
||||
// color: ThemeConfig.fontColor, fontWeight: FontWeight.w600),
|
||||
// ),
|
||||
// ),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.only(bottom: 8.0),
|
||||
// child: Container(
|
||||
// height: 36,
|
||||
// child: TextField(
|
||||
// controller: data.otpPasswordController,
|
||||
// autofocus: false,
|
||||
// obscureText: true,
|
||||
// enableSuggestions: false,
|
||||
// autocorrect: false,
|
||||
// decoration: InputDecorations.basic(
|
||||
// prefixIcon: Icon(
|
||||
// Icons.lock,
|
||||
// size: 18,
|
||||
// color: ThemeConfig.fontColor,
|
||||
// ),
|
||||
// hint_text: "• • • • • • • •"),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.only(bottom: 4.0),
|
||||
// child: Text(
|
||||
// AppLang.local(context).confirm_password_ucf,
|
||||
// style: TextStyle(
|
||||
// color: ThemeConfig.fontColor, fontWeight: FontWeight.w600),
|
||||
// ),
|
||||
// ),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.only(bottom: 8.0),
|
||||
// child: Container(
|
||||
// height: 36,
|
||||
// child: TextField(
|
||||
// controller: data.otpPasswordConfirmController,
|
||||
// autofocus: false,
|
||||
// obscureText: true,
|
||||
// enableSuggestions: false,
|
||||
// autocorrect: false,
|
||||
// decoration: InputDecorations.basic(
|
||||
// prefixIcon: Icon(
|
||||
// Icons.lock,
|
||||
// size: 18,
|
||||
// color: ThemeConfig.fontColor,
|
||||
// ),
|
||||
// hint_text: "• • • • • • • •"),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 30.0),
|
||||
child: SizedBox(
|
||||
height: 45,
|
||||
child: Button.minSize(
|
||||
width: getWidth(context),
|
||||
height: 50,
|
||||
color: ThemeConfig.red,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(6.0))),
|
||||
child: Text(
|
||||
AppLang.local(context).send,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
onPressed: () {
|
||||
data.onPressOTP();
|
||||
}),
|
||||
),
|
||||
),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.only(top: 20.0),
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// Button(
|
||||
// minWidth: 20,
|
||||
// child: Text(
|
||||
// AppLang.local(context).resend_otp_all_cap,
|
||||
// style: TextStyle(
|
||||
// color: ThemeConfig.accentColor,
|
||||
// fontSize: 14,
|
||||
// fontWeight: FontWeight.w600),
|
||||
// ),
|
||||
// onPressed: () {
|
||||
// // Navigator.push(context,
|
||||
// // MaterialPageRoute(builder: (context) {
|
||||
// // return Registration();
|
||||
// // }));
|
||||
// },
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
347
app_code/lib/screens/auth/registration.dart
Normal file
347
app_code/lib/screens/auth/registration.dart
Normal file
@@ -0,0 +1,347 @@
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/constant/country_code.dart';
|
||||
import 'package:grostore/constant/country_search.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/input_decorations.dart';
|
||||
import 'package:grostore/helpers/common_functions.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/presenters/auth/auth_presenter.dart';
|
||||
import 'package:grostore/screens/auth/login.dart';
|
||||
import 'package:intl_phone_number_input/intl_phone_number_input.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../custom_ui/auth_ui.dart';
|
||||
|
||||
class Registration extends StatefulWidget {
|
||||
@override
|
||||
_RegistrationState createState() => _RegistrationState();
|
||||
}
|
||||
|
||||
class _RegistrationState extends State<Registration> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Provider.of<AuthPresenter>(context).setContext(context);
|
||||
return AuthScreen.buildScreen(
|
||||
context, buildBody(context, getWidth(context)));
|
||||
}
|
||||
|
||||
Widget buildBody(BuildContext context, double screenWidth) {
|
||||
return Consumer<AuthPresenter>(builder: (context, data, child) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
width: screenWidth * (3 / 4),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
||||
/// #Create New Account
|
||||
Container(
|
||||
width: getWidth(context),
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).create_new_account_ucf,
|
||||
style: StyleConfig.fs24fwBold,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
|
||||
/// #Name
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).name,
|
||||
style: TextStyle(
|
||||
color: ThemeConfig.fontColor, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Container(
|
||||
height: 36,
|
||||
child: TextField(
|
||||
controller: data.regNameController,
|
||||
autofocus: false,
|
||||
// decoration:InputDecoration(
|
||||
// focusedBorder: OutlineInputBorder(
|
||||
// borderRadius: BorderRadius.all(Radius.circular(5)),
|
||||
// borderSide: BorderSide(
|
||||
// color: ThemeConfig.red
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
decoration: InputDecorations.basic(
|
||||
prefixIcon: Icon(
|
||||
Icons.person_outline,
|
||||
size: 18,
|
||||
color: ThemeConfig.mediumGrey,
|
||||
),
|
||||
hint_text: "Mr.John"),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
/// #Phone Number
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).phone,
|
||||
style: TextStyle(
|
||||
color: ThemeConfig.fontColor, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Container(
|
||||
decoration: BoxDecorations.basic(),
|
||||
height: 36,
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14.0),
|
||||
child: Icon(
|
||||
Icons.phone,
|
||||
size: 18,
|
||||
color: ThemeConfig.mediumGrey,
|
||||
),
|
||||
),
|
||||
// Button(
|
||||
// minWidth: 80,
|
||||
// onPressed: () {
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// builder: (context) {
|
||||
// return buildFilterDialog(data);
|
||||
// });
|
||||
// },
|
||||
// child: Row(
|
||||
// children: [
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// child: Image.asset(
|
||||
// "${getAssetFlag(data.regCountry.code.toLowerCase())}.png"),
|
||||
// ),
|
||||
// Text(
|
||||
// data.regCountry.dial_code,
|
||||
// style: StyleConfig.fs14fwNormal,
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
Text(
|
||||
"+998",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
width: getWidth(context) - 200,
|
||||
child: TextField(
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
decoration: const InputDecoration.collapsed(
|
||||
hintText: "XX XXX XXX"),
|
||||
controller: data.regPhoneNumberController,
|
||||
),
|
||||
)
|
||||
],
|
||||
)),
|
||||
),
|
||||
|
||||
/// #Password
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).password,
|
||||
style: TextStyle(
|
||||
color: ThemeConfig.fontColor, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Container(
|
||||
height: 36,
|
||||
child: TextField(
|
||||
controller: data.regPasswordController,
|
||||
autofocus: false,
|
||||
obscureText: true,
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
decoration: InputDecorations.basic(
|
||||
prefixIcon: Icon(
|
||||
Icons.lock,
|
||||
size: 18,
|
||||
color: ThemeConfig.mediumGrey,
|
||||
),
|
||||
hint_text: "• • • • • • • •"),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
AppLang.local(context).password_must_be_at_last_6_digit,
|
||||
style: TextStyle(
|
||||
color: ThemeConfig.lightGrey,
|
||||
fontStyle: FontStyle.italic),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).confirm_password_ucf,
|
||||
style: TextStyle(
|
||||
color: ThemeConfig.fontColor, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Container(
|
||||
height: 36,
|
||||
child: TextField(
|
||||
controller: data.regPasswordConfirmController,
|
||||
autofocus: false,
|
||||
obscureText: true,
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
decoration: InputDecorations.basic(
|
||||
prefixIcon: Icon(
|
||||
Icons.lock,
|
||||
size: 18,
|
||||
color: ThemeConfig.mediumGrey,
|
||||
),
|
||||
hint_text: "• • • • • • • •"),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
/// #Send button
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 30.0),
|
||||
child: Container(
|
||||
height: 45,
|
||||
child: Button.minSize(
|
||||
width: getWidth(context),
|
||||
height: 50,
|
||||
color: ThemeConfig.red,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(6.0))),
|
||||
child: Text(
|
||||
AppLang.local(context).sign_up_ucf,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
onPressed: () {
|
||||
data.onPressSignUp();
|
||||
}),
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
/// #Text
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 20.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Center(
|
||||
child: Text(
|
||||
AppLang.local(context).already_have_an_account,
|
||||
style:
|
||||
TextStyle(color: ThemeConfig.fontColor, fontSize: 12),
|
||||
)),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
|
||||
/// #login route text
|
||||
Button(
|
||||
minWidth: 20,
|
||||
child: Text(
|
||||
AppLang.local(context).login,
|
||||
style: TextStyle(
|
||||
color: ThemeConfig.red,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.push(context,
|
||||
MaterialPageRoute(builder: (context) {
|
||||
return const Login();
|
||||
}));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
// Country country = Country(name:"Uzbekistan" , dial_code: "+998", code: "+998");
|
||||
|
||||
// AlertDialog buildFilterDialog(AuthPresenter data) {
|
||||
// return AlertDialog(
|
||||
// title: const Text('Search Country'),
|
||||
// content: Container(
|
||||
// height: 300,
|
||||
// child: Column(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: <Widget>[
|
||||
// TextField(
|
||||
// onChanged: data.filterCountry,
|
||||
// decoration: const InputDecoration(
|
||||
// hintText: 'Search',
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(height: 16.0),
|
||||
// Expanded(
|
||||
// child: SingleChildScrollView(
|
||||
// child: Consumer<AuthPresenter>(
|
||||
// builder: (context, filterData, child) {
|
||||
// return Column(
|
||||
// children: List.generate(filterData.filteredCountry.length,
|
||||
// (index) {
|
||||
// country = filterData.filteredCountry[index];
|
||||
// return ListTile(
|
||||
// leading: Image.asset(
|
||||
// getAssetFlag("${country.code.toLowerCase()}.png"),
|
||||
// height: 30,
|
||||
// width: 30,
|
||||
// ),
|
||||
// title: Text(country.name),
|
||||
// onTap: () {
|
||||
// // data.onChangeCountry(country);
|
||||
// Navigator.of(context).pop();
|
||||
// filterData.filteredCountry = filterData.country;
|
||||
// },
|
||||
// );
|
||||
// }),
|
||||
// );
|
||||
// }),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
}
|
||||
316
app_code/lib/screens/cart.dart
Normal file
316
app_code/lib/screens/cart.dart
Normal file
@@ -0,0 +1,316 @@
|
||||
import 'package:dotted_line/dotted_line.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/Image_view.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/presenters/cart_presenter.dart';
|
||||
import 'package:grostore/screens/check_out.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../helpers/common_functions.dart';
|
||||
|
||||
class Cart extends StatefulWidget {
|
||||
const Cart({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Cart> createState() => _CartState();
|
||||
}
|
||||
|
||||
class _CartState extends State<Cart> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: ThemeConfig.xxlightGrey,
|
||||
appBar: CommonAppbar.show(
|
||||
title: AppLang.local(context).cart, context: context),
|
||||
body: SizedBox(
|
||||
height: getHeight(context),
|
||||
width: getWidth(context),
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
child: Consumer<CartPresenter>(
|
||||
builder: (context, data, child) {
|
||||
if(data.isCartResponseFetch && data.cartResponse.carts.isNotEmpty) {
|
||||
return ListView.separated(
|
||||
padding: const EdgeInsets.only(top: 16, bottom: 200),
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
margin: EdgeInsets.only(
|
||||
left: StyleConfig.padding,
|
||||
right: StyleConfig.padding,
|
||||
bottom:
|
||||
index == data.cartResponse.carts.length - 1
|
||||
? 80
|
||||
: 0),
|
||||
decoration: BoxDecorations.shadow(),
|
||||
width: getWidth(context),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ImageView(
|
||||
url: data.cartResponse.carts[index].thumbnailImage,
|
||||
width: 120,
|
||||
height: 100,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 8
|
||||
),
|
||||
Expanded(
|
||||
flex:2,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
data.cartResponse.carts[index].category,
|
||||
style: StyleConfig.fs10,
|
||||
maxLines: 1,
|
||||
),
|
||||
Text(
|
||||
data.cartResponse.carts[index].name,
|
||||
style: StyleConfig.fs14fwBold,
|
||||
maxLines: 1,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
data.cartResponse.carts[index].unit,
|
||||
style: StyleConfig.fs12,
|
||||
maxLines: 1,
|
||||
),
|
||||
Text(
|
||||
"Narx: ",
|
||||
style: StyleConfig.fs12,
|
||||
maxLines: 1,
|
||||
),
|
||||
Text(
|
||||
showPrice(data.cartResponse.carts[index].price),
|
||||
style: StyleConfig.fs12,
|
||||
maxLines: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
quantitySection(context, data, index),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
print(index);
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding),
|
||||
child: Divider(
|
||||
height: 1,
|
||||
color: ThemeConfig.grey,
|
||||
),
|
||||
);
|
||||
},
|
||||
itemCount: data.cartResponse.carts.length);
|
||||
} else {
|
||||
return Center(child: Text(AppLang.local(context).empty,style: StyleConfig.fs16fwBold,));
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
Consumer<CartPresenter>(builder: (context, data, child) {
|
||||
return data.cartResponse.carts.isNotEmpty
|
||||
? Positioned(
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Column(
|
||||
children: [
|
||||
|
||||
Container(
|
||||
height: 200,
|
||||
width: 400,
|
||||
decoration: BoxDecorations.customRadius(
|
||||
radius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(24),
|
||||
topRight: Radius.circular(24)))
|
||||
.copyWith(color: ThemeConfig.white),
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
Text(
|
||||
AppLang.local(context).order_info_ucf,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding,
|
||||
vertical: 5),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).subtotal}:",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
"${showPrice(data.cartResponse.subTotal)}",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding,
|
||||
vertical: 5),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).coupon_discount_ucf}:",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
"${showPrice(data.cartResponse.couponDiscount)}",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
/// Dotted line
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding,
|
||||
vertical: 5),
|
||||
child: DottedLine(
|
||||
direction: Axis.horizontal,
|
||||
lineLength: double.infinity,
|
||||
lineThickness: 1.0,
|
||||
dashLength: 4.0,
|
||||
dashColor: ThemeConfig.grey,
|
||||
//dashGradient: [Colors.red, Colors.blue],
|
||||
dashRadius: 0.0,
|
||||
dashGapLength: 4.0,
|
||||
dashGapColor: Colors.transparent,
|
||||
//dashGapGradient: [Colors.red, Colors.blue],
|
||||
dashGapRadius: 0.0,
|
||||
),
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding,
|
||||
vertical: 5),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).total}:",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
"${showPrice(data.cartResponse.total)}",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding),
|
||||
child: Button(
|
||||
shape: StyleConfig.buttonRadius(4),
|
||||
color: ThemeConfig.red,
|
||||
onPressed: () {
|
||||
MakeRoute.go(context, const CheckOut());
|
||||
},
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
minWidth: getWidth(context),
|
||||
child: Text(
|
||||
AppLang.local(context)
|
||||
.review_n_payment_ucf,
|
||||
style: StyleConfig.fs16cWhitefwBold,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
))
|
||||
: const SizedBox.shrink();
|
||||
})
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container quantitySection(BuildContext context, CartPresenter data, index) {
|
||||
return Container(
|
||||
// padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
//height: 50,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Button(
|
||||
minWidth: 20,
|
||||
shape: const CircleBorder(),
|
||||
color: ThemeConfig.fontColor,
|
||||
padding: const EdgeInsets.all(8),
|
||||
onPressed: () {
|
||||
data.updateCart(
|
||||
cartId: data.cartResponse.carts[index].id,
|
||||
action: "decrease",
|
||||
context: context);
|
||||
},
|
||||
child: const Icon(
|
||||
Icons.remove,
|
||||
color: ThemeConfig.white,
|
||||
size: 10,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 2),
|
||||
constraints: const BoxConstraints(minWidth: 40),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
"${data.cartResponse.carts[index].quantity}",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
)),
|
||||
Button(
|
||||
minWidth: 20,
|
||||
shape: const CircleBorder(),
|
||||
color: ThemeConfig.red,
|
||||
padding: const EdgeInsets.all(8),
|
||||
onPressed: () {
|
||||
data.updateCart(
|
||||
cartId: data.cartResponse.carts[index].id,
|
||||
action: "increase",
|
||||
context: context);
|
||||
},
|
||||
child: const Icon(
|
||||
Icons.add,
|
||||
color: ThemeConfig.white,
|
||||
size: 10,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
80
app_code/lib/screens/categories.dart
Normal file
80
app_code/lib/screens/categories.dart
Normal file
@@ -0,0 +1,80 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/category_ui.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/shimmers.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/presenters/categories_presenter.dart';
|
||||
import 'package:grostore/screens/filter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class Categories extends StatefulWidget {
|
||||
Categories({Key? key, this.fromBottomBar = true}) : super(key: key);
|
||||
bool fromBottomBar;
|
||||
|
||||
@override
|
||||
State<Categories> createState() => _CategoriesState();
|
||||
}
|
||||
|
||||
class _CategoriesState extends State<Categories> {
|
||||
@override
|
||||
void initState() {
|
||||
Provider.of<CategoriesPresenter>(context, listen: false)
|
||||
.setContext(context);
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
Provider.of<CategoriesPresenter>(context, listen: false).initState();
|
||||
});
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: ThemeConfig.xxlightGrey,
|
||||
appBar: CommonAppbar.show(
|
||||
title: AppLang.local(context).categories,
|
||||
context: context,
|
||||
showBackButton: !widget.fromBottomBar),
|
||||
body: Consumer<CategoriesPresenter>(builder: (context, data, child) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: data.onRefresh,
|
||||
child: data.isCategoryInit
|
||||
? GridView.builder(
|
||||
controller: data.scrollController,
|
||||
padding: EdgeInsets.only(
|
||||
left: 10,
|
||||
right: 10,
|
||||
top: 10,
|
||||
bottom: widget.fromBottomBar ? 80 : 10),
|
||||
itemCount: data.categories.length,
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 3,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
childAspectRatio: 1),
|
||||
itemBuilder: (context, index) => Button(
|
||||
minWidth: getWidth(context),
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: () {
|
||||
MakeRoute.go(
|
||||
context,
|
||||
Filter(
|
||||
category_id:
|
||||
data.categories[index].id.toString(),
|
||||
));
|
||||
},
|
||||
child: CategoryUi(
|
||||
img: data.categories[index].thumbnailImage,
|
||||
name: data.categories[index].name),
|
||||
))
|
||||
: Shimmers.gridShimmer(3, 15));
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
912
app_code/lib/screens/check_out.dart
Normal file
912
app_code/lib/screens/check_out.dart
Normal file
@@ -0,0 +1,912 @@
|
||||
import 'package:dotted_line/dotted_line.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/Image_view.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/input_decorations.dart';
|
||||
// import 'package:grostore/custom_ui/loading.dart';
|
||||
import 'package:grostore/custom_ui/shimmers.dart';
|
||||
import 'package:grostore/helpers/common_functions.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/models/payment_types_response.dart';
|
||||
import 'package:grostore/models/time_slote_response.dart';
|
||||
import 'package:grostore/presenters/check_out_presenter.dart';
|
||||
import 'package:grostore/screens/address/addresses.dart';
|
||||
// import 'package:grostore/presenters/user_presenter.dart';
|
||||
// import 'package:grostore/screens/main.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class CheckOut extends StatefulWidget {
|
||||
const CheckOut({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<CheckOut> createState() => _CheckOutState();
|
||||
}
|
||||
|
||||
class _CheckOutState extends State<CheckOut> {
|
||||
bool pay = false;
|
||||
String dostavka = '';
|
||||
@override
|
||||
void initState() {
|
||||
Provider.of<CheckOutPresenter>(context, listen: false)
|
||||
.init(context);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: ThemeConfig.xxlightGrey,
|
||||
appBar: CommonAppbar.show(
|
||||
title: AppLang.local(context).check_out_ucf, context: context),
|
||||
body: SingleChildScrollView(
|
||||
child: Consumer<CheckOutPresenter>(builder: (context, data, child) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 24),
|
||||
|
||||
/// #build shipping address
|
||||
buildShippingAddress(context, data),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
/// #Billing address
|
||||
// buildBillingAddress(context, data),
|
||||
// const SizedBox(
|
||||
// height: 24
|
||||
// ),
|
||||
|
||||
/// #Build Logistics
|
||||
if (data.logistics.isNotEmpty)
|
||||
buildLogistic(context, data)
|
||||
else
|
||||
Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecorations.shadow(radius: 8).copyWith(color: ThemeConfig.red),
|
||||
child: Text(AppLang.local(context).we_are_not_shipping_to_your_city_now,style: StyleConfig.fs14cWhitefwNormal,)),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
/// #Prefer Delivery time text
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Text(
|
||||
AppLang.local(context).preferred_delivery_time,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
),
|
||||
|
||||
/// #Prefer Delivery time
|
||||
data.isFetchTimeSlot?buildDeliveryTime(context, data):timeSlotShimmer(),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
/// #Personal info
|
||||
buildPersonalInfo(context,data),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
/// #Payment Method text
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Text(
|
||||
AppLang.local(context).payment_method,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
|
||||
/// #Payment Method Button
|
||||
Container(
|
||||
height: 100,
|
||||
decoration: BoxDecorations.shadow(radius: 8),
|
||||
margin: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding,vertical: 10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Material(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
child: InkWell(
|
||||
onTap: (){
|
||||
pay = !pay;
|
||||
data.peyMethod("Karta");
|
||||
},
|
||||
child: Container(
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
padding: EdgeInsets.all(5),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
border: Border.all(
|
||||
width: 1.5,
|
||||
color:pay ?ThemeConfig.red:ThemeConfig.xxlightGrey
|
||||
)
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(Icons.add_card,color:pay?ThemeConfig.red :ThemeConfig.xlightGrey),
|
||||
Text(AppLang.local(context).when_receiving_by_card,style:pay? StyleConfig.fs12Red :StyleConfig.fs12cGrey,textAlign: TextAlign.center,),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
Expanded(
|
||||
child: Material(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
child: InkWell(
|
||||
onTap: (){
|
||||
pay = !pay;
|
||||
data.peyMethod("Naqd pul");
|
||||
},
|
||||
child: Container(
|
||||
height: MediaQuery.sizeOf(context).height,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
border: Border.all(
|
||||
width: 1.5,
|
||||
color:pay?ThemeConfig.xxlightGrey :ThemeConfig.red
|
||||
)
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(Icons.payments_outlined,color:pay ?ThemeConfig.xxlightGrey :ThemeConfig.red,),
|
||||
Text(AppLang.local(context).when_receiving_by_cash,style:pay? StyleConfig.fs12cGrey:StyleConfig.fs12Red ,textAlign: TextAlign.center,),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
|
||||
/// #Tips title
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Text(
|
||||
AppLang.local(context).add_tips_for_deliveryman,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10
|
||||
),
|
||||
|
||||
/// #tips
|
||||
Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding, vertical: 10),
|
||||
decoration: BoxDecorations.shadow(radius: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
AppLang.local(context).tips,
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
TextField(
|
||||
controller: data.tipsTxt,
|
||||
keyboardType: TextInputType.phone,
|
||||
decoration: InputDecorations.phone(hint_text: AppLang.local(context).tips),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
/// #Order Summary
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Text(
|
||||
AppLang.local(context).order_summary,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
width: getWidth(context),
|
||||
decoration: BoxDecorations.shadow(radius: 8),
|
||||
margin: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding14,
|
||||
vertical: StyleConfig.padding14),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).subtotal} :",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
showPrice(data.orderSummeryResponse.subTotal),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).delivery_fee_ucf} :",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
showPrice("${data.orderSummeryResponse.shippingCharge}"),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).tax} :",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
showPrice(data.orderSummeryResponse.tax),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).coupon_discount_ucf} :",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
showPrice(data.orderSummeryResponse.couponDiscount),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: DottedLine(
|
||||
direction: Axis.horizontal,
|
||||
lineLength: double.infinity,
|
||||
lineThickness: 1.0,
|
||||
dashLength: 4.0,
|
||||
dashColor: ThemeConfig.grey,
|
||||
//dashGradient: [Colors.red, Colors.blue],
|
||||
dashRadius: 0.0,
|
||||
dashGapLength: 4.0,
|
||||
dashGapColor: Colors.transparent,
|
||||
//dashGapGradient: [Colors.red, Colors.blue],
|
||||
dashGapRadius: 0.0,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).total} :",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
showPrice("${data.orderSummeryResponse.total} so'm} "),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox( height: 24 ),
|
||||
|
||||
/// #Order contract button
|
||||
Button(
|
||||
minWidth: getWidth(context),
|
||||
color: ThemeConfig.red,
|
||||
onPressed: (){
|
||||
data.placeOrder(context);
|
||||
},
|
||||
padding: const EdgeInsets.symmetric(vertical: 20),
|
||||
child: Text(
|
||||
AppLang.local(context).place_order,
|
||||
// "Place Order",
|
||||
style: StyleConfig.fs16cWhitefwBold,
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// int subster(String text){
|
||||
// final a = text.substring(0,6);
|
||||
// final b = a.split(",");
|
||||
// final c = "${b[0]}${b[1]}";
|
||||
// print("-----------");
|
||||
// print("heloH :: $c ::");
|
||||
// print("-----------");
|
||||
// final e = int.parse(c);
|
||||
// return e;
|
||||
// }
|
||||
|
||||
/// #tieslot timer
|
||||
Widget timeSlotShimmer(){
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding,vertical: 5),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
|
||||
decoration: BoxDecorations.shadow(radius: 8),
|
||||
child: Shimmers(
|
||||
height: 40,
|
||||
width: getWidth(context),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
|
||||
decoration: BoxDecorations.shadow(radius: 8),
|
||||
child: Shimmers(
|
||||
height: 40,
|
||||
width: getWidth(context),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// #Delivery Time
|
||||
Column buildDeliveryTime(BuildContext context, CheckOutPresenter data) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Button(
|
||||
minWidth: getWidth(context),
|
||||
onPressed: () {
|
||||
data.onChangeDeliveryType("regular");
|
||||
},
|
||||
child:Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
|
||||
decoration: BoxDecorations.shadow(radius: 8).copyWith(
|
||||
border: data.shipping_delivery_type == "regular"
|
||||
? Border.all(color: ThemeConfig.red, width: 2)
|
||||
: null),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.local_shipping_outlined,
|
||||
size: 45,
|
||||
color: ThemeConfig.grey,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
AppLang.local(context).reg_delivery,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
SizedBox(
|
||||
width: 200,
|
||||
child: Text(
|
||||
AppLang.local(context).we_will_deliver_your_products_soon,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
,
|
||||
),
|
||||
),
|
||||
Button(
|
||||
minWidth: getWidth(context),
|
||||
onPressed: () {
|
||||
data.onChangeDeliveryType("scheduled");
|
||||
setState(() {});
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding, vertical: 10),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
|
||||
decoration: BoxDecorations.shadow(radius: 8).copyWith(
|
||||
border: data.shipping_delivery_type == "scheduled"
|
||||
? Border.all(color: ThemeConfig.red, width: 2)
|
||||
: null),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: getWidth(context) * 0.35,
|
||||
child: Button(
|
||||
minWidth: getWidth(context) * 0.35,
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
DateFormat("d MMM").format(data.selectedDate!),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
onPressed: () async {
|
||||
DateTime date = await chooseDate(data);
|
||||
data.onChangeDate(date);
|
||||
data.onChangeDeliveryType("scheduled");
|
||||
setState(() { });
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: getWidth(context) * 0.35,
|
||||
child: Button(
|
||||
minWidth: getWidth(context),
|
||||
child: SizedBox(
|
||||
width: getWidth(context) * 0.35,
|
||||
child: buildTimeDropDown(data),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
/// #Date Picker
|
||||
chooseDate(CheckOutPresenter data) async {
|
||||
return await showDatePicker(
|
||||
initialEntryMode: DatePickerEntryMode.calendar,
|
||||
initialDate: data.selectedDate!,
|
||||
firstDate: data.firstDate,
|
||||
lastDate: data.lastDate,
|
||||
context: context,
|
||||
);
|
||||
}
|
||||
|
||||
/// #Personal information
|
||||
Column buildPersonalInfo(BuildContext context,CheckOutPresenter data) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Text(
|
||||
AppLang.local(context).personal_information,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding, vertical: 10),
|
||||
decoration: BoxDecorations.shadow(radius: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
AppLang.local(context).phone,
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
TextField(
|
||||
controller:data.phoneTxt ,
|
||||
keyboardType: TextInputType.phone,
|
||||
decoration: InputDecorations.phone(hint_text: "Phone"),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
AppLang.local(context).alternative_phone_ucf,
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
TextField(
|
||||
controller: data.additionalPhoneTxt,
|
||||
keyboardType: TextInputType.phone,
|
||||
decoration: InputDecorations.phone(
|
||||
hint_text: AppLang.local(context).alternative_phone_ucf),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
AppLang.local(context).additional_info_ucf,
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
constraints: const BoxConstraints(minHeight: 80),
|
||||
width: getWidth(context),
|
||||
decoration: BoxDecorations.basic().copyWith(
|
||||
border: Border.all(color: ThemeConfig.grey, width: 1)),
|
||||
child: TextField(
|
||||
controller: data.additionalInfoTxt,
|
||||
decoration: InputDecoration.collapsed(
|
||||
hintText: AppLang.local(context).additional_info_ucf),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// #build shipping address
|
||||
Column buildShippingAddress(BuildContext context, CheckOutPresenter data) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
AppLang.local(context).delivery_address_ucf,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
Material(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
child: InkWell(
|
||||
onTap: (){
|
||||
MakeRoute.go(context, const Addresses());
|
||||
},
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: ThemeConfig.red,
|
||||
)
|
||||
),
|
||||
child: const Text("Manzil qo'shish"),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
//color: Colors.red,
|
||||
height: 150,
|
||||
width: getWidth(context),
|
||||
child: data.isFetchDeliveryAddress?ListView.separated(
|
||||
itemCount: data.addresses.length,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding, vertical: 10),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
decoration: BoxDecorations.shadow(radius: 8).copyWith(
|
||||
border: Border.all(
|
||||
width: 2,
|
||||
color:
|
||||
data.selectedShippingAddress.id == data.addresses[index].id
|
||||
? ThemeConfig.red
|
||||
: ThemeConfig.grey)),
|
||||
child: Button(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
|
||||
shape: StyleConfig.buttonRadius(8),
|
||||
minWidth: getWidth(context) * 0.5,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
data.addresses[index].countryName,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
data.addresses[index].stateName,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
data.addresses[index].cityName,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
data.addresses[index].address,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
maxLines: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
data.onChangeShippingAddress(data.addresses[index]);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return const SizedBox(
|
||||
width: 10,
|
||||
);
|
||||
},
|
||||
):Shimmers.horizontalList(10, getWidth(context) * 0.5, 100),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// #Build billing address
|
||||
Column buildBillingAddress(BuildContext context, CheckOutPresenter data) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Text(
|
||||
AppLang.local(context).billing_address_ucf,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
//color: Colors.red,
|
||||
height: 150,
|
||||
width: getWidth(context),
|
||||
child: data.isFetchDeliveryAddress?ListView.separated(
|
||||
itemCount: data.addresses.length,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding, vertical: 10),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
decoration: BoxDecorations.shadow(radius: 8).copyWith(
|
||||
border: Border.all(
|
||||
width: 2,
|
||||
color: data.billingAddressId == data.addresses[index].id
|
||||
? ThemeConfig.red
|
||||
: ThemeConfig.grey)),
|
||||
child: Button(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
|
||||
shape: StyleConfig.buttonRadius(8),
|
||||
minWidth: getWidth(context) * 0.5,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Text(
|
||||
data.addresses[index].countryName,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
data.addresses[index].stateName,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
data.addresses[index].cityName,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
data.addresses[index].address,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
data.onChangeBillingAddress(data.addresses[index].id);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return const SizedBox(
|
||||
width: 10,
|
||||
);
|
||||
},
|
||||
):Shimmers.horizontalList(10, getWidth(context) * 0.5, 100),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// #Build logistics
|
||||
Column buildLogistic(BuildContext context, CheckOutPresenter data) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Text(
|
||||
AppLang.local(context).available_logistics_ucf,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
//color: Colors.red,
|
||||
height: 150,
|
||||
width: getWidth(context),
|
||||
child:ListView.separated(
|
||||
itemCount: data.logistics.length,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding, vertical: 10),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
decoration: BoxDecorations.shadow(radius: 8).copyWith(
|
||||
border: Border.all(
|
||||
width: 2,
|
||||
color:
|
||||
data.selectedLogistic.id == data.logistics[index].id
|
||||
? ThemeConfig.red
|
||||
: ThemeConfig.grey)),
|
||||
child: Button(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
|
||||
shape: StyleConfig.buttonRadius(8),
|
||||
minWidth: getWidth(context) * 0.5,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Text(
|
||||
data.logistics[index].name,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
ImageView(
|
||||
url: data.logistics[index].image,
|
||||
height: 40,
|
||||
width: getWidth(context) * 0.4,
|
||||
),
|
||||
Text(
|
||||
showPrice(data.logistics[index].price),
|
||||
style: StyleConfig.fs12,
|
||||
),
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
data.onChangeLogistic(data.logistics[index]);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return const SizedBox(
|
||||
width: 10,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// #Build time dropdown
|
||||
Widget buildTimeDropDown(CheckOutPresenter data) {
|
||||
return DropdownButton<TimeSlot>(
|
||||
menuMaxHeight: 300,
|
||||
isDense: true,
|
||||
underline: Container(),
|
||||
isExpanded: true,
|
||||
onChanged: (TimeSlot? value) {
|
||||
data.onChangeTimeSlot(value!);
|
||||
},
|
||||
icon: const Icon(Icons.arrow_drop_down),
|
||||
value: data.selectedTimeslot,
|
||||
items: data.timeSlots
|
||||
.map(
|
||||
(value) => DropdownMenuItem<TimeSlot>(
|
||||
value: value,
|
||||
child: Text(
|
||||
value.timeline,
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
/// #Payment Method
|
||||
Future<PaymentTypesResponse?> showPaymentMethods(CheckOutPresenter data)async{
|
||||
return showDialog<PaymentTypesResponse>(context: context, builder: (context){
|
||||
return AlertDialog(
|
||||
titlePadding: EdgeInsets.zero,
|
||||
title: Container(
|
||||
alignment: Alignment.center,
|
||||
color: ThemeConfig.accentColor,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14,vertical: 24),
|
||||
child: Text("Choose Payment Method",style: StyleConfig.fs16cWhitefwBold,),
|
||||
),
|
||||
|
||||
content:Column(
|
||||
children: List.generate(data.paymentTypes.length, (index) {
|
||||
return Column(
|
||||
children: [
|
||||
Button(
|
||||
minWidth: getWidth(context),
|
||||
onPressed: (){
|
||||
Navigator.pop(context,data.paymentTypes[index]);
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
width: getWidth(context)*0.3,
|
||||
child: Text(data.paymentTypes[index].name,style: StyleConfig.fs14fwBold,)),
|
||||
Container(
|
||||
width: getWidth(context)*0.3,
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: ImageView.svg(url: data.paymentTypes[index].image,height:50,width: 50),
|
||||
),
|
||||
],
|
||||
))
|
||||
],
|
||||
);
|
||||
}),
|
||||
) ,
|
||||
actions: [
|
||||
Button(
|
||||
minWidth:getWidth(context),
|
||||
padding: const EdgeInsets.symmetric(vertical: 20),
|
||||
color: ThemeConfig.red,
|
||||
onPressed: (){
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text("Close",style: StyleConfig.fs14cWhitefwNormal,),
|
||||
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
229
app_code/lib/screens/coupons.dart
Normal file
229
app_code/lib/screens/coupons.dart
Normal file
@@ -0,0 +1,229 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_countdown_timer/countdown.dart';
|
||||
import 'package:flutter_countdown_timer/current_remaining_time.dart';
|
||||
import 'package:flutter_countdown_timer/flutter_countdown_timer.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/shimmers.dart';
|
||||
import 'package:grostore/custom_ui/toast_ui.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/presenters/coupon_presenter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class Coupons extends StatefulWidget {
|
||||
const Coupons({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Coupons> createState() => _CouponsState();
|
||||
}
|
||||
|
||||
class _CouponsState extends State<Coupons> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
Provider.of<CouponPresenter>(context, listen: false).initState();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CommonAppbar.show(
|
||||
title: AppLang.local(context).coupons, context: context),
|
||||
body: Consumer<CouponPresenter>(builder: (context, data, child) {
|
||||
print(data.isCouponsInit);
|
||||
if (!data.isCouponsInit) {
|
||||
return Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child:
|
||||
Shimmers.list(10, getWidth(context) - StyleConfig.padding, 150),
|
||||
);
|
||||
}
|
||||
|
||||
return ListView.separated(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
itemBuilder: (context, index) {
|
||||
return Container(
|
||||
height: getWidth(context) * 0.5,
|
||||
width: getWidth(context),
|
||||
decoration:
|
||||
BoxDecorations.image(url: data.coupons[index].banner),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
child: Text("UP to ${data.coupons[index].discountValue.toString()}${data.coupons[index].discountType== 'percent'?'%':''} OFF",style: StyleConfig.fs24fwBold.copyWith(color: Colors.red,),),
|
||||
),
|
||||
SizedBox(height: 14,),
|
||||
Container(
|
||||
height: 40,
|
||||
margin: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
decoration: BoxDecoration(
|
||||
// border: Border.all(),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
color: ThemeConfig.white
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left:8 ,right: 8.0),
|
||||
child: Text(data.coupons[index].code,style: StyleConfig.fs16fwBold,),
|
||||
),
|
||||
Spacer(),
|
||||
Button(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
color: ThemeConfig.accentColor,
|
||||
minHeight: 40.0,
|
||||
minWidth: 10,
|
||||
shape: StyleConfig.buttonRadius(8),
|
||||
onPressed: ()async{
|
||||
await Clipboard.setData(ClipboardData(text:data.coupons[index].code));
|
||||
ToastUi.show(context, "Copied");
|
||||
},
|
||||
child: Text(AppLang.local(context).copy_code_ucf,
|
||||
style: StyleConfig.fs14cWhitefwNormal,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 14,),
|
||||
buildCounterRow(data, index)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) => SizedBox(
|
||||
height: StyleConfig.smSectionSpacer,
|
||||
),
|
||||
itemCount: data.coupons.length);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Row buildCounterRow(CouponPresenter data, int index) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
CountdownTimer(
|
||||
controller: data.controller[index],
|
||||
widgetBuilder: (context, timer) {
|
||||
return buildCounterContainer(TimerType.day, timer);
|
||||
},
|
||||
),
|
||||
CountdownTimer(
|
||||
controller: data.controller[index],
|
||||
widgetBuilder: (context, timer) {
|
||||
return buildCounterContainer(TimerType.hours, timer);
|
||||
},
|
||||
),
|
||||
CountdownTimer(
|
||||
controller: data.controller[index],
|
||||
widgetBuilder: (context, timer) {
|
||||
return buildCounterContainer(TimerType.min, timer);
|
||||
},
|
||||
),
|
||||
CountdownTimer(
|
||||
controller: data.controller[index],
|
||||
widgetBuilder: (context, timer) {
|
||||
return buildCounterContainer(TimerType.sec, timer);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Container buildCounterContainer(TimerType timerType, CurrentRemainingTime? timer) {
|
||||
return Container(
|
||||
width: getWidth(context) / 6,
|
||||
height: getWidth(context) / 6,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: ThemeConfig.amber, width: 1),
|
||||
color: ThemeConfig.white),
|
||||
child:makeCounter(timerType, timer)
|
||||
);
|
||||
}
|
||||
|
||||
makeCounter(TimerType timerType, CurrentRemainingTime? timer){
|
||||
if(timerType==TimerType.day){
|
||||
return buildCounterDate(timer, context);
|
||||
}else if(timerType ==TimerType.hours){
|
||||
return buildCounterHours(timer, context);
|
||||
}else if(timerType ==TimerType.min){
|
||||
return buildCounterMin(timer, context);
|
||||
}else {
|
||||
return buildCounterSec(timer, context);
|
||||
}
|
||||
}
|
||||
|
||||
Column buildCounterDate(CurrentRemainingTime? timer, BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
timer?.days.toString() ?? "",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
AppLang.local(context).days,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
Column buildCounterHours(CurrentRemainingTime? timer, BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
timer?.hours.toString() ?? "",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
AppLang.local(context).hours,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
Column buildCounterMin(CurrentRemainingTime? timer, BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
timer?.min.toString() ?? "",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
AppLang.local(context).min,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
Column buildCounterSec(CurrentRemainingTime? timer, BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
timer?.sec.toString() ?? "",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Text(
|
||||
AppLang.local(context).sec,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
enum TimerType{
|
||||
day,hours,min,sec
|
||||
}
|
||||
475
app_code/lib/screens/filter.dart
Normal file
475
app_code/lib/screens/filter.dart
Normal file
@@ -0,0 +1,475 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_classes/system_data.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/category_ui.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/product_card.dart';
|
||||
import 'package:grostore/custom_ui/shimmers.dart';
|
||||
import 'package:grostore/helpers/common_functions.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/presenters/cart_presenter.dart';
|
||||
import 'package:grostore/presenters/categories_presenter.dart';
|
||||
import 'package:grostore/presenters/filter_presenter.dart';
|
||||
import 'package:grostore/screens/auth/login.dart';
|
||||
import 'package:grostore/screens/cart.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class Filter extends StatefulWidget {
|
||||
String? searchKey,
|
||||
sort_by,
|
||||
max_price,
|
||||
min_price,
|
||||
category_id,
|
||||
tag_id,
|
||||
per_page;
|
||||
bool isFocus;
|
||||
|
||||
Filter(
|
||||
{Key? key,
|
||||
this.searchKey,
|
||||
this.sort_by,
|
||||
this.max_price,
|
||||
this.min_price,
|
||||
this.category_id,
|
||||
this.tag_id,
|
||||
this.per_page,
|
||||
this.isFocus=false})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<Filter> createState() => _FilterState();
|
||||
}
|
||||
|
||||
class _FilterState extends State<Filter> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
Provider.of<FilterPresenter>(context,listen: false).setContext(context);
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
Provider.of<FilterPresenter>(context,listen: false).clearAll();
|
||||
if(!widget.isFocus) {
|
||||
Provider.of<FilterPresenter>(context, listen: false).setInitData(
|
||||
min_price: widget.min_price,
|
||||
max_price: widget.max_price,
|
||||
category_id: widget.category_id);
|
||||
Provider.of<FilterPresenter>(context, listen: false).initState();
|
||||
}
|
||||
Provider.of<FilterPresenter>(context, listen: false).getCategories();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: ThemeConfig.xxlightGrey,
|
||||
appBar: CommonAppbar.show(
|
||||
title: AppLang.local(context).filter,
|
||||
context: context,
|
||||
bottom: buildSearchOptions(context)),
|
||||
body: Consumer<FilterPresenter>(builder: (context, data, child) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: data.onRefresh,
|
||||
child:buildProductSection(data),
|
||||
);
|
||||
}),
|
||||
|
||||
/// #Bottom Navigation Bar
|
||||
bottomNavigationBar:BottomAppBar(
|
||||
color: ThemeConfig.white,
|
||||
child: Consumer<CartPresenter>(
|
||||
builder: (context, cart, child) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Your Cart: ${showPrice(cart.cartResponse.total)}",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
Button(
|
||||
color: ThemeConfig.red,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18,vertical: 8),
|
||||
shape: StyleConfig.buttonRadius(5),
|
||||
onPressed: () {
|
||||
if (SystemData.isLogIn) {
|
||||
MakeRoute.go(context, const Cart());
|
||||
} else {
|
||||
Navigator.push(
|
||||
context, MaterialPageRoute(builder: (context) => const Login()));
|
||||
return;
|
||||
}
|
||||
},
|
||||
child: Text(AppLang.local(context).go_to_cart,style: StyleConfig.fs14cWhitefwNormal,))
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
) ,
|
||||
/* bottomSheet:BottomSheet(
|
||||
onClosing: (){}, builder: (context)=>Container(
|
||||
height: 250,
|
||||
width: getWidth(context),
|
||||
color: Colors.red,
|
||||
child: Consumer<FilterPresenter>(
|
||||
builder: (context, data, child) {
|
||||
return Column(
|
||||
children: [
|
||||
spacer(height: 10),
|
||||
headerTitle(AppLang.local(context).categories),
|
||||
spacer(height: StyleConfig.xsSectionSpacer),
|
||||
buildCategorySection(data),
|
||||
spacer(height: StyleConfig.smSectionSpacer),
|
||||
headerTitle(AppLang.local(context).price_range_ucf),
|
||||
RangeSlider(
|
||||
onChanged: (nPrice) {
|
||||
data.onChangePrice(nPrice);
|
||||
print(nPrice);
|
||||
},
|
||||
//onChangeEnd: data.onChangePrice,
|
||||
|
||||
min: 0,
|
||||
max: 500,
|
||||
values: data.price,
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
data.price.start.round().toString(),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
SizedBox(
|
||||
width: StyleConfig.xsSectionSpacer,
|
||||
),
|
||||
Text(
|
||||
AppLang.local(context).to,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
SizedBox(
|
||||
width: StyleConfig.xsSectionSpacer,
|
||||
),
|
||||
Text(
|
||||
data.price.end.round().toString(),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
),
|
||||
))
|
||||
*/
|
||||
/*bottomNavigationBar: Container(
|
||||
color: ThemeConfig.white,
|
||||
height: 280,
|
||||
width: getWidth(context),
|
||||
child: Consumer<FilterPresenter>(
|
||||
builder: (context, data, child) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
spacer(height: 10),
|
||||
headerTitle(AppLang.local(context).categories),
|
||||
spacer(height: StyleConfig.xsSectionSpacer),
|
||||
buildCategorySection(data),
|
||||
spacer(height: StyleConfig.smSectionSpacer),
|
||||
headerTitle(AppLang.local(context).price_range_ucf),
|
||||
RangeSlider(
|
||||
onChanged: (nPrice) {
|
||||
data.onChangePrice(nPrice);
|
||||
},
|
||||
min: 0,
|
||||
max: 500,
|
||||
values: (data.price),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
data.price.start.round().toString(),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
SizedBox(
|
||||
width: StyleConfig.xsSectionSpacer,
|
||||
),
|
||||
Text(
|
||||
AppLang.local(context).to,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
SizedBox(
|
||||
width: StyleConfig.xsSectionSpacer,
|
||||
),
|
||||
Text(
|
||||
data.price.end.round().toString(),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
Button(
|
||||
color: ThemeConfig.green,
|
||||
minWidth: getWidth(context),
|
||||
padding: EdgeInsets.symmetric(vertical: 14),
|
||||
onPressed: (){
|
||||
|
||||
},
|
||||
child: Text(AppLang.local(context).filter,style: StyleConfig.fs16cWhitefwBold,))
|
||||
],
|
||||
);
|
||||
}
|
||||
),
|
||||
),*/
|
||||
);
|
||||
}
|
||||
|
||||
PreferredSize buildSearchOptions(BuildContext context) {
|
||||
return PreferredSize(
|
||||
preferredSize: Size(getWidth(context),50),
|
||||
child: Consumer<FilterPresenter>(
|
||||
builder: (context, data, child) {
|
||||
return Container(
|
||||
margin: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding14, vertical: 10),
|
||||
width: getWidth(context),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: ThemeConfig.grey, width: 1),
|
||||
borderRadius: BorderRadius.circular(8)),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.xsSectionSpacer, vertical: 10),
|
||||
|
||||
width: getWidth(context)-100,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: getWidth(context)-220,
|
||||
child: TextField(
|
||||
autofocus: widget.isFocus,
|
||||
controller: data.searchTxt,
|
||||
onEditingComplete: () {
|
||||
data.clearCategory();
|
||||
data.clearPriceRange();
|
||||
data.getFilteredProducts();
|
||||
},
|
||||
decoration: const InputDecoration.collapsed(hintText: "Search"),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
width: 30,
|
||||
|
||||
child: Button(
|
||||
padding: EdgeInsets.zero,
|
||||
minWidth: 30,
|
||||
onPressed: () {
|
||||
data.clearCategory();
|
||||
data.clearPriceRange();
|
||||
data.getFilteredProducts();
|
||||
},
|
||||
child: Icon(Icons.search,size:24,color: ThemeConfig.fontColor,)),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 60,
|
||||
child: Button(
|
||||
onPressed: (){
|
||||
showFilterDialog();
|
||||
},
|
||||
shape: StyleConfig.buttonRadius(6),
|
||||
color: ThemeConfig.red,
|
||||
padding: const EdgeInsets.symmetric( vertical: 16,horizontal: 10),
|
||||
minWidth: 40,
|
||||
child: Text(AppLang.local(context).filter,style: StyleConfig.fs14cWhitefwNormal,)),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildCategorySection(FilterPresenter data) {
|
||||
return SizedBox(
|
||||
height: 87,
|
||||
child: data.isCategoryInit
|
||||
? ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
itemBuilder: (context, index) {
|
||||
return SizedBox(
|
||||
width: 100,
|
||||
child: Button(
|
||||
shape: StyleConfig.buttonRadius(0).copyWith(
|
||||
side: BorderSide(
|
||||
color: data.categories[index].id.toString() ==
|
||||
data.selectedCategoryId.toString()
|
||||
? ThemeConfig.accentColor
|
||||
: ThemeConfig.noColor)),
|
||||
padding: const EdgeInsets.all(5),
|
||||
onPressed: () {
|
||||
data.onSelectCategory(data.categories[index].id);
|
||||
},
|
||||
child: CategoryUi(
|
||||
img: data.categories[index].thumbnailImage,
|
||||
name: data.categories[index].name),
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return const SizedBox(
|
||||
width: 8,
|
||||
);
|
||||
},
|
||||
itemCount: data.categories.length)
|
||||
: Shimmers.horizontalList(8, 80, 80),
|
||||
);
|
||||
}
|
||||
|
||||
Widget headerTitle(text) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Text(
|
||||
text,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget spacer({height = 24}) {
|
||||
return SizedBox(
|
||||
height: double.parse(height.toString()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Widget buildProductSection(FilterPresenter data){
|
||||
return GridView.builder(
|
||||
controller: data.scrollController,
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding,vertical: StyleConfig.smSectionSpacer),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
childAspectRatio: 0.72
|
||||
),
|
||||
itemCount: data.products.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ProductCard(
|
||||
product: data.products[index],context: this.context,);
|
||||
});
|
||||
}
|
||||
|
||||
showFilterDialog(){
|
||||
showDialog(context: context, builder: (context)=>Consumer<FilterPresenter>(
|
||||
builder: (context,data,child) {
|
||||
return AlertDialog(
|
||||
title: Center(child: Text("Filter Form",style: StyleConfig.fs14fwBold,)),
|
||||
content: Container(
|
||||
height: getHeight(context)*0.30,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
headerTitle(AppLang.local(context).categories),
|
||||
spacer(height: StyleConfig.xsSectionSpacer),
|
||||
SizedBox(
|
||||
width: getWidth(context),
|
||||
child: buildCategorySection(data)),
|
||||
spacer(height: StyleConfig.smSectionSpacer),
|
||||
headerTitle(AppLang.local(context).price_range_ucf),
|
||||
RangeSlider(
|
||||
onChanged: (nPrice) {
|
||||
data.onChangePrice(nPrice);
|
||||
},
|
||||
min: 0,
|
||||
max: 500,
|
||||
values: (data.price),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
data.price.start.round().toString(),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
SizedBox(
|
||||
width: StyleConfig.xsSectionSpacer,
|
||||
),
|
||||
Text(
|
||||
AppLang.local(context).to,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
SizedBox(
|
||||
width: StyleConfig.xsSectionSpacer,
|
||||
),
|
||||
Text(
|
||||
data.price.end.round().toString(),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
Button(
|
||||
shape: StyleConfig.buttonRadius(6),
|
||||
color: ThemeConfig.grey,
|
||||
onPressed: (){
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(AppLang.local(context).close,style: StyleConfig.fs12cWhite,)),
|
||||
Button(
|
||||
shape: StyleConfig.buttonRadius(6),
|
||||
color: ThemeConfig.green,
|
||||
onPressed: (){
|
||||
Navigator.pop(context);
|
||||
data.clearKeyWord();
|
||||
data.getFilteredProducts();
|
||||
}
|
||||
,
|
||||
child: Text(AppLang.local(context).submit,style: StyleConfig.fs12cWhite))
|
||||
],
|
||||
);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
Widget allProductShimmer() {
|
||||
return GridView.builder(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
childAspectRatio: 2/3),
|
||||
itemCount: 10,
|
||||
itemBuilder: (context, index) {
|
||||
return Shimmers(width: 160, height: 186,radius: 8,);
|
||||
});
|
||||
}
|
||||
}
|
||||
100
app_code/lib/screens/help_center.dart
Normal file
100
app_code/lib/screens/help_center.dart
Normal file
@@ -0,0 +1,100 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/presenters/help_center_presenter.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
|
||||
class HelpCenter extends StatefulWidget {
|
||||
const HelpCenter({super.key});
|
||||
|
||||
@override
|
||||
State<HelpCenter> createState() => _HelpCenterState();
|
||||
}
|
||||
|
||||
class _HelpCenterState extends State<HelpCenter> {
|
||||
HelpCenterPresenter helpCenterPresenter=HelpCenterPresenter();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
|
||||
helpCenterPresenter.initState();
|
||||
});
|
||||
|
||||
super.initState();
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: ThemeConfig.xxlightGrey,
|
||||
appBar: CommonAppbar.show(title: AppLang.local(context).help_center_ucf, context: context),
|
||||
body: Center(
|
||||
child: ListenableBuilder(
|
||||
listenable: helpCenterPresenter,
|
||||
builder: (context,child) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10,vertical: 10),
|
||||
margin: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
height: 200,
|
||||
width: getWidth(context),
|
||||
decoration: BoxDecorations.shadow(radius: 8),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.location_on_outlined),
|
||||
SizedBox(
|
||||
width: getWidth(context)*0.7,
|
||||
child: Text(helpCenterPresenter.helpCenter?.location??""))
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10,),
|
||||
Button(
|
||||
onPressed: (){
|
||||
launchUrl(Uri(scheme: 'tel', path: helpCenterPresenter.helpCenter?.contactNumber??"123"));
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.phone),
|
||||
SizedBox(
|
||||
width: getWidth(context)*0.7,
|
||||
child: Text(helpCenterPresenter.helpCenter?.contactNumber??""))
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
Button(
|
||||
onPressed: (){
|
||||
launchUrl(Uri(scheme: 'mailto', path: helpCenterPresenter.helpCenter?.email??""));
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.email_outlined),
|
||||
SizedBox(
|
||||
width: getWidth(context)*0.7,
|
||||
child: Text(helpCenterPresenter.helpCenter?.email??""))
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
317
app_code/lib/screens/home.dart
Normal file
317
app_code/lib/screens/home.dart
Normal file
@@ -0,0 +1,317 @@
|
||||
|
||||
import 'package:carousel_slider/carousel_slider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/category_ui.dart';
|
||||
import 'package:grostore/custom_ui/product_card.dart';
|
||||
import 'package:grostore/custom_ui/shimmers.dart';
|
||||
import 'package:grostore/helpers/common_functions.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/presenters/home_presenter.dart';
|
||||
import 'package:grostore/screens/filter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class Home extends StatefulWidget {
|
||||
String? id;
|
||||
|
||||
Home({Key? key, this.id}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Home> createState() => _HomeState();
|
||||
}
|
||||
|
||||
class _HomeState extends State<Home> {
|
||||
@override
|
||||
void initState() {
|
||||
Provider.of<HomePresenter>(context,listen: false).setContext(context);
|
||||
Provider.of<HomePresenter>(context, listen: false).initState(context);
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
// @override
|
||||
// void dispose() {
|
||||
// Provider.of<HomePresenter>(context, listen: false).dispose();
|
||||
// super.dispose();
|
||||
// }
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
backgroundColor: ThemeConfig.xxlightGrey,
|
||||
appBar: buildSearchOption(context),
|
||||
body: Consumer<HomePresenter>(builder: (context, data, child) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: data.onRefresh,
|
||||
child: SingleChildScrollView(
|
||||
controller: data.homeScrollController,
|
||||
child: SafeArea(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
buildSliderSection(data),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
AppLang.local(context).top_categories_ucf,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
Image.asset(
|
||||
getAssetIcon("fire.png"),
|
||||
height: 20,
|
||||
width: 20,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
buildTopCategorySection(data),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
AppLang.local(context).best_selling_products_ucf,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
Image.asset(
|
||||
getAssetIcon("fire.png"),
|
||||
height: 20,
|
||||
width: 20,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
SizedBox(
|
||||
// color: Colors.red,
|
||||
height:225,
|
||||
child: buildBestSellingProductSection(data)),
|
||||
const SizedBox(height: 14,),
|
||||
Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
AppLang.local(context).all_products_ucf,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
Image.asset(
|
||||
getAssetIcon("fire.png"),
|
||||
height: 20,
|
||||
width: 20,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
allProducts(data),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container buildTopCategorySection(HomePresenter data) {
|
||||
return Container(
|
||||
height: 100,
|
||||
child: data.isTopCategoryInitial
|
||||
? ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
itemBuilder: (context, index) {
|
||||
return Button(
|
||||
minWidth: 40,
|
||||
onPressed: (){
|
||||
MakeRoute.go(context, Filter(category_id:data.topCategoryList[index].id.toString() ,));
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 100,
|
||||
child: CategoryUi(
|
||||
img: data.topCategoryList[index].thumbnailImage,
|
||||
name: data.topCategoryList[index].name),
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return const SizedBox(
|
||||
width: 8,
|
||||
);
|
||||
},
|
||||
itemCount: data.topCategoryList.length)
|
||||
: categoryShimmer(),
|
||||
);
|
||||
}
|
||||
|
||||
SizedBox buildSliderSection(HomePresenter data) {
|
||||
return SizedBox(
|
||||
height: 170,
|
||||
child: CarouselSlider(
|
||||
items:
|
||||
data.isHomeBannerInitial ? data.homeBannerImages : sliderShimmer(),
|
||||
options: CarouselOptions(
|
||||
aspectRatio: 2,
|
||||
viewportFraction: 0.94,
|
||||
height: 150,
|
||||
// enlargeCenterPage: true,
|
||||
scrollDirection: Axis.horizontal,
|
||||
autoPlay: true,
|
||||
onPageChanged: (index, reason) {
|
||||
data.onChangeBannerIndex(index);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
PreferredSize buildSearchOption(BuildContext context) {
|
||||
return PreferredSize(
|
||||
preferredSize: Size(getWidth(context), 54),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 14),
|
||||
margin: const EdgeInsets.only(top:12, left: 24, right: 24),
|
||||
width: getWidth(context),
|
||||
decoration: BoxDecorations.shadow(radius: 6.0),
|
||||
child: Button(
|
||||
onPressed: ()=>MakeRoute.go(context, Filter(isFocus: true,)),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
getAssetIcon("search.png"),
|
||||
height: 16,
|
||||
width: 16,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
Text(
|
||||
AppLang.local(context).search_product_ucf,
|
||||
style: StyleConfig.fs12cGrey,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
List<Widget> sliderShimmer() {
|
||||
return [
|
||||
Shimmers(width: getWidth(context) - 40, height: 200),
|
||||
Shimmers(width: getWidth(context) - 40, height: 200),
|
||||
Shimmers(width: getWidth(context) - 40, height: 200),
|
||||
Shimmers(width: getWidth(context) - 40, height: 200),
|
||||
];
|
||||
}
|
||||
|
||||
ListView categoryShimmer() {
|
||||
return ListView.separated(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
return Shimmers(
|
||||
width: 76,
|
||||
height: 87,
|
||||
radius: 6.0,
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return const SizedBox(
|
||||
width: 8,
|
||||
height: 10,
|
||||
);
|
||||
},
|
||||
itemCount: 10);
|
||||
}
|
||||
|
||||
Widget allProductShimmer() {
|
||||
return GridView.builder(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
childAspectRatio: 2/3),
|
||||
itemCount: 10,
|
||||
itemBuilder: (context, index) {
|
||||
return Shimmers(width: 160, height: 186,radius: 8,);
|
||||
});
|
||||
}
|
||||
|
||||
Widget buildBestSellingProductSection(HomePresenter data){
|
||||
return
|
||||
data.isBestSellingProductInitial ?
|
||||
ListView.separated(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
return ProductCard(
|
||||
product: data.bestSellingProductList[index],context: this.context,);
|
||||
},
|
||||
separatorBuilder: (context,index)=>const SizedBox(width: 10,), itemCount: data.bestSellingProductList.length)
|
||||
:Shimmers.horizontalList(10, 160, 160);
|
||||
}
|
||||
|
||||
|
||||
Widget allProducts(HomePresenter data){
|
||||
String datas = '';
|
||||
return data.isAllProductInitial?GridView.builder(
|
||||
padding: EdgeInsets.only(left: StyleConfig.padding,right: StyleConfig.padding,bottom: 20),
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: data.products.length,
|
||||
itemBuilder: (context, index) {
|
||||
datas = data.products[index].name;
|
||||
return ProductCard(product: data.products[index],context: this.context,);
|
||||
},
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
childAspectRatio: 0.72,
|
||||
// childAspectRatio: 2.1/3
|
||||
),
|
||||
):allProductShimmer();
|
||||
}
|
||||
}
|
||||
115
app_code/lib/screens/landing_pages/auth_model.dart
Normal file
115
app_code/lib/screens/landing_pages/auth_model.dart
Normal file
@@ -0,0 +1,115 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/app_config.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/helpers/common_functions.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/screens/auth/login.dart';
|
||||
import 'package:grostore/screens/auth/registration.dart';
|
||||
|
||||
import '../../helpers/device_info_helper.dart';
|
||||
|
||||
class AuthPageModel extends StatelessWidget {
|
||||
const AuthPageModel({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
width: getWidth(context),
|
||||
height: getHeight(context),
|
||||
decoration: BoxDecoration(
|
||||
//color: ThemeConfig.splashBackgrund,
|
||||
image: DecorationImage(
|
||||
image: AssetImage(getAssetImage("splash_background.png")))),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Spacer(),
|
||||
Image.asset(
|
||||
getAssetLogo("img_logo2.png"),
|
||||
width: 150,
|
||||
height: 150,
|
||||
),
|
||||
// const SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
// Text(
|
||||
// AppConfig.appName,
|
||||
// style: StyleConfig.fs30fwEBold(),
|
||||
// textAlign: TextAlign.center,
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 64,
|
||||
// ),
|
||||
Text(
|
||||
AppLang.local(context).welcome_to_back,
|
||||
style: StyleConfig.fs22fwEBold,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
AppLang.local(context)
|
||||
.energetically_streamline_one_to_one_web_readiness_before_extensive_meta_services,
|
||||
style: StyleConfig.fs12cLightfwNormal,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const Spacer(),
|
||||
Row(
|
||||
children: [
|
||||
Button(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(5)),
|
||||
side: BorderSide(
|
||||
color: ThemeConfig.red
|
||||
)
|
||||
),
|
||||
// StyleConfig.buttonRadius(5),
|
||||
minWidth: getWidth(context) * 0.42,
|
||||
// color: ThemeConfig.secondaryColor,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding14,
|
||||
vertical: StyleConfig.padding14),
|
||||
child: Text(
|
||||
AppLang.local(context).login,
|
||||
style: StyleConfig.fs14cRedfwNormal,
|
||||
),
|
||||
onPressed: (){
|
||||
MakeRoute.go(context, const Login());
|
||||
},
|
||||
),
|
||||
const Spacer(),
|
||||
Button(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(5)),
|
||||
side: BorderSide(
|
||||
color: ThemeConfig.red
|
||||
)
|
||||
),
|
||||
// StyleConfig.buttonRadius(5),
|
||||
minWidth: getWidth(context) * 0.42,
|
||||
// color: ThemeConfig.secondaryColor,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding14,
|
||||
vertical: StyleConfig.padding14),
|
||||
onPressed: (){
|
||||
MakeRoute.go(context, Registration());
|
||||
},
|
||||
child: Text(
|
||||
AppLang.local(context).register,
|
||||
style: StyleConfig.fs14cRedfwNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
105
app_code/lib/screens/landing_pages/landing_page.dart
Normal file
105
app_code/lib/screens/landing_pages/landing_page.dart
Normal file
@@ -0,0 +1,105 @@
|
||||
import 'package:carousel_slider/carousel_slider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/helpers/shared_value_helper.dart';
|
||||
import 'package:grostore/presenters/landing_page_presenter.dart';
|
||||
import 'package:grostore/screens/landing_pages/page_model.dart';
|
||||
import 'package:grostore/screens/landing_pages/auth_model.dart';
|
||||
import 'package:grostore/screens/main.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
||||
class LandingPage extends StatefulWidget {
|
||||
const LandingPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<LandingPage> createState() => _LandingPageState();
|
||||
}
|
||||
|
||||
class _LandingPageState extends State<LandingPage> {
|
||||
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
||||
// );
|
||||
//show_landing_page.update((p0) => false);
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Provider.of<LandingPagePresenter>(context).setContext(context);
|
||||
Provider.of<LandingPagePresenter>(context).iniState();
|
||||
|
||||
return Consumer<LandingPagePresenter>(
|
||||
builder: (context,data,child) {
|
||||
return Scaffold(
|
||||
body: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: getHeight(context)*0.88,
|
||||
child: CarouselSlider(
|
||||
carouselController:data.controller ,
|
||||
items: data.pages,
|
||||
options: CarouselOptions(
|
||||
autoPlay: false,
|
||||
height: MediaQuery.of(context).size.height,
|
||||
initialPage: 0,
|
||||
enableInfiniteScroll: false,
|
||||
viewportFraction: 1.0,
|
||||
onPageChanged: (index, reason) {
|
||||
data.indexChange(index);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: data.pages.map((page) {
|
||||
int index = data.pages.indexOf(page);
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 100),
|
||||
width:data.currentIndex == index? 20:5,
|
||||
height:5,
|
||||
margin:const EdgeInsets.symmetric(horizontal: 4),
|
||||
decoration: BoxDecoration(
|
||||
// shape: BoxShape.circle,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: data.currentIndex == index ? ThemeConfig.red : Colors.grey,
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
const Spacer(),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Button(
|
||||
shape: StyleConfig.buttonRadius(5.0),
|
||||
color: ThemeConfig.red,
|
||||
padding: EdgeInsets.symmetric(vertical: StyleConfig.padding14),
|
||||
minWidth: getWidth(context),
|
||||
onPressed: (){
|
||||
if(data.currentIndex==3) {
|
||||
MakeRoute.goName(context, "/main");
|
||||
} else {
|
||||
data.onChangeSlider();
|
||||
}
|
||||
},
|
||||
child: Text(data.currentIndex==3?AppLang.local(context).skip:AppLang.local(context).next,style: StyleConfig.fs12cWhitefwBold,),),
|
||||
),
|
||||
const SizedBox(height: 14,)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
38
app_code/lib/screens/landing_pages/page_model.dart
Normal file
38
app_code/lib/screens/landing_pages/page_model.dart
Normal file
@@ -0,0 +1,38 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/helpers/common_functions.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
|
||||
|
||||
class PageModel extends StatelessWidget {
|
||||
String img,headerTxt,txt;
|
||||
PageModel({Key? key,required this.img,required this.headerTxt,required this.txt}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
AppLang.setContext(context);
|
||||
return SizedBox(
|
||||
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
Image.asset(getAssetImage(img),height: getHeight(context)*0.7,width: getWidth(context),fit: BoxFit.cover,),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal:StyleConfig.padding),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(headerTxt,style: StyleConfig.fs18BlackfwBold,textAlign: TextAlign.center,),
|
||||
SizedBox(height: 10,),
|
||||
Text(txt,style: StyleConfig.fs12cLightfwEBold,textAlign: TextAlign.center,),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
165
app_code/lib/screens/main.dart
Normal file
165
app_code/lib/screens/main.dart
Normal file
@@ -0,0 +1,165 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:badges/badges.dart' as badges;
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_classes/system_data.dart';
|
||||
import 'package:grostore/helpers/common_functions.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/models/product_mini_response.dart';
|
||||
import 'package:grostore/presenters/main_persenter.dart';
|
||||
import 'package:grostore/presenters/stock_locations_presenter.dart';
|
||||
import 'package:grostore/screens/auth/login.dart';
|
||||
import 'package:grostore/screens/cart.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../presenters/cart_presenter.dart';
|
||||
|
||||
class Main extends StatefulWidget {
|
||||
const Main({super.key});
|
||||
|
||||
@override
|
||||
_MainState createState() => _MainState();
|
||||
}
|
||||
|
||||
class _MainState extends State<Main> {
|
||||
@override
|
||||
void initState() {
|
||||
Provider.of<MainPresenter>(context, listen: false).setContext(context);
|
||||
Future.delayed(const Duration(seconds: 1)).then((value) {
|
||||
Provider.of<StockLocationsPresenter>(context, listen: false)
|
||||
.fetchLocations(context);
|
||||
});
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MainPresenter>(builder: (context, data, child) {
|
||||
return PopScope(
|
||||
onPopInvoked: (a) async {
|
||||
if (data.bottomAppbarIndex != 0) {
|
||||
data.onTapped(0);
|
||||
} else {
|
||||
return Future.delayed(Duration.zero);
|
||||
}
|
||||
return Future.delayed(Duration.zero);
|
||||
},
|
||||
child: Scaffold(
|
||||
extendBody: true,
|
||||
body: data.bottomAppbarChildren[data.bottomAppbarIndex],
|
||||
bottomNavigationBar: SizedBox(
|
||||
height: 90,
|
||||
child: BottomNavigationBar(
|
||||
type: BottomNavigationBarType.fixed,
|
||||
onTap: data.onTapped,
|
||||
currentIndex: data.bottomAppbarIndex,
|
||||
backgroundColor: Colors.white.withOpacity(0.95),
|
||||
unselectedItemColor: const Color.fromRGBO(168, 175, 179, 1),
|
||||
selectedItemColor: ThemeConfig.secondaryColor,
|
||||
selectedLabelStyle: TextStyle(
|
||||
fontWeight: FontWeight.w700,
|
||||
color: ThemeConfig.secondaryColor,
|
||||
fontSize: 12),
|
||||
unselectedLabelStyle: const TextStyle(
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Color.fromRGBO(168, 175, 179, 1),
|
||||
fontSize: 12),
|
||||
items: [
|
||||
BottomNavigationBarItem(
|
||||
icon: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Image.asset(
|
||||
getAssetIcon("home.png"),
|
||||
color: data.bottomAppbarIndex == 0
|
||||
? ThemeConfig.secondaryColor
|
||||
: ThemeConfig.grey,
|
||||
height: 16,
|
||||
),
|
||||
),
|
||||
label: AppLang.local(context).home),
|
||||
BottomNavigationBarItem(
|
||||
icon: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Image.asset(
|
||||
getAssetIcon("categories.png"),
|
||||
color: data.bottomAppbarIndex == 1
|
||||
? ThemeConfig.secondaryColor
|
||||
: ThemeConfig.grey,
|
||||
height: 16,
|
||||
),
|
||||
),
|
||||
label: AppLang.local(context).categories),
|
||||
BottomNavigationBarItem(
|
||||
icon: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Image.asset(
|
||||
getAssetIcon("orders.png"),
|
||||
color: data.bottomAppbarIndex == 2
|
||||
? ThemeConfig.secondaryColor
|
||||
: const Color.fromRGBO(153, 153, 153, 1),
|
||||
height: 16,
|
||||
),
|
||||
),
|
||||
label: AppLang.local(context).orders),
|
||||
BottomNavigationBarItem(
|
||||
icon: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Image.asset(
|
||||
getAssetIcon("profile.png"),
|
||||
color: data.bottomAppbarIndex == 3
|
||||
? ThemeConfig.secondaryColor
|
||||
: ThemeConfig.grey,
|
||||
height: 16,
|
||||
),
|
||||
),
|
||||
label: AppLang.local(context).profile,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () {
|
||||
if (SystemData.isLogIn) {
|
||||
MakeRoute.go(context, const Cart());
|
||||
} else {
|
||||
Navigator.push(
|
||||
context, MaterialPageRoute(builder: (context) => const Login()));
|
||||
return;
|
||||
}
|
||||
},
|
||||
backgroundColor: ThemeConfig.amber,
|
||||
child: badges.Badge(
|
||||
position: badges.BadgePosition.custom(end: 12, bottom: -15),
|
||||
badgeStyle: badges.BadgeStyle(
|
||||
shape: badges.BadgeShape.circle,
|
||||
badgeColor: ThemeConfig.red,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
borderSide: const BorderSide(width: 1, color: ThemeConfig.white)
|
||||
//padding: EdgeInsets.all(5),
|
||||
),
|
||||
badgeContent: Consumer<CartPresenter>(
|
||||
builder: (context, cart, child) {
|
||||
return Text(
|
||||
"${cart.cartResponse.cartCount}",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.white),
|
||||
);
|
||||
},
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: Image.asset(
|
||||
getAssetIcon("cart.png"),
|
||||
color: ThemeConfig.white,
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
floatingActionButtonLocation:
|
||||
FloatingActionButtonLocation.centerDocked,
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
472
app_code/lib/screens/order/order_details.dart
Normal file
472
app_code/lib/screens/order/order_details.dart
Normal file
@@ -0,0 +1,472 @@
|
||||
import 'package:dotted_line/dotted_line.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/order_item.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/presenters/order_details_presenter.dart';
|
||||
import 'package:grostore/screens/order/pdf_api.dart';
|
||||
import 'package:grostore/screens/order/pdf_invoice_api.dart';
|
||||
|
||||
import '../../helpers/common_functions.dart';
|
||||
|
||||
class OrderDetails extends StatefulWidget {
|
||||
final code;
|
||||
|
||||
const OrderDetails({super.key, this.code});
|
||||
|
||||
@override
|
||||
State<OrderDetails> createState() => _OrderDetailsState();
|
||||
}
|
||||
|
||||
class _OrderDetailsState extends State<OrderDetails> {
|
||||
OrderDetailsPresenter orderDetailsPresenter = OrderDetailsPresenter();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
orderDetailsPresenter.initState(widget.code);
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: ThemeConfig.xxlightGrey,
|
||||
appBar: CommonAppbar.show(
|
||||
title: AppLang.local(context).order_details, context: context),
|
||||
body: ListenableBuilder(
|
||||
listenable: orderDetailsPresenter,
|
||||
builder: (context, child) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () {
|
||||
return orderDetailsPresenter.onRefresh(widget.code);
|
||||
},
|
||||
child: SingleChildScrollView(
|
||||
child: orderDetailsPresenter.isInitDetails
|
||||
? Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 24),
|
||||
Container(
|
||||
width: getWidth(context),
|
||||
decoration: BoxDecorations.shadow(radius: 8),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8, vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Buyurtma raqami: ${orderDetailsPresenter.orderInfo?.code ?? ''}",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Text(
|
||||
"Buyurtma sanasi: ${orderDetailsPresenter.orderInfo?.date ?? ''}",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Text(
|
||||
"Billing Address",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8, vertical: 8),
|
||||
decoration: BoxDecorations.shadow(radius: 8),
|
||||
child: buildBillingAddress(context)),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Text(
|
||||
"Shipping Address",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecorations.shadow(radius: 8),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8, vertical: 8),
|
||||
child: buildShippingAddress(context)),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Text(
|
||||
"Products",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Container(
|
||||
//decoration: BoxDecorations.shadow(radius: 8),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8, vertical: 8),
|
||||
child: Column(
|
||||
children: [
|
||||
/*Row(
|
||||
|
||||
children: [
|
||||
Container(
|
||||
width: getWidth(context)*0.35,
|
||||
child: Text("Product Name")),
|
||||
Container(
|
||||
width: getWidth(context)*0.18,
|
||||
child: Text("Unit Price")),
|
||||
Container(
|
||||
width: getWidth(context)*0.1,
|
||||
child: Text("QTY")),
|
||||
Container(
|
||||
width: getWidth(context)*0.18,
|
||||
child: Text("Total Price")),
|
||||
],
|
||||
),
|
||||
Divider(color: ThemeConfig.fontColor,),*/
|
||||
GridView.builder(
|
||||
//padding: EdgeInsets.only(left: StyleConfig.padding,right: StyleConfig.padding,bottom: 20),
|
||||
shrinkWrap: true,
|
||||
physics:
|
||||
const NeverScrollableScrollPhysics(),
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 8,
|
||||
childAspectRatio: 0.62),
|
||||
itemBuilder: (context, index) =>
|
||||
OrderItem(
|
||||
context: context,
|
||||
onReq: (value) {
|
||||
if (value) {
|
||||
orderDetailsPresenter
|
||||
.onRefresh(widget.code);
|
||||
}
|
||||
},
|
||||
item: orderDetailsPresenter
|
||||
.orderInfo!.items[index],
|
||||
)
|
||||
/*Container(
|
||||
child: Row(
|
||||
|
||||
children: [
|
||||
Container(
|
||||
width: getWidth(context)*0.35,
|
||||
child: Text(orderDetailsPresenter.orderInfo?.items[index].product?.name??"")),
|
||||
Container(
|
||||
width: getWidth(context)*0.18,
|
||||
child: Text(showPrice(orderDetailsPresenter.orderInfo?.items[index].unitPrice??""))),
|
||||
Container(
|
||||
width: getWidth(context)*0.1,
|
||||
child: Text("${orderDetailsPresenter.orderInfo?.items[index].qty??''}")),
|
||||
Container(
|
||||
width: getWidth(context)*0.18,
|
||||
child: Text(showPrice(orderDetailsPresenter.orderInfo?.items[index].totalPrice??""))),
|
||||
],
|
||||
),
|
||||
),
|
||||
,
|
||||
separatorBuilder: (context, index) => Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
Divider(color: ThemeConfig.fontColor,),
|
||||
],
|
||||
)*/
|
||||
,
|
||||
itemCount: orderDetailsPresenter
|
||||
.orderInfo?.items.length ??
|
||||
0),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Payment Method",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
orderDetailsPresenter
|
||||
.orderInfo?.payment_method
|
||||
.toUpperCase() ??
|
||||
"",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Sub Total",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
showPrice(orderDetailsPresenter
|
||||
.orderInfo?.subTotalAmount ??
|
||||
""),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Tips",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
showPrice(orderDetailsPresenter
|
||||
.orderInfo?.totalTips ??
|
||||
""),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Shipping Cost",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
showPrice(orderDetailsPresenter
|
||||
.orderInfo?.totalShippingCost ??
|
||||
""),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Coupon Discount",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
showPrice(orderDetailsPresenter
|
||||
.orderInfo?.couponDiscountAmount ??
|
||||
""),
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
const DottedLine(),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Total Price",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
showPrice(orderDetailsPresenter
|
||||
.orderInfo?.totalPrice ??
|
||||
""),
|
||||
style: StyleConfig.fs14fwBold
|
||||
.copyWith(color: ThemeConfig.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
Button(
|
||||
minHeight: 40.0,
|
||||
shape: StyleConfig.buttonRadius(10),
|
||||
minWidth: MediaQuery.sizeOf(context).width,
|
||||
color: ThemeConfig.red,
|
||||
child: Text(
|
||||
AppLang.local(context).download_invoice,
|
||||
style: StyleConfig.fs14cWhitefwBold,
|
||||
),
|
||||
onPressed: () async {
|
||||
final pdf = await PdfInvoiceApi.generate(orderDetailsPresenter.orderInfo);
|
||||
PdfApi.openFile(pdf);
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
: SizedBox(
|
||||
height: getHeight(context),
|
||||
child:
|
||||
const Center(child: CircularProgressIndicator())),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Column buildBillingAddress(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.billingAddress?.address ?? "",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
maxLines: 1,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).city}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.billingAddress?.cityName ?? "",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).state}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.billingAddress?.stateName ??
|
||||
"",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).country}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.billingAddress?.countryName ??
|
||||
"",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Column buildShippingAddress(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.shippingAddress?.address ?? "",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
maxLines: 1,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).city}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.shippingAddress?.cityName ??
|
||||
"",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).state}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.shippingAddress?.stateName ??
|
||||
"",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"${AppLang.local(context).country}: ",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
Text(
|
||||
orderDetailsPresenter.orderInfo?.shippingAddress?.countryName ??
|
||||
"",
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
148
app_code/lib/screens/order/orders.dart
Normal file
148
app_code/lib/screens/order/orders.dart
Normal file
@@ -0,0 +1,148 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/order_view_model.dart';
|
||||
import 'package:grostore/custom_ui/shimmers.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/presenters/order_presenter.dart';
|
||||
import 'package:grostore/screens/main.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class Orders extends StatefulWidget {
|
||||
bool fromBottomBar;
|
||||
bool fromCheckOut;
|
||||
|
||||
Orders({Key? key, this.fromBottomBar = true,this.fromCheckOut=false}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Orders> createState() => _OrdersState();
|
||||
}
|
||||
|
||||
class _OrdersState extends State<Orders> {
|
||||
OrderPresenter order = OrderPresenter();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
Provider.of<OrderPresenter>(context, listen: false).setContext(context);
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
Provider.of<OrderPresenter>(context, listen: false).initState();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PopScope(
|
||||
onPopInvoked: (a) async {
|
||||
if(widget.fromCheckOut){
|
||||
MakeRoute.goAndRemoveAll(context, const Main());
|
||||
return Future(() => true);
|
||||
}
|
||||
return Future(() => true);
|
||||
},
|
||||
child: Scaffold(
|
||||
backgroundColor: ThemeConfig.xxlightGrey,
|
||||
appBar: CommonAppbar.show(
|
||||
title: AppLang.local(context).orders,
|
||||
context: context,
|
||||
gotoMain: widget.fromCheckOut,
|
||||
showBackButton: !widget.fromBottomBar),
|
||||
body: Consumer<OrderPresenter>(builder: (context, data, child) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => data.onRefresh(),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
buildTapbar(context, data),
|
||||
if (!data.isOrdersInit)
|
||||
SizedBox(
|
||||
width: getWidth(context),
|
||||
height: getHeight(context) - 100,
|
||||
child: Shimmers.list(10, getWidth(context), 80),
|
||||
)
|
||||
else if (data.isOrdersInit && data.orders.isNotEmpty)
|
||||
ListView.separated(
|
||||
padding: EdgeInsets.only(
|
||||
left: 10,
|
||||
right: 10,
|
||||
top: 10,
|
||||
bottom: widget.fromBottomBar ? 80 : 10),
|
||||
scrollDirection: Axis.vertical,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemCount: data.orders.length,
|
||||
separatorBuilder: (context, index) {
|
||||
return const SizedBox(
|
||||
height: 10,
|
||||
);
|
||||
},
|
||||
itemBuilder: (context, index) {
|
||||
return Button(
|
||||
//padding: EdgeInsets.symmetric(vertical: 10,horizontal: 20),
|
||||
minWidth: 100,
|
||||
onPressed: () {},
|
||||
child: OrderViewModel(
|
||||
orderInfo: data.orders[index],
|
||||
context: context,
|
||||
));
|
||||
},
|
||||
)
|
||||
else
|
||||
Container(
|
||||
height: getHeight(context)-180,
|
||||
alignment: Alignment.center,
|
||||
child: Text(AppLang.local(context).data_is_not_available))
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
SizedBox buildTapbar(BuildContext context, OrderPresenter data) {
|
||||
return SizedBox(
|
||||
// color: Colors.red,
|
||||
width: getWidth(context),
|
||||
height: 40,
|
||||
child: ListView.separated(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: data.searchKey.values.length,
|
||||
separatorBuilder: (context, index) {
|
||||
return const SizedBox(
|
||||
width: 10,
|
||||
);
|
||||
},
|
||||
itemBuilder: (context, index) {
|
||||
return Button(
|
||||
padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 15),
|
||||
color: data.keySelectedIndex == index
|
||||
? ThemeConfig.red
|
||||
: ThemeConfig.white,
|
||||
minWidth: 80,
|
||||
minHeight: 40.0,
|
||||
shape: StyleConfig.buttonRadius(10),
|
||||
onPressed: () {
|
||||
data.onChangeIndex(index);
|
||||
},
|
||||
child: Text( data.searchKey.values.elementAt(index),
|
||||
style: data.keySelectedIndex == index
|
||||
? StyleConfig.fs14cWhitefwBold
|
||||
: StyleConfig.fs14fwBold,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
27
app_code/lib/screens/order/pdf_api.dart
Normal file
27
app_code/lib/screens/order/pdf_api.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:open_file/open_file.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:pdf/widgets.dart';
|
||||
|
||||
class PdfApi {
|
||||
static Future<File> saveDocument({
|
||||
required String name,
|
||||
required Document pdf,
|
||||
}) async {
|
||||
final bytes = await pdf.save();
|
||||
|
||||
final dir = await getApplicationDocumentsDirectory();
|
||||
final file = File('${dir.path}/$name');
|
||||
|
||||
await file.writeAsBytes(bytes);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static Future openFile(File file) async {
|
||||
final url = file.path;
|
||||
|
||||
await OpenFile.open(url);
|
||||
}
|
||||
}
|
||||
152
app_code/lib/screens/order/pdf_invoice_api.dart
Normal file
152
app_code/lib/screens/order/pdf_invoice_api.dart
Normal file
@@ -0,0 +1,152 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart' show Colors;
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:grostore/helpers/common_functions.dart';
|
||||
import 'package:grostore/screens/order/pdf_api.dart';
|
||||
import 'package:pdf/pdf.dart';
|
||||
import 'package:pdf/widgets.dart' as pw;
|
||||
import 'package:pdf/widgets.dart';
|
||||
|
||||
import '../../models/order/order_details_response.dart';
|
||||
|
||||
class PdfInvoiceApi {
|
||||
static Future<File> generate(OrderDetailsInfo? detailsInfo) async {
|
||||
final img = await rootBundle.load(getAssetLogo("logo2x2.png"));
|
||||
final imageBytes = img.buffer.asUint8List();
|
||||
|
||||
final imgQr = await rootBundle.load(getAssetLogo("img.png"));
|
||||
final qr = imgQr.buffer.asUint8List();
|
||||
final pdf = Document();
|
||||
|
||||
pdf.addPage(MultiPage(
|
||||
build: (context) => [
|
||||
buildLogo(imageBytes),
|
||||
pw.SizedBox(height: 0.3 * PdfPageFormat.cm),
|
||||
buildDottedDivider(),
|
||||
pw.SizedBox(height: 0.5 * PdfPageFormat.cm),
|
||||
buildAddress(
|
||||
"${detailsInfo?.shippingAddress?.address}, ${detailsInfo?.shippingAddress?.cityName}, ${detailsInfo?.shippingAddress?.stateName}, ${detailsInfo?.shippingAddress?.countryName}"),
|
||||
pw.SizedBox(height: 0.3 * PdfPageFormat.cm),
|
||||
buildPhoneNumber("${detailsInfo?.payment_method}"),
|
||||
pw.SizedBox(height: 0.5 * PdfPageFormat.cm),
|
||||
buildDottedDivider(),
|
||||
pw.SizedBox(height: 0.5 * PdfPageFormat.cm),
|
||||
buildCheckDate("${detailsInfo?.code}", "${detailsInfo?.date}"),
|
||||
pw.SizedBox(height: 0.3 * PdfPageFormat.cm),
|
||||
buildDottedDivider(),
|
||||
pw.SizedBox(height: 0.5 * PdfPageFormat.cm),
|
||||
buildItemsList(detailsInfo?.items ?? []),
|
||||
pw.SizedBox(height: 0.7 * PdfPageFormat.cm),
|
||||
buildDottedDivider(),
|
||||
pw.SizedBox(height: 0.5 * PdfPageFormat.cm),
|
||||
buildSummery(detailsInfo),
|
||||
buildDottedDivider(),
|
||||
pw.SizedBox(height: 1.2 * PdfPageFormat.cm),
|
||||
buildQrCode(qr)
|
||||
],
|
||||
//footer: (context) => buildFooter(invoice),
|
||||
));
|
||||
|
||||
return PdfApi.saveDocument(name: 'Check.pdf', pdf: pdf);
|
||||
}
|
||||
|
||||
static Widget buildLogo(Uint8List image) {
|
||||
return Row(mainAxisAlignment: pw.MainAxisAlignment.spaceBetween, children: [
|
||||
Text("Karvon market",
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
)),
|
||||
pw.Image(pw.MemoryImage(image), height: 40)
|
||||
]);
|
||||
}
|
||||
|
||||
static Widget buildDottedDivider() {
|
||||
return Row(
|
||||
children: List.generate(
|
||||
800 ~/ 10,
|
||||
(index) => index % 2 == 0
|
||||
? Expanded(
|
||||
child: pw.Container(height: 1, color: PdfColor(0, 0, 0)),
|
||||
)
|
||||
: Expanded(
|
||||
child: Container(height: 2, color: null),
|
||||
)));
|
||||
}
|
||||
|
||||
static Widget buildAddress(String address) {
|
||||
return pw.Text(address, style: TextStyle(fontSize: 14));
|
||||
}
|
||||
|
||||
static Widget buildPhoneNumber(String phoneNumber) {
|
||||
return pw.Text("To'lov turi: $phoneNumber", style: TextStyle(fontSize: 14));
|
||||
}
|
||||
|
||||
static Widget buildCheckDate(String checkNumber, String date) {
|
||||
return Column(
|
||||
mainAxisAlignment: pw.MainAxisAlignment.start,
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Check raqami: $checkNumber", style: TextStyle(fontSize: 14)),
|
||||
pw.SizedBox(height: 0.2 * PdfPageFormat.cm),
|
||||
Text("Chiqarilgan: $date", style: TextStyle(fontSize: 14))
|
||||
]);
|
||||
}
|
||||
|
||||
static Widget buildItemsList(List<Item> items) {
|
||||
return Column(
|
||||
mainAxisSize: pw.MainAxisSize.min,
|
||||
mainAxisAlignment: pw.MainAxisAlignment.start,
|
||||
children: List.generate(
|
||||
items.length,
|
||||
(index) => Column(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("${index + 1}.${items[index].product?.name}",
|
||||
style: TextStyle(
|
||||
fontSize: 16, fontWeight: pw.FontWeight.bold)),
|
||||
pw.SizedBox(height: 0.1 * PdfPageFormat.cm),
|
||||
Row(
|
||||
mainAxisAlignment: pw.MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Text("Narxi:",
|
||||
style: TextStyle(
|
||||
fontSize: 16, fontWeight: pw.FontWeight.normal)),
|
||||
Text(items[index].unitPrice,
|
||||
style: TextStyle(
|
||||
fontSize: 15, fontWeight: pw.FontWeight.normal)),
|
||||
Text("${items[index].qty} ta",
|
||||
style: TextStyle(
|
||||
fontSize: 15, fontWeight: pw.FontWeight.normal)),
|
||||
Text(items[index].totalPrice,
|
||||
style: TextStyle(
|
||||
fontSize: 17, fontWeight: pw.FontWeight.bold)),
|
||||
])
|
||||
]),
|
||||
));
|
||||
}
|
||||
|
||||
static Widget buildSummery(OrderDetailsInfo? info) {
|
||||
return Column(
|
||||
crossAxisAlignment: pw.CrossAxisAlignment.start,
|
||||
mainAxisAlignment: pw.MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Mahsulot narxi: ${info?.subTotalAmount}",
|
||||
style: TextStyle(fontSize: 15)),
|
||||
pw.SizedBox(height: 0.2 * PdfPageFormat.cm),
|
||||
Text("Yuk tashish narxi:${info?.totalShippingCost}",
|
||||
style: TextStyle(fontSize: 15)),
|
||||
pw.SizedBox(height: 0.2 * PdfPageFormat.cm),
|
||||
Text("Chegirmasi: ${info?.couponDiscountAmount}",
|
||||
style: TextStyle(fontSize: 15)),
|
||||
pw.SizedBox(height: 0.2 * PdfPageFormat.cm),
|
||||
Text("Jami narxi: ${info?.totalPrice}",
|
||||
style: TextStyle(fontSize: 15, fontWeight: pw.FontWeight.bold)),
|
||||
pw.SizedBox(height: 0.5 * PdfPageFormat.cm),
|
||||
]);
|
||||
}
|
||||
|
||||
static Widget buildQrCode(Uint8List qrcode) {
|
||||
return pw.Center(child: pw.Image(pw.MemoryImage(qrcode), height: 200));
|
||||
}
|
||||
}
|
||||
44
app_code/lib/screens/pages.dart
Normal file
44
app_code/lib/screens/pages.dart
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/presenters/page_presenter.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
class Pages extends StatefulWidget {
|
||||
final String slug;
|
||||
|
||||
const Pages({super.key, required this.slug});
|
||||
|
||||
@override
|
||||
State<Pages> createState() => _PagesState();
|
||||
}
|
||||
|
||||
class _PagesState extends State<Pages> {
|
||||
PagePresenter pagePresenter = PagePresenter();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
pagePresenter.initState(widget.slug);
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListenableBuilder(
|
||||
listenable: pagePresenter,
|
||||
builder: (context,child) {
|
||||
return Scaffold(
|
||||
appBar: CommonAppbar.show(title: pagePresenter.pageInfo?.title??"", context: context),
|
||||
body:Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: WebViewWidget(controller: pagePresenter.controller,),
|
||||
) ,
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
67
app_code/lib/screens/payment.dart
Normal file
67
app_code/lib/screens/payment.dart
Normal file
@@ -0,0 +1,67 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/configs/app_config.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/helpers/shared_value_helper.dart';
|
||||
import 'package:grostore/presenters/page_presenter.dart';
|
||||
import 'package:grostore/presenters/payment_presenter.dart';
|
||||
import 'package:grostore/screens/order/orders.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
class Payment extends StatefulWidget {
|
||||
final int code;
|
||||
final String payment_method;
|
||||
final String title;
|
||||
|
||||
const Payment(
|
||||
{super.key,
|
||||
required this.code,
|
||||
required this.payment_method,
|
||||
required this.title});
|
||||
|
||||
@override
|
||||
State<Payment> createState() => _PaymentState();
|
||||
}
|
||||
|
||||
class _PaymentState extends State<Payment> {
|
||||
PaymentPresenter paymentPresenter = PaymentPresenter();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
|
||||
// WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
// paymentPresenter.initState(widget.code, widget.payment_method);
|
||||
// });
|
||||
paymentPresenter.controller.loadRequest(
|
||||
Uri.parse(
|
||||
"${AppConfig.apiUrl}/order/online-payment?code=${widget.code}&payment_method=${widget.payment_method}"),
|
||||
headers: {"Authorization": "Bearer ${access_token.$}"});
|
||||
|
||||
paymentPresenter.controller.setNavigationDelegate(NavigationDelegate(
|
||||
onPageFinished: (page){
|
||||
if(page.contains('checkout-complete')||page.contains('success')||page.contains("cancel")||page.contains("callback")){
|
||||
MakeRoute.go(context, Orders(fromBottomBar: false,fromCheckOut: true,));
|
||||
}
|
||||
}
|
||||
));
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListenableBuilder(
|
||||
listenable: paymentPresenter,
|
||||
builder: (context, child) {
|
||||
return Scaffold(
|
||||
appBar: CommonAppbar.show(title: widget.title, context: context),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: WebViewWidget(
|
||||
controller: paymentPresenter.controller,
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
548
app_code/lib/screens/product_details.dart
Normal file
548
app_code/lib/screens/product_details.dart
Normal file
@@ -0,0 +1,548 @@
|
||||
import 'package:carousel_slider/carousel_slider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_classes/system_data.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/Image_view.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/product_card.dart';
|
||||
import 'package:grostore/custom_ui/shimmers.dart';
|
||||
import 'package:grostore/custom_ui/toast_ui.dart';
|
||||
import 'package:grostore/helpers/common_functions.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/presenters/cart_presenter.dart';
|
||||
import 'package:grostore/presenters/product_details_presenter.dart';
|
||||
import 'package:grostore/presenters/wishlist_presenter.dart';
|
||||
import 'package:grostore/screens/auth/login.dart';
|
||||
import 'package:grostore/screens/cart.dart';
|
||||
import 'package:badges/badges.dart' as badges;
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ProductDetails extends StatefulWidget {
|
||||
late String slug;
|
||||
|
||||
ProductDetails({Key? key, required this.slug}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<ProductDetails> createState() => _ProductDetailsState();
|
||||
}
|
||||
|
||||
class _ProductDetailsState extends State<ProductDetails> {
|
||||
// WishlistPresenter wishlistPresenter = WishlistPresenter();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
Provider.of<ProductDetailsPresenter>(context, listen: false)
|
||||
.setContext(context);
|
||||
Future.delayed(const Duration(seconds: 0)).then((value) {
|
||||
Provider.of<ProductDetailsPresenter>(context, listen: false)
|
||||
.iniState(widget.slug);
|
||||
});
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<ProductDetailsPresenter>(builder: (context, data, child) {
|
||||
return Scaffold(
|
||||
backgroundColor: ThemeConfig.xxlightGrey,
|
||||
appBar: CommonAppbar.show(
|
||||
title: data.productInfo != null ? data.productInfo!.name : "",
|
||||
context: context),
|
||||
body: RefreshIndicator(
|
||||
onRefresh: data.onRefresh,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
buildSliderSection(data),
|
||||
buildProductNameSection(context, data),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Text(
|
||||
AppLang.local(context).description,
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16
|
||||
),
|
||||
data.isProductInfoInitial
|
||||
? Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Text(
|
||||
data.productInfo?.shortDescription??"",
|
||||
style: StyleConfig.fs14fwNormal.copyWith(height: 1.8),
|
||||
),
|
||||
)
|
||||
: Shimmers(width: getWidth(context), height: 150),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
if (data.productInfo != null)
|
||||
Container(
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: ListView.separated(
|
||||
physics:const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (context, variationIndex) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
data.variations[variationIndex].name,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Wrap(
|
||||
spacing: 10,
|
||||
children: List.generate(
|
||||
data.variations[variationIndex].values
|
||||
.length, (valueIndex) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 5, vertical: 5),
|
||||
decoration: BoxDecorations.shadow(radius: 6)
|
||||
.copyWith(
|
||||
border: Border.all(
|
||||
color: data
|
||||
.variations[
|
||||
variationIndex]
|
||||
.values[valueIndex]
|
||||
.isChosen
|
||||
? ThemeConfig.accentColor
|
||||
: ThemeConfig.grey,
|
||||
width: 2)),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
data.onChangeVariation(
|
||||
variationIndex, valueIndex);
|
||||
},
|
||||
child: data.variations[variationIndex]
|
||||
.id ==
|
||||
2
|
||||
? Container(
|
||||
height: 40,
|
||||
width: 40,
|
||||
color: Color(int.parse(data
|
||||
.variations[variationIndex]
|
||||
.values[valueIndex]
|
||||
.code)),
|
||||
)
|
||||
: Text(
|
||||
data.variations[variationIndex]
|
||||
.values[valueIndex].name,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return const SizedBox(
|
||||
height: 16,
|
||||
);
|
||||
},
|
||||
itemCount: data.variations.length),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
buildPriceAndQuantitySection(context, data),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Text(
|
||||
AppLang.local(context).related_product_ucf,
|
||||
style: StyleConfig.fs16fwBold,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
buildRelatedProductSection(data),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
/*floatingActionButton: Container(
|
||||
//margin: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
width: getWidth(context),
|
||||
height: 70,
|
||||
//color: Colors.red,
|
||||
child:Button(
|
||||
shape: StyleConfig.buttonRadius(10),
|
||||
color: ThemeConfig.accentColor,
|
||||
minWidth: getWidth(context)-40,
|
||||
onPressed: (){},
|
||||
child: Text(AppLang.local(context).add_to_cart,style: StyleConfig.fs14cWhitefwNormal,),
|
||||
),
|
||||
),
|
||||
*/
|
||||
|
||||
// floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
|
||||
bottomNavigationBar: data.selectedVariation != null
|
||||
? SizedBox(
|
||||
width: getWidth(context),
|
||||
height: 50,
|
||||
child: Button(
|
||||
color: ThemeConfig.fontColor,
|
||||
minWidth: getWidth(context) - 40,
|
||||
onPressed: () {
|
||||
if (SystemData.isLogIn) {
|
||||
MakeRoute.go(context, const Cart());
|
||||
}else{
|
||||
MakeRoute.go(context, const Login());
|
||||
}
|
||||
},
|
||||
child: Consumer<CartPresenter>(
|
||||
builder: (context,data,child) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text("Total: ${showPrice(data.cartResponse.subTotal)}",style: StyleConfig.fs16cWhitefwBold,),
|
||||
Text(
|
||||
AppLang.local(context).go_to_cart,
|
||||
style: StyleConfig.fs16cWhitefwBold,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget relatedProductShimmer() {
|
||||
return GridView.builder(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
childAspectRatio: 0.8),
|
||||
itemCount: 10,
|
||||
itemBuilder: (context, index) {
|
||||
return Shimmers(
|
||||
width: 160,
|
||||
height: 186,
|
||||
radius: 8,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget buildRelatedProductSection(ProductDetailsPresenter data) {
|
||||
return data.isRelatedInitial
|
||||
? GridView.builder(
|
||||
padding: EdgeInsets.only(
|
||||
left: StyleConfig.padding,
|
||||
right: StyleConfig.padding,
|
||||
bottom: StyleConfig.padding,
|
||||
),
|
||||
shrinkWrap: true,
|
||||
physics:const NeverScrollableScrollPhysics(),
|
||||
gridDelegate:const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
childAspectRatio: 0.65
|
||||
),
|
||||
itemCount: data.relatedProducts.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ProductCard(
|
||||
product: data.relatedProducts[index],
|
||||
context: this.context,
|
||||
);
|
||||
})
|
||||
: relatedProductShimmer();
|
||||
}
|
||||
|
||||
Container buildPriceAndQuantitySection(
|
||||
BuildContext context, ProductDetailsPresenter data) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
height: 50,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
AppLang.local(context).price,
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 6,
|
||||
),
|
||||
data.isProductInfoInitial
|
||||
? Text(showPrice(data.selectedVariation!.price),
|
||||
style: StyleConfig.fs16cRedfwBold)
|
||||
: Shimmers(width: 100, height: 25),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
|
||||
|
||||
/// Add to cart or login route
|
||||
Consumer<WishlistPresenter>(
|
||||
// listenable: wishlistPresenter,
|
||||
builder: (context,wishlistPresenter,child) {
|
||||
return Button(
|
||||
onPressed: () {
|
||||
if(SystemData.isLogIn) {
|
||||
if(wishlistPresenter.isAddedWishlist) {
|
||||
wishlistPresenter.deleteWishlist(data.productInfo!.id,context);
|
||||
}else{
|
||||
wishlistPresenter.addWishlist(data.productInfo!.id, context);
|
||||
}
|
||||
|
||||
} else {
|
||||
MakeRoute.go(context,const Login());
|
||||
}
|
||||
},
|
||||
child: Icon(wishlistPresenter.isAddedWishlist? Icons.favorite:Icons.favorite_border,color: ThemeConfig.red,size: 35,));
|
||||
},
|
||||
),
|
||||
Button(
|
||||
minWidth:40,
|
||||
shape: StyleConfig.buttonRadius(6),
|
||||
color: ThemeConfig.red,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24,vertical: 12),
|
||||
onPressed: () {
|
||||
if (SystemData.isLogIn) {
|
||||
if (data.selectedVariation!.sock > 0) {
|
||||
Provider.of<CartPresenter>(context, listen: false)
|
||||
.addToCart(data.selectedVariation!.id,
|
||||
data.quantity, context);
|
||||
} else {
|
||||
ToastUi.show(context, "Stock out");
|
||||
}
|
||||
}else{
|
||||
MakeRoute.go(context, const Login());
|
||||
}
|
||||
|
||||
},
|
||||
child:Text(AppLang.local(context).add_to_cart,style: StyleConfig.fs12cWhitefwBold,)
|
||||
/* Icon(
|
||||
Icons.add_shopping_cart_outlined,
|
||||
color: ThemeConfig.white,
|
||||
size: 18,
|
||||
),*/
|
||||
),
|
||||
/*Button(
|
||||
|
||||
minWidth: 30,
|
||||
shape: CircleBorder(),
|
||||
color: ThemeConfig.fontColor,
|
||||
padding: EdgeInsets.all(8),
|
||||
onPressed: () {
|
||||
data.decrementQty();
|
||||
},
|
||||
child: Icon(
|
||||
Icons.remove,
|
||||
color: ThemeConfig.white,
|
||||
size: 18,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 5),
|
||||
constraints: BoxConstraints(minWidth: 40),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
"${data.quantity}",
|
||||
style: StyleConfig.fs14fwBold,
|
||||
)),
|
||||
Button(
|
||||
minWidth: 30,
|
||||
shape: CircleBorder(),
|
||||
color: ThemeConfig.accentColor,
|
||||
padding: EdgeInsets.all(8),
|
||||
onPressed: () {
|
||||
data.incrementQty();
|
||||
},
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: ThemeConfig.white,
|
||||
size: 18,
|
||||
),
|
||||
),*/
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container buildProductNameSection(
|
||||
BuildContext context, ProductDetailsPresenter data) {
|
||||
return Container(
|
||||
height: 60,
|
||||
width: getWidth(context),
|
||||
color: ThemeConfig.white,
|
||||
child: Container(
|
||||
alignment: Alignment.bottomLeft,
|
||||
padding: EdgeInsets.only(left: StyleConfig.padding),
|
||||
decoration: BoxDecorations.customRadius(
|
||||
radius: const BorderRadius.only(topLeft: Radius.circular(70)),
|
||||
color: ThemeConfig.xxlightGrey),
|
||||
child: data.isProductInfoInitial
|
||||
? Text(
|
||||
data.productInfo!.name,
|
||||
style: StyleConfig.fs20fwBold,
|
||||
)
|
||||
: Shimmers(width: 170, height: 30)),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildSliderSection(ProductDetailsPresenter data) {
|
||||
return Container(
|
||||
height: 200,
|
||||
decoration: BoxDecorations.customRadius(
|
||||
radius: const BorderRadius.only(bottomRight: Radius.circular(70))),
|
||||
child: Column(
|
||||
children: [
|
||||
Stack(
|
||||
children: [
|
||||
CarouselSlider(
|
||||
items: data.isProductInfoInitial
|
||||
? buildImages(data)
|
||||
: sliderShimmer(),
|
||||
options: CarouselOptions(
|
||||
aspectRatio: 1,
|
||||
height: 150,
|
||||
enlargeCenterPage: true,
|
||||
scrollDirection: Axis.horizontal,
|
||||
autoPlay: true,
|
||||
onPageChanged: (index, reason) {
|
||||
data.onChangeBannerIndex(index);
|
||||
},
|
||||
),
|
||||
),
|
||||
/*Positioned(
|
||||
right: 10,
|
||||
top: 10,
|
||||
child: Button(
|
||||
onPressed: () {
|
||||
MakeRoute.go(context, const Cart());
|
||||
},
|
||||
shape: StyleConfig.buttonRadius(30),
|
||||
padding: EdgeInsets.all(8),
|
||||
color:ThemeConfig.amber,
|
||||
minWidth: 35,
|
||||
child: badges.Badge(
|
||||
position: badges.BadgePosition.custom(end: 12, bottom: -15),
|
||||
badgeStyle: badges.BadgeStyle(
|
||||
shape: badges.BadgeShape.circle,
|
||||
badgeColor: ThemeConfig.red,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
borderSide: BorderSide(width: 1, color: ThemeConfig.white)
|
||||
//padding: EdgeInsets.all(5),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: Image.asset(
|
||||
getAssetIcon("cart.png"),
|
||||
color: ThemeConfig.white,
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
badgeContent: Consumer<CartPresenter>(
|
||||
builder: (context, cart, child) {
|
||||
return Text(
|
||||
"${cart.cartResponse.cartCount}",
|
||||
style: TextStyle(fontSize: 10, color: Colors.white),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
)*/
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
if (data.isProductInfoInitial)
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: data.productInfo!.galleryImages.map((page) {
|
||||
int index = data.productInfo!.galleryImages.indexOf(page);
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 100),
|
||||
width: data.currentSlider == index ? 20 : 8,
|
||||
height: 8,
|
||||
margin: const EdgeInsets.symmetric(horizontal: 4),
|
||||
decoration: BoxDecoration(
|
||||
// shape: BoxShape.circle,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: data.currentSlider == index
|
||||
? ThemeConfig.accentColor
|
||||
: ThemeConfig.accentColor.withOpacity(0.4),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget imageSample(String data) {
|
||||
// print(data);
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 5),
|
||||
child: ImageView(
|
||||
url: data,
|
||||
width: getWidth(context) - 40,
|
||||
height: 200,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
buildImages(ProductDetailsPresenter data) {
|
||||
List<Widget> sliders = [];
|
||||
data.productInfo!.galleryImages.forEach((image) {
|
||||
sliders.add(imageSample(image));
|
||||
});
|
||||
return sliders;
|
||||
}
|
||||
|
||||
List<Widget> sliderShimmer() {
|
||||
return [
|
||||
Shimmers(width: getWidth(context) - 40, height: 200),
|
||||
Shimmers(width: getWidth(context) - 40, height: 200),
|
||||
Shimmers(width: getWidth(context) - 40, height: 200),
|
||||
Shimmers(width: getWidth(context) - 40, height: 200),
|
||||
];
|
||||
}
|
||||
}
|
||||
300
app_code/lib/screens/profile.dart
Normal file
300
app_code/lib/screens/profile.dart
Normal file
@@ -0,0 +1,300 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_classes/system_data.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/Image_view.dart';
|
||||
import 'package:grostore/helpers/common_functions.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/presenters/auth/auth_presenter.dart';
|
||||
import 'package:grostore/screens/address/addresses.dart';
|
||||
import 'package:grostore/screens/auth/login.dart';
|
||||
import 'package:grostore/screens/coupons.dart';
|
||||
import 'package:grostore/screens/help_center.dart';
|
||||
import 'package:grostore/screens/main.dart';
|
||||
import 'package:grostore/screens/order/orders.dart';
|
||||
import 'package:grostore/screens/pages.dart';
|
||||
import 'package:grostore/screens/profile_edit.dart';
|
||||
import 'package:grostore/screens/refund.dart';
|
||||
import 'package:grostore/screens/setting.dart';
|
||||
import 'package:grostore/screens/stock_locations.dart';
|
||||
import 'package:grostore/screens/track_order.dart';
|
||||
import 'package:grostore/screens/wallet.dart';
|
||||
import 'package:grostore/screens/wishlist.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:route_transitions/route_transitions.dart';
|
||||
import 'package:toast/toast.dart';
|
||||
|
||||
class Account extends StatefulWidget {
|
||||
const Account({super.key});
|
||||
|
||||
@override
|
||||
_AccountState createState() => _AccountState();
|
||||
}
|
||||
|
||||
class _AccountState extends State<Account> with TickerProviderStateMixin {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: ThemeConfig.secondaryColor,
|
||||
// appBar: AppBar(
|
||||
// backgroundColor: ThemeConfig.accentColor,
|
||||
// elevation: 0,
|
||||
// leading: SizedBox.shrink(),
|
||||
// actions: [
|
||||
// buildBackButtonContainer(context),
|
||||
// ],
|
||||
// ),
|
||||
// PreferredSize(preferredSize: Size(getWidth(context),40),
|
||||
// child:
|
||||
// ),
|
||||
body: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 15,),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Container(
|
||||
height: 80,
|
||||
width: getWidth(context),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding, vertical: 10),
|
||||
child:SystemData.isLogIn ?
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
child: ImageView(url: SystemData.userInfo.avatar,fit: BoxFit.cover, width: 50, height: 50,radius:50),
|
||||
),
|
||||
const SizedBox(width: 14,),
|
||||
|
||||
/// Name and Phone number.
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
|
||||
Text(SystemData.userInfo.name??"JAhongir",style: StyleConfig.fs16cWhitefwBold,),
|
||||
const SizedBox(height: 10,),
|
||||
Text(SystemData.userInfo.phone,style: StyleConfig.fs12cWhitefwBold,),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
Button(
|
||||
onPressed: (){
|
||||
MakeRoute.go(context, ProfileEdit());
|
||||
},
|
||||
minWidth: 60,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10,vertical: 10),
|
||||
shape: StyleConfig.buttonRadius(8).copyWith(
|
||||
side: const BorderSide(width: 1, color: ThemeConfig.white))
|
||||
// RoundedRectangleBorder(borderRadius: BorderRadius.c),
|
||||
,
|
||||
child: Text(AppLang.local(context).edit_profile_ucf, style: StyleConfig.fs12cWhitefwBold,),
|
||||
)
|
||||
],
|
||||
)
|
||||
:
|
||||
/// ELSE Condition
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
height:50,width: 50,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(45),
|
||||
color: ThemeConfig.extraDarkGrey
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14,vertical: 14),
|
||||
child: Image.asset(getAssetIcon("profile.png"),color: ThemeConfig.lightGrey,),
|
||||
),
|
||||
const SizedBox(width: 10,),
|
||||
Button(minWidth: 20,
|
||||
// shape: StyleConfig.buttonRadius(10).copyWith(side: BorderSide(width: 1,color: ThemeConfig.white))
|
||||
// RoundedRectangleBorder(borderRadius: BorderRadius.c),
|
||||
onPressed:(){
|
||||
MakeRoute.go(context, const Login());
|
||||
},
|
||||
child: Text("Login", style: StyleConfig.fs16fwBold.copyWith(
|
||||
decoration: TextDecoration.underline),),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// SizedBox(height: 20,),
|
||||
Expanded(
|
||||
flex: 6,
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(left: StyleConfig.padding,
|
||||
right: StyleConfig.padding,
|
||||
top: 40),
|
||||
//height: getHeight(context)-220,
|
||||
decoration: BoxDecorations.customRadius(radius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(10), topRight: Radius.circular(10)),
|
||||
color: ThemeConfig.white),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
|
||||
optionModel(AppLang
|
||||
.local(context)
|
||||
.pick_a_location, getAssetIcon("address.png"), StockLocations()),
|
||||
if(SystemData.isLogIn)
|
||||
Column(
|
||||
children: [
|
||||
/// #Voucherva Cupon
|
||||
// optionModel(AppLang
|
||||
// .local(context)
|
||||
// .voucher_n_offers_ucf, getAssetIcon("coupons.png"),
|
||||
// const Coupons()),
|
||||
optionModel(AppLang
|
||||
.local(context)
|
||||
.favorite, getAssetIcon("favorite.png"),
|
||||
const Wishlist()),
|
||||
optionModel(AppLang
|
||||
.local(context)
|
||||
.order_n_recording_ucf, getAssetIcon("orders.png"),
|
||||
Orders(fromBottomBar: false,)),
|
||||
// optionModel(AppLang
|
||||
// .local(context)
|
||||
// .my_profile_ucf, getAssetIcon("profile.png"),
|
||||
// Container()),
|
||||
optionModel(AppLang.local(context).address, getAssetIcon("address.png"),const Addresses()),
|
||||
// optionModel(AppLang
|
||||
// .local(context)
|
||||
// .notification, getAssetIcon("notification.png"),
|
||||
// Container()),
|
||||
// optionModel(AppLang
|
||||
// .local(context)
|
||||
// .security, getAssetIcon("security.png"),
|
||||
// Container()),
|
||||
optionModel(AppLang
|
||||
.local(context)
|
||||
.track_my_order_ucf, getAssetIcon("track.png"),
|
||||
const TrackOrder()),
|
||||
// optionModel(AppLang
|
||||
// .local(context)
|
||||
// .wallet_history_ucf, getAssetIcon("wallet.png"),
|
||||
// const Wallet()),
|
||||
// optionModel(AppLang
|
||||
// .local(context)
|
||||
// .refund_history_ucf, getAssetIcon("refund.png"),
|
||||
// const Refund()),
|
||||
|
||||
],
|
||||
),
|
||||
|
||||
optionModel(AppLang
|
||||
.local(context)
|
||||
.help_center_ucf, getAssetIcon("help_center.png"),
|
||||
const HelpCenter()),
|
||||
optionModel(AppLang
|
||||
.local(context)
|
||||
.settings, getAssetIcon("setting.png"),const Setting()),
|
||||
optionModel(AppLang
|
||||
.local(context)
|
||||
.terms_n_conditions_ucf,
|
||||
getAssetIcon("terms_condition.png"), const Pages(slug: "terms-conditions")),
|
||||
|
||||
if(SystemData.isLogIn)
|
||||
logoutModel(AppLang
|
||||
.local(context)
|
||||
.log_out_ucf, getAssetIcon("logout.png"),(){
|
||||
Provider.of<AuthPresenter>(context,listen: false).logout(context);
|
||||
MakeRoute.goAndRemoveAll(context, const Main());
|
||||
}),
|
||||
|
||||
if(!SystemData.isLogIn)
|
||||
optionModel(AppLang
|
||||
.local(context)
|
||||
.login, getAssetIcon("login.png"), const Login()),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Container buildBackButtonContainer(BuildContext context) {
|
||||
return Container(
|
||||
height: 47,
|
||||
alignment: Alignment.topRight,
|
||||
child: SizedBox(
|
||||
width: 47,
|
||||
child: Button(
|
||||
minWidth: 0,
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: () {
|
||||
pop(context);
|
||||
},
|
||||
child: const Icon(
|
||||
Icons.close,
|
||||
size: 30,
|
||||
color: ThemeConfig.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Widget optionModel(String title, String logo, Widget route) {
|
||||
return Container(
|
||||
margin: EdgeInsets.only(bottom: StyleConfig.xsSectionSpacer),
|
||||
height: 50,
|
||||
child: Button(
|
||||
minWidth: 50,
|
||||
onPressed: () {
|
||||
MakeRoute.go(context, route);
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Image.asset(logo, width: 25, height: 25, color: ThemeConfig.extraDarkGrey),
|
||||
const SizedBox(width: 26,),
|
||||
Text(title, style: StyleConfig.fs14fwNormal,),
|
||||
const Spacer(),
|
||||
// Image.asset(getAssetIcon("next.png"), width: 14,
|
||||
// height: 14,
|
||||
// color: ThemeConfig.fontColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget logoutModel(String title, String logo, dynamic onPress) {
|
||||
return Container(
|
||||
margin: EdgeInsets.only(bottom: StyleConfig.padding),
|
||||
height: 40,
|
||||
child: Button(
|
||||
minWidth: 40,
|
||||
onPressed:onPress,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Image.asset(logo, width: 18, height: 18, color: ThemeConfig.extraDarkGrey),
|
||||
const SizedBox(width: 26,),
|
||||
Text(title, style: StyleConfig.fs14fwNormal,),
|
||||
const Spacer(),
|
||||
// Image.asset(getAssetIcon("next.png"), width: 14,
|
||||
// height: 14,
|
||||
// color: ThemeConfig.fontColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
465
app_code/lib/screens/profile_edit.dart
Normal file
465
app_code/lib/screens/profile_edit.dart
Normal file
@@ -0,0 +1,465 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_classes/system_data.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/Image_view.dart';
|
||||
import 'package:grostore/custom_ui/input_decorations.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/presenters/user_presenter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ProfileEdit extends StatefulWidget {
|
||||
@override
|
||||
_ProfileEditState createState() => _ProfileEditState();
|
||||
}
|
||||
|
||||
class _ProfileEditState extends State<ProfileEdit> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: buildAppBar(context),
|
||||
body: Consumer<UserPresenter>(builder: (context, data, child) {
|
||||
return buildBody(data);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
AppBar buildAppBar(BuildContext context) {
|
||||
return AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
centerTitle: false,
|
||||
leading: Builder(
|
||||
builder: (context) => IconButton(
|
||||
icon: Icon(Icons.arrow_back, color: ThemeConfig.darkGrey),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
AppLang.local(context).edit_profile_ucf,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: ThemeConfig.fontColor,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
elevation: 0.0,
|
||||
titleSpacing: 0,
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildBody(UserPresenter data) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: data.refresh,
|
||||
color: ThemeConfig.accentColor,
|
||||
backgroundColor: Colors.white,
|
||||
//onRefresh: _onPageRefresh,
|
||||
displacement: 10,
|
||||
child: CustomScrollView(
|
||||
physics: const BouncingScrollPhysics(
|
||||
parent: AlwaysScrollableScrollPhysics()),
|
||||
slivers: [
|
||||
SliverList(
|
||||
delegate: SliverChildListDelegate([
|
||||
buildTopSection(data),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.0),
|
||||
),
|
||||
buildProfileForm(data)
|
||||
]),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
buildTopSection(UserPresenter data) {
|
||||
log("Data.file is not empty${data.file?.path ?? "NO data"}");
|
||||
log("User avatar ${SystemData.userInfo.avatar}");
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16.0, bottom: 8.0),
|
||||
child: Stack(
|
||||
children: [
|
||||
data.file != null
|
||||
? ImageView.roundFileImage(
|
||||
file: File(data.file!.path),
|
||||
height: 120.0,
|
||||
width: 120.0,
|
||||
context: context,
|
||||
radius: 60)
|
||||
: ImageView.round(
|
||||
url: SystemData.userInfo.avatar,
|
||||
height: 120.0,
|
||||
width: 120.0,
|
||||
context: context,
|
||||
radius: 60),
|
||||
/*
|
||||
Container(
|
||||
width: 120,
|
||||
height: 120,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(100),
|
||||
border: Border.all(
|
||||
color: Color.fromRGBO(112, 112, 112, .3), width: 2),
|
||||
//shape: BoxShape.rectangle,
|
||||
),
|
||||
child: ClipRRect(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
borderRadius: BorderRadius.all(Radius.circular(100.0)),
|
||||
child: FadeInImage.assetNetwork(
|
||||
placeholder: 'assets/placeholder.png',
|
||||
image: "${avatar_original.$}",
|
||||
fit: BoxFit.fill,
|
||||
)),
|
||||
),*/
|
||||
Positioned(
|
||||
right: 8,
|
||||
bottom: 8,
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: Button(
|
||||
padding: const EdgeInsets.all(0),
|
||||
shape: CircleBorder(
|
||||
side: BorderSide(color: ThemeConfig.lightGrey),
|
||||
),
|
||||
color: ThemeConfig.lightGrey,
|
||||
onPressed: () {
|
||||
data.chooseAndUploadImage(context);
|
||||
},
|
||||
child: Icon(
|
||||
Icons.edit,
|
||||
color: ThemeConfig.fontColor,
|
||||
size: 14,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
buildProfileForm(UserPresenter data) {
|
||||
return Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(top: 8.0, bottom: 8.0, left: 16.0, right: 16.0),
|
||||
child: Container(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
buildBasicInfo(data),
|
||||
buildChangePassword(data),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Column buildChangePassword(UserPresenter data) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 30.0, bottom: 10),
|
||||
child: Text(
|
||||
AppLang.local(context).password_change_ucf,
|
||||
style: StyleConfig.fs14fwBold,
|
||||
textHeightBehavior:
|
||||
const TextHeightBehavior(applyHeightToFirstAscent: false),
|
||||
textAlign: TextAlign.center,
|
||||
softWrap: false,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).password,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: ThemeConfig.fontColor,
|
||||
fontWeight: FontWeight.normal),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecorations.basic(),
|
||||
height: 36,
|
||||
child: TextField(
|
||||
style: const TextStyle(fontSize: 12),
|
||||
controller: data.passwordController,
|
||||
autofocus: false,
|
||||
obscureText: !data.showPassword,
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
decoration:
|
||||
InputDecorations.basic(hint_text: "• • • • • • • •")
|
||||
.copyWith(
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: ThemeConfig.accentColor),
|
||||
),
|
||||
suffixIcon: InkWell(
|
||||
onTap: () {
|
||||
data.passwordShowHide();
|
||||
},
|
||||
child: Icon(
|
||||
data.showPassword
|
||||
? Icons.visibility_outlined
|
||||
: Icons.visibility_off_outlined,
|
||||
color: ThemeConfig.red,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).password_must_be_at_last_6_digit,
|
||||
style: TextStyle(
|
||||
color: ThemeConfig.red, fontStyle: FontStyle.italic),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).confirm_password_ucf,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: ThemeConfig.fontColor,
|
||||
fontWeight: FontWeight.normal),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Container(
|
||||
decoration: BoxDecorations.basic(),
|
||||
height: 36,
|
||||
child: TextField(
|
||||
controller: data.passwordConfirmController,
|
||||
autofocus: false,
|
||||
obscureText: !data.showConfirmPassword,
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
decoration:
|
||||
InputDecorations.basic(hint_text: "• • • • • • • •").copyWith(
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: ThemeConfig.accentColor),
|
||||
),
|
||||
suffixIcon: InkWell(
|
||||
onTap: () {
|
||||
data.conPasswordShowHide();
|
||||
},
|
||||
child: Icon(
|
||||
data.showConfirmPassword
|
||||
? Icons.visibility_outlined
|
||||
: Icons.visibility_off_outlined,
|
||||
color: ThemeConfig.red,
|
||||
),
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
width: 150,
|
||||
child: Button(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
minWidth: MediaQuery.of(context).size.width,
|
||||
color: ThemeConfig.red,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0))),
|
||||
child: Text(
|
||||
AppLang.local(context).update_password_ucf,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
onPressed: () {
|
||||
data.onPressUpdatePassword(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Column buildBasicInfo(UserPresenter data) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 18.0),
|
||||
child: Text(
|
||||
AppLang.local(context).basic_info,
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).name,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: ThemeConfig.fontColor,
|
||||
fontWeight: FontWeight.normal),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 14.0),
|
||||
child: Container(
|
||||
decoration: BoxDecorations.basic(),
|
||||
height: 36,
|
||||
child: TextField(
|
||||
controller: data.nameController,
|
||||
autofocus: false,
|
||||
style: TextStyle(color: ThemeConfig.fontColor, fontSize: 12),
|
||||
decoration:
|
||||
InputDecorations.basic(hint_text: "John Doe").copyWith(
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: ThemeConfig.accentColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).phone,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: ThemeConfig.fontColor,
|
||||
fontWeight: FontWeight.normal),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 14.0),
|
||||
child: Container(
|
||||
decoration: BoxDecorations.basic(),
|
||||
height: 36,
|
||||
child: TextField(
|
||||
controller: data.phoneController,
|
||||
autofocus: false,
|
||||
keyboardType: TextInputType.phone,
|
||||
style: TextStyle(color: ThemeConfig.fontColor, fontSize: 12),
|
||||
decoration:
|
||||
InputDecorations.basic(hint_text: "+01xxxxxxxxxx").copyWith(
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: ThemeConfig.red),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: true,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Text(
|
||||
AppLang.local(context).name,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: ThemeConfig.fontColor,
|
||||
fontWeight: FontWeight.normal),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 14.0),
|
||||
child: Container(
|
||||
decoration: BoxDecorations.basic(),
|
||||
height: 36,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
data.emailController.text,
|
||||
style: TextStyle(fontSize: 12, color: ThemeConfig.grey),
|
||||
)
|
||||
/*TextField(
|
||||
style: TextStyle(color:ThemeConfig.grey_153,fontSize: 12),
|
||||
enabled: false,
|
||||
enableIMEPersonalizedLearning: true,
|
||||
controller: _emailController,
|
||||
autofocus: false,
|
||||
decoration: InputDecorations.buildInputDecoration_1(
|
||||
|
||||
hint_text: "jhon@example.com").copyWith(
|
||||
//enabled: false,
|
||||
labelStyle: TextStyle(color: ThemeConfig.grey_153),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
|
||||
),),
|
||||
),*/
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
width: getWidth(context) / 2.5,
|
||||
child: Button(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
minWidth: MediaQuery.of(context).size.width,
|
||||
color: ThemeConfig.red,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0))),
|
||||
child: Text(
|
||||
AppLang.local(context).update_profile_ucf,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
onPressed: () {
|
||||
data.onPressUpdate(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
93
app_code/lib/screens/refund.dart
Normal file
93
app_code/lib/screens/refund.dart
Normal file
@@ -0,0 +1,93 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/no_data.dart';
|
||||
import 'package:grostore/custom_ui/shimmers.dart';
|
||||
import 'package:grostore/helpers/common_functions.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/presenters/refund_presenter.dart';
|
||||
import 'package:grostore/presenters/wallet_presenter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
||||
class Refund extends StatefulWidget {
|
||||
const Refund({super.key});
|
||||
|
||||
@override
|
||||
State<Refund> createState() => _RefundState();
|
||||
}
|
||||
|
||||
class _RefundState extends State<Refund> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
print("object11");
|
||||
Provider.of<RefundPresenter>(context,listen: false).initState();
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CommonAppbar.show(title: AppLang.local(context).refund_history_ucf, context: context),
|
||||
body: Consumer<RefundPresenter>(
|
||||
builder: (context,data,child) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: data.onRefresh,
|
||||
child: SingleChildScrollView(
|
||||
physics: AlwaysScrollableScrollPhysics(),
|
||||
child: data.isRefundInit && data.refundHistory.isEmpty?const NoData():data.isRefundInit?ListView.separated(
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
itemBuilder: (context,index)=>Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 14,vertical: 10),
|
||||
decoration: BoxDecorations.shadow(radius: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: getWidth(context)*0.4,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(data.refundHistory[index].date),
|
||||
SizedBox(height: 8,),
|
||||
Text(data.refundHistory[index].orderCode),
|
||||
SizedBox(height: 8,),
|
||||
Text(data.refundHistory[index].productName),
|
||||
],
|
||||
),
|
||||
),
|
||||
Spacer(),
|
||||
SizedBox(
|
||||
width: getWidth(context)*0.4,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text(data.refundHistory[index].status.toUpperCase(),style: StyleConfig.fs14cSecondryfwBold.copyWith(color: data.refundHistory[index].status=="refunded"?ThemeConfig.fontColor:null),),
|
||||
SizedBox(height: 8,),
|
||||
Text(showPrice(data.refundHistory[index].amount),style: StyleConfig.fs14fwNormal),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
separatorBuilder: (context,index)=>SizedBox(height: StyleConfig.padding,), itemCount: data.refundHistory.length):
|
||||
Padding(padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Shimmers.list(15, getWidth(context), 55.0),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
154
app_code/lib/screens/setting.dart
Normal file
154
app_code/lib/screens/setting.dart
Normal file
@@ -0,0 +1,154 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/models/currency_response.dart';
|
||||
import 'package:grostore/models/language_response.dart';
|
||||
import 'package:grostore/presenters/setting_presenter.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../presenters/bloc/lang/lang_bloc.dart';
|
||||
|
||||
class Setting extends StatefulWidget {
|
||||
const Setting({super.key});
|
||||
|
||||
@override
|
||||
State<Setting> createState() => _SettingState();
|
||||
}
|
||||
|
||||
class _SettingState extends State<Setting> {
|
||||
@override
|
||||
void initState() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
Provider.of<SettingPresenter>(context, listen: false).initState();
|
||||
});
|
||||
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
}
|
||||
|
||||
String datas = "uz";
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: ThemeConfig.xxlightGrey,
|
||||
appBar: CommonAppbar.show(
|
||||
title: AppLang.local(context).settings, context: context),
|
||||
body: Consumer<SettingPresenter>(builder: (context, data, child) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: StyleConfig.padding,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
/* DropdownButton<LanguageInfo>(
|
||||
value: data.selectedLanguage,
|
||||
icon: const Icon(Icons.arrow_downward),
|
||||
elevation: 16,
|
||||
style: const TextStyle(color: Colors.deepPurple),
|
||||
underline: Container(
|
||||
height: 2,
|
||||
color: Colors.deepPurpleAccent,
|
||||
),
|
||||
onChanged: (LanguageInfo? value) {
|
||||
// This is called when the user selects an item.
|
||||
if(value!=null) {
|
||||
data.setLocale(value);
|
||||
}
|
||||
},
|
||||
items: data.languageList.map<DropdownMenuItem<LanguageInfo>>((LanguageInfo value) {
|
||||
return DropdownMenuItem<LanguageInfo>(
|
||||
value: value,
|
||||
child: Text(value.name),
|
||||
);
|
||||
}).toList(),
|
||||
),*/
|
||||
Text(
|
||||
AppLang.local(context).currency,
|
||||
style: StyleConfig.fs14fwBold,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 14,
|
||||
),
|
||||
Container(
|
||||
width: getWidth(context),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||
decoration: BoxDecorations.customRadius(
|
||||
radius: BorderRadius.circular(5))
|
||||
.copyWith(
|
||||
color: ThemeConfig.white,
|
||||
),
|
||||
child: DropdownButton<CurrencyInfo>(
|
||||
isExpanded: true,
|
||||
value: data.selectedCurrency,
|
||||
elevation: 16,
|
||||
underline: const SizedBox.shrink(),
|
||||
style: const TextStyle(color: Colors.deepPurple),
|
||||
onChanged: (CurrencyInfo? value) {
|
||||
// This is called when the user selects an item.
|
||||
if (value != null) {
|
||||
data.onChange(value);
|
||||
}
|
||||
},
|
||||
items: data.currencyList.map<DropdownMenuItem<CurrencyInfo>>(
|
||||
(CurrencyInfo value) {
|
||||
return DropdownMenuItem<CurrencyInfo>(
|
||||
value: value,
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
value.name,
|
||||
style: StyleConfig.fs14fwNormal,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10,),
|
||||
// BlocBuilder<LangBloc, LangState>(
|
||||
// builder: (context, state) {
|
||||
// return Container(
|
||||
// height: 100,
|
||||
// margin: const EdgeInsets.only(top: 20),
|
||||
// width: getWidth(context),
|
||||
// padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||
// decoration: BoxDecoration(
|
||||
// color: Colors.white,
|
||||
// borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
// ),
|
||||
// child: DropdownButton<String>(
|
||||
// value: datas ?? "uz",
|
||||
// icon: Icon(Icons.arrow_drop_down_rounded),
|
||||
// style: const TextStyle(color: Colors.deepPurple),
|
||||
// onChanged: (String? value) {
|
||||
// datas = value ?? "uz";
|
||||
// context
|
||||
// .read<LangBloc>()
|
||||
// .add(LanguageEvent(locale: Locale(datas)));
|
||||
// },
|
||||
// items: const [
|
||||
// DropdownMenuItem<String>(value: "uz", child: Text("Uz")),
|
||||
// DropdownMenuItem<String>(value: 'en', child: Text("En")),
|
||||
// DropdownMenuItem<String>(value: "ru", child: Text("Ru")),
|
||||
// ]));
|
||||
// },
|
||||
// )
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
109
app_code/lib/screens/splash.dart
Normal file
109
app_code/lib/screens/splash.dart
Normal file
@@ -0,0 +1,109 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/apis/auth_api.dart';
|
||||
import 'package:grostore/apis/setting_api.dart';
|
||||
import 'package:grostore/configs/app_config.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_classes/system_data.dart';
|
||||
import 'package:grostore/helpers/common_functions.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/route.dart';
|
||||
import 'package:grostore/helpers/shared_value_helper.dart';
|
||||
import 'package:grostore/presenters/auth/auth_presenter.dart';
|
||||
import 'package:grostore/presenters/cart_presenter.dart';
|
||||
import 'package:grostore/presenters/setting_presenter.dart';
|
||||
import 'package:grostore/screens/landing_pages/landing_page.dart';
|
||||
import 'package:grostore/screens/main.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class Splash extends StatefulWidget {
|
||||
const Splash({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Splash> createState() => _SplashState();
|
||||
}
|
||||
|
||||
class _SplashState extends State<Splash> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
getSettings();
|
||||
|
||||
system_currency.load().then((value){
|
||||
|
||||
Provider.of<SettingPresenter>(context, listen: false).initState();
|
||||
});
|
||||
|
||||
Future.delayed(const Duration(seconds: 2)).then((value) {
|
||||
access_token.load();
|
||||
show_landing_page.load().then((value) {
|
||||
checkLogin();
|
||||
});
|
||||
//Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (context)=>Main()), (route) => false);
|
||||
});
|
||||
}
|
||||
|
||||
checkLogin() async {
|
||||
await show_landing_page.load();
|
||||
var res = await AuthApi.tokenCheck(context);
|
||||
print("-----}${res.result}{----");
|
||||
if (res.result) {
|
||||
SystemData.isLogIn = true;
|
||||
SystemData.userInfo = res.user;
|
||||
await app_language.load();
|
||||
await stock_location_id.load();
|
||||
Provider.of<CartPresenter>(context, listen: false).fetchCart();
|
||||
}
|
||||
if (show_landing_page.$) {
|
||||
show_landing_page.$=false;
|
||||
show_landing_page.save();
|
||||
MakeRoute.goAndRemoveAll(context, const LandingPage());
|
||||
} else {
|
||||
Provider.of<AuthPresenter>(context,listen: false).tokenCheck(context);
|
||||
|
||||
MakeRoute.goAndRemoveAll(context, const Main());
|
||||
}
|
||||
}
|
||||
|
||||
getSettings() async {
|
||||
var res = await SettingApi.getSettings();
|
||||
SystemData.settings = res.object;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
width: getWidth(context),
|
||||
height: getHeight(context),
|
||||
decoration: BoxDecoration(
|
||||
color: ThemeConfig.splashBackground,
|
||||
image: DecorationImage(
|
||||
image: AssetImage(getAssetImage("splash_background.png")))),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
getAssetLogo("logo4x4.png"),
|
||||
width: 250,
|
||||
height: 300,
|
||||
),
|
||||
// const SizedBox(
|
||||
// height: 10,
|
||||
// ),
|
||||
// Text(
|
||||
// AppConfig.appName,
|
||||
// style: StyleConfig.fs30fwEBold(),
|
||||
// textAlign: TextAlign.center,
|
||||
// ),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
const CircularProgressIndicator()
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
174
app_code/lib/screens/stock_locations.dart
Normal file
174
app_code/lib/screens/stock_locations.dart
Normal file
@@ -0,0 +1,174 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/Boxdecorations.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/shimmers.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/helpers/shared_value_helper.dart';
|
||||
import 'package:grostore/presenters/stock_locations_presenter.dart';
|
||||
import 'package:toast/toast.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class StockLocations extends StatefulWidget {
|
||||
StockLocations({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_StockLocationsState createState() => _StockLocationsState();
|
||||
}
|
||||
|
||||
class _StockLocationsState extends State<StockLocations> {
|
||||
|
||||
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
Provider.of<StockLocationsPresenter>(context,listen: false).setContext(context);
|
||||
}
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
|
||||
super.didChangeDependencies();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: buildAppBar(context),
|
||||
body: Consumer<StockLocationsPresenter>(
|
||||
builder: (context,data,child) {
|
||||
return RefreshIndicator(
|
||||
//color: MyTheme.accent_color,
|
||||
backgroundColor: Colors.white,
|
||||
onRefresh: data.onRefresh,
|
||||
displacement: 0,
|
||||
child: CustomScrollView(
|
||||
physics: const BouncingScrollPhysics(
|
||||
parent: AlwaysScrollableScrollPhysics()),
|
||||
slivers: [
|
||||
SliverList(
|
||||
delegate: SliverChildListDelegate([
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(18.0),
|
||||
child: buildLanguageMethodList(data),
|
||||
),
|
||||
]),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
AppBar buildAppBar(BuildContext context) {
|
||||
return CommonAppbar.show(title: AppLang.local(context).locations, context: context);
|
||||
}
|
||||
|
||||
buildLanguageMethodList(StockLocationsPresenter data) {
|
||||
if (!data.isLocationInit && data.locations.isEmpty) {
|
||||
return SingleChildScrollView(
|
||||
child: Shimmers.list(10, getWidth(context), 20));
|
||||
} else if (data.locations.isNotEmpty) {
|
||||
return SingleChildScrollView(
|
||||
child: ListView.separated(
|
||||
separatorBuilder: (context, index) {
|
||||
return const SizedBox(
|
||||
height: 14,
|
||||
);
|
||||
},
|
||||
itemCount: data.locations.length,
|
||||
scrollDirection: Axis.vertical,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (context, index) {
|
||||
return buildCard(index,data);
|
||||
},
|
||||
),
|
||||
);
|
||||
} else if (data.isLocationInit && data.locations.isEmpty) {
|
||||
return Container(
|
||||
height: 100,
|
||||
child: Center(
|
||||
child: Text(
|
||||
AppLang.local(context).data_is_not_available,
|
||||
style: TextStyle(color: ThemeConfig.fontColor),
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
GestureDetector buildCard(index,StockLocationsPresenter data) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
print(data.locations[index].id);
|
||||
data.onchange(data.locations[index].id);
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
decoration: BoxDecorations.basic().copyWith(
|
||||
border: Border.all(
|
||||
color: stock_location_id.$ == data.locations[index].id.toString()
|
||||
? ThemeConfig.accentColor: ThemeConfig.lightGrey,
|
||||
width: stock_location_id.$ == data.locations[index].id.toString() ? 1.0 : 0.0)),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 150,
|
||||
height: 50,
|
||||
alignment: Alignment.center,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Text(
|
||||
"${data.locations[index].name}",
|
||||
textAlign: TextAlign.left,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: ThemeConfig.fontColor,
|
||||
fontSize: 14,
|
||||
height: 1.6,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
// Positioned(
|
||||
// left: 16,
|
||||
// top: 16,
|
||||
// child: buildCheckContainer(data.selectedIndex == index),
|
||||
// )
|
||||
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Container buildCheckContainer(bool check) {
|
||||
// return check
|
||||
// ? Container(
|
||||
// height: 16,
|
||||
// width: 16,
|
||||
// decoration: BoxDecoration(
|
||||
// borderRadius: BorderRadius.circular(16.0), color: Colors.green),
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(3),
|
||||
// child: Icon(Icons.check, color: Colors.white, size: 10),
|
||||
// ),
|
||||
// )
|
||||
// : Container();
|
||||
// }
|
||||
|
||||
}
|
||||
186
app_code/lib/screens/track_order.dart
Normal file
186
app_code/lib/screens/track_order.dart
Normal file
@@ -0,0 +1,186 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_classes/system_data.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/input_decorations.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/presenters/order_presenter.dart';
|
||||
|
||||
class TrackOrder extends StatefulWidget {
|
||||
const TrackOrder({super.key});
|
||||
|
||||
@override
|
||||
State<TrackOrder> createState() => _TrackOrderState();
|
||||
}
|
||||
|
||||
class _TrackOrderState extends State<TrackOrder> {
|
||||
OrderPresenter orderPresenter = OrderPresenter();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CommonAppbar.show(
|
||||
title: AppLang.local(context).track_my_order_ucf, context: context),
|
||||
body: ListenableBuilder(
|
||||
listenable: orderPresenter,
|
||||
builder: (context, child) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecorations.shadow(),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: ThemeConfig.grey,
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(6),
|
||||
bottomLeft: Radius.circular(6),
|
||||
)),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10, vertical: 10),
|
||||
child:
|
||||
Text(SystemData.settings?.orderCodePrefix ?? ""),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6),
|
||||
width: getWidth(context) * 0.5,
|
||||
child: TextField(
|
||||
onSubmitted: (text) {
|
||||
orderPresenter.trackOrder(text.trim(), context);
|
||||
},
|
||||
controller: orderPresenter.trackOrderController,
|
||||
decoration: const InputDecoration.collapsed(
|
||||
hintText: "123456")),
|
||||
),
|
||||
Spacer(),
|
||||
SizedBox(
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: Button(
|
||||
onPressed: () {
|
||||
orderPresenter.trackOrder(
|
||||
orderPresenter.trackOrderController.text
|
||||
.trim(),
|
||||
context);
|
||||
},
|
||||
child: Icon(Icons.search))),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 24,),
|
||||
|
||||
if(orderPresenter.trackInfo!=null)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(AppLang.local(context).order_tracking,style: StyleConfig.fs16fwBold,),
|
||||
SizedBox(height: 14,),
|
||||
Container(
|
||||
decoration: BoxDecorations.shadow(radius: 5)
|
||||
.copyWith(border: Border.all(color: ThemeConfig.grey)),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0,vertical: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: getWidth(context) * 0.25,
|
||||
child: Text(
|
||||
AppLang.local(context).date,
|
||||
style: StyleConfig.fs14fwBold,
|
||||
)),
|
||||
SizedBox(
|
||||
width: getWidth(context) * 0.55,
|
||||
child: Text(
|
||||
AppLang.local(context).note,
|
||||
style: StyleConfig.fs14fwBold,
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: getWidth(context),
|
||||
height: 1,
|
||||
color: ThemeConfig.grey,
|
||||
),
|
||||
Column(
|
||||
children: List.generate(
|
||||
orderPresenter.trackInfo?.orderUpdates.length ?? 0,
|
||||
(index) => Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: getWidth(context) * 0.25,
|
||||
child: Text(orderPresenter.trackInfo
|
||||
?.orderUpdates[index].date ??
|
||||
"")),
|
||||
SizedBox(
|
||||
width: getWidth(context) * 0.55,
|
||||
child: Text(orderPresenter.trackInfo
|
||||
?.orderUpdates[index].note ??
|
||||
"")),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
width: getWidth(context),
|
||||
height: 1,
|
||||
color: ThemeConfig.grey,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: getWidth(context) * 0.25,
|
||||
child: Text(orderPresenter.trackInfo?.createdDate ??
|
||||
"")),
|
||||
SizedBox(
|
||||
width: getWidth(context) * 0.55,
|
||||
child: Text(AppLang.local(context).order_has_been_placed)),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
81
app_code/lib/screens/wallet.dart
Normal file
81
app_code/lib/screens/wallet.dart
Normal file
@@ -0,0 +1,81 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/custom_ui/BoxDecorations.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/shimmers.dart';
|
||||
import 'package:grostore/helpers/device_info_helper.dart';
|
||||
import 'package:grostore/presenters/wallet_presenter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
||||
class Wallet extends StatefulWidget {
|
||||
const Wallet({super.key});
|
||||
|
||||
@override
|
||||
State<Wallet> createState() => _WalletState();
|
||||
}
|
||||
|
||||
class _WalletState extends State<Wallet> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
Provider.of<WalletPresenter>(context,listen: false).initState();
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CommonAppbar.show(title: AppLang.local(context).wallet_history_ucf, context: context),
|
||||
body: Consumer<WalletPresenter>(
|
||||
builder: (context,data,child) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: data.onRefresh,
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: data.isWalletInit && data.walletHistory.isEmpty?
|
||||
SizedBox(
|
||||
height: getHeight(context),
|
||||
child: Center(
|
||||
child: Text(AppLang.local(context).data_is_not_available),
|
||||
),
|
||||
)
|
||||
: data.isWalletInit?
|
||||
ListView.separated(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
itemBuilder: (context,index)=>Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14,vertical: 10),
|
||||
decoration: BoxDecorations.shadow(radius: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(data.walletHistory[index].date),
|
||||
const SizedBox(height: 8,),
|
||||
Text(data.walletHistory[index].paymentMethod),
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
Text(data.walletHistory[index].amount,style: StyleConfig.fs14cSecondryfwBold,),
|
||||
],
|
||||
),
|
||||
),
|
||||
separatorBuilder: (context,index)=>SizedBox(height: StyleConfig.padding,), itemCount: data.walletHistory.length):
|
||||
|
||||
Padding(padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding),
|
||||
child: Shimmers.list(15, getWidth(context), 55.0),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
90
app_code/lib/screens/wishlist.dart
Normal file
90
app_code/lib/screens/wishlist.dart
Normal file
@@ -0,0 +1,90 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:grostore/app_lang.dart';
|
||||
import 'package:grostore/configs/style_config.dart';
|
||||
import 'package:grostore/configs/theme_config.dart';
|
||||
import 'package:grostore/custom_ui/Button.dart';
|
||||
import 'package:grostore/custom_ui/common_appbar.dart';
|
||||
import 'package:grostore/custom_ui/shimmers.dart';
|
||||
import 'package:grostore/presenters/wishlist_presenter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../custom_ui/product_card.dart';
|
||||
|
||||
|
||||
|
||||
class Wishlist extends StatefulWidget {
|
||||
const Wishlist({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Wishlist> createState() => _WishlistState();
|
||||
}
|
||||
|
||||
class _WishlistState extends State<Wishlist> {
|
||||
|
||||
WishlistPresenter data = WishlistPresenter();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
Provider.of<WishlistPresenter>(context,listen: false).setContext(context);
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
// Provider.of<WishlistPresenter>(context,listen: false).initState();
|
||||
data.initState();
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return
|
||||
Scaffold(
|
||||
appBar: CommonAppbar.show(title: AppLang.local(context).wishlist, context: context),
|
||||
body: ListenableBuilder(
|
||||
listenable: data,
|
||||
builder: (context,child) {
|
||||
return Container(
|
||||
child: data.isWishlistInit?buildProductSection():Shimmers.gridShimmer(2, 10),
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
}
|
||||
Widget buildProductSection(){
|
||||
return RefreshIndicator(
|
||||
onRefresh: data.reFresh,
|
||||
child: GridView.builder(
|
||||
padding: EdgeInsets.symmetric(horizontal: StyleConfig.padding,vertical: StyleConfig.smSectionSpacer),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
childAspectRatio: 0.8),
|
||||
itemCount: data.wishlists.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
ProductCard(
|
||||
product: data.wishlists[index].product,context: this.context,),
|
||||
Positioned(
|
||||
right: 0,
|
||||
top: 0,
|
||||
child: Button(
|
||||
shape: StyleConfig.buttonRadius(25),
|
||||
color: ThemeConfig.lightGrey,
|
||||
onPressed: (){
|
||||
data.deleteWishlist(data.wishlists[index].product.id,context);
|
||||
},
|
||||
minWidth: 10.0,
|
||||
minHeight: 10.0,
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: const Icon(Icons.delete,size: 24,color: Colors.red,),
|
||||
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user