schedule conflict flutter firebase in adding a date that has already been taken - flutter

I am trying to achieve schedule conflict in my uni app, itenerary, where a user wouldnt be allowed to add a trip that has a date that is already taken.
I am struggling to get the right query but this is what i have tried
List dateinput= [];
DateTime? pickeddate = await showDatePicker(context: context,
initialDate:DateTime.now(),
firstDate: DateTime.now().subtract(Duration(days: 0)),
lastDate: DateTime(2025));
setState(() {
date.text= DateFormat('yyyy-MM-dd').format(pickeddate!);
});
//my query
final collection = FirebaseFirestore.instance.collection('UserTrip')
.orderBy('tripDate')
.get()
.then((value) =>
value.docs.forEach((element) {
List data1 = element.data() as List;
dateinput.add(data1);
print(dateinput);
}));
//and I'm trying to implement that return error on pressed on the add trip button
if (dateinput.contains(date.text)) {
//return error
} else {
uploadFile();}

Related

shared_preferences values returning null in flutter

I am using shared_preferences to store a bool value locally but I think I am doing something wrong.
So first of all, here is my initState:
#override
initState(){
super.initState();
checkIfUserHasData();
getBoolValuesSF();
}
on checkIfUserHasData, Im calling another function at the end (addBoolToSF)
Future<void> checkIfUserHasData ()async {
var collection = FirebaseFirestore.instance.
collection('users').doc(userID).collection('personalInfo');
var querySnapshots = await collection.get();
for (var snapshot in querySnapshots.docs) {
documentID = snapshot.id;
}
await FirebaseFirestore.instance
.collection('users')
.doc(userID)
.collection('personalInfo').doc(documentID)
.get().then((value) {
if (!mounted) return;
setState(() {
gender = value.get('gender');
profileImageUrl = value.get('url');
print(profileImageUrl);
print(gender);
});
});
if (gender != null){
if (!mounted) return;
setState((){
isUserNew = false;
});
if(gender == "Male"){
setState(() => genderIsMale = true);
addBoolToSF();
}else{
setState(() => genderIsMale = false);
addBoolToSF();
}
}else {
return;
}
}
Then addBoolToSF:
addBoolToSF() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool('genderType', genderIsMale);
}
Lastely getBoolValuesSF:
getBoolValuesSF() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
bool _genderType = ((prefs.getBool('genderType') ?? true)) ;
genderType = _genderType;
});
}
When the genderType value is obtained I then decide which image to be the background image on the screen:
CachedNetworkImage(
placeholder: (context, url) =>
CircularProgressIndicator(),
imageUrl: genderType ? // : //
With all of that said, here is what is happening when the gender is changed on the firebase firestore:
The first time I navigate or refresh the screen nothing is changed and I get this error:
type 'Null' is not a subtype of type 'bool'
The second time I refresh or navigate to the screen, I do get the correct image on place but I get the same error message again
type 'Null' is not a subtype of type 'bool'
I have tried several ways to solve this issue but i dont seem to get it right.
Edit: I have noticed that when I removed the last part for CachedNetworkImage, I get no error so I think the problem might be on this part
In case like that when you need to wait for a future to build some UI, the go to way is to use a FutureBuilder
You use it like this
FutureBuilder<bool>(
future: getBoolValuesSF,
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
// build your UI here based on snapshot value
},
)
checkIfUserHasData() and getBoolValuesSF() both are future method. you can create another async method and put it inside initState.
#override
initState(){
super.initState();
newMthod();
}
newMthod() async{
await checkIfUserHasData();
await getBoolValuesSF();
}

Flutter filter or sort list by 2 dates

I have a list which I am fetching from store look like this
I/flutter (10562): [{lastupdate: Timestamp(seconds=1622228400, nanoseconds=0), customerName: Abc}, {lastupdate: Timestamp(seconds=1622228400, nanoseconds=0), customerName: Xyz}]
I want to sort this like I have 2 dates. And only those data will show which match or between these dates.
I am using datepicker for this like
DateTime selectedDate = DateTime.now();
Future<void> _selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(2021, 5),
lastDate: DateTime(2101));
if (picked != null && picked != selectedDate)
setState(() {
selectedDate = picked;
print(restore.sort((a,b) {
var adate = selectedDate;
var bdate = DateTime.now();
return -adate.compareTo(bdate);
}));
});
}
As I mentioned in an earlier, now-deleted version of your question, your callback to .sort makes no sense. The purpose of the .sort callback is to indicate the relative ordering of a and b, but your callback ignores a and b entirely and instead compares the selected date and DateTime.now().
You don't say what restore is, and I don't know what Timestamp class you're using, but you should be able to do something like:
import 'dart:math';
// ...
var selectedSeconds = selectedDate.millisecondsSinceEpoch ~/ 1000;
var nowSeconds = DateTime.now().millisecondsSinceEpoch ~/ 1000;
// You can avoid this if `selectedDate` is already guaranteed to be in the past
// (or guaranteed to be in the future).
var lowerBoundSeconds = min(selectedSeconds, nowSeconds);
var upperBoundSeconds = max(selectedSeconds, nowSeconds);
var filteredList = restore.where((element) {
var timestamp = element['lastupdate'];
return timestamp != null &&
timestamp.seconds >= lowerBoundSeconds &&
timestamp.seconds <= upperBoundSeconds;
}).toList();
filteredList.sort(
(a, b) => a['lastupdate']!.seconds.compareTo(b['lastupdate']!.seconds));
Note that for simplicity, the above code ignores the nanoseconds field. You will need to make adjustments if you require that degree of precision.

Flutter - Filter Stream based on Date picked

I have a simple flutter application where I retrieve a bunch of records from Firebase. The records contain a field called DATE, which is in DateTime format.(Date + time + TZ)
But from my application, How can I make a page where I can filter the records just for a selected DATE.
When I use .where('time', isGreaterThan : _selectedDate) , it works. But it gives all days after the selected date. I just want to filter for just ONE selected day.
Heres my Code:
Stream<QuerySnapshot> _getCurrentOders() async* {
yield* FirebaseFirestore.instance
.collection('ItemList')
.where('time', isGreaterThan: _selectedDate)
.orderBy('time', descending: false)
.snapshots();
}
I also use a DateTime picker to select a date.
DateTimeField(
initialValue: DateTime.now(),
onChanged: (val) {
setState(() {
_selectedDate = val;
});
},
format: format,
onShowPicker: (context, currentValue) {
return showDatePicker(
context: context,
firstDate: DateTime(2019),
initialDate: currentValue ?? DateTime.now(),
lastDate: DateTime(2100));
},
),
Thank you for the support!
// this gives you the first millisecond of the day
var startOfTheDay = DateTime(_selectedDate.year, _selectedDate.month, _selectedDate.day);
//and this gives you the first millisecond of the next day
var endOfTheDay = startOfTheDay.add(Duration(days: 1);
and after that you can use:
.where('time', isGreaterThan : startOfTheDay).where('time', isLessThan : endOfTheDay)

Flutter- show loading screen till firestore document changes

I am building a ridesharing app with flutter. So far i am stuck on how to communicate between the rider and driver app.
After rider submits pickup request to firestore db, i want the loading screen to show until a driver accepts the request(possibly by updating firestore db) then move to screen with driver info.
if (event is PaymentMadeEvent) {
yield TaxiBookingLoadingState(
state:
PaymentNotInitializedState(booking: null, methodsAvaiable: null));
TaxiBooking booking = await TaxiBookingStorage.addDetails(TaxiBooking.named(paymentMethod: event.paymentMethod));
String docID = await TaxiBookingController.submitRequest(
booking.source.areaDetails,
booking.destination.areaDetails,
[booking.source.position.latitude,booking.source.position.longitude],
[booking.destination.position.latitude,booking.destination.position.longitude],
booking.estimatedPrice,
booking.estimatedDuration,
booking.estimatedDistance
);
booking = await TaxiBookingStorage.addDetails(TaxiBooking.named(dbID: docID));
await TaxiBookingController.generateToken();
TaxiDriver taxiDriver = await TaxiBookingController.getTaxiDriver(booking);
// Timer.periodic(Duration(seconds: 5), (Timer t) async* {
// } );
taxiDriver = await TaxiBookingController.getTaxiDriver(booking);
yield TaxiNotConfirmedState(booking: booking, driver: taxiDriver);
}
static Future<TaxiDriver> getTaxiDriver(TaxiBooking booking) async {
TaxiDriver taxis2;
var driver = await Firestore.instance.collection("rider_pickup_pairing")
// .where(DocumentReference,isEqualTo: booking.dbID)
.where("driver_id",isEqualTo: 'jk')
.getDocuments()
.then((QuerySnapshot snapshot) {
if (snapshot.documents == []) {
taxis2 = null;
} else {
snapshot.documents.forEach((f) =>
taxis2 = TaxiDriver.named(
driverPic:
"https://upload.wikimedia.org/wikipedia/commons/thumb/e/e3/profilepic.jpg",
driverName: "John Doe",
driverRating: 4.5,
taxiDetails: "Toyota Corolla(ABJ823KU)")
);
TaxiBookingStorage.addDetails(TaxiBooking.named(driver: taxis2.driverName));
}
return taxis2;
});
return driver;
}
You should be using .onSnapshot() instead of .getDocument() in order to achieve this.
The difference between these two methods is that getDocument() will only retrieve the document once while onSnapshot() will keep listening to any event on Firestore. This is covered in these documents: get realtime updates and get data once.
Hope you find this useful.

Flutter Driver select date from date picker

I would like to select a date through date picker as part of a flutter driver test. however, I can't seem to figure out exactly how I would do this?
I've tried using a find.textandfind.bySemanticsLabel, and have tried but have had no luck thus far.
my code :
Future<void> executeStep() async {
await FlutterDriverUtils.waitForFlutter(world.driver);
NewOrderForm newOrderForm = NewOrderForm(world.driver);
await newOrderForm.setFieldKontrak();
//Open Date Picker
await newOrderForm.setDateKontrak();
//Select date 24
await driver.waitFor(find.bySemanticsLabel('24'));
await driver.tap(find.text('24'),timeout: Duration(seconds: 15));
await driver.waitFor(find.text('OK'));
await driver.tap(find.text('OK'));
await newOrderForm.setProyekField();
}
Screen capture :
I ran a sample test that selects a date from datepicker and it worked well. Below is what I did:
main.dart has a simple RaisedButton upon clicking on which DatePicker opens:
return Scaffold(
body: Center(
child: RaisedButton(
onPressed: () {
_showDatePicker();
},
child: Text('Click')
)
)
);
void _showDatePicker() async {
DateTime picked = await showDatePicker(
context: context,
initialDate: new DateTime.now(),
firstDate: new DateTime(2019),
lastDate: new DateTime(2021)
);
if(picked != null) setState(() => _value = picked.toString());
}
Below is the flutter driver test that first identifies the RaisedButton -> taps on it -> finds the date to be selected -> taps on it -> taps OK
test('datepicker test', () async {
final dateButton = find.text('Click');
await driver.waitFor(dateButton);
await driver.tap(dateButton);
await driver.tap(find.text('15'));
await driver.tap(find.text('OK'));
print('October 15 selected and tapped OK');
});
Test result:
In the code you provided, you may try below snippet, ie, tap on 24 and directly tap on OK instead of telling driver to wait for OK button to find.
await driver.tap(find.text('24'));
await driver.tap(find.text('OK'));
Hope this helps you to resolve the issue.