i'm currently developing an e-commerce app,
i'm trying to increase the quantity of items the user are trying to shop and then show them in the "items Cart" but instead, i get multiple times the same item.
cart_Items_Screen
here's the code i'm using for it:
FlatButton(
onPressed: () {
_addToCart(context, this.widget.product);
},
textColor: Colors.redAccent,
child: Row(
children: [
Text('Add to Cart'),
IconButton(
icon: Icon(Icons.shopping_cart), onPressed: () {}),
],
),
),
_addToCart(BuildContext context, Product product) async {
var result = await _cartService.addToCart(product);
if (result > 0) {
print(result);
_showSnackMessage(Text(
'Item added to cart successfully!',
style: TextStyle(color: Colors.green),
));
} else {
_showSnackMessage(Text(
'Failed to add to cart!',
style: TextStyle(color: Colors.red),
));
}
}
addToCart(Product product) async {
List<Map> items =
await _repository.getLocalByCondition('carts', 'productId', product.id);
if (items.length > 0) {
product.quantity = items.first['productQuantity'] + 1;
return await _repository.updateLocal(
'carts', 'productId', product.toMap());
}
print(items);
product.quantity = 1;
return await _repository.saveLocal('carts', product.toMap());
}
Have anyone has experience something like this?
Can anyone help me?
What are you using to keep your items? Local database or just a list? In any case you need to check your items contains first, then if it is you need update only quantity if it is not you need to add as a new element. I mean as I understand you check this with items.length > 0 and it looks too general, items.contains('productId') would be more specific to use.
Related
So I'm relatively new to flutter and I've been trying to dynamically add Sections(TextFormFields) that are represented in a form that has Form.Helper as its child and in the process to get the saveAndValidate method to work i had to use a GlobalKey to be able to access the currentState of its so i can validate and save user input and such, but whenever i try add another Section to the screen it display this error massage
════════ Exception caught by widgets library ═══════════════════════════════════
Multiple widgets used the same GlobalKey.
════════════════════════════════════════════════════════════════════════════════
here is the code I wrote and I'd appreciate any help in solving this error please.
#1- the code for the model I used:
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class AddCourse with ChangeNotifier {
String? sectionName;
List<String>? sections;
List<dynamic>? addVids;
AddCourse({this.sectionName, this.sections, this.addVids});
/*where we save our values later to push them to firbase/database*/
Map<String, dynamic> toJson() {
final Map<String, dynamic> sectionData = <String, dynamic>{};
sectionData['Section #'] =
sections; // where current section number is saved and is stored dynamicly and updates as user adds more or less sections.
sectionData['Section Name'] =
sectionName; // where the input of the textformfield is saved and to be later pushed to the database and also is stored in a list so it can hold multiple section names as such.
return sectionData;
}
/* this is another model data for a functionality thats not implemented yet*/
Map<dynamic, dynamic> toJson2() {
final Map<dynamic, dynamic> vidData = <dynamic, dynamic>{};
vidData['Videos #'] = addVids;
return vidData;
}
}
#2 this the code for the form I created
import 'package:flutter/material.dart';
import 'package:snippet_coder_utils/FormHelper.dart';
import '../provider/course_add_model.dart';
class CourseCardBody extends StatefulWidget {
const CourseCardBody({
Key? key,
}) : super(key: key);
#override
State<CourseCardBody> createState() => _CourseCardBodyState();
}
class _CourseCardBodyState extends State<CourseCardBody> {
/* this is where i set up my global key that has the type of GlobalKey<FormState>*/
/*State associated with a [Form] widget. such as textformfields/forms/textfields..etc// the use of the (FormState) is to be able to Access the Functions "save"/"validate"/"reset" as to use them with forms/textformfields that you want to validate thier input or save it*/
GlobalKey<FormState> globalkey = GlobalKey();
AddCourse coursesModel = AddCourse();
#override
void initState() {
super.initState();
coursesModel.sections = List<String>.empty(growable: true);
coursesModel.sections?.add("");
// adds empty sections to the list of sections when the add button is used
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Add Courses'),
centerTitle: true,
),
body: ListView.separated(
shrinkWrap: true,
physics: const ScrollPhysics(),
itemBuilder: ((context, index) => Column(
children: [
_uiWidget(index),
Center(
// the submit button here needs some work to only be show once but for now sorry for this annoying button.
child: FormHelper.submitButton('Save', () {
if (validateAndSave()) {
print(coursesModel.toJson());
}
}),
),
],
)),
separatorBuilder: ((context, index) => const Divider()),
itemCount: coursesModel.sections!.length,
),
);
}
Widget _uiWidget(index) {
/* this form here is the parent of form fields/Formhelper widgets as seen below*/
return Form(
/* -- note here--
if we use a UniqueKey()
instead of our globalkey
here and comment the ValidateAndSave() function here
the form will work in terms of adding and removing sections
but we won't be able to either
save content/input of the user in the fields or
either validate
them so that sucks. */
/*this form is where global key is first used*/
key: globalkey,
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_sectionsContainer(index),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
flex: 1,
fit: FlexFit.loose,
child: FormHelper.inputFieldWidgetWithLabel(
context,
'Add Section$index',
'',
'Section Title',
(onValidate) {
if (onValidate.isEmpty) {
return 'section ${index + 1} name cant be empty';
}
return null;
},
(onSavedVal) {
coursesModel.sections![index++] = index.toString();
onSavedVal = index;
},
onChange: (onChangedval) {
coursesModel.sectionName = onChangedval;
},
initialValue: coursesModel.sectionName ?? "",
borderColor: Colors.black,
borderFocusColor: Colors.black,
fontSize: 14,
labelFontSize: 14,
validationColor: Colors.redAccent,
),
),
Visibility(
visible: index == coursesModel.sections!.length - 1,
child: IconButton(
onPressed: () {
addEmailControl();
},
icon: const Icon(
Icons.add_circle,
color: Colors.greenAccent,
),
),
),
Visibility(
visible: index > 0,
child: SizedBox(
width: 35,
child: IconButton(
onPressed: () {
removeEmailControl(index);
},
icon: const Icon(
Icons.remove_circle,
color: Colors.redAccent,
),
),
),
),
],
),
],
),
),
);
}
Widget _sectionsContainer(index) {
/* the widget used to create the current section displayed on the top left of each textformfields*/
return Column(
children: [
Padding(
padding: const EdgeInsets.all(10),
child: Text(
'Section ${index + 1}',
textAlign: TextAlign.left,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
),
],
);
}
void addEmailControl() {
setState(() {
coursesModel.sections!.add('');
});
}
void removeEmailControl(index) {
setState(() {
if (coursesModel.sections!.length > 1) {
coursesModel.sections!.removeAt(index);
}
});
}
bool validateAndSave() {
/* we're especially using the <FormState> that is provided by the Globalkey to be able access the currentState of widget/form that has the global key in order to either validate or save the textformfields input or both in the same time*/
// validate each form
if (globalkey.currentState!.validate()) {
// If all data are correct then save data to out variables
// save each form
globalkey.currentState!.save();
return true;
} else {
return false;
}
}
}
I'm trying my best to figure it out on my own as I want to know how to solve this problem properly and where did I go wrong, and any help is very much appreciated thank you!
I suggest to create List<GlobalKey> variable. When you dynamically add or delete sub forms, you add or remove list items accordingly. It is impossible to use same GlobalKey for multiple widgets. So you need to create separate GlobalKeys for each form.
You may create a file of Global variables that may be shared across multiple files to ensure you are using a single instance.
Example globals.dart file
GlobalKey<SomeState> myGlobalKey = GlobalKey<SomeState>();
Example of implementation inside main.dart (or whatever file)
import './[path-to-globals]/globals.dart' // enter the appropriate path for your project
... // some code
Form(
key: myGlobalKey,
... // code
)
... // maybe more code
I’m making a conversation starter app and inside this app, there are different categories of questions a user can choose from. This is how the home page of the app looks like after the user logs in:
The way I’m currently listing all these categories is by saving the category names as the document ID’s under a collection I call ‘users’. Then I use the following snippet of code to get all these document IDs/ categories and add them to a List. I then use a FutureBuilder to convert this List<String> to a List of buttons. The code below can help clarify what I am doing:
Step 1: get all document IDs/category names:
List<String> questionCategories = [];
Future getCategories() async {
await FirebaseFirestore.instance
.collection('users')
.get()
.then((snapshot) => snapshot.docs.forEach(
(document) {
questionCategories.add(document.reference.id);
));
}
Step 2: Use the questionCategories List<String> to create a List of buttons
FutureBuilder(
future: getCategories(),
builder: (context, snapshot) {
return SizedBox(
height: MediaQuery.of(context).size.height - 250,
child: ListView.builder(
itemCount: questionCategories.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: //questionPageInit,
() {
print(collectionList);
Navigator.push(context,
MaterialPageRoute(builder: (context) {
//return ForgotPasswordPage();
return CategoryPage(
categoryName: questionCategories[index],
);
}));
},
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.deepPurple,
borderRadius: BorderRadius.circular(12),
),
child: Center(
child: Text(questionCategories[index],
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
))))),
);
},
),
);
},
),
Upon picking a category, questions are displayed one at a time on a question card, wherein below this card a user can switch between the next and previous questions and then shuffle. This page looks like so:
The way I’m getting these questions displayed is by getting a List of all the fields under a document ID and adding it to a List<String>. When the user presses shuffle, next, or previous, I just change a global index variable and set the state again to display a new question based on which question appears to be at that specific index in the List. The following code should help clarify what I am doing:
void printAllQuestionsList(snapshot) {
Map<String, dynamic> data = snapshot.data() as Map<String, dynamic>;
for (String key in data.keys) {
print(key + data[key]!);
questionsList.add(data[key]);
}
}
Future getQuestionList() async {
if (questIndex > 1) {
return;
}
if (widget.categoryName == "ALL") {
await FirebaseFirestore.instance
.collection('users')
.get()
.then(((snapshot) => snapshot.docs.forEach((document) {
print(document.reference.id);
FirebaseFirestore.instance
.collection('users')
.doc(document.reference.id)
.get()
.then((snapshot) => {printAllQuestionsList(snapshot)});
})));
} else {
await FirebaseFirestore.instance
.collection('users')
.doc(widget.categoryName)
.get()
.then((snapshot) => {printQuestionList(snapshot)});
}
}
Inside the widget Build function, I have this snippet of code:
FutureBuilder(
future: getQuestionList(),
builder: ((context, snapshot) {
// return TextField(
// decoration: InputDecoration(
// enabledBorder: OutlineInputBorder(
// borderSide: BorderSide(
// width: 5, //<-- SEE HERE
// color: Colors.greenAccent,
// ),
// borderRadius: BorderRadius.circular(50.0),
// ),
// ),
// );f
return Container(
margin: const EdgeInsets.all(15.0),
padding: const EdgeInsets.all(10.0),
width: 350,
height: 350,
decoration: BoxDecoration(
color: Colors.deepPurple[200],
borderRadius:
BorderRadius.all(Radius.circular(20))
// border: Border.all(color: Colors.blueAccent)
),
child: Align(
alignment: Alignment.center,
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Text(
questionsList[index],
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 32,
),
textDirection: TextDirection.ltr,
textAlign: TextAlign.center,
),
),
));
}))
I have a second page on this app that is used to submit questions to an existing or new Category (if they enter the right password that I set).
I use the following snippet of code to do so:
Future addQuestion(String category, String question) async {
var usersRef = questionCollection.doc(category);
await FirebaseFirestore.instance
.collection('users')
.get()
.then((snapshot) => snapshot.docs.forEach(
(document) {
existingQuestionCategories.add(document.reference.id);
},
));
if (existingQuestionCategories.contains(category)) {
print("Document Exists! ");
questionCollection.doc(category).update({question: question});
} else {
// FieldPath pathfield = FieldPath.fromString(category);
//String category2 = pathfield.category;
print('No such document exists so now about to set document anew!');
print(category);
FirebaseFirestore.instance
.collection("users")
.doc(category)
.set({question: question});
}
}
Here’s how my Firestore database is organized
Users -> Question Categories (Document IDs) -> question Key: question field
This is how I want to set it up:
Users -> Autogenerated ID -> Question Categories as collections -> question key (titled “question”): question key (“the actual question here)
This way under each collection I can also list fields pertaining to the question like if it’s light, medium, or deep that I may be able to add on to later.
I also want to do it this way because sometimes when I try to use my submit question page, the question I type does not get submitted and I think it may be because I’m submitting the question under a document ID and not under a collection.
In summary, my question to you is how do I list all the questions on my home page as a list of collections from my database? Also, how would this change the code I wrote to (1) view the questions on individual cards when clicking a category name and (2) submit new questions to a specific category/collection?
If what I’m trying to do cannot be done in the way I want it done, is there a more efficient way to do this?
I tried searching for how to get a list of collections on Firestore on Flutter but all the answers I found gave me a solution on how to get a List of fields under a document ID. This is why I'm asking this question.
Actually the Firebase SDK for Flutter ( and I'm assuming that for Android/IOS) doesn't have any pre-built methods to get a List of all collections in the firestore database.
But, as I know you can get them with a cloud function written as example with Node.js, refer to this and this.
if you're willing to write a cloud function to achieve this on your flutter project, then it's fine.
However, I can think about a practical solution, if that interest's you:
Create another collection/document where you list your firestore collections, for your precedent collections, I guess you have no option but to add them manually, but if you're creating new collections for the future in your project, you can implement general methods that check for the existence of a collection name, and act based on it.
I have a listView, in which I have some products. I wanted a rating system on each product details page so I go through this answer How to save User rating in flutter rating bar?. Now the problem is that I am getting my star rating the same on each product detail page. Now please suggest to me, to save the value of the star with respect to product id in my shared preferences.
Or anyone has another solution please share it with me.
Rating Controller
class RatingController extends GetxController {
int currentRating = 0;
final box = GetStorage();
late SharedPreferences prefs;
#override
void onInit() { // called whenever we initialize the controller
super.onInit();
currentRating = box.read('rating') ?? 0; // initializing current rating from storage or 0 if storage is null
}
void updateAndStoreRating(int rating) {
currentRating = rating;
prefs.setInt('rating', rating); //SharedPreferences way
update(); // triggers a rebuild of the GetBuilder Widget
}
Future<void> initSp() async {
prefs = await SharedPreferences.getInstance();
currentRating = prefs.getInt('rating') ?? 0;
}
Widget buildRatingStar(int index) {
if (index < currentRating) {
return Icon(
Icons.star,
color: Colors.yellow,
);
} else {
return Icon(
Icons.star,
color: Colors.white,
);
}
}
}
Rating Widget
SharedPreferences? _prefs;
final controller = Get.find<RatingController>();
Widget _buildBody() {
final stars = List<Widget>.generate(5, (index) {
return GetBuilder<RatingController>( // rebuilds when update() is called from GetX class
builder: (controller) => Expanded(
child: GestureDetector(
child: controller.buildRatingStar(index),
onTap: () {
controller.updateAndStoreRating(index + 1);
print(index + 1);// +1 because index starts at 0 otherwise the star rating is offset by one
},
),
),
);
});
return Row(
children: [
Expanded(
child: Row(
children: stars,
),
),
Expanded(
child: TextButton(
onPressed: () {
controller.updateAndStoreRating(0);
},
child: Text(
"Clear",
style: TextStyle(color: Colors.white),
),
),
),
],
);
}
This working and saving star values but I am getting this value in all my list data's detail page. so please suggest me to save using particular index.
GetStorage cant save Map based data type and in your case it's better to use Hive :
First, add hive to your dependencies:
hive: ^2.0.4
hive_flutter: ^1.1.0
Then initialize it at the beginning of the application:
await Hive.initFlutter();
And use it like this:
var box = await Hive.openBox('myBox');
var person = Person()
..name = 'Dave'
..age = 22;
box.add(person);
print(box.getAt(0)); // Dave - 22
person.age = 30;
person.save();
print(box.getAt(0)) // Dave - 30
You can see more examples about using hive in this link.
I have a FLUTTER problem that I couldn't solve.
Scenario:
1. Implement a QR reader application.
2. The app, read the QR code
3. When you read the QR code, you redirect me to a user's detail page
Problem:
I want to edit that person's data, that's why place a TexFormField, valid fields, but when I call
FUTURE function to send the parameters by post, transforming the body in a JSON so that my server detects it, the button DOES NOTHING.
This is My code
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
child : Text("Escanea el codigo QR ", style: TextStyle(fontSize: 25.0),)
),
),
floatingActionButton: FloatingActionButton(
onPressed: obtenerValorQR,
child: Icon(Icons.settings_overscan,),
backgroundColor:Color(0xFF56AB2F)
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
---------------------------LOGIC -------------------------
Future obtenerValorQR()
async{
_scantemp= await FlutterBarcodeScanner.scanBarcode("#004297", "salir", true);
setState(() {
value=_scantemp;
});
if (value == null) {
Navigator.pushNamed(context, QrPageRoute);
} else {
Navigator.pushNamed(context, HomePageRoute, arguments: value);
}
}
2. App read QR code
Widget _infoPerfilUsuario(BuildContext context , index ){
return Container(
height: 120.0,
child: Card(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: ListTile(
leading: CircleAvatar(backgroundImage:
NetworkImage(widget.usuarios[index].urlFoto), radius: 30.0,),
title: Text("Nombre: ${widget.usuarios[index].nombres}"),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("Apellidos: ${widget.usuarios[index].apellidos}"),
Text("Zona: ${widget.usuarios[index].territorio}")
],
),
),
)
),
);
}
QR DETAIL
4. I WANT TO OTHER PARAMETERS IN DETAILPAGE FOR EXAMPLE " PESO" BUT TH RAISED BUTTON DONT COMPILE THE CODE
Code where I send the "peso" parameter that I implement, but does not do what I am looking for.
widget _botonesAcciones(BuildContext context , int index ){
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
RaisedButton(child: Text("SAVE "), color: Colors.green,
onPressed: () {
final form = formKey.currentState;
if(form.validate()) {
_sendData( context , index );
Navigator.pushNamed(context, QrPageRoute);
}
}
),
],
);
}
I IMPLEMENT THIS FUNCTION IF THE FIELD IS VALIDATED, I just want the data to be sent, I don't want the response body returned, just send the data to my DataBase
Future <void> _sendData (BuildContext context , int index ) async {
final url = Uri.https( _url,'/searchdata.php');
await http.post(url,
body: json.encode({
"id" : "${widget.usuarios[index].idUsuarioMobile}",
"peso" : peso
}),
);
}
Something is wrong?
I think my mistake is in the sendData () function
Hi the solucion is simple:
void _sendData(BuildContext context , int index ) {
var url = Uri.https( _url,'/updatePuntos.php');
http.post(url,
body: json.encode({
"id" : "${widget.usuarios[index].idUsuarioMobile}",
"peso" : peso
}),
);
Looking for me econtre, the answer to my question, was something as simple as returning a void method and sending the data to the server. You should use,
body: json.encode
it will make your life easier.
Im having trouble populating ListTile in ListView.builder from database.
I dont have "model class" since i dont need to update delete data i just need simple query.
I have ExpansionTile with three categories and in each one i need query from db. I dont know hoe to write or what to return from db class for this to work.
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemBuilder: (context, i) => ExpansionTile(
title: new Text(
'${categoryName[i]}',
style: TextStyle(
fontSize: 18,
fontStyle: FontStyle.normal,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(49, 85, 158, 1)),
),
children: list //final list = new List.generate(17, (i) => "Item ${i + 1}"); --just to populete with dummy items, instad of this i need db data
.map((val) => ListTile(
// leading: Icon(Icons.add),
title: new Row(
children: <Widget>[
new Checkbox(
value: _isCheck,
onChanged: (bool value) {
onChange(value);
}),
new Expanded(child: new Text(val)),
],
)))
.toList(),
),
itemCount: categoryName.length,
),
),
],
),
From my db class :
Future<List> getAllNotes() async {
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'books.db');
Database database = await openDatabase(path, version: 1);
//var dbClient = await database();
var result = await database.rawQuery('SELECT * FROM $booksTable WHERE $colDescription = ${'Adventure'}');
return result.toList();
}
So how to write simple query to get result in ListView/ListTile?
You really need to provide much more details about your problem. Anyways, ill try to answer with what I have understood.
Let's say you have a table names 'booksTable' with 3 fields:
bookId | bookName | bookCategory
1 Book A Adventure
2 Book B History
3 Book C Adventure
4 Book D History
Make sure you create all these database functions in DatabaseHelper() class, so that you don't have to write logic to db again and again.
Now you query will look something like this:
Future<List<String>> getAllNotes(String category) async {
var dbClient = await database();
List<String> bookNames = List<String();
var result = await dbClient.rawQuery("SELECT bookname FROM booksTable WHERE bookCategory = $category");
result.forEach((item) {
bookNames.add(item["bookname"]);
});
return bookNames;
}
This will work only if you have to deserialise 1 column. If you have multiple columns selected, you have to create a model class.
Now in your front view, you have two options:
1) You can use initState to populate your List with bookNames of category in the parameter
2) You can use FutureBuilder to populate your list as well
(You have to use StatefulWidget for both these options)
I'll show you how to do it using initState here. If you want to know how to do it using FutureBuilder, let me know in comments.
List<String> booksList =List<String>();
var db = DatabaseHelper();
readList() async {
booksList = await db.getAllNotes("Adventure");
}
#override
void initState() {
super.initState();
readList();
}
ListView.builder(
itemBuilder: (context, i) {
Column( crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
ExpansionTile(
title: new Text(
"Adventure Category",
style: TextStyle(
fontSize: 18,
fontStyle: FontStyle.normal,
fontWeight: FontWeight.bold,
color: Color.fromRGBO(49, 85, 158, 1)),
),
ListTile(
title: new Row(
children: <Widget>[
new Checkbox(
value: _isCheck,
onChanged: (bool value) {
onChange(value);
}),
Expanded(child: new Text("${booksList[i]}")),
],
)))
),])}
itemCount: booksList.length,
),
),
],
)
Note: There might be typos in the code above, since i have typed it on phone, but you get the idea how to do it, right?
So, i have ListView (with 3 expanded groups) im geting them from array: ( List categoryName = ['Part 1: Adventure', 'Part 2: History','Part 3: Horror'];
And passing then here :
child: Column(
children: [
Expanded(
child: ListView.builder(
itemBuilder: (context, i) => ExpansionTile(
title: new Text(
'${categoryName[i]}',
),
That part working fine, i get 3 expandeble titles, now children of that ( ListTile ) need to be populate from db .
With your example :
readList() async {
sinsAgainstGod = await db.getSins("Adventure");
}
I get error: ...near "Adventure": syntax error..
And keep geting 0 lenght on booksList...
Future<List<String>> getNotes(String category) async {
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'books.db');
Database database = await openDatabase(path, version: 1);
List<String> bookNames = List<String>();
var result = await database.rawQuery("SELECT $colDescription FROM $booksTable WHERE = $category ");
result.forEach((item) {
bookNames.add(item['Category']);
});
return bookNames;
}
What this result.forEach(item) suppose to do?
Thank you for your answer it was helpful.
Can you tell me why im getting 20 same description instead literate through all with this code:
Future<List<String>> getSins(String column) async {
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'confession.db');
Database database = await openDatabase(path, version: 1);
List<String> bookNames = List<String>();
for (int i = 0; i < 20; i++) {
var result = await database.rawQuery(
'SELECT * FROM $plannerTable WHERE $colCategory= "Adventure');
bookNames.add((result[0][column].toString()));
}
return bookNames;
}
I want to get all decription from adventure category. Tnx