import 'dart:convert';
import 'dart:io';
import 'package:Shopper/_commonWidget/_progressLoader.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'package:google_map_location_picker/google_map_location_picker.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:Shopper/_commonWidget/_categories.dart';
import 'package:Shopper/_contstants/GlobalConst.dart';
import 'package:http/http.dart' as http;
import 'package:toast/toast.dart';
class AddPost extends StatefulWidget {
@override
_AddPostState createState() => _AddPostState();
}
class _AddPostState extends State<AddPost> {
final _descriptionNode = FocusNode();
final _couponNode = FocusNode();
final _discountNode = FocusNode();
final _videoNode = FocusNode();
final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
List<File> _pData = List<File>();
List _cities = List();
List<String> _encData = List<String>();
var discount_value = "new";
var _discountRatio = "0";
var _expireDateTime = "Expire DateTime";
List<String> _selectedLocation = new List<String>();
List<String> _callAction = new List<String>();
var _mDescription = "";
var _selectedCity = "Faisalabad";
var _couponCode="";
var _videoUrl="";
bool isLoading = true;
var _selectedCategory = GlobalConst.AD_CATEGORIES[0];
ProgressLoader _pl;
@override
void initState() {
super.initState();
_pl = new ProgressLoader(context);
}
_AddPostState() {
this.fetchCities();
}
Future fetchCities() async{
try {
await http.post(GlobalConst.SHOPPER_API, body: {
"country": "Pakistan",
"action": "get_city",
}).then((res) {
if (res.statusCode == 200) {
var resBody = jsonDecode(res.body);
setState(() {
_selectedCity = resBody[0];
_cities = resBody;
isLoading = false;
});
}
}).catchError((err) {
print(err);
});
} catch(e){
print(e);
}
}
Future _dopostToAPI() async{
_pl.showAlertDialog(context);
if(_pData.length == 0){ Navigator.pop(context,_pl); Toast.show("ERROR: Images Not Selected", context,gravity: Toast.CENTER); return;}
if(_discountRatio == "0" && discount_value == "flat" || discount_value == "upto"){ Navigator.pop(context,_pl); Toast.show("ERROR: Discount Values Not Correct", context,gravity: Toast.CENTER); return;}
if(_mDescription.length < 5){ Navigator.pop(context,_pl); Toast.show("ERROR: Description is Missing", context,gravity: Toast.CENTER); return;}
if(_expireDateTime == "Expire DateTime"){ Navigator.pop(context,_pl); Toast.show("ERROR: Expire Date/Time Not Selected", context,gravity: Toast.CENTER); return;}
SharedPreferences _session = await SharedPreferences.getInstance();
String _uid = await _session.getString("ID");
_encData.clear();
for(var c = 0; c < _pData.length; c++){
_encData.add(base64Encode(_pData[c].readAsBytesSync()));
}
http.post(GlobalConst.SHOPPER_API, body: {
"adimg": jsonEncode(_encData),
"ad_location": (_selectedLocation.length > 0) ? _selectedLocation.join("|") : "0",
"ad_discount": (discount_value.toString() == "deal" || discount_value.toString() == "new") ? discount_value.toString() : discount_value.toString()+_discountRatio.toString(),
"ad_area": _selectedCity.toString(),
"seller_id": _uid,
"ad_desc": _mDescription,
"ad_video": _videoUrl.toString(),
"ad_category": _selectedCategory.toString(),
"ad_coupon": _couponCode.toString(),
"ad_callaction": (_callAction.length > 0) ? _callAction.join("|") : "0",
"ad_expire": _expireDateTime.toString(),
"ad_imgcount": _encData.length.toString(),
"action": "post_ad",
}).then((res) {
Navigator.pop(context,_pl);
if(res.body == "success"){
Toast.show("Ad Successfully Posted, Under Review", context);
Navigator.pop(context,this);
}else{
Toast.show("[SERVER_ERROR] "+ res.body, context);
}
}).catchError((err) {
print("ERROR: "+err);
Navigator.pop(context,_pl);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
_addPostBar(),
_adPostMediaPicker(),
_ExpireNCategory(),
_discountPicker(),
_contactNumber(),
_couponandvideo(),
_postDescription(),
],
),
),
),
),
),
);
}
Widget _addPostBar() {
return Container(
color: Colors.white,
padding: EdgeInsets.only(
left: 10,
right: 10
),
height: 60,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Post an ad",
style: TextStyle(
fontSize: 20,
),
)
],
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton(
color: Colors.blue,
onPressed: () {
_dopostToAPI();
},
child: Text(
"Done",
style: TextStyle(
color: Colors.white,
),
),
)
],
)
],
),
);
}
Widget _contactNumber(){
return Container(
margin: EdgeInsets.fromLTRB(10,5,10,5),
child: new Theme(
data: new ThemeData(
primaryColor: Color(0xff888888),
),
child: Row(
children: <Widget>[
_selectedLocationItemsButton(),
Expanded(child: _LocationBtn()),
SizedBox(width:10),
SizedBox(width: 135,child: _CallBtn()),
_selectedCallItemsButton(),
],
)
),
);
}
Widget _couponandvideo(){
return Container(
margin: EdgeInsets.fromLTRB(10,5,10,5),
child: new Theme(
data: new ThemeData(
primaryColor: Color(0xff888888),
),
child: Row(
children: <Widget>[
SizedBox(
width: 150,
height: 40,
child: TextFormField(
onFieldSubmitted: (v){
FocusScope.of(context).requestFocus(_videoNode);
},
focusNode: _couponNode,
onChanged: (value) {
setState(() {
_couponCode = value;
});
},
keyboardType: TextInputType.number,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(5),
border: new OutlineInputBorder(
borderSide: new BorderSide(
color: Color.fromARGB(1, 55, 55, 55)
)
),
hintText: "Code",
labelText: "Coupon",
labelStyle: TextStyle(
fontSize: 14.0
),
suffixIcon: Icon(Icons.loyalty),
),
),
),
SizedBox(width:10),
Expanded(
child: new Theme(
data: new ThemeData(
primaryColor: Color(0xff888888),
),
child: SizedBox(
height: 40,
child: TextFormField(
onFieldSubmitted: (v){
FocusScope.of(context).requestFocus(_descriptionNode);
},
focusNode: _videoNode,
onChanged: (value) {
setState(() {
_videoUrl = value;
});
},
keyboardType: TextInputType.url,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(5),
border: new OutlineInputBorder(
borderSide: new BorderSide(
color: Color.fromARGB(1, 55, 55, 55)
)
),
hintText: "Youtube Video Url",
labelText: "Video Link",
labelStyle: TextStyle(
fontSize: 14.0
),
suffixIcon: Icon(Icons.link),
),
),
),
),
)
],
)
),
);
}
Widget _selectedCallItemsButton(){
return PopupMenuButton<String>(
child: Container(
height: 36,
width: 24,
padding: EdgeInsets.only(top: 2),
color: Colors.amber,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(Icons.list,size: 24,color: Colors.white,),
],
),
),
onSelected: (value) {
setState(() {
_callAction.remove(value);
});
Toast.show("Number removed from list", context,
gravity: Toast.CENTER);
},
itemBuilder: (context) => _callAction
.map((item) => PopupMenuItem<String>(
value: item,
child: Text(
item
),
)).toList()
);
}
getCallNo(){
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return CustomDialog();
});
}
Widget _CallBtn(){
return RaisedButton(
padding: EdgeInsets.symmetric(horizontal: 0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.call,color: Colors.black38,),
Text("Add Numbers"),
],
),
color: Colors.white,
onPressed: (){
if(_callAction.length < 5) {
getCallNo();
}else{
Toast.show("[LIMIT_ALERT]: only (5) numbers allowed", context, gravity: Toast.CENTER);
}
},
);
}
Widget _postDescription(){
return Container(
margin: EdgeInsets.fromLTRB(10,5,10,5),
child: new Theme(
data: new ThemeData(
primaryColor: Color(0xff888888),
),
child: TextFormField(
focusNode: _descriptionNode,
onChanged: (value) {
setState(() {
_mDescription = value;
});
},
maxLines: 5,
maxLength: 170,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(10),
border: new OutlineInputBorder(
borderSide: new BorderSide(
color: Color.fromARGB(1, 55, 55, 55)
)
),
hintText: "Tell people about your Ad...",
labelText: "Description",
labelStyle: TextStyle(
fontSize: 14.0
),
alignLabelWithHint: true
),
),
),
);;
}
Widget _discountPicker() {
return Container(
margin: EdgeInsets.fromLTRB(10,5,10,5),
child: Row(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width/4,
child: new Theme(
data: new ThemeData(
primaryColor: Color(0xff888888),
),
child: SizedBox(
height: 48,
child: TextFormField(
focusNode: _discountNode,
onChanged: (value) {
if(int.parse(value) < 5 && int.parse(value) > 95){
Toast.show("ERROR: Choose in between 5 to 95", context,gravity: Toast.CENTER);
} else {
_discountRatio = value;
}
},
buildCounter: (BuildContext context, { int currentLength, int maxLength, bool isFocused }) => null,
maxLength: 2,
keyboardType: TextInputType.number,
onFieldSubmitted: (v){
FocusScope.of(context).requestFocus(_couponNode);
},
decoration: InputDecoration(
contentPadding: EdgeInsets.all(5),
border: new OutlineInputBorder(
borderSide: new BorderSide(
color: Color.fromARGB(1, 55, 55, 55)
)
),
hintText: "Ratio",
labelText: "Discount",
labelStyle: TextStyle(
fontSize: 14.0
),
suffixText: "%",
),
),
),
),
),
SizedBox(width: 10),
SizedBox(
width:30,
child: Radio(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
activeColor: Colors.indigoAccent,
value: 'flat',
groupValue: discount_value,
onChanged: _setDiscountValue,
),
),Text('Flat'),
SizedBox(
width: 30,
child: Radio(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
activeColor: Colors.indigoAccent,
value: 'upto',
groupValue: discount_value,
onChanged: _setDiscountValue
),
),Text("Upto"),
SizedBox(
width:30,
child: Radio(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
activeColor: Colors.indigoAccent,
value: 'deal',
groupValue: discount_value,
onChanged: _setDiscountValue
),
),Text("Deal"),
SizedBox(
width:30,
child: Radio(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
activeColor: Colors.indigoAccent,
value: 'new',
groupValue: discount_value,
onChanged: _setDiscountValue
),
), Text("New"),
],
),
);
}
_setDiscountValue(v){
setState(() {
discount_value = v;
});
}
Widget _PickedImagesList(){
return (_pData.length > 0) ? Container(
height: 70,
child: ListView(
scrollDirection: Axis.horizontal,
children: _pData.map((data) {
return Container(
margin: EdgeInsets.only(left:5,right:5),
child: Stack(
children: <Widget>[
Positioned(
child: Image.file(data),
),
Positioned(
right: 3,
top: 3,
child: GestureDetector(
child: Icon(
Icons.remove_circle,
color: Colors.red
),
onTap: (){
var index = _pData.indexOf(data);
setState(() {
_pData.removeAt(index);
});
},
),
),
],
),
);
}).toList(),
),
) : Center();
}
Widget _adPostMediaPicker() {
return Container(
margin: EdgeInsets.fromLTRB(10,5,10,5),
child: Row(
children: <Widget>[
(_pData.length > 0) ? Expanded(
child: _PickedImagesList(),
) : Center(),
RaisedButton(
padding: EdgeInsets.only(top: 3, bottom: 3),
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
color: Colors.white,
onPressed: () => { _dialogCall(context, false)},
child: Column(
children: <Widget>[
Icon(
Icons.image,
color: Colors.black38,
size: 24,
),
Text(
"Add Photo",
textAlign: TextAlign.center,
)
],
),
),
SizedBox(width: 10,),
]
),
);
}
_openGallery() async {
try {
var _pic = await ImagePicker.pickImage(
source: ImageSource.gallery,
);
_pic =
await ImageCropper.cropImage(sourcePath: _pic.path, aspectRatioPresets: [
CropAspectRatioPreset.square,
]);
setState(() {
_pData.add(_pic);
});
} catch (e) {
print("no img");
}
Navigator.of(context, rootNavigator: true).pop();
}
_openCamera() async {
try {
var _pic = await ImagePicker.pickImage(
source: ImageSource.camera,
);
_pic =
await ImageCropper.cropImage(sourcePath: _pic.path, aspectRatioPresets: [
CropAspectRatioPreset.square,
]);
setState(() {
_pData.add(_pic);
});
} catch (e) {
print("no img");
}
Navigator.of(context, rootNavigator: true).pop();
}
Future<void> _dialogCall(BuildContext context, bool dismiss) {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Container(
height: 100,
child: Column(
children: <Widget>[
Text("Choose From...", style: TextStyle(fontSize: 18,),),
SizedBox(height: 10,),
GestureDetector(
child: Row(
children: <Widget>[
Icon(Icons.camera,color: Colors.black38,),
SizedBox(width: 5),
Text('Camera'),
],
),
onTap: () async {
_openCamera();
}
),
SizedBox(height: 20,),
GestureDetector(
child: Row(
children: <Widget>[
Icon(Icons.collections,color: Colors.black38,),
SizedBox(width: 5),
Text('Gallery'),
],
),
onTap: () async {
_openGallery();
}),
],
),
)
);
}
);
}
Widget _selectedLocationItemsButton(){
return PopupMenuButton<String>(
child: Container(
height: 36,
width: 24,
padding: EdgeInsets.only(top: 2),
color: Colors.amber,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(Icons.list,size: 24,color: Colors.white,),
],
),
),
onSelected: (value) {
setState(() {
_selectedLocation.remove(value);
});
Toast.show("Location removed from list", context,
gravity: Toast.CENTER);
},
itemBuilder: (context) => _selectedLocation
.map((item) => PopupMenuItem<String>(
value: item,
child: Text(
loctocitystr(item.toString()),
),
)).toList()
);
}
String loctocitystr(loc){
var chunks = loc.split(",");
return chunks[chunks.length-3];
}
Future getLocation() async {
if(_selectedLocation.length < 5) {
LocationResult result = await showLocationPicker(
context, "AIzaSyCkIVKoOIsfuhT6d4wUchL5lNJ4Nc0vAv0");
try {
if (mounted) {
setState(() {
_selectedLocation.add(result.address);
});
Toast.show("Location Added To List (Tap icon to see)", context,
gravity: Toast.CENTER);
}
}catch(e){
print(e);
}
}
else{
Toast.show("[LIMIT_ALERT]: only (5) locations allowed", context,
gravity: Toast.CENTER);
}
}
Widget _LocationBtn(){
return RaisedButton(
padding: EdgeInsets.symmetric(horizontal: 0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.map,color: Colors.black38,),
Text("Pick Location"),
],
),
color: Colors.white,
onPressed: (){
getLocation();
},
);
}
Widget _citiesDrop(){
return (!isLoading) ? Container(
width: 120.0,
height: 40,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
border: Border.all(
color: Colors.black38, style: BorderStyle.solid, width: 0.60),
),
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: new DropdownButton(
isExpanded: true,
items: _cities.map((city_val) {
return new DropdownMenuItem(
value: city_val,
child: new Text(
city_val,
style: new TextStyle(fontSize: 14.0)
),
);
}).toList(),
value: _selectedCity,
onChanged: (city_val_changed){
setState(() {
_selectedCity = city_val_changed;
});
},
),
),
),
) : Text("Select City");
}
Widget _ExpireNCategory(){
return Container(
margin: EdgeInsets.fromLTRB(10,5,10,5),
child: Row(
children: <Widget>[
Expanded(child: _Categories()),
SizedBox(width: 10,),
Expanded(child: _ExpiryDate()),
],
),
);
}
Widget _Categories(){
return Container(
height: 40,
child: CategoriesDropdown(
SelectedValue: _selectedCategory,
onSelectParam: (val){
setState(() {
_selectedCategory = val;
});
},
),
);
}
Widget _ExpiryDate(){
return RaisedButton(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.timer,color: Colors.black38,),
Container(
width: MediaQuery.of(context).size.width/3.5,
child: Column(
children: <Widget>[
Text(_expireDateTime),
],
),
),
],
),
color: Colors.white,
onPressed: (){
DatePicker.showDateTimePicker(
context,
showTitleActions: true,
onConfirm: (date) {
setState(() {
_expireDateTime = date.toString().replaceFirst(new RegExp(r'(\.000|\.00)$'),"");
});
});
},
);
}
}
class FieldBox extends StatefulWidget {
@override
_FieldBoxState createState() => _FieldBoxState();
}
class _FieldBoxState extends State<FieldBox> {
@override
Widget build(BuildContext context) {
return Container(
child: Text('calling method'),
);
}
}
class CustomDialog extends StatefulWidget {
@override
_CustomDialogState createState() => _CustomDialogState();
}
class _CustomDialogState extends State<CustomDialog> {
List<Widget> widgetList = [];
int removeIndex = -1;
String pickedData="";
List<String> _callAction = new List<String>();
@override
void initState() {
widgetList.add(textFormFiled());
super.initState();
}
@override
Widget build(BuildContext context) {
return Theme(
data: new ThemeData(
primaryColor: Color(0xff888888)),
child: Dialog(
insetPadding:
const EdgeInsets.symmetric(horizontal: 16.0, vertical: 16.0),
child: Container(
height: 354.0,
width: double.maxFinite,
color: Colors.white,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 12),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding:
const EdgeInsets.symmetric(vertical: 12, horizontal: 12),
child: Text(
'Add Number',
style: TextStyle(
color: Colors.black,
fontSize: 22.0,
fontWeight: FontWeight.w600),
),
),
Container(
height: widgetList.length>2?200:null,
child: ListView.builder(
shrinkWrap: true,
itemCount: widgetList.length,
itemBuilder: (context, index) {
removeIndex = index;
return widgetList[index];
}),
),
SizedBox(
height: 8,
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
InkWell(
onTap: () {
if (widgetList.length > 1) {
widgetList.removeAt(removeIndex);
setState(() {});
}
},
child: Icon(
Icons.remove,
color: Colors.red,
),
),
SizedBox(
width: 16,
),
InkWell(
child: Icon(
Icons.add,
color: Colors.blue,
),
onTap: () {
widgetList.add(textFormFiled());
setState(() {});
},
),
],
),
Spacer(),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new FlatButton(
child: Text('Add',style:TextStyle(color: Colors.white)),
color: Colors.amberAccent,
onPressed: () {
if(pickedData!=null&&pickedData.length > 2) {
setState(() {
_callAction.add(pickedData);
});
Toast.show(
"Number Added To List (Tap icon to see)", context,
gravity: Toast.CENTER);
}else{
Toast.show(
"Not a valid number to add", context,
gravity: Toast.CENTER);
}
Navigator.of(context).pop();
},
),
SizedBox(
width: 15,
),
new FlatButton(
child: Text('Cancle',style:TextStyle(color: Colors.white)),
color: Colors.amberAccent,
onPressed: () {
Navigator.of(context, rootNavigator: true).pop();
}
),
SizedBox(
width: 15,
),
],
)
],
),
),
),
),
);
}
Widget textFormFiled() {
return Container(
margin: const EdgeInsets.only(bottom: 12),
child: TextField(
keyboardType: TextInputType.number,
onChanged: (v){
},
decoration: new InputDecoration(
border: new OutlineInputBorder(
borderSide: new BorderSide(
color: Color.fromARGB(1, 55, 55, 55)
)
),
hintText: '92xxxxxxxxxx',
labelText: 'Mobile/Phone No.#',
prefixIcon: Icon(Icons.call),
),
),
);
}
}
https://prnt.sc/ui29yi
What I have tried:
field adds successfully but problem is nomber not goes correctly in pickedData i guess