I am trying to write a program to check if the time selected by the user already exists in the firebase firestore or not. If it does then I navigate back to the page where they select time again.
But as of now, I am succeeded in sending the date and time to firebase and but not the latter part.
DateTime _eventDate;
bool processing;
String _time;
bool conditionsStatisfied ;
#override
void initState() {
super.initState();
_eventDate = DateTime.now();
processing = false ;
}
inside showDatePicker()
setState(() {
print('inside the setState of listTile');
_eventDate = picked ;
});
inside the button (SAVE):
onPressed: () async {
if (_eventDate != null) {
final QuerySnapshot result = await FirebaseFirestore
.instance
.collection('events')
.where('event_date', isEqualTo: this._eventDate)
.where('selected_time', isEqualTo: this._time)
.get();
final List <DocumentSnapshot> document = result.docs;
if (document.length > 0) {
setState(() {
print('inside the method matching conditions');
showAlertDialogue(context);
});
}else{
final data = {
// "title": _title.text,
'selected_time ': this._time,
"event_date": this._eventDate
};
if (widget.note != null) {
await eventDBS.updateData(widget.note.id, data);
} else {
await eventDBS.create(data);
}
Navigator.pop(context);
setState(() {
processing = false;
});
}
};
some guidance needed on how do I resolve this issue!
Also, because of the else statement now the program won't write the date into firestore.
After Alot of research, I came to realize that if you send the data from calendar in DateTime format then, because of the timestamp at the end of the Date it becomes impossible to match to dates. Hence I formatted the DateTime value into (DD/MM/YYYY).
Here is the rest of the code for reference:
class _AddEventPageState extends State<AddEventPage> {
String _eventDate;
bool processing;
String _time;
#override
void initState() {
super.initState();
// _eventDate = DateTime.now();
processing = false ;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Please select a date'),),
body: Column(
children: [
hourMinute30Interval(),
Text('$_time'),
ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: <Widget>[
ListTile(
title: Text(
'$_eventDate'),
onTap: () async {
DateTime picked = await showDatePicker(context: context,
initialDate: DateTime.now(),
firstDate: DateTime(DateTime.now().year - 1),
lastDate: DateTime(DateTime.now().year + 10),);
if (picked != null) {
setState(() {
print('inside the setState of listTile');
_eventDate = DateFormat('dd/MM/yyyy').format(picked) ;
});
}
},
),
SizedBox(height: 10.0),
ListTile(
title: Center(
child: Text('Select time for appointment!', style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
),
),
processing
? Center(child: CircularProgressIndicator())
: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(30.0),
color: Theme
.of(context)
.primaryColor,
child:MaterialButton(
child: Text('SAVE', style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.bold,
)),
onPressed: () async {
if (_eventDate != null) {
AddingEventsUsingRajeshMethod().getAvailableSlots(
_eventDate, _time).then((QuerySnapshot docs) async {
if (docs.docs.length == 1) {
showAlertDialogue(context);
}
else{
final data = {
// "title": _title.text,
'selected_time': this._time,
"event_date": _eventDate,
};
if (widget.note != null) {
await eventDBS.updateData(widget.note.id, data);
} else {
await eventDBS.create(data);
}
Navigator.pop(context);
setState(() {
processing = false;
});
}
});
}
}
),
),
),
],
),
],
),
);
}
showAlertDialogue method :
showAlertDialogue(BuildContext context) {
Widget okButton = FlatButton(onPressed: (){
Timer(Duration(milliseconds: 500), () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => datePicker()),
);
});
}, child: Text(' OK! '));
AlertDialog alert = AlertDialog(
title: Text('Slot unavailable'),
content: Text('This slot is already booked please select another slot'),
actions: [
okButton,
],
);
showDialog(context: context ,
builder: (BuildContext context){
return alert ;
}
);
}
The hourMinute30Interval() is nothing but a Widget that returns a timePickerSpinner which is a custom Widget. Tap here for that.
The Query that is run after passing the _eventDate and _time is in another class, and it goes as follows :
class AddingEventsUsingRajeshMethod {
getAvailableSlots(String _eventDate , String _time){
return FirebaseFirestore.instance
.collection('events')
.where('event_date', isEqualTo: _eventDate )
.where('selected_time', isEqualTo: _time)
.get();
}
}
You can name it something prettier ;)
Related
When I tried to change the state from outside the function the state is not changing.
void _showAlertDialog(BuildContext context) {
// flutter defined function
showDialog(
context: context,
builder: (BuildContext context) {
// return object of type Dialog
return AlertDialog(
title: const Text("Diabetes Prediction"),
content: StatefulBuilder(
return _predictedResult == "" ? Column(
mainAxisSize: MainAxisSize.min,
children: [
const CircularProgressIndicator(),
Text(loadingText),
],
) : Text(_predictedResult);
},
),
actions: <Widget>[
// usually buttons at the bottom of the dialog
TextButton(
child: const Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
Elevated button helps in calling the _showAlertDialog the loadingText is declared inside the class
ElevatedButton(
child: const Text("Predict"),
onPressed: () async {
// Pregnancies, Glucose, Blood Pressure, Insulin, Skin Thickness, Pedigree Function, Weight,
// Height, Age
_predictedResult = "";
loadingText = "";
var data = _formatData();
var result = Serializer().serialize(data);
_showAlertDialog(context);
setState(() {
loadingText = "Sending data to server...";
});
await Future.delayed(const Duration(seconds: 2), (){
});
setState(() {
loadingText = "Analyzing data...";
});
// await Future.delayed(const Duration(seconds: 2), (){
// print("data received");
// });
await _predict(result);
},
),
The output comes as Sending data to server...
String _predictedResult = '';
StreamController<String>? controller;
String loadingText = '';
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[900],
body: Center(
child: ElevatedButton(
child: const Text("Predict"),
onPressed: () async {
controller = StreamController<String>();
// Pregnancies, Glucose, Blood Pressure, Insulin, Skin Thickness, Pedigree Function, Weight,
// Height, Age
_predictedResult = "";
loadingText = "";
_showAlertDialog(context);
controller!.add("Sending data to server...");
await Future.delayed(const Duration(seconds: 2), () {});
controller!.add("Analyzing data...");
await Future.delayed(const Duration(seconds: 2), () {
print("data received");
});
controller!.add("data received!");
},
),
),
);
}
void _showAlertDialog(BuildContext context) {
// flutter defined function
showDialog(
context: context,
builder: (BuildContext context) {
// return object of type Dialog
return AlertDialog(
title: const Text("Diabetes Prediction"),
content: StreamBuilder(
stream: controller!.stream,
builder: (context, AsyncSnapshot<String> snap) {
return _predictedResult == ""
? Column(
mainAxisSize: MainAxisSize.min,
children: [
const CircularProgressIndicator(),
Text(snap.data ?? "Loading..."),
],
)
: Text(_predictedResult);
},
),
actions: <Widget>[
// usually buttons at the bottom of the dialog
TextButton(
child: const Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
Use Stream
Flutter Stream Basics for Beginners
I want to get data of inventory but not getting. I am doing API integration without model because there are some issues in Model just to get data and want to display in to my view.
this is my service class of get data through API.
Future<dynamic> getInventory() async {
var data;
String? userId = await preferenceService.getuserId();
String? accessToken = await preferenceService.getAccessToken();
var response = await http.get(Uri.parse('${AppUrl.getInventory}/$userId'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': 'Barear $accessToken'
});
print("The data of the specific inventory ===========>>>>>>>> " +
response.body.toString());
if (response.statusCode == 200) {
data = jsonDecode(response.body);
print('This is futr dsta --->>> $data');
} else {
data=[];
}
return data;
}
This is my controller class where i am using above service function
Future getMyInvenoryFromService() async {
try {
isLoadingInventory(true);
await inventoryService.getInventory().then((val) {
if (val != []) {
inventoryData = val;
} else {
inventoryData = [];
}
});
} finally {
isLoadingInventory(false);
}
}
But when i am accessing the data with inventoryData (in controller) i am getting null, but in controller i am getting values when debugging. but i am not understanding why i am receiving null values in view.
This is my view,
class _UserInventoryScreenState extends State<UserInventoryScreen> {
InventoryController inventoryController = Get.put(InventoryController());
InventoryService inventoryService = InventoryService();
GiftController giftController = Get.put(GiftController());
GiftStorageService giftStorageService = GiftStorageService();
#override
void initState() {
super.initState();
/*Future delay() async {
await new Future.delayed(new Duration(milliseconds: 3000), () {
inventoryController.getMyInvenoryFromService();
});
}*/
Timer.run(() {
inventoryController.getMyInvenoryFromService();
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.pinkAppBar,
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.transparent,
leading: InkWell(
onTap: () {
Get.back();
},
child: Icon(Icons.arrow_back)),
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Inventory'),
InkWell(
onTap: () {
Get.to(AddInventoryScreen());
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration:
BoxDecoration(border: Border.all(color: Colors.white)),
child: Text(
"Add Inventory",
style: TextStyle(fontSize: 16),
),
),
)
],
),
),
body: Obx(() {
return inventoryController.isLoadingInventory.value == true
? Center(child: CircularProgressIndicator())
: ElevatedButton(
onPressed: () async {
await inventoryController.getMyInvenoryFromService();
},
child: Text("${inventoryController.inventoryData.length}"),
);
If your response.statusCode isn't 200 it might be because you are setting wrong your headers:
'Authorization': 'Barear $accessToken'
Change it to:
'Authorization': 'Bearer $accessToken'
Background: I am creating one app, where the internet connection status should be shown to the user dynamically. The result is already showing but I want the background color to be changed dynamically. I tried to implement it in setState() but the text color is not getting changed. and I don't know how to implement setState() inside button without onPressed.
main code:
import 'dart:async';
import 'dart:io';
import 'package:connectivity/connectivity.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:quote_app_one/components/TextStyles_Icons.dart';
import 'package:quote_app_one/utils/HexColor.dart';
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
Color _newAppBgColor = HexColor("#111328");
Map _source = {ConnectivityResult.none: false};
MyConnectivity _connectivity = MyConnectivity.instance;
#override
void initState() {
super.initState();
_connectivity.initialise();
_connectivity.myStream.listen((source) {
setState(() => _source = source);
});
}
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
systemNavigationBarColor: _newAppBgColor, // navigation bar color
));
String string;
switch (_source.keys.toList()[0]) {
case ConnectivityResult.none:
string = "Offline";
break;
case ConnectivityResult.mobile:
string = "Online";
break;
case ConnectivityResult.wifi:
string = "Online";
}
//This is the setState() I have implemented
String cData = string;
setState(() {
cData = string;
if(cData == "Online"){
return Text("Online",
style: TextStyle(
color: Colors.green
),);
}
else{
return Text("Offline",
style: TextStyle(
color: Colors.red
),);
}
});
return Scaffold(
appBar: AppBar(
title: homeScreenAppBarText,
backgroundColor: _newAppBgColor,
),
backgroundColor: _newAppBgColor,
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(10, 10, 0, 0),
child: cStatusText,
),
Text( cData,
// style: TextStyle(
// color: Colors.white
// ),
)
],
),
),
new Container(
child: Row(
children: [
// custom widgets
],
),
)
],
),
),
);
}
}
class MyConnectivity {
MyConnectivity._internal();
static final MyConnectivity _instance = MyConnectivity._internal();
static MyConnectivity get instance => _instance;
Connectivity connectivity = Connectivity();
StreamController controller = StreamController.broadcast();
Stream get myStream => controller.stream;
void initialise() async {
ConnectivityResult result = await connectivity.checkConnectivity();
_checkStatus(result);
connectivity.onConnectivityChanged.listen((result) {
_checkStatus(result);
});
}
void _checkStatus(ConnectivityResult result) async {
bool isOnline = false;
try {
final result = await InternetAddress.lookup('example.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
isOnline = true;
} else
isOnline = false;
} on SocketException catch (_) {
isOnline = false;
}
controller.sink.add({result: isOnline});
}
void disposeStream() => controller.close();
}
connectivity_services code:
import 'package:flutter/material.dart';
import 'package:connectivity/connectivity.dart';
class ConnectivityChangeNotifier extends ChangeNotifier {
ConnectivityChangeNotifier() {
Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
resultHandler(result);
});
}
ConnectivityResult _connectivityResult = ConnectivityResult.none;
String _pageText =
'Currently connected to no network. Please connect to a wifi network!';
ConnectivityResult get connectivity => _connectivityResult;
String get pageText => _pageText;
void resultHandler(ConnectivityResult result) {
_connectivityResult = result;
if (result == ConnectivityResult.none) {
_pageText =
'Currently connected to no network. Please connect to a wifi network!';
} else if (result == ConnectivityResult.mobile) {
_pageText =
'Currently connected to a celluar network. Please connect to a wifi network!';
} else if (result == ConnectivityResult.wifi) {
_pageText = 'Connected to a wifi network!';
}
notifyListeners();
}
void initialLoad() async {
ConnectivityResult connectivityResult =
await (Connectivity().checkConnectivity());
resultHandler(connectivityResult);
}
}
In the image, my code is displaying as offline.. but I want that offline beside status as shown in the image and the background color should change dynamically when the status is online. How can I implement this?
You're almost there, you just need to put all that functionality in the stream listener you have setup and not in the build method.
Since you already have a listener following changes in connectivity status, that listener just needs to update a Color variable. Here's a simplified example.
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
Color _newAppBgColor = HexColor("#111328");
// these 2 get updated on connectivity changes
Color statusColor = Colors.red;
String cData = 'Offline';
Map _source = {ConnectivityResult.none: false};
MyConnectivity _connectivity = MyConnectivity.instance;
#override
void initState() {
super.initState();
_connectivity.initialise();
_connectivity.myStream.listen((source) {
setState(() {
_source = source;
_updateStatusText(); // moved from build method to listener
});
});
}
void _updateStatusText() {
switch (_source.keys.toList()[0]) {
case ConnectivityResult.none:
cData = "Offline";
statusColor = Colors.red;
break;
case ConnectivityResult.mobile:
cData = "Online";
statusColor = Colors.green;
break;
case ConnectivityResult.wifi:
cData = "Online";
statusColor = Colors.green;
}
}
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
systemNavigationBarColor: _newAppBgColor, // navigation bar color
));
return Scaffold(
appBar: AppBar(
// title: homeScreenAppBarText, // didn't have the origin of homeScreenAppBarText to test this
title: Text('Demo'),
backgroundColor: _newAppBgColor,
),
backgroundColor: _newAppBgColor,
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(10, 10, 0, 0),
// child: cStatusText, // didn't have the origin of cStatusText to test this
child: Text('status',
style: TextStyle(
color:
statusColor)),
),
Text(
cData, // this updates on change in connectivity status
style: TextStyle(
color:
statusColor, // this updates on change in connectivity status
),
)
],
),
),
new Container(
child: Row(
children: [
// custom widgets
],
),
)
],
),
),
);
}
}
I have implemented a function to form submitting.I want to have SnackBar Alert to after submitted. I have tried but it doesn't work.After I added SnackBar routing also doesn't work.
addTicket() async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
try{
DocumentReference ref = await db.collection('CostalLineTicketDetails').
document(ticketCato).collection("Tickets").add(
{
'startStation':startStation,
'endStation':endStation,
'price':price,
'ticketType':ticketCato,
'contactNo':contactNo,
'dateTime':dateTime,
});
setState(() => id = ref.documentID);
Navigator.push(context, new MaterialPageRoute(builder: (context) => CostalLine()));
Scaffold.of(context).showSnackBar(SnackBar(content: Text('Ticket Added Sucessfully')));
}catch(e){
print(e);
}
}
}
}
You cannot show showSnackBar on same page after going to another screen.
You can declare _scaffoldKey and pass it to Scaffold like this
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
Scaffold(
key: _scaffoldKey,
then open snackbar like this
_scaffoldKey.currentState.showSnackBar(SnackBar(
content: Text(
'Welcome',
),
duration: Duration(seconds: 2),
));
Output:
Edit
You can also use flash where you don't need to pass _scaffoldKey every time.
example:
void _showBasicsFlash({
Duration? duration,
flashStyle = FlashBehavior.floating,
}) {
showFlash(
context: context,
duration: duration,
builder: (context, controller) {
return Flash(
controller: controller,
behavior: flashStyle,
position: FlashPosition.bottom,
boxShadows: kElevationToShadow[4],
horizontalDismissDirection: HorizontalDismissDirection.horizontal,
child: FlashBar(
content: Text('This is a basic flash'),
),
);
},
);
}
try this,
addTicket() async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
try{
DocumentReference ref = await
db.collection('CostalLineTicketDetails').
document(ticketCato).collection("Tickets").add(
{
'startStation':startStation,
'endStation':endStation,
'price':price,
'ticketType':ticketCato,
'contactNo':contactNo,
'dateTime':dateTime,
});
setState(() => id = ref.documentID);
// Navigator.push(context, new MaterialPageRoute(builder: (context) => CostalLine()));
Scaffold.of(context).showSnackBar(SnackBar(content:
Text('Ticket Added Sucessfully')));
}catch(e){
print(e);
}
}
}
}
Define this code in any of the generalized dart file, and you can call this function at any place and will display a generic type scaffold.
import 'package:flutter/material.dart';
void showWarningSnackBar(BuildContext context, String message) {
// Find the Scaffold in the widget tree and use it to show a SnackBar.
ScaffoldFeatureController<Widget, dynamic> _scaffold;
// Find the Scaffold in the widget tree and use it to show a SnackBar.
_scaffold = Scaffold.of(context).showSnackBar(SnackBar(
content: InkWell(
onTap: () {
_scaffold.close();
},
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
AppImage.asset(
assetName: YOUR_IMAGE_NAME,
fit: BoxFit.contain,
width: 20,
color: COLOR),
const SizedBox(
width: 10,
),
Text(
'$message',
maxLines: 2,
),
],
),
),
duration: const Duration(seconds: 10),
backgroundColor: COLOR,
));
}
I'm developing a flutter app, where I need to scan some barcodes, so, for that, I use a plugin called barcode_scan (https://pub.dartlang.org/packages/barcode_scan).
So, the problem comes when I try to call a function from a RaisedButton which is stored on a List of Steps, because I need show that button inside Stepper widget, when I call the function for init the barcode scanner on the onPressed, Android studio show this message 'only static members can be accessed in initializers'.
The function for init barcode scanner:
Future scan() async {
try {
String barcode = await BarcodeScanner.scan();
setState(() => this.barcode = barcode);
} on PlatformException catch (e) {
if (e.code == BarcodeScanner.CameraAccessDenied) {
setState(() {
this.barcode = 'The user did not grant the camera permission!';
});
} else {
setState(() => this.barcode = 'Unknown error: $e');
}
} on FormatException{
setState(() => this.barcode = 'null (User returned using the "back"-button before scanning anything. Result)');
} catch (e) {
setState(() => this.barcode = 'Unknown error: $e');
}}
And the code for the Step List
List<Step> mySteps = [
new Step(title: new Text("Scan first"),
content: new Column(
children: <Widget>[
new Text("Code"),
new Container(
padding: EdgeInsets.only(top: 20),
child: new Text("A08B",style: TextStyle(
fontSize: 30,
color: Colors.red
),
)
,),
new Container(
child: new RaisedButton(onPressed: scan ,
child: new Text("Scan"),),
)
],
))];
Full dart class:
void main() => runApp(MaterialApp(
home: Ubicacion(),
));
class Ubicacion extends StatefulWidget {
#override
_UbicacionState createState() => _UbicacionState();}
class _UbicacionState extends State<Ubicacion> {
String barcode = "";
Future scan() async {
try {
String barcode = await BarcodeScanner.scan();
setState(() => this.barcode = barcode);
} on PlatformException catch (e) {
if (e.code == BarcodeScanner.CameraAccessDenied) {
setState(() {
this.barcode = 'The user did not grant the camera permission!';
});
} else {
setState(() => this.barcode = 'Unknown error: $e');
}
} on FormatException{
setState(() => this.barcode = 'null (User returned using the "back"-button before scanning anything. Result)');
} catch (e) {
setState(() => this.barcode = 'Unknown error: $e');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('hello'),
),
body: Container(
padding: EdgeInsets.all(32.0),
child: Center(
child: Column(
children: <Widget>[
new Container(
child: new Stepper(steps: mySteps,
currentStep: this.pasoActual,
onStepContinue: (){
setState(() {
if(pasoActual <mySteps.length -1){
pasoActual++;
}else{
pasoActual = 0;
}
});
},
onStepCancel: (){
setState(() {
if(pasoActual >0){
pasoActual--;
}else{
pasoActual = 0;
}
});
},),
)
],
),
),
),
);
}
int pasoActual = 0;
List<Step> mySteps = [
new Step(title: new Text("Escanear palet"),
content: new Column(
children: <Widget>[
new Text("Codigo"),
new Text("ID",),
new Text("PLU"),
new Container(
padding: EdgeInsets.only(top: 20),
child: new Text("A08B",style: TextStyle(
fontSize: 30,
color: Colors.red
),
)
,),
new Container(
child: new RaisedButton(onPressed: null ,
child: new Text("Escanear"),),
)
],
))
];
}
The above error occurs when you try to initialize a non-static variable directly when declaring it inside a class.
In your case I assume it's the mySteps list which you are initializing directly.
Try initializing it inside your initState() method if you are using a Stateful Widgetor inside a class constructor and the error will go away.
You can also check this answer for a detailed explanation regarding the same issue.