brianegan / brianegan/flutter_architecture_samples
How to link the data from the internal SQFLite db with that Mysql (localhost)? Recovered data must be based on data entered into the internal db
- Dominant language
- Dart
- Stars
- 8.9k
- Forks
- 1.7k
- PR merge metrics
- No merged PRs in 30d
Description
I have an external database (localhost) that contains a "questions" table characterized by their level (Easy, Medium, Hard) and class(1st class, 2nd class, 3rd class).
I have an internal database that contains a "student" table with level and class attributes that contain in the external database.
I want to post only the questions that correspond to the level and class of the student that is already added in the internal database "SQFLite".
I posted all the questions in the JSON form but did not match the level and class of the student,
But I want when I add a new student with their level and class in the internal database, the questions that are displayed must be matched to that of the student.
**model.dart**: contains the student's model
```
class Student {
int _id;
String _name;
String _level;
String _classes ;
String _date;
Student(this._name, this._level, this._classes, this._date);
Student.withId(this._id, this._name, this._level, this._classes ,this._date);
String get date => _date;
String get level => _level;
String get classes => _classes;
String get name => _name;
int get id => _id;
set date(String value) {
_date = value;
}
set level(String value) {
_level = value;
}
set classes(String value) {
_classes = value;
}
set name(String value) {
if (value.length <= 255) {
_name = value;
}
}
Map toMap() {
var map = Map();
map["id"] = this._id;
map["name"] = this._name;
map["level"] = this._level;
map["classes"] = this._classes;
map["date"] = this._date;
return map;
}
Student.getMap(Map map){
this._id = map["id"];
this._name = map["name"];
this._level = map["level"];
this._classes= map["classes"];
this._date = map["date"];
}
}
```
**sql_helper.dart**: contains the internal database
```
import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart';
import 'dart:async';
import 'dart:io';
import 'model.dart';
import 'package:path_provider/path_provider.dart';
class SQL_Helper {
static SQL_Helper dbHelper;
static Database _database;
SQL_Helper._createInstance();
factory SQL_Helper() {
if (dbHelper == null) {
dbHelper = SQL_Helper._createInstance();
}
return dbHelper;
}
String tableName = "students_table";
String _id = "id";
String __name = "name";
String __level= "level";
String __classes = "classes";
String __date = "date";
Future get database async {
if (_database == null){
_database = await initializedDatabase();
}
return _database;
}
Future initializedDatabase() async {
Directory directory = await getApplicationDocumentsDirectory();
String path = directory.path + "students.db";
var studentDB = await openDatabase(path, version: 1, onCreate: createDatabase);
return studentDB;
}
void createDatabase(Database db, int version) async {
await db.execute(
"CREATE TABLE $tableName($_id INTEGER PRIMARY KEY AUTOINCREMENT, $__name TEXT, $__level TEXT,$__classes TEXT, $__date TEXT )");
}
Future>> getStudentMapList() async {
Database db = await this.database;
var result = await db.query(tableName, orderBy: "$_id ASC");
return result;
}
Future insertStudent(Student student) async {
Database db = await this.database;
var result = await db.insert(tableName, student.toMap());
return result;
}
Future updateStudent(Student student) async{
Database db = await this.database;
var result = await db.update(tableName, student.toMap(), where: "$_id = ?", whereArgs: [student.id]);
return result;
}
Future deleteStudent(int id) async {
var db = await this.database;
int result = await db.rawDelete("DELETE FROM $tableName WHERE $_id = $id");
return result;
}
Future getCount() async {
Database db = await this.database;
List> all = await db.rawQuery("SELECT COUNT (*) FROM $tableName");
int result = Sqflite.firstIntValue(all);
return result;
}
Future> getStudentList() async{
var studentMapList = await getStudentMapList();
int count = studentMapList.length;
List students = new List();
for (int i = 0; i <= count -1; i++){
students.add(Student.getMap(studentMapList[i]));
}
return students;
}
}
```
**main.dart**
```
import 'package:flutter/material.dart';
import 'package:relationtables/sql_helper.dart';
import 'package:sqflite/sqflite.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import 'dart:convert';
import 'model.dart';
import 'dart:async';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
title: "Students List",
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.cyan
),
home: StudentsList(),
);
}
}
class StudentsList extends StatefulWidget{
@override
State createState() {
// TODO: implement createState
return StudentsState();
}
}
class StudentsState extends State {
SQL_Helper helper = new SQL_Helper();
List studentsList;
int count = 0;
@override
Widget build(BuildContext context) {
if (studentsList == null) {
studentsList = new List();
updateListView();
}
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text("Students"),
),
body: getStudentsList(),
floatingActionButton: FloatingActionButton(
onPressed: () {
navigateToStudent(Student('','','', ''), "Add New Student");
},
tooltip: 'Add Student',
child: Icon(Icons.add),
)
);
}
ListView getStudentsList() {
return ListView.builder(
itemCount: count,
itemBuilder: (BuildContext context, int position) {
return Card(
color: Colors.white,
elevation: 2.0,
child: ListTile(
leading: Icon(Icons.person_pin),
title: Text(this.studentsList[position].name),
subtitle: Text(this.studentsList[position].level+ " | " + this.studentsList[position].classes+' '+this.studentsList[position].date),
trailing:
GestureDetector(
child: Icon(Icons.delete, color: Colors.grey,),
onTap: () {
_delete(context, this.studentsList[position]);
},
)
,
onTap: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) {
return Menu();
}));
},
),
);
});
}
void _delete(BuildContext context, Student student) async {
int ressult = await helper.deleteStudent(student.id);
if (ressult != 0) {
_showSenckBar(context, "Student has been deleted");
updateListView();
}
}
void _showSenckBar(BuildContext context, String msg) {
final snackBar = SnackBar(content: Text(msg),);
Scaffold.of(context).showSnackBar(snackBar);
}
void updateListView() {
final Future db = helper.initializedDatabase();
db.then((database) {
Future> students = helper.getStudentList();
students.then((theList) {
setState(() {
this.studentsList = theList;
this.count = theList.length;
});
});
});
}
void navigateToStudent(Student student, String appTitle) async {
bool result = await Navigator.push(
context, MaterialPageRoute(builder: (context) {
return StudentDetail(student, appTitle);
}));
if (result) {
updateListView();
}
}
}
class StudentDetail extends StatefulWidget{
String screenTitle;
Student student;
StudentDetail(this.student , this.screenTitle);
@override
State createState() {
// TODO: implement createState
return Students(this.student, screenTitle);
}
}
class Students extends State {
static var _level = ["Easy", "Medium","Hard"];
static var _classes =["1st class", "2nd class","3rd class"];
String screenTitle;
Student student;
SQL_Helper helper = new SQL_Helper();
Students(this.student ,this.screenTitle);
TextEditingController studentName = new TextEditingController();
@override
Widget build(BuildContext context) {
TextStyle textStyle = Theme
.of(context)
.textTheme
.title;
studentName.text = student.name;
// TODO: implement build
return
WillPopScope(
onWillPop: () {
debugPrint("WillPopScope Button");
goBack();
},
child: Scaffold(
appBar: AppBar(
title: Text(screenTitle),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
goBack();
},
),
),
body: Padding(
padding: EdgeInsets.only(top: 15.0, left: 10.0, right: 10.0),
child: ListView(
children: [
Padding(
padding: EdgeInsets.only(top: 15.0, bottom: 15.0),
child: TextField(
controller: studentName,
style: textStyle,
onChanged: (value) {
student.name = value;
},
decoration: InputDecoration(
labelText: "Name :",
labelStyle: textStyle,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
)
),
),
),
Row(
children: [
SizedBox(width: 3),
Expanded(
child: DropdownButton(
isDense: true,
hint: Text('Level'),
isExpanded: true,
iconSize: 20,
items: _level.map((String dropDownStringItem) {
return DropdownMenuItem(
value: dropDownStringItem,
child: Text(dropDownStringItem),
);
}).toList(),
value: student.level == '' ? null : student.level,
onChanged: (String value) {
updateLevel(value);
},
),
),
SizedBox(width: 3),
Expanded(
child: DropdownButton(
isDense: true,
hint: Text('Class'),
isExpanded: true,
iconSize: 20,
items: _classes.map((String dropDownStringItem) {
return DropdownMenuItem(
value: dropDownStringItem,
child: Text(dropDownStringItem),
);
}).toList(),
value: student.classes == '' ? null : student.classes,
onChanged: (String value) {
updateClass(value);
},
),
),
],
),
Padding(
padding: EdgeInsets.only(top: 15.0, bottom: 15.0),
child: Row(
children: [
Expanded(
child: RaisedButton(
color: Theme
.of(context)
.primaryColorDark,
textColor: Theme
.of(context)
.primaryColorLight,
child: Text(
'SAVE', textScaleFactor: 1.5,
),
onPressed: () {
setState(() {
debugPrint("User Click SAVED");
_save();
});
},
),
),
Container(width: 5.0,),
Expanded(
child: RaisedButton(
color: Theme
.of(context)
.primaryColorDark,
textColor: Theme
.of(context)
.primaryColorLight,
child:
Text(
'Delete', textScaleFactor: 1.5,
),
onPressed: () {
setState(() {
debugPrint("User Click Delete");
_delete();
});
},
),
),
],
),
)
],
),
),
)
);
}
void goBack() {
Navigator.pop(context, true);
}
void updateLevel(String value) {
setState(() {
student.level = value;
});
}
void updateClass(String value) {
setState(() {
student.classes = value;
});
}
void _save() async {
goBack();
student.date = DateFormat.yMMMd().format(DateTime.now());
int result;
if (student.id == null) {
result = await helper.insertStudent(student);
} else {
result = await helper.updateStudent(student);
}
if (result == 0) {
showAlertDialog('Sorry', "Student not saved");
} else {
showAlertDialog('Congratulations', 'Student has been saved successfully');
}
}
void showAlertDialog(String title, String msg){
AlertDialog alertDialog = AlertDialog(
title: Text(title),
content: Text(msg),
);
showDialog(context: context, builder: (_) => alertDialog);
}
void _delete() async {
goBack();
if (student.id == null){
showAlertDialog('Ok Delete', "No student was deleted");
return;
}
int result = await helper.deleteStudent(student.id);
if (result == 0) {
showAlertDialog('Ok Delete', "No student was deleted");
} else {
showAlertDialog('Ok Delete', "Student has been deleted");
}
}
}
class Menu extends StatefulWidget {
@override
_MenuState createState() => _MenuState();
}
class _MenuState extends State {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.tealAccent,
padding: EdgeInsets.only(top:150),
child: Center(
child: GridView.count(
crossAxisCount: 1,
padding: EdgeInsets.all(50),
children: [
Card(
margin: EdgeInsets.all(70.0),
child: InkWell(
onTap: (){
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Questions()
),
);
},
splashColor: Colors.deepPurple,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.library_books, size:70.0, color:Colors.blue,),
Text("Questions List",style: new TextStyle(fontSize: 20.0,color: Colors.black , fontWeight: FontWeight.bold))
],
),
),
)
),
]
),
)
);
}
}
class Questions extends StatefulWidget {
@override
_QuestionsState createState() => _QuestionsState();
}
class _QuestionsState extends State {
getMethod()async{
String theUrl = 'http://10.0.2.2/Try/Try.php';
var res = await http.get(Uri.encodeFull(theUrl),headers:{"Accept":"application/json"});
var responsBody = json.decode(res.body);
print(responsBody);
return responsBody;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title:Text("Questions", style: TextStyle(fontWeight: FontWeight.bold),) ,
backgroundColor: Colors.blue[700],
),
backgroundColor: Colors.blue[99],
body:FutureBuilder(
future: getMethod(),
builder: (BuildContext context , AsyncSnapshot snapshot){
List snap = snapshot.data;
if(snapshot.connectionState == ConnectionState.waiting){
return Center(
child: CircularProgressIndicator(),
);
}
if(snapshot.hasError){
return Center(
child: Text("Error .... "),
);
}
return ListView.separated(
separatorBuilder: (context, index) => Divider(
color: Colors.indigo,
),
itemCount: snap.length,
itemBuilder: (context,index){
return ListTile(
title: Text(
"${snap[index]['description']}", style: TextStyle(fontSize: 18.0)),
leading:Icon(Icons.question_answer, color:Colors.green , size: 20, ) ,
);
},
);
},
),
);
}
}
```
Contributor guide
Research direction
Start by reading model.dart, sql_helper.dart, and the student-selection flow in main.dart to trace how level and class are stored and how questions are loaded. Determine how the external MySQL data is exposed to the Flutter app, then verify that the displayed questions are filtered by the selected student's level and class.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- dart, flutter, mysql
- Domain
- databases, mobile-dev
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100