I am tried a lot of method for get sub collection data from[enter image description here] cloud firestore image of database
my future builder code
FutureBuilder<BasicInfoModela?>(
future: FirstoreService()
.getDoctorbasicsDetails(id: '123456'),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
default:
if (snapshot.hasError) {
return buildText("$snapshot");
} else if (snapshot.hasData) {
final data = snapshot.data;
print('called');
print(data);
final provider = Provider.of<WorKProvider>(context);
provider.setData(data!);
return body();
} else {
print('calledb');
return CircularProgressIndicator();
}
}
},
)),
my model code
factory BasicInfoModela.fromData(
Map<String, dynamic> data ) {
return BasicInfoModela(
userId: data['userId'],
firstName: data['firstname'],
lastName: data['lastname'],
email: data['email'],
contactnumber: data['contactnumber'],
dob: data['dod'],
gender: data['gender'],
city: data['city'],
state: data['state'],
country: data['coutry'],
experience: data['experience'],
speclization: data[''],
);
my future code for get data
Future<BasicInfoModela?> getDoctorbasicsDetails({String? id}) async {
try {
var dbdata = _usersCollectionReference.doc(id).snapshots();
String joinString = jsonDecode(dbdata.toString());
print(joinString);
return BasicInfoModela.fromData(jsonDecode(joinString));
} catch (e) {
if (e is PlatformException) {
}
}
}
how can read the sub collection?
in this code i get always null
i know its simple thing but i my case its note working
_usersCollectionReference.doc(id).snapshots()
this will return a Stream<DocumentSnapshot>
Try this code
Future<BasicInfoModela?> getDoctorbasicsDetails({String? id}) async {
try {
var dbdata = await _usersCollectionReference.doc(id).get();
return BasicInfoModela.fromData(dbdata.data);
} catch (e) {
if (e is PlatformException) {}
}
}
Related
I am building a sign in functionality using bloc pattern, if the entered credentials are invalid, bloc will return a authErrorState, so I will display a invalid credentials popup as soon as the bloc return a authError State
please check the code :
if (state is IsAuthLoadingState) {
return const LoadingSpinnerWidget();
} else if (state is IsAuthenticatedState) {
WidgetsBinding.instance.addPostFrameCallback((_) {
stopTimer();
BlocProvider.of<AuthBloc>(context).add(LoadAuthStatus());
Navigator.pop(context, true);
});
} else if (state is AuthErrorState) {
WidgetsBinding.instance.addPostFrameCallback((_) {
stopTimer();
showCustomPopUp(state.message);
});
}
Bloc code :
void _onLoginUser(LoginUser event, Emitter<AuthState> emit) async {
emit(IsAuthLoadingState());
final UserLoggedInResponse userDetails =
await authRepository.handleLoginUser(event.phoneNumber, event.otp);
if (userDetails.status == "success") {
for (var item in userDetails.wishlist) {
await _localRepo.addWishlistItem(item);
}
for (var item in userDetails.cart) {
await _localRepo.addCartItem(item);
}
for (var item in userDetails.recentSearches) {
await _localRepo.addRecentSearchTerm(item);
}
await _localRepo.addPurchasedItems(userDetails.purchasedItemIds);
await _localRepo.setIsAuthenticated(
userDetails.accessToken, userDetails.userId);
emit(IsAuthenticatedState());
} else {
emit(AuthErrorState(
message: userDetails.message, content: userDetails.content));
}
}
But, the invalid credentials popup written in authErrorState is getting called multiple times.
Any help is really appreciated. Thank you.
As I didn't found any alternative options, I someone tried to manage this for now like this,
I used a bool variable called isErrorShown, and it was set to false by default,
once the code in widgetsBinding is executed, it will set the isErrorShown to true, function is widgetsBinding checks the value of isErrorShown and executes only if it is false :
else if (state is AuthErrorState) {
print("error state");
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!isErrorShown) {
stopTimer();
if (state.message ==
"user does not exits, please create user") {
Navigator.pushReplacementNamed(context, '/create-user',
arguments: CreateUserPage(
showProfile: widget.showProfile,
phoneNumber: phoneNumberController.text,
otp: otpController.text,
));
// BlocProvider.of<AuthBloc>(context).add(LoadAuthStatus());
// Navigator.pushNamed(context, '/create-user');
} else {
showCustomPopUp(state.message);
}
isErrorShown = true;
}
});
In Firestore there is a collection "students" which has two fields "date" and "onBus". I want to update these two fields everyday automatically based on the day date,
like "everyday reset "on_bus" to "0" and set "date" to today date for all students".
How can I do this for flutter app?
i try the following code but it does not work
Future<bool> resetStudentOnBus() async {
var now = DateTime.now();
var formatter = DateFormat('yyyy-MM-dd');
String formattedDate = formatter.format(now);
for (var doc in FirebaseFirestore.instance.collection('students').docs) {
if (doc?.date != formattedDate && doc?.onBus == "1") {
try {
db.collection(FirebaseConstants.pathStudentUserCollection)
.doc()
.update({"on_bus": "0", "date": formattedDate}).then((value) {
print("success");
return true;
}).catchError((onError) {
print(onError);
return false;
});
return true;
} catch (e) {
return false;
}
}
else {
return false;
}
}
}
since Firebase was updated I have been having some issues, first it was because now, instead of a map, an Object? is returned and that is now fixed, but I can't seem to get any data from the database. I can put it there fine but the reading is not working.
This is on my firebase_utils .dart file
FirebaseDatabase data = FirebaseDatabase.instance;
DatabaseReference database = data.ref();
Future<void> init() async {
FirebaseAuth.instance.userChanges().listen((user) {
if (user != null) {
//_loginState = ApplicationLoginState.loggedIn;
} else {
//_loginState = ApplicationLoginState.loggedOut;
}
});
if (!kIsWeb) {
data.setPersistenceEnabled(true);
data.setPersistenceCacheSizeBytes(10000000);
}
}
I have this class:
class ReservationStreamPublisher {
Stream<List<Reservation>> getReservationStream() {
final stream = database.child('reservations').onValue;
final streamToPublish = stream
.map((event) {
List<Reservation> reservationList = [];
Map<String, dynamic>.from(event.snapshot.value as dynamic)
.forEach((key, value) => reservationList.add(Reservation.fromRTDB(value)));
print(reservationList);
return reservationList;
});
return streamToPublish;
}
}
Next is my Reservation.fromRTDB
factory Reservation.fromRTDB(Map<String, dynamic> data) {
return Reservation(
pin: data['pin'],
day: data['day'],
hour: data['hour'],
duration: data['duration'],
state: data['state'],
userEmail: data['client_email'],
completed: data['completed'],
id: data['id'],
dateMade: '',
timeMade: '');
}
And this is one of the places where I am supposed to show data
Text('Slots Reservados neste dia:'),
_selectedDate != null
? StreamBuilder(
stream:
ReservationStreamPublisher().getReservationStream(),
builder: (context, snapshot) {
final tilesList = <ListTile>[];
if (snapshot.hasData) {
List reservations =
snapshot.data as List<Reservation>;
int i = 0;
do {
if (reservations.isNotEmpty) {
if (reservations[i].day !=
(DateFormat('dd/MM/yyyy')
.format(_selectedDate!))) {
reservations.removeAt(i);
i = i;
} else
i++;
}
} while (i < reservations.length);
try {
tilesList
.addAll(reservations.map((nextReservation) {
return ListTile(
leading: Icon(Icons.lock_clock),
title: Text(
"Das ${nextReservation.hour} as ${nextReservation.duration}"),
);
}));
} catch (e) {
return Text(
'Ainda nao existem reservas neste dia');
}
}
// }
if (tilesList.isNotEmpty) {
return Expanded(
child: ListView(
children: tilesList,
),
);
}
return Text('Ainda nao existem reservas neste dia');
})
: SizedBox(),
I am not getting any error at the moment, but no data is returned.This is a Reservation example on my RTDB
I just want to say if the document exists setState(the first one) else setState(the second one). I'm new in flutter so please don't hate :)
Thanks for helping!
Future<String> TerminBesetztOderFrei(String Friseur, String Tag, String Uhrzeit) async {
await Firestore.instance.collection("$Friseur/1/$Tag/1/$Uhrzeit")
.getDocuments()
.then((querySnapshot) {
querySnapshot.documents.forEach((result) {
print(result.exists);
setState(() {
terminText = "Termin nicht verfügbar!";
terminTextFarbe = Colors.red;
buttonVisible = false;
});
});
});
setState(() {
if(nameController.text != "" && telController.text != "") {
terminText = "Termin verfügbar!";
terminTextFarbe = Colors.green;
buttonVisible = true;
} else {
terminText = "Termin verfügbar! Bitte Name und Telefon eingeben!";
terminTextFarbe = Colors.green;
buttonVisible = false;
}
});
}
If you have the document Id:
final docSnapshot = await Firestore.instance
.collection("$Friseur/1/$Tag/1/$Uhrzeit")
.document(${doc_id_here})
.get();
if(docSnapshot.exists) {
setState(...)
}
else {
setState(...)
}
If you haven't
final querySnapshot = await Firestore.instance
.collection("$Friseur/1/$Tag/1/$Uhrzeit")
.getDocuments();
if(querySnapshot.documents.isNotEmpty) {
setState(...)
}
I am stuck in handling future and getting distance on extracting address from Firebase and displaying on the marker,
though I have managed to write some code for getting the current user location, calculating the distance, and converting the address to LatLng but still I am facing difficulties.
Below I have attached my code and also highlighted where I want to calculate the distance( Inside widget setMapPins() )
I have stored the addresses inside collection shops and document named Address in firebase
Please help me to calculate the distance inside Streambuilder and display it on the marker. Thanks in Advance.
This is the link to my complete map.dart file
'necessary imports'
'necessary initialization'
_getCurrentLocation() async {
await _geolocator
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high)
.then((Position position) async {
setState(() {
_currentPosition = position;
sourceLocation =
LatLng(_currentPosition.latitude, _currentPosition.longitude);
print('CURRENT POS: $_currentPosition');
mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(position.latitude, position.longitude),
zoom: 14.0,
),
),
);
});
await _getAddress();
}).catchError((e) {
print(e);
});
}
// Method for retrieving the address
_getAddress() async {
try {
List<Placemark> p = await _geolocator.placemarkFromCoordinates(
_currentPosition.latitude, _currentPosition.longitude);
Placemark place = p[0];
setState(() {
_currentAddress =
"${place.name}, ${place.locality}, ${place.postalCode}, ${place.country}";
startAddressController.text = _currentAddress;
_startAddress = _currentAddress;
});
} catch (e) {
print(e);
}
}
// Method for calculating the distance between two places
Future<bool> _calculateDistance() async {
try {
// Retrieving placemarks from addresses
List<Placemark> startPlacemark =
await _geolocator.placemarkFromAddress(_startAddress);
List<Placemark> destinationPlacemark =
await _geolocator.placemarkFromAddress(_destinationAddress);
if (startPlacemark != null && destinationPlacemark != null) {
Position startCoordinates = _startAddress == _currentAddress
? Position(
latitude: _currentPosition.latitude,
longitude: _currentPosition.longitude)
: startPlacemark[0].position;
Position destinationCoordinates = destinationPlacemark[0].position;
await _createPolylines(startCoordinates, destinationCoordinates);
double totalDistance = 0.0;
// Calculating the total distance by adding the distance
// between small segments
for (int i = 0; i < polylineCoordinates.length - 1; i++) {
totalDistance += _coordinateDistance(
polylineCoordinates[i].latitude,
polylineCoordinates[i].longitude,
polylineCoordinates[i + 1].latitude,
polylineCoordinates[i + 1].longitude,
);
}
setState(() {
_placeDistance = totalDistance.toStringAsFixed(2);
return true;
}
} catch (e) {
print(e);
}
return false;
}
// formula
double _coordinateDistance(lat1, lon1, lat2, lon2) {
var p = 0.017453292519943295;
var c = cos;
var a = 0.5 -
c((lat2 - lat1) * p) / 2 +
c(lat1 * p) * c(lat2 * p) * (1 - c((lon2 - lon1) * p)) / 2;
return 12742 * asin(sqrt(a));
}
// Create the polylines for showing the route between two places
_createPolylines(start, destination) async {
polylinePoints = PolylinePoints();
List<PointLatLng> result = await polylinePoints.getRouteBetweenCoordinates(
googleAPIKey, // Google Maps API Key
start.latitude, start.longitude,
destination.latitude, destination.longitude,
);
if (result.isNotEmpty) {
result.forEach((PointLatLng point) {
polylineCoordinates.add(LatLng(point.latitude, point.longitude));
});
}
}
Widget setMapPins() {
return StreamBuilder(
stream: Firestore.instance.collection('shops').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return Text('Loading maps... Please Wait');
for (int i = 0; i < snapshot.data.documents.length; i++) {
print(snapshot.data.documents[i]);
/// here i want to calculate distance by extracting address from Firebase and then displaying on marker
}
return Container();
});
}
#override
void initState() {
super.initState();
_getCurrentLocation();
}
To reduce the complexity of your code,you can use this function to calculate the distance between 2 points.(..in GeoLocator package)
double distanceInMeters =Geolocator().distanceBetween(lat1, long1,lat2,long2);
UPDATE 2:-
make a function to do the async task,
var distInMeters;
getDist({var latt,var longg}) async{
distanceInMeters = await Geolocator().distanceBetween(latt, longg,lat2,long2);// lat2 and long2 are global variables with current user's location
}
In your Streambuilder,
StreamBuilder(
stream: Firestore.instance.collection('shops').snapshots(),
builder: (BuildContext context,
AsyncSnapshot<List<DocumentSnapshot>> snapshots) {
if (snapshots.connectionState == ConnectionState.active &&
snapshots.hasData) {
print(snapshots.data);
return ListView.builder(
itemCount: snapshots.data.length,
itemBuilder: (BuildContext context, int index) {
DocumentSnapshot doc = snapshots.data[index];
Map yourdata= doc.data;
/*
Here, you can get latitude and longitude from firebase, using keys,based on your document structure.
Example, var lat=yourdata["latitude"];
var long=yourdata["longitude"];
Now, you can calculate the distance,
getDist(latt:lat,longg:long);
here lat2 and long2 are current user's latitude and longitude.
print(distInMeters);
*/
return Text("please upvote and accept this as the answer if it helped :) "),
);
},
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),