Flutter Firebase: not able update Database - flutter

I want to update my Collection with an NumberPicker in a Alert Dialog. I do not get any errors in code or from the emulator. When i press the button to update the code the terminal do not give any errors. Everything looks fine but for some reason i do not work. When you need more Information just leave a comment with what you excactly need. :)
import 'package:flutter/material.dart';
import 'package:numberpicker/numberpicker.dart';
import 'package:percent_indicator/circular_percent_indicator.dart';
import 'package:testapp/services/Services.dart';
import 'models/Goals.dart';
class Statistics extends StatefulWidget {
#override
_StatisticsState createState() => _StatisticsState();
}
class _StatisticsState extends State<Statistics> {
int _currentFirstValue = 1;
int totalFirst;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: 260,
child: StreamBuilder(
stream: FirestoreService().getGoals(),
builder: (context, AsyncSnapshot<List<Goal>> snapshot) {
if (snapshot.hasError || !snapshot.hasData) {
return Center(child: CircularProgressIndicator(
backgroundColor: Color(0XFF1954A1),
));
}
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 1,
itemBuilder: (BuildContext context, int index) {
// ignore: missing_return
Goal goal = snapshot.data[index];
return Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
margin: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
height: 230,
width: 350,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(10.0)),
boxShadow: [
BoxShadow(
color: Colors.grey[300],
offset: const Offset(0.5, 1),
blurRadius: 4.0,
spreadRadius: 0.1,
),
]),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Text('WeekGoals', style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.w500,
),),
SizedBox(width: 100),
SizedBox(
height: 20,
width: 87,
child: FlatButton(
child: Text('edit', style: TextStyle(
fontSize: 17,
color: Colors.yellow[700]
),),
onPressed: () {
return showDialog(
context: context,
barrierDismissible: true,
builder: (context) => AlertDialog(
content: Column(
children: <Widget>[
Text('weekly goals'),
NumberPicker.integer(
initialValue: _currentFirstValue,
minValue: 1,
maxValue: 100,
onChanged: (newGoal) => setState(() => {
_currentFirstValue = newGoal,
totalFirst = _currentFirstValue,
})
),
Row(
children: <Widget>[
RaisedButton(
child: Text('edit goals'),
onPressed: () async {
Goal goal = Goal(
weekActivityGoal: totalFirst,
);
await FirestoreService().updateGoal(goal);
Navigator.pop(context, false);
},
),
FlatButton(
child: Text('Close'),
onPressed: () {
Navigator.pop(context, false);
},
)
],
)
],
),
)
);
},
),
)
],
),
SizedBox(height: 10),
Row(
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(horizontal: 17.5),
child: CircularPercentIndicator(
header: Text('activitys', style: TextStyle(
fontSize: 17,
),),
radius: 130,
progressColor: Colors.red,
lineWidth: 8,
backgroundColor: Colors.grey[200],
percent: goal.weekActivity*100/goal.weekActivityGoal,
center: Text('${goal.weekActivity}/${goal.weekActivityGoal}'),
),
),
],
),
],
),
),
],
);
});
}),
),
);
}
}

Here this has been helping a lot of people try i out might help you too.
StreamBuilder(
stream: Firestore.instance.collection('Hearings').snapshots(),
builder: (context, snapshot) {
if (snapshot.hasError) return Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Select lot');
case ConnectionState.waiting:
return Text('Awaiting bids...');
case ConnectionState.active:
{
print('active');
return Text('${snapshot.data}');
}
case ConnectionState.done:
{
print('Done');
return _buildList(context, snapshot.data);
}
}
return null;
}),
));
}
Widget _buildList(BuildContext context, List<DocumentSnapshot> snapshot) {
return ListView(
padding: const EdgeInsets.only(top: 20.0),
children: snapshot.map((data) => _buildListItem(context, data)).toList(),
);
}
Widget _buildListItem(BuildContext context, DocumentSnapshot data) {
final record = Record.fromSnapshot(data);
return Padding(
key: ValueKey(record.name),
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(5.0),
),
child: ListTile(
title: Text(record.name),
trailing: Text(record.votes.toString()),
onTap: () => Firestore.instance.runTransaction((transaction) async {
final freshSnapshot = await transaction.get(record.reference);
final fresh = Record.fromSnapshot(freshSnapshot);
await transaction
.update(record.reference, {'votes': fresh.votes + 1});
}),
),
),
);
}
}
class Record {
final String name;
final int votes;
final DocumentReference reference;
Record.fromMap(Map<String, dynamic> map, {this.reference})
: assert(map['name'] != null),
assert(map['votes'] != null),
name = map['name'],
votes = map['votes'];
Record.fromSnapshot(DocumentSnapshot snapshot)
: this.fromMap(snapshot.data, reference: snapshot.reference);
#override
String toString() => "Record<$name:$votes>";
}
This is where the link this info came from.

Related

How to pass a variable (TextEditingController) to another class

class that i have the variable in
...
class _ActivitiesParticipantsState extends State<ActivitiesParticipants> {
final activityController = TextEditingController();
final user = FirebaseAuth.instance.currentUser!;
//Activities participants
List<String> docIDs = [];
//get docIDS
Future getDocId() async {
await FirebaseFirestore.instance
.collection(
activityController.text.trim(),
)
.get()
.then(
(snapshot) => snapshot.docs.forEach(
(element) {
docIDs.add(element.reference.id);
},
),
);
//stuff
}
#override
void dispose() {
activityController.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextFormField(
controller: activityController,
decoration: InputDecoration(
labelText: 'e',
border: InputBorder.none,
),
),
GestureDetector(
onTap: () async {
setState(
() {
getDocId();
},
);
},
child: Container(
padding: EdgeInsets.all(
20,
),
decoration: BoxDecoration(
color: Colors.deepPurple,
borderRadius: BorderRadius.circular(12),
),
child: Center(
child: Text(
'Test',
style: TextStyle(
color: Colors.white,
fontFamily: 'Quicksand',
fontWeight: FontWeight.w600,
fontSize: 18,
),
),
),
),
),
Expanded(
child: FutureBuilder(
builder: (context, snapshot) {
return ListView.builder(
itemCount: wee(),
//docIDs.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 15),
child: ListTile(
dense: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)),
tileColor: Color.fromARGB(255, 235, 235, 235),
title: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10, vertical: 20),
child: Column(
children: [
SizedBox(
height: 5,
),
Align(
alignment: Alignment.centerLeft,
child: Title(
color: Colors.black,
child: InterestedName(
documentID: docIDs[index]),
),
),
SizedBox(
height: 20,
),
],
),
),
),
);
},
);
},
),
),
],
),
),
),
);
}
}
...
How do I get the variable "activityController" to another class?
This other class is used to get Text to fill the ListTile
class that I want to get the variable
final String documentID;
InterestedName({required this.documentID});
#override
Widget build(BuildContext context) {
// get the collection
CollectionReference users = FirebaseFirestore.instance.collection('Project Koalas [test]');
return FutureBuilder<DocumentSnapshot>(
future: users.doc(documentID).get(),
builder: ((context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data =
snapshot.data!.data() as Map<String, dynamic>;
return Text(
'Name: ${data['name']}',
style: TextStyle(
fontSize: 16,
fontFamily: 'Quicksand',
fontWeight: FontWeight.w600),
);
}
return Text('loading...');
}),
);
}
}
I would like to get the variable to be able to get the collection name that I want to take data from, as the collection I would like to take from is dependent on the user's choice.
If there is any way else to somehow fill the List tile in the same class, please let me know how.
Any help appreciated!

Searchdelegates class using flutter firebase

I have a searchDelagate class...inside the class i want to diapaly some dat that comes from the collection"users"...Here actually my problem is i have two collection users and company ..i want to dispaly the data that match with the uid of another collection company..so i tried to call the function like this
class SearchPage extends SearchDelegate {
CollectionReference _firebaseFirestore =
FirebaseFirestore.instance.collection('users').where('pid',isEqualTo:widget.uid);
but when use "widget.uid"it become an error
i attach the full code below
class SearchPage extends SearchDelegate {
CollectionReference _firebaseFirestore =
FirebaseFirestore.instance.collection('users').where('pid',isEqualTo:widget.uid);
#override
List<Widget>? buildActions(BuildContext context) {
return <Widget>[
IconButton(
onPressed: () {
query = "";
},
icon: Icon(Icons.close)),
];
}
#override
Widget? buildLeading(BuildContext context) {
return IconButton(
onPressed: () {
Navigator.of(context).pop();
},
icon: Icon(Icons.arrow_back));
}
#override
Widget buildResults(BuildContext context) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 500,
// color: Colors.indigo,
// height: 300,
child: Column(
children: [
Row(
children: [
buildTextTitle("Reg no", 60),
buildTextTitle("Name", 100),
buildTextTitle("Address", 100),
buildTextTitle("Phone", 100),
buildTextTitle("Monthly amount", 70),
buildTextTitle("Opening balance", 70),
],
),
const Divider(
height: 20,
thickness: 1,
color: Colors.black,
),
Expanded(
child: Container(
child: StreamBuilder<QuerySnapshot>(
stream: _firebaseFirestore.snapshots().asBroadcastStream(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
} else {
print(snapshot.data);
return ListView(
children: [
...snapshot.data!.docs
.where(
(QueryDocumentSnapshot<Object?> element) =>
element["RegNo"]
.toLowerCase()
.contains(query.toLowerCase()))
.map((QueryDocumentSnapshot<Object?> data) {
final String regno = data.get("RegNo");
final String name = data["Name"];
final String phone = data["Phone"];
final String address = data["Address"];
final String opening = data["Opening"];
final String monthly = data["Monthly"];
final String id = data["id"];
final String pid = data["pid"];
final String pdis = data["pdis"];
final String pemail = data["pemail"];
final String pname = data["pname"];
final String pphone = data["pphone"];
final String pregno = data["pregno"];
final String ppost = data["ppost"];
//final String id=data["id"];
return Container(
// height:100,
//width: 150,
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CollectionPage(
RegNo: regno,
Phone: phone,
Name: name,
Address: address,
Monthly: monthly,
Opening: opening,
id: id,
pdis: pdis,
pemail: pemail,
pid: pid,
pname: pname,
pphone: pphone,
ppost: ppost,
pregno: pregno,
)));
},
child: Column(
children: [
Row(
children: [
buildSizedBox(regno, 60),
buildSizedBox(name, 100),
buildSizedBox(address, 100),
buildSizedBox(phone, 100),
buildSizedBox("${monthly}/-", 70),
buildSizedBox("${opening}/-", 70),
],
),
Row(
children: [
Expanded(
child: const Divider(
height: 20,
thickness: 1,
// indent: 200,
// endIndent: 50,
color: Colors.green,
),
)
],
),
],
),
),
);
})
],
);
}
},
),
),
),
],
),
),
),
);
}
#override
Widget buildSuggestions(BuildContext context) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 500,
child: Column(
children: [
Row(
children: [
buildTextTitle("Reg no", 60),
buildTextTitle("Name", 100),
buildTextTitle("Address", 100),
buildTextTitle("Phone", 100),
buildTextTitle("Monthly amount", 70),
buildTextTitle("Opening balance", 70),
],
),
const Divider(
height: 20,
thickness: 1,
color: Colors.black,
),
Expanded(
child: SingleChildScrollView(
child: Container(
child: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('users')
where('pid',isEqualTo: widget.uid)
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData)
return CircularProgressIndicator();
{
return ListView.separated(
shrinkWrap: true,
itemCount: snapshot.data!.docs.length,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (context, index) {
return Container();
},
itemBuilder: (BuildContext context, int index) {
return Container(
// height:100,
//width: 150,
child: GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CollectionPage(
RegNo: snapshot.data
?.docs[index]['RegNo'],
Phone: snapshot.data
?.docs[index]['Phone'],
Name: snapshot.data
?.docs[index]['Name'],
Address: snapshot.data
?.docs[index]['Address'],
Monthly: snapshot.data
?.docs[index]['Monthly'],
Opening: snapshot.data
?.docs[index]['Opening'],
id: snapshot.data?.docs[index]
['id'],
pdis: snapshot.data
?.docs[index]['pdis'],
pemail: snapshot.data
?.docs[index]['pemail'],
pid: snapshot
.data?.docs[index]['pid'],
pname: snapshot.data
?.docs[index]['pname'],
pphone: snapshot.data
?.docs[index]['pphone'],
ppost: snapshot.data
?.docs[index]['ppost'],
pregno: snapshot.data
?.docs[index]['pregno'],
)));
},
child: Column(
children: [
Row(
children: [
buildSizedBox(
snapshot.data!.docs[index]
['RegNo'],
60),
buildSizedBox(
snapshot.data!.docs[index]
['Name'],
100),
buildSizedBox(
snapshot.data!.docs[index]
['Address'],
100),
buildSizedBox(
snapshot.data!.docs[index]
['Phone'],
100),
buildSizedBox(
"${snapshot.data!.docs[index]['Monthly']}/-",
70),
buildSizedBox(
"${snapshot.data!.docs[index]['Opening']}/-",
70),
],
),
Row(
children: [
Expanded(
child: const Divider(
height: 20,
thickness: 1,
// indent: 200,
// endIndent: 50,
color: Colors.green,
),
)
],
),
],
),
),
);
},
);
}
},
),
),
),
),
],
),
),
),
);
}
SizedBox buildSizedBox(String value, double size) {
return SizedBox(
width: size,
child: Text(
value,
style: const TextStyle(
letterSpacing: 0,
color: Colors.black,
fontSize: 15,
fontWeight: FontWeight.w400),
));
}
SizedBox buildTextTitle(String title, double width) {
return SizedBox(
width: width,
child: Text(
title,
style: const TextStyle(
letterSpacing: 0,
color: Colors.red,
fontSize: 14,
fontWeight: FontWeight.w500),
),
);
}
}

How to get back a value from a customly created widget in Flutter

I am showing a showModalBottomSheet using a function. I want that as soon as it closes, value of a variable should change. I wanted to change value of two variables, but I am not able to change for even one. Please help me with this. I tried to make my own onChanged and also tried to return the value using function, but nothing happens.
This is the function, please scroll to the last of it and check out the onTap function and return.
String showChapterSelectionSheet(
BuildContext context,
List<ChapterModel> chapter_list,
String chapter_name,
final Function(String) onChapterChanged) {
String retValue = chapter_name;
showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
elevation: 0,
isScrollControlled: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20), topRight: Radius.circular(20)),
),
builder: (context) {
return StatefulBuilder(
builder: (BuildContext context,
StateSetter setState /*You can rename this!*/) {
return makeDismissible(
context,
child: DraggableScrollableSheet(
initialChildSize: 0.81,
minChildSize: 0.5,
maxChildSize: 0.81,
builder: (_, controller) => Container(
padding: EdgeInsets.all(getProportionateScreenWidth(25)),
height: getProportionateScreenWidth(600),
decoration: BoxDecoration(
color: backgroundColor2,
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
child: Column(
children: [
Padding(
padding: EdgeInsets.only(
top: getProportionateScreenHeight(32),
bottom: getProportionateScreenHeight(16)),
child: Text(
AppLocalizations.of(context)!.chapters,
style: Theme.of(context)
.textTheme
.headline2!
.apply(color: Colors.white),
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
controller: controller,
itemCount: chapter_list.length,
itemBuilder: (_, index) {
return GestureDetector(
child: Padding(
padding: EdgeInsets.only(
top: getProportionateScreenHeight(8)),
child: Card(
child: Container(
height: getProportionateScreenHeight(56),
width: getProportionateScreenWidth(341),
decoration: BoxDecoration(
border: Border.all(color: cardColor),
color: chapter_list[index].chapter_name! ==
chapter_name
? backgroundColor
: cardColor,
),
child: Padding(
padding: EdgeInsets.all(0),
child: Center(
child: Row(
children: [
Container(
width:
getProportionateScreenWidth(
32),
child: chapter_list[index]
.chapter_name! ==
chapter_name
? Icon(
Icons.check,
color: brandYellow,
)
: SizedBox()),
Text(
"Chapter ${chapter_list[index].position!}: ",
style: Theme.of(context)
.textTheme
.bodyText2!
.apply(color: brandYellow),
),
Expanded(
child: Text(
chapter_list[index]
.chapter_name!,
style: Theme.of(context)
.textTheme
.bodyText2!
.apply(
color: chapter_list[
index]
.chapter_name! ==
chapter_name
? tertiaryTextColor
: primaryTextColor)),
),
],
),
),
),
),
),
),
onTap: () {
onChapterChanged(chapter_list[index].chapter_name!);
setState(() {
retValue = chapter_list[index].chapter_name!;
});
Navigator.pop(context);
},
);
},
),
),
],
),
),
),
);
},
);
},
);
return retValue;
}
And I am accessing it here -
return InkWell(
onTap: () async {
if(dataList.isNotEmpty) {
chapterName.value = showChapterSelectionSheet(
context,dataList,chapterName.value,(val) {
setState(() {
chapterName.value = val;
print("Val is - $val");
});
}
);
}
},
child: .....
);
In the above InkWell, the print statement is working fine but value is not changing.
And I want to update and use the value here -
child: ValueListenableBuilder(
valueListenable: chapterName,
builder: (context, String val, Widget? child) {
return Text(
val,
style: TextStyle(
color: Colors.white,
fontSize: 15,
),
);
},
),
It is possible you are just missing await before await showModalBottomSheet(..).
You can follow this simplified snippet.
class BVChange extends StatefulWidget {
const BVChange({Key? key}) : super(key: key);
#override
State<BVChange> createState() => _BVChangeState();
}
class _BVChangeState extends State<BVChange> {
String var1 = "Old", var2 = "old1";
Future<String> _showDialog(String v) async {
double _sliderValue = 0.0;
await showModalBottomSheet(
context: context,
builder: (_) {
return StatefulBuilder(
builder: (context, sbSate) => Column(
children: [
Text(_sliderValue.toString()),
Slider(
value: _sliderValue,
onChanged: (sval) {
sbSate(() {
_sliderValue = sval;
});
}),
],
),
);
});
return _sliderValue.toString();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
GestureDetector(
onTap: () async {
final data = await _showDialog(var1);
setState(() {
var1 = data;
});
},
child: Text("var1 : $var1")),
GestureDetector(
onTap: () async {
final data = await _showDialog(var2);
setState(() {
var2 = data;
});
},
child: Text("var 2 : $var2"),
),
],
),
);
}
}

Not showing the future builder of hot products which is placed after the department future builder in column

I am trying to show two future builders with gridview in the column widget, but it is showing me one future builder of the department and not showing the other future builder when scrolling it. how to show the future builder of hot product? it will be helpful for me
import 'dart:convert';
import 'package:apipractice/Models/Category_model.dart';
import 'package:apipractice/Models/Department_model.dart';
import 'package:apipractice/Models/HotProduct_model.dart';
import 'package:apipractice/Screens/Department.dart';
import 'package:apipractice/Screens/cart.dart';
import 'package:apipractice/Screens/categorry.dart';
import 'package:apipractice/Screens/products.dart';
import 'package:apipractice/Screens/selected_Category.dart';
import 'package:apipractice/Screens/subCategory.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
Future<HotProductModel> getHotProducts() async {
var data = jsonDecode(response.body);
if (response.statusCode == 200) {
return HotProductModel.fromJson(data[0]);
} else {
throw Exception('Failed to load album');
}
}
List images = [
"assets/Image1.jpeg",
"assets/Image2.jpeg",
"assets/Image3.jpeg",
"assets/Image4.jpeg",
"assets/Image5.jpeg",
"assets/Image6.jpeg",
];
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
child: ListTile(
leading: CircleAvatar(
child: Image(image: AssetImage("images/user.png")),
radius: 25,
),
title: Text(
"Username",
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text("abcuser#gmail.com"),
),
),
ListTile(
leading: Icon(Icons.note),
title: const Text('Show Product'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Products()),
);
},
),
ListTile(
leading: Icon(Icons.note),
title: const Text('Show Category'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Categorry()),
);
},
),
ListTile(
leading: Icon(Icons.note),
title: const Text('Department'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Department()),
);
},
),
],
),
),
appBar: AppBar(
backgroundColor: Color.fromARGB(255, 24, 119, 197),
title: Text("Dubai Super Store"),
actions: [
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: ((context) => Cart()),
),
);
},
icon: Icon(Icons.shopping_cart))
],
),
body: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
margin: EdgeInsets.all(10),
height: 35,
width: double.infinity,
child: TextField(
decoration: InputDecoration(
hoverColor: Colors.blue,
prefixIconColor: Colors.blue,
labelText: "Search Product",
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
),
),
),
),
Text(
"Note: Free Delivery Above Rs.2000",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.red.shade700,
fontSize: 17),
),
Container(
height: 200,
width: double.infinity,
child: CarouselSlider.builder(
itemCount: images.length,
options: CarouselOptions(
height: 400,
viewportFraction: 1,
autoPlay: true,
),
itemBuilder: (context, index, realindex) {
final urlImages = images[index];
return buildImage(urlImages, index);
},
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
child: Column(
children: [
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Categorry()),
);
},
child: Image(
height: 70,
width: 70,
image: AssetImage("assets/Categories.jpeg"),
),
),
Text("Categories")
],
),
),
Container(
child: Column(
children: [
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SubCategory()),
);
},
child: Image(
height: 70,
width: 70,
image: AssetImage("assets/SubCategory.jpeg")),
),
Text("Sub Category")
],
),
)
],
),
SizedBox(height: 20),
Text(
"Department",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
color: Color.fromARGB(255, 16, 113, 192)),
),
FutureBuilder<DepartmentModel>(
future: getDepartment(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return GridView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemCount: snapshot.data!.sKUDepartmentDetail!.length,
itemBuilder: (context, index) {
return InkWell(
onTap: () {
var fetchid =
"${snapshot.data!.sKUDepartmentDetail![index].sKUDeptId}";
fetchCategory = fetchid;
setState(() {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SelectedCategory()),
);
});
},
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(20.0),
),
),
elevation: 10.0,
child: Column(
children: [
ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(20.0),
),
child: Stack(children: [
CachedNetworkImage(
imageUrl: snapshot
.data!
.sKUDepartmentDetail![index]
.imageUrl1!,
height: 150,
width: 200,
fit: BoxFit.fitWidth,
errorWidget: (context, url, error) {
return Image(
image: AssetImage(
"assets/placeholder.jpg"));
},
),
]),
),
Text(
snapshot
.data!.sKUDepartmentDetail![index].name!,
style: TextStyle(fontWeight: FontWeight.bold),
)
],
),
),
);
});
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
// SizedBox(height: 20),
Text(
"Hot Product",
style: TextStyle(fontSize: 20),
),
FutureBuilder<HotProductModel>(
future: getHotProducts(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data!.productDetail!.length,
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(10),
),
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 3,
offset: Offset(1.0, 1.0),
)
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CachedNetworkImage(
imageUrl: snapshot.data!.productDetail![index]
.sKUImageURL1!,
height:
MediaQuery.of(context).size.height * 0.12,
width: double.infinity,
fit: BoxFit.fitWidth,
errorWidget: (context, url, error) {
return Image(
image: AssetImage(
"assets/placeholder.jpg"));
},
),
SizedBox(
height: 10,
),
Text(
"${snapshot.data!.productDetail![index].sKUName!}"),
Text(
"Rs: ${snapshot.data!.productDetail![index].salePrice!}",
style: TextStyle(
color: Colors.blue,
fontSize: 20,
fontWeight: FontWeight.bold),
),
Text(
"Rs: ${snapshot.data!.productDetail![index].retailPrice!}",
style: TextStyle(
decoration: TextDecoration.lineThrough,
color: Colors.red),
),
ElevatedButton(
onPressed: () {
var product = snapshot
.data!.productDetail![index].sKUId;
if (cartList.contains(product)) {
print("already exist");
} else {
cartList.add({
"Id": snapshot
.data!.productDetail![index].sKUId
});
}
},
child: Text("Add to Cart"))
],
),
);
});
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
} else {
return CircularProgressIndicator();
}
})
],
),
),
);
}
This is the output of the code
[![output image][1]][1]
The problem is solved it is only not showing because of screen navigation bar now its fine

Flutter: Change ListTile based on Firestore query

I'm trying to configure the appearance of a list tile based on a firestore query.
So I have a set of list tiles as such:
What I want to achieve, when this page is loaded, the left side of the tile marks if a user has completed that particular lesson. So an 'x' means he has not but a 'tick' would mean that he has. Currently it is all hard coded to be 'x':
ListTile makeLessonListTile(Lesson lesson) => ListTile(
contentPadding:
EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
leading: Container(
padding: EdgeInsets.only(right: 12.0),
decoration: new BoxDecoration(
border: new Border(
right: new BorderSide(width: 1.0, color: Colors.white24))),
child: IconButton(
icon: Icon(Icons.close, color: Colors.white), // Hardcoded to be 'x'
),
),
title: Text(
lesson.title,
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
subtitle: Row(
children: <Widget>[
Expanded(
flex: 1,
child: Container(
child: LinearProgressIndicator(
backgroundColor: Color.fromRGBO(209, 224, 224, 0.2),
value: lesson.indicatorValue,
valueColor: AlwaysStoppedAnimation(Colors.green)),
)),
Expanded(
flex: 4,
child: Padding(
padding: EdgeInsets.only(left: 10.0),
child: Text(lesson.level,
style: TextStyle(color: Colors.white))),
)
],
),
trailing:
Icon(Icons.keyboard_arrow_right, color: Colors.white, size: 30.0),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => QuizPage(
lesson: lesson,
auth: widget.auth,
onSignedOut: widget.onSignedOut,
userId: widget.userId,
)
)
);
},
);
Card makeLessonCard(Lesson lesson) => Card(
elevation: 8.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Container(
decoration: BoxDecoration(color: Color.fromRGBO(64, 75, 96, .9)),
child: makeLessonListTile(lesson),
),
);
// the scaffold body
final makeLessonBody = Container(
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: lessons.length,
itemBuilder: (BuildContext context, int index) {
return makeLessonCard(lessons[index]);
},
),
);
I know how to do the query, I'm just not sure where to do it such that when the page loads, it is automatically updated to ticks and crosses based on the user results.
The query would be :
FirebaseUser user = await widget.auth.getCurrentUser();
Firestore.instance
.collection('Users')
.document(user.email)
.collection('Quiz Data')
.document('Courses')
.collection(lesson.abbr.toString().substring(5))
.document(lesson.title)
.get()
.then((DocumentSnapshot ds) {
if (ds.exists) {
if (ds['pass']) return true;
}
return false;
});
Base Auth Class I use for Authentication:
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
abstract class BaseAuth {
Future<String> signIn(String email, String password);
Future<String> signUp(String email, String password);
Future<FirebaseUser> getCurrentUser();
Future<void> sendEmailVerification();
Future<void> signOut();
Future<bool> isEmailVerified();
}
class Auth implements BaseAuth {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
Future<String> signIn(String email, String password) async {
FirebaseUser user = await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return user.uid;
}
Future<String> signUp(String email, String password) async {
FirebaseUser user = await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
return user.uid;
}
Future<FirebaseUser> getCurrentUser() async {
FirebaseUser user = await _firebaseAuth.currentUser();
return user;
}
Future<void> signOut() async {
return _firebaseAuth.signOut();
}
Future<void> sendEmailVerification() async {
FirebaseUser user = await _firebaseAuth.currentUser();
user.sendEmailVerification();
}
Future<bool> isEmailVerified() async {
FirebaseUser user = await _firebaseAuth.currentUser();
return user.isEmailVerified;
}
}
Update - What I tried to do:
Use ternary operator:
class _NavigationPageState extends State<NavigationPage> {
. . . // omitted code
bool passed;
#override
void initState() {
passed = false;
. . . // omitted code
super.initState();
}
checkUserPassedLesson (Lesson lesson) async {
FirebaseUser user = await widget.auth.getCurrentUser();
Firestore.instance
.collection('Users')
.document(user.email)
.collection('Quiz Data')
.document('Courses')
.collection(lesson.abbr.toString().substring(5))
.document(lesson.title)
.get()
.then((DocumentSnapshot ds) {
if (ds.exists) {
if (ds['pass']) {
passed = true;
return;
}
}
passed = false;
});
}
#override
Widget build(BuildContext context) {
// for lesson page
ListTile makeLessonListTile(Lesson lesson) => ListTile(
contentPadding:
EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
leading: Container(
padding: EdgeInsets.only(right: 12.0),
decoration: new BoxDecoration(
border: new Border(
right: new BorderSide(width: 1.0, color: Colors.white24))),
child: IconButton(
icon: passed ? Icon(Icons.done, color: Colors.white) : Icon(Icons.close, color: Colors.white),
),
),
title: Text(
lesson.title,
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
subtitle: Row(
children: <Widget>[
Expanded(
flex: 1,
child: Container(
child: LinearProgressIndicator(
backgroundColor: Color.fromRGBO(209, 224, 224, 0.2),
value: lesson.indicatorValue,
valueColor: AlwaysStoppedAnimation(Colors.green)),
)),
Expanded(
flex: 4,
child: Padding(
padding: EdgeInsets.only(left: 10.0),
child: Text(lesson.level,
style: TextStyle(color: Colors.white))),
)
],
),
trailing:
Icon(Icons.keyboard_arrow_right, color: Colors.white, size: 30.0),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => QuizPage(
lesson: lesson,
auth: widget.auth,
onSignedOut: widget.onSignedOut,
userId: widget.userId,
)
)
);
},
);
Card makeLessonCard(Lesson lesson) => Card(
elevation: 8.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Container(
decoration: BoxDecoration(color: Color.fromRGBO(64, 75, 96, .9)),
child: makeLessonListTile(lesson),
),
);
// query here and route accordingly
final makeLessonBody = Container(
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: lessons.length,
itemBuilder: (BuildContext context, int index) {
checkUserPassedLesson(lessons[index]);
return makeLessonCard(lessons[index]);
},
),
);
. . . // omitted code
return Scaffold(
backgroundColor: Color.fromRGBO(58, 66, 86, 1.0),
appBar: topAppBar,
body: makeLessonBody,
bottomNavigationBar: makeBottom,
);
}
}
Put Query in init:
class _NavigationPageState extends State<NavigationPage> {
... // omitted code
bool passed = false;
Container makeLessonBody;
#override
void initState() {
... // omitted code
// for lesson page
ListTile makeLessonListTile(Lesson lesson) => ListTile(
contentPadding:
EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
leading: Container(
padding: EdgeInsets.only(right: 12.0),
decoration: new BoxDecoration(
border: new Border(
right: new BorderSide(width: 1.0, color: Colors.white24))),
child: IconButton(
icon: passed ? Icon(Icons.done, color: Colors.white) : Icon(Icons.close, color: Colors.white),
),
),
title: Text(
lesson.title,
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
subtitle: Row(
children: <Widget>[
Expanded(
flex: 1,
child: Container(
child: LinearProgressIndicator(
backgroundColor: Color.fromRGBO(209, 224, 224, 0.2),
value: lesson.indicatorValue,
valueColor: AlwaysStoppedAnimation(Colors.green)),
)),
Expanded(
flex: 4,
child: Padding(
padding: EdgeInsets.only(left: 10.0),
child: Text(lesson.level,
style: TextStyle(color: Colors.white))),
)
],
),
trailing:
Icon(Icons.keyboard_arrow_right, color: Colors.white, size: 30.0),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => QuizPage(
lesson: lesson,
auth: widget.auth,
onSignedOut: widget.onSignedOut,
userId: widget.userId,
)
)
);
},
);
Card makeLessonCard(Lesson lesson) => Card(
elevation: 8.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Container(
decoration: BoxDecoration(color: Color.fromRGBO(64, 75, 96, .9)),
child: makeLessonListTile(lesson),
),
);
makeLessonBody = Container(
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: lessons.length,
itemBuilder: (BuildContext context, int index) {
checkUserPassedLesson(lessons[index]);
debugPrint(passed.toString());
return makeLessonCard(lessons[index]);
},
),
);
super.initState();
}
void checkUserPassedLesson (Lesson lesson) async {
FirebaseUser user = await widget.auth.getCurrentUser();
Firestore.instance
.collection('Users')
.document(user.email)
.collection('Quiz Data')
.document('Courses')
.collection(lesson.abbr.toString().substring(5))
.document(lesson.title)
.get()
.then((DocumentSnapshot ds) {
if (ds.exists) {
if (ds['pass']) {
setState(() {
debugPrint(ds['pass'].toString());
passed = true;
});
}
} else {
setState(() {
passed = false;
});}
});
}
... // omitted code
#override
Widget build(BuildContext context) {
... // omitted code
return Scaffold(
backgroundColor: Color.fromRGBO(58, 66, 86, 1.0),
appBar: topAppBar,
body: makeLessonBody,
bottomNavigationBar: makeBottom,
);
}
}
Latest Update: Since the above methods were not working out, I tried to use a FutureBuilder using the ternary operator and it worked.
Full code:
class NavigationPage extends StatefulWidget {
NavigationPage({Key key, this.auth, this.userId, this.onSignedOut, this.userEmail}) : super(key: key);
final BaseAuth auth;
final VoidCallback onSignedOut;
final String userId;
final String userEmail;
#override
_NavigationPageState createState() => _NavigationPageState();
}
class _NavigationPageState extends State<NavigationPage> {
List courses;
List lessons;
String title;
TabStatus tabStatus;
bool showLessons;
bool _isLoading;
#override
void initState() {
title = COURSE_PAGE_TITLE;
_isLoading = false;
tabStatus = TabStatus.COURSE;
showLessons = false;
courses = StaticMethods.getCourses();
// temp value
lessons = StaticMethods.getLessons(Abbr.P01);
super.initState();
}
_signOut() async {
setState(() {
_isLoading = true;
});
try {
await widget.auth.signOut();
widget.onSignedOut();
setState(() {
_isLoading = false;
});
} catch (e) {
setState(() {
_isLoading = false;
});
print(e);
}
}
Widget _showLoading(){
if (_isLoading) {
return Center(
child: ColorLoader5(
dotOneColor: Colors.white24,
dotTwoColor: Colors.white70,
dotThreeColor: Colors.white,
dotType: DotType.circle,
dotIcon: Icon(Icons.adjust),
duration: Duration(seconds: 1),
)
);
}
return Container(height: 0.0, width: 0.0,);
}
Widget _showLoadingTile() {
return Center (
child: Container(
height: MediaQuery.of(context).size.height/10,
width: MediaQuery.of(context).size.width/2,
child: ColorLoader5(
dotOneColor: Colors.white24,
dotTwoColor: Colors.white70,
dotThreeColor: Colors.white,
dotType: DotType.circle,
dotIcon: Icon(Icons.adjust),
duration: Duration(seconds: 1),
),
)
);
}
Future<bool> checkUserPassedLesson (Lesson lesson) async {
bool passed;
await Firestore.instance
.collection('Users')
.document(widget.userEmail)
.collection('Quiz Data')
.document('Courses')
.collection(lesson.abbr.toString().substring(5))
.document(lesson.title)
.get()
.then((DocumentSnapshot ds) {
debugPrint("querying");
if (ds.exists) {
debugPrint('exists');
passed = ds['pass'];
} else passed = false;
});
return passed;
}
#override
Widget build(BuildContext context) {
// for lesson page
ListTile makeLessonListTile(Lesson lesson, bool passed) => ListTile(
contentPadding:
EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
leading: Container(
padding: EdgeInsets.only(right: 12.0),
decoration: new BoxDecoration(
border: new Border(
right: new BorderSide(width: 1.0, color: Colors.white24))),
child: IconButton(
icon: passed ? Icon(Icons.done, color: Colors.white) : Icon(Icons.close, color: Colors.white),
),
),
title: Text(
lesson.title,
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
subtitle: Row(
children: <Widget>[
Expanded(
flex: 1,
child: Container(
child: LinearProgressIndicator(
backgroundColor: Color.fromRGBO(209, 224, 224, 0.2),
value: lesson.indicatorValue,
valueColor: AlwaysStoppedAnimation(Colors.green)),
)),
Expanded(
flex: 4,
child: Padding(
padding: EdgeInsets.only(left: 10.0),
child: Text(lesson.level,
style: TextStyle(color: Colors.white))),
)
],
),
trailing:
Icon(Icons.keyboard_arrow_right, color: Colors.white, size: 30.0),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => QuizPage(
lesson: lesson,
auth: widget.auth,
onSignedOut: widget.onSignedOut,
userId: widget.userId,
)
)
);
},
);
Card makeLessonCard(Lesson lesson, bool passed) => Card(
elevation: 8.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Container(
decoration: BoxDecoration(color: Color.fromRGBO(64, 75, 96, .9)),
child: makeLessonListTile(lesson, passed),
),
);
final makeLessonBody = Container(
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: lessons.length,
itemBuilder: (BuildContext context, int index) {
return FutureBuilder<bool>(
future: checkUserPassedLesson(lessons[index]),
builder: (BuildContext context,
AsyncSnapshot<bool> snapshot) {
if (snapshot.hasError) return new Text('${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Center(child: _showLoadingTile());
default:
return makeLessonCard(lessons[index], snapshot.data);
}
},
);
},
),
);
return Scaffold(
backgroundColor: Color.fromRGBO(58, 66, 86, 1.0),
appBar: topAppBar, // omitted code
body: makeLessonBody,
bottomNavigationBar: makeBottom, // omitted code
);
}
}
You don't have to repeat the function just to change the icon. Use a ternary operator instead (C# example but the concept is the same).
bool passed = checkUserPassedLesson(lesson);
...
IconButton(
icon: passed ? Icon(Icons.done, color: Colors.white) : Icon(Icons.close, color: Colors.white),
),
If passed is true it uses the done icon and close icon if its not.