I am creating a workout app using flutter & firebase. I have an ExerciseStream
class which contains a StreamBuilder widget. in the StreamBuilder contains a ListView. in the ListView I pass the ExerciseCard
class. In the ExerciseCard class I have if statements which determines which type of card I wanna return. A CardiovascularCard
and a StrengthCard
. but I get an error inside the if statements.
solution
instead of data!.docs[widget.index][exerciseType] == strength
I did this data!.docs[widget.index]['exerciseType'] == strength
and it worked. I was missing the quotes around exercisetype
error
when I hover over data!.docs[widget.index][exerciseType] as String == 'strength'
in ExerciseCard
Class
I get this error:
The argument type 'String?' can't be assigned to the parameter type 'Object'
where is the 'object' in this situation?
code
ExerciseStream
class _ExerciseStreamState extends State<ExerciseStream> {
@override
Widget build(BuildContext context) {
bool? firstLoad = false;
CollectionReference users = FirebaseFirestore.instance.collection('users');
return StreamBuilder<QuerySnapshot>(
stream: users
.doc(FirebaseAuth.instance.currentUser?.uid.toString())
.collection('workout')
.orderBy('exerciseName', descending: true)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
List<Map<String, dynamic>?>? documentData = snapshot.data?.docs
.map((e) => e.data() as Map<String, dynamic>?)
.toList();
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
} else {
if (snapshot.hasError) {
return const Center(child: Text('Something went wrong'));
} else {
if (snapshot.data!.size == 0) {
firstLoad = false;
Future.delayed(Duration.zero, () => ExerciseTypeDialog(context))
.then((_) => firstLoad = true);
return const SizedBox(height: 0.0);
} else {
firstLoad = true;
print('documentData = $documentData');
return Expanded(
child: ListView.builder(
itemCount: snapshot.data!.size,
itemBuilder: (context, index) {
return CardiovascularCard(snapshot, index);
}),
);
}
}
}
});
}
}
ExerciseTypeDialog
TextEditingController exerciseNameController = TextEditingController();
final uid = FirebaseAuth.instance.currentUser?.uid;
String? exerciseType;
String? strength = 'Strength';
String? cardiovascualar = 'Cardiovascular';
Future<void> ExerciseTypeDialog(BuildContext context) {
return showDialog(
barrierDismissible: firstLoad ?? true,
context: context,
builder: (context) {
return AlertDialog(
backgroundColor: Colors.blueGrey,
title: const Text('Exercise type'),
content: Column(mainAxisSize: MainAxisSize.min, children: [
ListTile(
onTap: () {
exerciseType = strength;
Navigator.pop(context);
Future.delayed(
Duration.zero,
() => ExerciseNameDialog(
context, exerciseType!, strength, cardiovascualar));
},
title: Text(strength!),
),
ListTile(
onTap: () {
exerciseType = cardiovascualar;
Navigator.pop(context);
Future.delayed(
Duration.zero,
() => ExerciseNameDialog(
context, exerciseType!, strength, cardiovascualar));
},
title: Text(cardiovascualar!),
),
]),
);
});
}
ExerciseNameDialog
TextEditingController exerciseNameController = TextEditingController();
final uid = FirebaseAuth.instance.currentUser?.uid;
Future<void> ExerciseNameDialog(
BuildContext context, String exerciseType, strength, cardiovascualar) {
return showDialog(
barrierDismissible: firstLoad ?? true,
context: context,
builder: (context) {
return AlertDialog(
backgroundColor: Colors.blueGrey,
title: Text(exerciseType),
content: TextField(
controller: exerciseNameController,
),
actions: [
GradientElevatedButton(
onPressed: () async {
if (exerciseType == strength &&
exerciseNameController.text.isNotEmpty) {
print(exerciseType);
await FirebaseFirestore.instance
.collection('users')
.doc(uid)
.collection('workout')
.add({
'exerciseName': exerciseNameController.text,
'reps': 0.toString(),
'sets': 0.toString(),
'weight': 0.0.toString(),
'rest': 0.0.toString(),
'exerciseType': exerciseType
});
exerciseNameController.clear();
Navigator.pop(context);
} else {
if (exerciseType == cardiovascualar &&
exerciseNameController.text.isNotEmpty) {
await FirebaseFirestore.instance
.collection('users')
.doc(uid)
.collection('workout')
.add({
'exerciseName': exerciseNameController.text,
'caloriesBurnt': 0,
'time': 0.0,
'exerciseType': exerciseType
});
exerciseNameController.clear();
Navigator.pop(context);
} else {
SnackBar _snackBar = const SnackBar(
content: Text("Text field can't be empty"),
);
ScaffoldMessenger.of(context).showSnackBar(_snackBar);
}
}
},
child: const Text(
'ADD',
style: TextStyle(color: Colors.white),
))
],
);
});
}
ExerciseCard
class ExerciseCard extends StatefulWidget {
AsyncSnapshot<QuerySnapshot> snapshot;
int index;
ExerciseCard(this.snapshot, this.index, {Key? key}) : super(key: key);
@override
State<ExerciseCard> createState() => _ExerciseCardState();
}
class _ExerciseCardState extends State<ExerciseCard> {
@override
Widget build(BuildContext context) {
final data = widget.snapshot.data;
if (data!.docs[widget.index][exerciseType] as String == 'strength') {
return StrengthCard(widget.snapshot, widget.index);
} else if (data.docs[widget.index][exerciseType].toString() ==
'cardiovascualar') {
return CardiovascularCard(widget.snapshot, widget.index);
} else {
Future.delayed(Duration.zero, () => ExerciseTypeDialog(context));
return const SizedBox(height: 0.0);
}
}
}
CardiovascularCard
class CardiovascularCard extends StatefulWidget {
AsyncSnapshot<QuerySnapshot> snapshot;
int index;
CardiovascularCard(this.snapshot, this.index, {Key? key})
: super(key: key);
@override
State<CardiovascularCard> createState() => _CardiovascularCardState();
}
String deleteExerciseText = 'Delete exercise';
final uid = FirebaseAuth.instance.currentUser?.uid;
TextEditingController _calorieController = TextEditingController();
TextEditingController _timeController = TextEditingController();
class _CardiovascularCardState extends State<CardiovascularCard> {
@override
Widget build(BuildContext context) {
String deleteExerciseText = 'Delete exercise';
final uid = FirebaseAuth.instance.currentUser?.uid;
final data = widget.snapshot.data;
final exerciseId = data!.docs[widget.index].reference.id;
void deleteExerciseFunction() {
FirebaseFirestore.instance
.runTransaction((Transaction myTransaction) async {
myTransaction.delete(data.docs[widget.index].reference);
});
}
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(children: [
Card(
elevation: 8,
color: const Color.fromARGB(255, 81, 108, 122),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
data.docs[widget.index]['exerciseName'],
style: const TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
),
),
const Divider(thickness: 1.0),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: const [
Text(
'Calories',
style: TextStyle(color: Colors.white),
),
Text(
'Time',
style: TextStyle(color: Colors.white),
),
],
),
Slidable(
endActionPane: ActionPane(
motion: const ScrollMotion(),
children: [
SlidableAction(
onPressed: (context) {
DialogInstance(context, deleteExerciseFunction,
deleteExerciseText);
},
label: 'Delete',
backgroundColor: Colors.red,
icon: Icons.delete,
)
],
),
child: ListTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.145,
child: TextField(
style: const TextStyle(fontWeight: FontWeight.bold),
cursorColor: Colors.white,
onSubmitted: (value) async {
FirebaseFirestore.instance.runTransaction(
(Transaction myTransaction) async {
FirebaseFirestore.instance
.collection('users')
.doc(uid)
.collection('workout')
.doc(exerciseId)
.update({'caloriesBurnt': value});
});
},
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
controller: _calorieController,
decoration: InputDecoration(
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
hintText: data.docs[widget.index]['caloriesBurnt']
.toString()),
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.145,
child: TextField(
style: const TextStyle(fontWeight: FontWeight.bold),
cursorColor: Colors.white,
onSubmitted: (value) async {
FirebaseFirestore.instance.runTransaction(
(Transaction myTransaction) async {
FirebaseFirestore.instance
.collection('users')
.doc(uid)
.collection('workout')
.doc(exerciseId)
.update({'time': value});
});
},
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
controller: _timeController,
decoration: InputDecoration(
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
hintText:
data.docs[widget.index]['time'].toString()),
),
),
],
),
),
),
],
),
),
]),
);
}
}
StrengthCard
class StrengthCard extends StatefulWidget {
final AsyncSnapshot<QuerySnapshot> snapshot;
int index;
StrengthCard(this.snapshot, this.index, {Key? key}) : super(key: key);
@override
State<StrengthCard> createState() => _StrengthCardState();
}
String deleteExerciseText = 'Delete exercise';
final uid = FirebaseAuth.instance.currentUser?.uid;
late TextEditingController _setsController;
late TextEditingController _repsController;
late TextEditingController _weightController;
late TextEditingController _restController;
class _StrengthCardState extends State<StrengthCard> {
@override
void initState() {
_repsController = TextEditingController();
_setsController = TextEditingController();
_weightController = TextEditingController();
_restController = TextEditingController();
super.initState();
}
@override
Widget build(BuildContext context) {
final data = widget.snapshot.data;
final exerciseId = data!.docs[widget.index].reference.id;
void deleteExerciseFunction() {
FirebaseFirestore.instance
.runTransaction((Transaction myTransaction) async {
myTransaction.delete(data.docs[widget.index].reference);
});
}
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(children: [
Card(
elevation: 8,
color: const Color.fromARGB(255, 81, 108, 122),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
data.docs[widget.index]['exerciseName'],
style: const TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
),
),
const Divider(thickness: 1.0),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: const [
Text(
'Reps',
style: TextStyle(color: Colors.white),
),
Text(
'Sets',
style: TextStyle(color: Colors.white),
),
Text(
'Weight',
style: TextStyle(color: Colors.white),
),
Text(
'rest',
style: TextStyle(color: Colors.white),
)
],
),
Slidable(
endActionPane: ActionPane(
motion: const ScrollMotion(),
children: [
SlidableAction(
onPressed: (context) {
DialogInstance(context, deleteExerciseFunction,
deleteExerciseText);
},
label: 'Delete',
backgroundColor: Colors.red,
icon: Icons.delete,
)
],
),
child: ListTile(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.145,
child: TextField(
style: const TextStyle(fontWeight: FontWeight.bold),
cursorColor: Colors.white,
onSubmitted: (value) async {
FirebaseFirestore.instance.runTransaction(
(Transaction myTransaction) async {
FirebaseFirestore.instance
.collection('users')
.doc(uid)
.collection('workouts')
.doc(exerciseId)
.update({'reps': value});
});
},
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
controller: _repsController,
decoration: InputDecoration(
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
hintText:
data.docs[widget.index]['reps'].toString()),
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.145,
child: TextField(
style: const TextStyle(fontWeight: FontWeight.bold),
cursorColor: Colors.white,
onSubmitted: (value) async {
FirebaseFirestore.instance.runTransaction(
(Transaction myTransaction) async {
FirebaseFirestore.instance
.collection('users')
.doc(uid)
.collection('workout')
.doc(exerciseId)
.update({'sets': value});
});
},
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
controller: _setsController,
decoration: InputDecoration(
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
hintText:
data.docs[widget.index]['sets'].toString()),
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.145,
child: TextField(
style: const TextStyle(fontWeight: FontWeight.bold),
cursorColor: Colors.white,
onSubmitted: (value) async {
FirebaseFirestore.instance.runTransaction(
(Transaction myTransaction) async {
FirebaseFirestore.instance
.collection('users')
.doc(uid)
.collection('workout')
.doc(exerciseId)
.update({'weight': value});
});
},
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
controller: _weightController,
decoration: InputDecoration(
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
hintText:
data.docs[widget.index]['weight'].toString()),
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.145,
child: TextField(
style: const TextStyle(fontWeight: FontWeight.bold),
cursorColor: Colors.white,
onSubmitted: (value) async {
FirebaseFirestore.instance.runTransaction(
(Transaction myTransaction) async {
FirebaseFirestore.instance
.collection('users')
.doc(uid)
.collection('workout')
.doc(exerciseId)
.update({'rest': value});
});
},
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
controller: _restController,
decoration: InputDecoration(
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
hintText:
data.docs[widget.index]['rest'].toString()),
),
),
],
),
),
),
],
),
),
]),
);
}
}
Thanks!
CodePudding user response:
If you are sure that it's type is string, try cast it with as
keyword
CodePudding user response:
Try this
data!.docs[widget.index][exerciseType]?.toString() == 'strength'
Remove '?' if the variable is non-nullable
CodePudding user response:
instead of data!.docs[widget.index][exerciseType] == strength
I did this data!.docs[widget.index]['exerciseType'] == strength
and it worked