How to configure the eventloader with data from sqlite? - flutter

Hi I'm beginner of flutter
I want to make marker on my calendar with eventloader
I try to take the data from SQLite and deliver it to the eventloader, but I saw the log that it failed because it was a Future type.
Sqlite has data List of "Challenge"
event loader need Map<DateTime, List> selectedEvents
When I exit and run the application again, the events stored in the currently selected event disappear.
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_auth/firebase_auth.dart';
import ...
// //
main(){
WidgetsFlutterBinding.ensureInitialized();
runApp(HomePage());
}
// //
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
late Map<DateTime, List<Event>> selectedEvents;
CalendarFormat format = CalendarFormat.month;
DateTime selectedDay = DateTime.now();
DateTime focusedDay = DateTime.now();
DatabaseReference ref = FirebaseDatabase.instance.ref("performance");
List<Challenge> makeList = [];
Map<DateTime, List<dynamic>> _events = {};
TextEditingController _eventController = TextEditingController(); // 텍스트 필드에서 text 가져오기
String name = "";
#override
void initState() {
selectedEvents = {};
super.initState();
}
List<Event> _getEventsfromDay(DateTime date) {
return selectedEvents[date] ?? [];
}
#override
void dispose() {
_eventController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: const Color(0xfff2a900),
title: Text("Challenge"),
centerTitle: true,
),
body: Column(
children: [
TableCalendar(
focusedDay: selectedDay,
firstDay: DateTime(1990),
lastDay: DateTime(2050),
calendarFormat: format,
onFormatChanged: (CalendarFormat _format) {
setState(() {
format = _format;
});
},
startingDayOfWeek: StartingDayOfWeek.sunday,
daysOfWeekVisible: true,
//Day Changed
onDaySelected: (DateTime selectDay, DateTime focusDay) {
setState(() {
selectedDay = selectDay;
focusedDay = focusDay;
});
// print(focusedDay);
},
selectedDayPredicate: (DateTime date) {
return isSameDay(selectedDay, date);
},
eventLoader: _getEventsfromDay,
//To style the Calendar
calendarStyle: CalendarStyle(
isTodayHighlighted: true,
selectedDecoration: BoxDecoration(
color: Color(0xff60584C),
// color: (255, 188, 80),
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10.0),
),
selectedTextStyle: TextStyle(color: Colors.white),
todayDecoration: BoxDecoration(
color: const Color(0xfff2a900),
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10.0),
),
defaultDecoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10.0),
),
weekendDecoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10.0),
),
),
headerStyle: HeaderStyle(
formatButtonVisible: true,
titleCentered: true,
formatButtonShowsNext: false,
formatButtonDecoration: BoxDecoration(
color: Color(0xff60584C),
borderRadius: BorderRadius.circular(10.0),
),
formatButtonTextStyle: TextStyle(
color: Colors.white,
),
),
),
/// 새로추가
Expanded(
child:FutureBuilder<List<Challenge>>(
future: DatabaseHelper.instance.getChallenge(),
builder: (BuildContext context,
AsyncSnapshot<List<Challenge>> snapshot){
if(!snapshot.hasData){
return Center(child:Text('Loading'));
}
return snapshot.data!.isEmpty
? Center(child:Text('챌린지에 참여해보세요!'))
: ListView( // 챌린지 리스트
children: snapshot.data!.map((challenge){
DateTime sqlDate = DateTime.parse(challenge.date);
return Card(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(10),
child: Row(
children: [
SizedBox(
width: 200,
height: 50,
child: Center(
child: Text(challenge.challenge,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
color: const Color(0xff60584C),
),
),
)
),
],
)
),
Container(
// width: MediaQuery.of(context).size.width * 0.7,
child: Align(
alignment: Alignment.bottomRight,
child: Text(
challenge.date,
style: TextStyle(
fontSize: 15,
color: Colors.grey),
),
),
)
],
)
);
return Center(
child:ListTile(
title:Text(challenge.challenge),
),
);
}).toList(),
);
}),
),
],
),
floatingActionButton: FloatingActionButton.extended(
backgroundColor: Color(0xfff2a900),
onPressed: () => showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text("Today's Challenge"),
content: TextFormField(
controller: _eventController,
),
actions: [
TextButton(
child: Text("Cancel"),
onPressed: () => Navigator.pop(context),
),
TextButton(
child: Text("Ok"),
onPressed: () async {
// 텍스트 필드가 비었을 때
if (_eventController.text.isEmpty) {
} else { // challenge 입력
/// 마커만들 때 쓰일 Map<DateTime, List<Event>> 원소 추가 코드
if (selectedEvents[selectedDay] != null) {
selectedEvents[selectedDay]?.add(
Event(title: _eventController.text),
);
} else {
selectedEvents[selectedDay] = [
Event(title: _eventController.text)
];
}
///
// 로그인한 사용자정보
User? user = FirebaseAuth.instance.currentUser;
for(final providerProfile in user!.providerData){
final emailAddress = providerProfile.email;
List<String>? currentUser = emailAddress?.split('#');
name = currentUser![0];
}
// 현재 날짜
final dateStr = DateFormat('yyyy-MM-dd').format(selectedDay);
// realtime firebase
await ref
.child(name)
.set(_eventController.text)
.asStream();
// sqlite
await DatabaseHelper.instance.add(
Challenge(date:dateStr, challenge: _eventController.text),
);
// _fetchEvents();
}
Navigator.pop(context);
_eventController.clear();
setState((){
///
///
});
return;
},
),
],
),
),
label: Text("🌱"),
icon: Icon(Icons.add),
),
);
}
}
class Challenge{
final int? id;
final String date;
final String challenge;
Challenge({this.id, required this.date, required this.challenge});
factory Challenge.fromMap(Map<String, dynamic> json) => new Challenge(
id : json['id'],
date : json['date'],
challenge: json['challenge']);
Map<String, dynamic> toMap(){
return {
'id' : id,
'date' : date,
'challenge' : challenge,
};
}
}
class DatabaseHelper{
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
static Database? _database;
Future<Database> get database async => _database ??=await _initDatabase();
Future<Database> _initDatabase() async{
String path = join(await getDatabasesPath(), 'my_challenge.db');
return await openDatabase(
path,
version: 1,
onCreate: _onCreate,
);
}
Future _onCreate(Database db, int version) async{
await db.execute('''
CREATE TABLE my_challenge(
id INTEGER PRIMARY_KEY,
date TEXT,
challenge TEXT
)
''');
}
Future<List<Challenge>> getChallenge() async {
Database db = await instance.database;
var challenges = await db.query('my_challenge', orderBy: 'date');
List<Challenge> challengeList = challenges.isNotEmpty
? challenges.map((c)=>Challenge.fromMap(c)).toList()
:[];
/// selectedEvents : Map<Datetime, List<Event>>
///
return challengeList;
}
Future<int> add(Challenge challenge) async{
Database db = await instance.database;
return await db.insert('my_challenge', challenge.toMap());
}
}
class Event
class Event {
final String title;
Event({required this.title});
String toString() => this.title;
}

Related

Return null value between two dates in sqflite and flutter

i have spent three days for find solution but nothing , always have a same value NULL!
I create database and the function to calculate total in chossing period here :
1/ class Database
class DatabaseHelper {
static DatabaseHelper _databaseHelper; // Singleton DatabaseHelper
static Database _database; // Singleton Database
String clientTable = 'client_table';
String colId = 'id';
String colNumerotelephone = 'numerotelephone';
String colCode = 'code';
String colPrix = 'prix';
String colPriority = 'priority';
String colColor = 'color';
String colDate = 'date';
DatabaseHelper._createInstance(); // Named constructor to create instance of DatabaseHelper
factory DatabaseHelper() {
if (_databaseHelper == null) {
_databaseHelper = DatabaseHelper
._createInstance(); // This is executed only once, singleton object
}
return _databaseHelper;
}
Future<Database> get database async {
if (_database == null) {
_database = await initializeDatabase();
}
return _database;
}
Future<Database> initializeDatabase() async {
Directory directory = await getApplicationDocumentsDirectory();
String path = directory.path + 'clients.db';
var clientsDatabase =
await openDatabase(path, version: 1, onCreate: _createDb);
return clientsDatabase;
}
void _createDb(Database db, int newVersion) async {
await db.execute(
'CREATE TABLE $clientTable($colId INTEGER PRIMARY KEY AUTOINCREMENT, $colNumerotelephone TEXT,$colCode TEXT, '
'$colPrix REAL, $colPriority INTEGER, $colColor INTEGER,$colDate TEXT)');
}
.......
// code where i get the null value
Future claculTotalPeriod (String startDate, String endDate) async {
var totalClientperiod = await database;
var resulttotalperiod = await totalClientperiod.rawQuery("SELECT SUM($colPrix) AS TOTAL from $clientTable WHERE $colDate BETWEEN '$startDate' AND '$endDate'");
return resulttotalperiod.toList();
}
}
2/and this class for displaying database data
class ClientList extends StatefulWidget {
const ClientList({Key key}) : super(key: key);
#override
State<StatefulWidget> createState() {
return ClientListState();
}
}
class ClientListState extends State<ClientList> {
DatabaseHelper databaseHelper = DatabaseHelper();
List<Client> clientList;
double somme_period = 00;
String somme_total_period = "00.00";
String startDate='';
String endDate='';
TextEditingController startdate = TextEditingController();
TextEditingController finishdate = TextEditingController();
void calcul_total_period() async {
var totalSumPeriod = (await databaseHelper.claculTotalPeriod(startDate, endDate))[0]['TOTAL']; //['$startDate''$endDate'];
setState(() {
somme_period = totalSumPeriod ?? 00;
somme_total_period = somme.toStringAsFixed(2);
});
}
#override
Widget build(BuildContext context) {
if (clientList == null) {
clientList = [];
updateListView();
}
return Scaffold(
appBar: myAppBar(),
body: clientList.isEmpty
? Container(
color: Colors.white,
child: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text('ADD Client',
style: Theme.of(context).textTheme.bodyText2),
),
),
)
: Container(
color: Colors.white,
child: getClientsList(),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
navigateToDetail(Client('', '', '', 3, 0, 0.0), 'new');
},
tooltip: 'Add',
shape: const CircleBorder(
side: BorderSide(color: Colors.black, width: 2.0)),
child: const Icon(Icons.add, color: Colors.black),
backgroundColor: Colors.white,
),
bottomNavigationBar: OutlinedButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return Container(
margin: const EdgeInsets.all(20),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
color: Colors.white,
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(height: 20,),
TextField(
controller: startdate,
//editing controller of this TextField
decoration: const InputDecoration(
icon: Icon(Icons.calendar_today), //icon of text field
labelText: "start date" //label text of field
),
readOnly: true,
//set it true, so that user will not able to edit text
onTap: () async {
DateTime pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2022,12),
lastDate: DateTime(2026,12));
if (pickedDate != null) {
print(
pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000
String formattedDate =
DateFormat('yyyy-MM-dd').format(pickedDate);
print(
formattedDate); //formatted date output using intl package => 2021-03-16
setState(() {
startdate.text =
formattedDate;
startDate = startdate.text.toString(); //set output date to TextField value.
});
} else {}
},
),
const SizedBox(height: 20,),
TextField(
controller: finishdate,
//editing controller of this TextField
decoration: const InputDecoration(
icon: Icon(Icons.calendar_today), //icon of text field
labelText: "end date" //label text of field
),
readOnly: true,
//set it true, so that user will not able to edit text
onTap: () async {
DateTime pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2022,12),
lastDate: DateTime(2026,12));
if (pickedDate != null) {
print(
pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000
String formattedDate =
DateFormat('yyyy-MM-dd').format(pickedDate);
print(
formattedDate); //formatted date output using intl package => 2021-03-16
setState(() {
finishdate.text =
formattedDate; //set output date to TextField value.
endDate = finishdate.text.toString();
});
} else {}
},
),
const SizedBox(height: 20,),
OutlinedButton(
onPressed: () {
calcul_total_period();
},
child: const Text(' period total')),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
somme_total_period,
style: Theme.of(context).textTheme.headline5,
textAlign: TextAlign.center,
),
),
],
),
),
);
});
},
child: const Text('totalinperiod')),
);
}
void updateListView() {
final Future<Database> dbFuture = databaseHelper.initializeDatabase();
dbFuture.then((database) {
Future<List<Client>> clientListFuture = databaseHelper.getClientList();
clientListFuture.then((clientList) {
setState(() {
this.clientList = clientList;
count = clientList.length;
});
});
});
}
}
when i execute the code always i get the null value for the resulttotalperiod
can same one help me please.

Put request in flutter ,does not update the object when I change only one field on edit screen

When making a put request and I edit all the field the object is updated. But if I only update one field on the edit screen than the object is not update. I think this is because the unchanged controllers do not keep the value that is already given to them in the Set state method.
Can anyone give me some hints how to solve this ?
import 'package:fin_app/apiservice/variables.dart';
import 'package:fin_app/screens/reminder/reminder_screen.dart';
import 'package:fin_app/screens/login_screen/login_screen.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../../models/user.dart';
import '../monthly_expense/expense_app_theme.dart';
const String myhomepageRoute = '/';
const String myprofileRoute = 'profile';
class ReminderEdit extends StatefulWidget {
final String id;
final String title;
final String date;
final int amount;
const ReminderEdit({Key? key, required this.id, required this.title,required this.date,required this.amount}) : super(key: key);
#override
_ReminderEditState createState() => _ReminderEditState();
}
class _ReminderEditState extends State<ReminderEdit> {
final GlobalKey<FormState> _formKey = GlobalKey();
String id="";
final TextEditingController _titleInput = TextEditingController();
final TextEditingController _dateInput = TextEditingController();
final TextEditingController _amountInput = TextEditingController();
Future<Reminder>? _futureReminder;
Future<void> edit(String id,String title,String date,int amount) async {
Map<String, String> requestHeaders = {
'Content-type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $token'
};
final editReminder = jsonEncode({
'title': title,
'date': date,
'amount': amount
});
if (_titleInput.text.isNotEmpty &&
_dateInput.text.isNotEmpty ) {
var response = await http.put(
Uri.parse("$baseUrl/reminder/me/$id/details"),
body: editReminder,
headers: requestHeaders);
if (response.statusCode == 200) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Profile edited succesfully.")));
} else {
print(response.statusCode);
print(id);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Could not edit the reminder.")));
}
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Please fill out the field.")));
}
}
#override
void initState() {
_dateInput.text = ""; //set the initial value of text field
super.initState();
setState(() {
id = widget.id;
_titleInput.text = widget.title;
_dateInput.text = widget.date;
_amountInput.text=widget.amount.toString();
});
}
void navigate() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AlarmPage()),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: ExpenseAppTheme.background,
body: Padding(
padding: const EdgeInsets.all(16.0),
child: ListView(
children: <Widget>[
const Align(
alignment: Alignment.topLeft,
child: Text("Edit reminder",
style: TextStyle(
fontSize: 24,
)),
),
const SizedBox(
height: 20,
),
Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
TextFormField(
controller: _titleInput,
decoration: const InputDecoration(
labelText: 'Title',
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0)),
borderSide:
BorderSide(color: Colors.grey, width: 0.0),
),
border: OutlineInputBorder()),
keyboardType: TextInputType.number,
validator: (value) {
if (value == null ||
value.isEmpty ||
value.contains(RegExp(r'^[a-zA-Z\-]'))) {
return 'Use only text!';
}
},
),
const SizedBox(
height: 20,
),
TextFormField(
controller:_dateInput, //editing controller of this TextField
decoration: InputDecoration(
icon: Icon(Icons.calendar_today), //icon of text field
labelText: "Enter Date" //label text of field
),
readOnly:
true, //set it true, so that user will not able to edit text
onTap: () async {
DateTime? pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(
2000), //DateTime.now() - not to allow to choose before today.
lastDate: DateTime(2101));
if (pickedDate != null) {
print(
pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000
String formattedDate =
DateFormat('yyyy-MM-dd').format(pickedDate);
print(
formattedDate); //formatted date output using intl package => 2021-03-16
//you can implement different kind of Date Format here according to your requirement
setState(() {
_dateInput.text =
formattedDate; //set output date to TextField value.
});
} else {
print("Date is not selected");
}
},
),
const SizedBox(
height: 35,
),
TextFormField(
controller: _amountInput,
decoration: const InputDecoration(
labelText: 'Amount',
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0)),
borderSide:
BorderSide(color: Colors.grey, width: 0.0),
),
border: OutlineInputBorder()),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Amount must not be empty';
} else if (value.contains(RegExp(r'^[0-9]*$'))) {
return 'Amount must only contain numbers';
}
},
), const SizedBox(
height: 20,
),
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size.fromHeight(60)),
onPressed: () {
edit(widget.id,_titleInput.text,_dateInput.text,int.parse(_amountInput.text));
navigate();
},
child: const Text("Submit"),
),
],
),
),
],
),
),
);
}
FutureBuilder<Reminder> buildFutureBuilder() {
return FutureBuilder<Reminder>(
future: _futureReminder,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text('Expense added');
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
);
}
}

Provider not rebuilding on flutter

suddently from nowhere i came up with provider not re rendering my home page when it's updated. I've inspected it and it IS UPDATED. It has newer data when i change it in firebase but the UI won't re-render showing the new data. That's my code:
Main function
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:my_event_app/pages/HomePage/home_page.dart';
import 'package:my_event_app/pages/Login/login_page.dart';
import 'package:my_event_app/providers/User/user.dart';
import 'package:provider/provider.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => UserModel()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
// is not restarted.
primarySwatch: Colors.blue,
),
home: const Wrapper(),
),
);
}
}
class Wrapper extends StatelessWidget {
const Wrapper({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.userChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
User? user = snapshot.data;
if (user == null) {
return const LoginPage();
}
return StreamBuilder<DocumentSnapshot>(
stream: FirebaseFirestore.instance
.collection('users')
.doc(FirebaseAuth.instance.currentUser!.uid)
.snapshots(),
builder: (context, userSnapshot) {
if (userSnapshot.hasData) {
Provider.of<UserModel>(context, listen: true)
.fromJson(userSnapshot.data!.data());
return const HomePage();
}
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
});
} else {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
},
);
}
}
And this is the home page:
import 'package:flutter/material.dart';
import 'package:my_event_app/http/auth/user/sign_out.dart';
import 'package:my_event_app/pages/Create_Event/create_event_page.dart';
import 'package:my_event_app/pages/Onboarding/onboarding_page.dart';
import 'package:my_event_app/providers/User/user.dart';
import 'package:my_event_app/widgets/event_card_widget.dart';
import 'package:provider/provider.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Consumer<UserModel>(builder: (context, user, child) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.help_outline, color: Colors.black, size: 30),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return const OnboardingPage();
}));
},
),
actions: [
IconButton(
icon: const Icon(
Icons.arrow_forward_ios_sharp,
color: Colors.black,
),
onPressed: () {
signOut();
},
),
],
elevation: 0,
backgroundColor: Colors.white,
),
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Container(
color: Colors.white,
padding: const EdgeInsets.all(16),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const CircleAvatar(
radius: 25,
backgroundImage: NetworkImage(
"https://cdnnmundo1.img.sputniknews.com/img/07e5/09/13/1116212032_100:0:1273:1173_1920x0_80_0_0_efb734331af13dfe11ff6d43293c60e2.png"),
),
Container(
height: 50,
width: 50,
decoration: BoxDecoration(
color: Colors.orange[400],
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
spreadRadius: 1,
blurRadius: 5,
offset: const Offset(0, 3),
),
],
),
child: Center(
child: IconButton(
color: Colors.white,
onPressed: () {
// Navigate to add event widget
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return const CreateEventPage();
}));
},
icon: const Icon(Icons.add),
),
),
),
],
),
const SizedBox(height: 32),
SizedBox(
width: double.infinity,
child: Text('Welcome, ${user.name}',
style: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
fontFamily: "Roboto")),
),
const SizedBox(height: 32),
Container(
padding: const EdgeInsets.all(16),
height: 100,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
spreadRadius: 1,
blurRadius: 5,
offset: const Offset(0, 3),
),
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Stack(alignment: Alignment.center, children: [
SizedBox(
height: 45,
width: 45,
child: CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation(Colors.orange[400]),
value: 14 / 20,
semanticsValue: "14/20",
color: Colors.black,
),
),
const Text("78%",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
fontFamily: "Roboto")),
]),
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text("Weekly progress",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
)),
Text("14/20 tasks completed"),
],
),
const Icon(Icons.bar_chart),
],
),
),
Container(
margin: const EdgeInsets.symmetric(vertical: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
Text("You have 5 tasks for today",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
)),
Icon(Icons.calendar_today_outlined)
],
),
),
_renderEvents(user),
],
),
),
),
);
});
}
}
Column _renderEvents(UserModel user) {
return Column(
children: [
for (var event in user.events)
EventCard(
eventId: event,
),
],
);
}
And here's the provider:
import 'package:flutter/material.dart';
class UserModel extends ChangeNotifier {
String _name = '';
String _surnames = '';
String _uid = '';
String _email = '';
List<dynamic> _events = [];
String get name => _name;
String get surnames => _surnames;
String get uid => _uid;
String get email => _email;
List<dynamic> get events => _events;
UserModel();
set name(String value) {
_name = value;
notifyListeners();
}
set surnames(String value) {
_surnames = value;
notifyListeners();
}
set uid(String value) {
_uid = value;
notifyListeners();
}
set email(String value) {
_email = value;
notifyListeners();
}
set events(List<dynamic> value) {
_events = value;
notifyListeners();
}
void addEvent(String event) {
_events.add(event);
notifyListeners();
}
void removeEvent(String event) {
_events.remove(event);
notifyListeners();
}
void updateUser(String name, String uid) {
name = name;
uid = uid;
notifyListeners();
}
void clearUser() {
_name = '';
_uid = '';
notifyListeners();
}
Map<String, dynamic> toJson() {
return {
'name': _name,
'surnames': _surnames,
'uid': _uid,
'email': _email,
'events': _events
};
}
fromJson(Object? json) {
try {
Map<dynamic, dynamic> map = json as Map<dynamic, dynamic>;
_name = map['name'];
_surnames = map['surnames'];
_uid = map['uid'];
_email = map['email'];
_events = map['events'];
} catch (e) {
print(e);
}
}
}
```
As you can see i use Consumer in order to read data and i have a change notifier in the begginig, but it won't re render and show for example new name if i change it in fireabase.
Thank you so much!
You are using fromJson method to update values in UserModel, but it does not call notifyListeners. Add notifyListeners(); to the end of this method:
fromJson(Object? json) {
try {
Map<dynamic, dynamic> map = json as Map<dynamic, dynamic>;
_name = map['name'];
_surnames = map['surnames'];
_uid = map['uid'];
_email = map['email'];
_events = map['events'];
notifyListeners(); // add this
} catch (e) {
print(e);
}
}
Also some other things:
Consider declaring class UserModel with ChangeNotifier instead of class UserModel extends ChangeNotifier.
fromJson methods usually are acting as factory methods, meaning these return a new instance, and don't set members in an existing instance.
Instead of Provider.of<UserModel>(context, listen: true).fromJson(userSnapshot.data!.data()); you can try: context.read<UserModel>().fromJson(userSnapshot.data!.data());. Here you don't really need listening, you just want to find the provider and call fromJson. Your Consumer is the one which is listening to the changes accordingly.

Using Flutter GetX and an API, how do I display the API data into a Text widget?

I have been watching YouTube videos and reading how to use GetX to display API data but I cannot get it to work with my API. I cannot figure out what I am missing to be able to display the price of a stock from my StockQuoteModel. I am attempting to put the price into the trailing section of my ListView but do not know how to access the data.
Picture of the App
main.dart
void main() async {
await GetStorage.init();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
homepage.dart
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
final StockController sC = Get.put(StockController());
final StockQuoteController sQC = Get.put(StockQuoteController());
TextEditingController tEC = TextEditingController();
return Scaffold(
appBar: AppBar(
title: Text('Add to List Practice'),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Get.bottomSheet(
Container(
height: 150,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.fromLTRB(100, 0, 100, 10),
child: TextField(
controller: tEC,
autofocus: true,
maxLines: 1,
autocorrect: false,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.characters,
decoration: InputDecoration(
labelText: 'Add Stock',
border: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.black87,
),
borderRadius: BorderRadius.circular(10),
),
),
onSubmitted: (text) {
sC.stocks.add(Stock(symbol: tEC.text));
tEC.clear();
Get.back();
},
),
),
// SizedBox(height: 15),
ElevatedButton(
onPressed: () {
sC.stocks.add(Stock(symbol: tEC.text));
tEC.clear();
Get.back();
},
child: Text('Enter'),
style: ElevatedButton.styleFrom(
primary: Colors.blue,
),
),
],
),
),
enableDrag: false,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30.0),
topRight: Radius.circular(30.0)),
),
backgroundColor: Colors.white,
);
},
child: Icon(Icons.add),
),
body: Container(
child: Padding(
padding: EdgeInsets.all(5),
child: Obx(
() => ListView.separated(
itemCount: sC.stocks.length,
separatorBuilder: (context, index) {
return Divider(
color: Colors.black,
thickness: 0.1,
height: 0.0,
);
},
itemBuilder: (context, index) {
return Dismissible(
key: UniqueKey(),
direction: DismissDirection.endToStart,
onDismissed: (direction) {
sC.stocks.removeAt(index);
},
background: Container(
alignment: Alignment.centerRight,
padding: EdgeInsets.only(right: 20.0),
color: Colors.red,
child: Icon(
Icons.delete,
color: Colors.white,
),
),
child: ListTile(
leading: Text(
sC.stocks[index].symbol,
),
trailing: Obx(() {
if (sQC.isLoading.value)
return Text('loading');
else
return Text(
sQC.stockQuote.price); // stuck here!
}),
),
);
},
),
),
),
),
);
}
}
services.dart
class StockQuoteServices {
static Future<StockQuote?> getStockQuote() async {
String url =
'https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=sq&apikey=***********';
http.Response response;
response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
StockQuote stockQuote = StockQuote.fromJson(json.decode(response.body));
return stockQuote;
} else {
return null;
}
}
}
This is the api json
{
"Global Quote": {
"01. symbol": "SQ",
"02. open": "261.8500",
"03. high": "267.7700",
"04. low": "261.2800",
"05. price": "264.0000",
"06. volume": "6374083",
"07. latest trading day": "2021-07-23",
"08. previous close": "260.5900",
"09. change": "3.4100",
"10. change percent": "1.3086%"
}
}
controller.dart
class StockController extends GetxController {
var stocks = [].obs;
void add(Stock s) {
stocks.add(s);
}
#override
void onInit() {
List? storedStocks = GetStorage().read<List>('stocks');
if (storedStocks != null) {
stocks = storedStocks.map((e) => Stock.fromJson(e)).toList().obs;
}
ever(stocks, (_) {
GetStorage().write('stocks', stocks.toList());
});
super.onInit();
}
}
class StockQuoteController extends GetxController {
var isLoading = true.obs;
var stockQuote = StockQuote().obs;
#override
void onInit() {
getStockQuote();
super.onInit();
}
void getStockQuote() async {
try {
isLoading(true);
var quotes = await StockQuoteServices.getStockQuote();
if (quotes != null) {
stockQuote.value = quotes;
}
} finally {
isLoading(false);
}
}
}
stockmodel.dart
class Stock {
String symbol;
Stock({required this.symbol});
factory Stock.fromJson(Map<String, dynamic> json) =>
Stock(symbol: json['symbol']);
Map<String, dynamic> toJson() => {'symbol': symbol};
}
stockquotemodel.dart
class StockQuote {
GlobalQuote? globalQuote;
StockQuote({this.globalQuote});
StockQuote.fromJson(Map<String, dynamic> json) {
globalQuote = json['Global Quote'] != null
? new GlobalQuote.fromJson(json['Global Quote'])
: null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.globalQuote != null) {
data['Global Quote'] = this.globalQuote?.toJson();
}
return data;
}
}
class GlobalQuote {
String? symbol;
String? open;
String? high;
String? low;
String? price;
String? volume;
String? latestTradingDay;
String? previousClose;
String? change;
String? changePercent;
GlobalQuote(
{this.symbol,
this.open,
this.high,
this.low,
this.price,
this.volume,
this.latestTradingDay,
this.previousClose,
this.change,
this.changePercent});
GlobalQuote.fromJson(Map<String, dynamic> json) {
symbol = json['01. symbol'];
open = json['02. open'];
high = json['03. high'];
low = json['04. low'];
price = json['05. price'];
volume = json['06. volume'];
latestTradingDay = json['07. latest trading day'];
previousClose = json['08. previous close'];
change = json['09. change'];
changePercent = json['10. change percent'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['01. symbol'] = this.symbol;
data['02. open'] = this.open;
data['03. high'] = this.high;
data['04. low'] = this.low;
data['05. price'] = this.price;
data['06. volume'] = this.volume;
data['07. latest trading day'] = this.latestTradingDay;
data['08. previous close'] = this.previousClose;
data['09. change'] = this.change;
data['10. change percent'] = this.changePercent;
return data;
}
}
Krish Bhanushali answered it.
I was missing value.
sQC.stockQuote.value.globalQuote!.price as String worked for me.
Had to add the null check and as String for null safety. Not sure if this was the best way but it works.

how to build sorted listview in flutter (sort as per dates)

I want to display a listview from database. The notes stored in 'note' table are displayed successully. I want to display it as per the dates. i.e recent ones at the top and later ones(future ones) below them. if the date is of tomorrow then it should be at the top and day after tomorrow one below it. If the dates are same I want to sort them as per priority. Can anyone please help me.
(If u use any other date and time picker which can accept date and time together would also be helpful). In my case the table calendar only accepts the date. I am storing the date as TEXT(i dont know if its right)
new_note.dart// this is where I add a new note to the database.
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:table_calendar/table_calendar.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:smooth_star_rating/smooth_star_rating.dart';
import 'package:intl/intl.dart';
import 'package:vers2cts/models/color_dropdown.dart';
import 'package:vers2cts/models/customer_model.dart';
import 'package:vers2cts/models/note_model.dart';
import 'package:vers2cts/services/db_service.dart';
import 'package:vers2cts/utils/form_helper.dart';
class NewNote extends StatefulWidget{
final NoteModel note;
final CustomerModel customer;
NewNote(this.customer,this. note);
#override
State<StatefulWidget> createState() {
return New_NoteState(this.customer,this.note);
}
}
class New_NoteState extends State<NewNote> with SingleTickerProviderStateMixin{
New_NoteState(this.customer,this.note);
NoteModel note=new NoteModel();
CustomerModel customer=new CustomerModel();
TextEditingController NoteController=TextEditingController();
TextEditingController custfNameController = TextEditingController();
DateTime _reminderDate = DateTime.now();
DateTime _selectedDay = DateTime.now();
DBService dbService=new DBService();
double _height;
double _width;
dynamic currentTime = DateFormat.jm().format(DateTime.now());
String _setTime, _setDate;
String _hour, _minute, _time;
String dateTime;
DateTime selectedDate = DateTime.now();
TimeOfDay selectedTime = TimeOfDay(hour: 00, minute: 00);
TextEditingController _dateController = TextEditingController();
TextEditingController _timeController = TextEditingController();
SpeedDial _speedDial(){
return SpeedDial(
animatedIcon: AnimatedIcons.add_event,
animatedIconTheme: IconThemeData(size: 24.0),
backgroundColor: Colors.yellow,
curve: Curves.easeInCirc,
children: [
SpeedDialChild(
child: Icon(Icons.location_on,color: Colors.yellow,),
label: 'Add Location',
),
SpeedDialChild(
child: Icon(Icons.keyboard_voice),
label: 'Add voice',
),
SpeedDialChild(
child: Icon(Icons.attachment_outlined,color :Colors.redAccent),
label: 'Add File',
),
SpeedDialChild(
child: Icon(Icons.image,color: Colors.lightBlue,),
label: 'Add Image',
),
],
);
}
//for Switch
bool isSwitched = false;
var textValue = 'Switch is OFF';
void toggleSwitch(bool value) {
if(isSwitched == false)
{
setState(() {
isSwitched = true;
note.rmnd_ind=1;
});
}
else
{
setState(() {
isSwitched = false;
note.rmnd_ind=0;
});
}
}
Future<Null> _selectTime(BuildContext context) async {
final TimeOfDay picked = await showTimePicker(
context: context,
initialTime: selectedTime,
);
if (picked != null)
setState(() {
selectedTime = picked;
_hour = selectedTime.hour.toString();
_minute = selectedTime.minute.toString();
_time = _hour + ' : ' + _minute;
_timeController.text = _time;
});
}
#override
void initState() {
_timeController.text=currentTime;
super.initState();
}
#override
Widget build(BuildContext context) {
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
var name=customer.first_name+" "+customer.last_name;
custfNameController.text = name;
String _chosenValue;
return WillPopScope(
onWillPop: () {navigationBar
moveToLastScreen();
},
child: Scaffold(
appBar:AppBar(),
body:ListView(
children: <Widget>[
SizedBox(
height: 2.0,
),
TextField(controller: custfNameController,
style: TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
textAlign: TextAlign.center),
Align(
alignment: Alignment.centerLeft,
child: Text("Add New",textAlign: TextAlign.left,
style: TextStyle(fontSize: 22,fontWeight: FontWeight.bold),),
),
SizedBox(
height: 2.0,
),
Divider(),
SizedBox(
height: 2.0,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: NoteController,
decoration: InputDecoration(
border: OutlineInputBorder(
borderSide: const BorderSide(width: 2.0),)),
keyboardType: TextInputType.multiline,
minLines: 5,//Normal textInputField will be displayed
maxLines: 5, // when user presses enter it will adapt to it
onChanged: (value) {
this.note.note = value;
},
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: TableCalendar(
selectedDayPredicate: (day) {
return isSameDay(_selectedDay, day);
},
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDay=selectedDay;
String _reminderDate = DateFormat('dd-MM-yyyy').format(_selectedDay);
note.actn_on=_reminderDate.toString();
});
},// Set initial date
focusedDay: DateTime.now(),
firstDay: DateTime.utc(2010, 10, 16),
lastDay: DateTime.utc(2030, 3, 14),),
),
Row(
children: <Widget>[
Expanded(child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text("Set time",style: TextStyle(fontSize: 20),),
)),
Expanded(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: InkWell(
onTap: () {
_selectTime(context);
},
child: TextFormField(
style: TextStyle(fontSize: 30),
textAlign: TextAlign.center,
onSaved: (String val) {
_setTime = val;
},
enabled: false,
keyboardType: TextInputType.text,
controller: _timeController,
),
),
),
),
]
),
SizedBox(
height: height*0.03,
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
children: <Widget>[
Text("Remind me",style: TextStyle(fontSize: 20),),
Padding(
padding: const EdgeInsets.only(left:80.0),
child: Container(
child: Switch(
onChanged: toggleSwitch,
value: isSwitched,
),
),
),
],),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(mainAxisAlignment: MainAxisAlignment.start,
children:<Widget>[
Text("Priority",style: TextStyle(fontSize: 20.0),),
Padding(
padding: const EdgeInsets.only(left:20.0),
child: Container(
child: SmoothStarRating(
size: height=50.0,
allowHalfRating: false,
onRated: (value) {
this.note.prty=value;
print("rating value -> $value");
},
),
),
)]),
),
SizedBox(
height: height*0.08,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 55.0,
width: 200,
child: RaisedButton(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
color: Theme.of(context).primaryColorDark,
textColor: Colors.white,
child: Text('Save',textScaleFactor: 1.5,),
onPressed: (){
setState(() {
_save();
});
},
),
),
),
],
),
floatingActionButton:_speedDial(),
));
}
void moveToLastScreen() {
Navigator.pop(context, true);
}
void _save() async {
moveToLastScreen();
note.cust_id=customer.cust_id;
print(customer.cust_id);
print(note.cust_id);
int result;
if (note.note_id != null) { // Case 1: Update operation
result = await dbService.updateNote(note);
} else {
result = await dbService.insertNote(note);
}
if (result != 0) {
FormHelper.showAlertDialog(context,'Status', 'Note Saved Successfully');
} else {
FormHelper.showAlertDialog(context,'Status', 'Problem Saving Note');
}
}
}
note_info.dart // This is the screen which displays the listview
import 'dart:io';
import 'package:vers2cts/models/note_model.dart';
import 'package:vers2cts/models/customer_model.dart';
import 'package:vers2cts/services/db_service.dart';
import 'package:vers2cts/utils/db_helper.dart';
import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart';
import 'package:vers2cts/utils/form_helper.dart';
import 'new_note.dart';
class Note_Info extends StatefulWidget{
final String appBarTitle;
final CustomerModel customer;
Note_Info(this. customer, this.appBarTitle);
#override
State<StatefulWidget> createState() {
return Note_InfoState(this. customer,this.appBarTitle);
}
}
class Note_InfoState extends State<Note_Info> {
DBService dbService = DBService();
List<NoteModel> noteList;
int count = 0;
static final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
NoteModel note=NoteModel();
String appBarTitle;
CustomerModel customer=new CustomerModel();
Note_InfoState(this.customer, this.appBarTitle);
bool rememberMe = false;
DateTime _date = DateTime.now();
TextEditingController custfNameController = TextEditingController();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
updateListView();
if (noteList == null) {
noteList = List<NoteModel>();
updateListView();
}
TextStyle titleStyle = Theme.of(context).textTheme.subhead;
var height = MediaQuery.of(context).size.height;
var name=customer.first_name+" "+customer.last_name;
custfNameController.text = name;
return DefaultTabController(
length: 4,
child: Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(
Icons.add,
),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => NewNote(customer,note)));
},
)
],
),
body: Container(
child: Column(
children: <Widget>[
TextField(controller: custfNameController,
style: TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
textAlign: TextAlign.center),
Padding(
padding: const EdgeInsets.all(15.0),
child: Row(children: [
ImageProfile(customer.cust_photo),
Padding(
padding: const EdgeInsets.only(left: 30.0),
child: IconButton(
icon: Icon(
Icons.call,
color: Colors.green,
size: 45,
),
onPressed: () {
},
),
),
],),
),
SizedBox(
height: 50,
child: AppBar(
bottom: TabBar(
tabs: [
Tab(
text: "All",
),
Tab(
text: "Pending",
),
Tab(
text: "Cancelled",
),
Tab(
text: "Completed",
),
],
),
),
),
// create widgets for each tab bar here
Expanded(
child: TabBarView(
children: [
// first tab bar view widget
Container(
child: getNotecheckList()
),
// second tab bar viiew widget
Container(
),
Container(
child: Center(
child: Text(
'Cancelled',
),
),
),
Container(
child: Center(
child: Text(
'Completed',
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 55.0,
width: 200,
child: RaisedButton(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
color: Theme
.of(context)
.primaryColorDark,
textColor: Colors.white,
child: Text('Save', textScaleFactor: 1.5,),
onPressed: () {
setState(() {
//_reset();
});
},
),
),
),
]
),
)
));
}
Widget ImageProfile(String fileName) {
return Center(
child: CircleAvatar(
radius: 80.0,
backgroundImage: fileName == null
?AssetImage('images/person_icon.jpg')
:FileImage(File(customer.cust_photo))),
);
}
ListView getNoteListView() {
TextStyle titleStyle = Theme.of(context).textTheme.subhead;
return ListView.builder(
itemCount: count,
itemBuilder: (BuildContext context, int position) {
return Card(
color: Colors.white,
elevation: 2.0,
child: ListTile(
title: Text(this.noteList[position].note, style: titleStyle,),
//subtitle: Text(this.customerList[position].date),
trailing: GestureDetector(
child: Icon(Icons.delete, color: Colors.grey,),
onTap: () {
// _delete(context, customerList[position]);
},
),
onTap: () {
//navigateToDetail(this.customerList[position],'Edit ');
},
),
);
},
);
}
Future<void> updateListView() {
final Future<Database> dbFuture = DB.init();
dbFuture.then((database) {
int cid=customer.cust_id;
Future<List<NoteModel>> noteListFuture = dbService.getCustomerNotes(cid);
noteListFuture.then((noteList) {
setState(() {
this.noteList = noteList;
this.count = noteList.length;
});
});
});
}
int _isChecked=-1;
var selectedIndices = [];
ListView getNotecheckList() {
return ListView.builder(
itemCount: count,
itemBuilder: (BuildContext context, int position) {
return Card(
color: Colors.white,
elevation: 2.0,
child: CheckboxListTile(
title: Text(this.noteList[position].note),
subtitle: Text(this.noteList[position].actn_on),
value: selectedIndices.contains(position),
onChanged: (_) {
if (selectedIndices.contains(position)) {
selectedIndices.remove(position);// unselect
} else {
selectedIndices.add(position); // select
}
},
controlAffinity: ListTileControlAffinity.leading,
),
);
},
);
}
}
}
note_model.dart
import 'model.dart';
class NoteModel extends Model {
static String table = 'note';
bool isSelected=false;
int note_id;
int cust_id;
String note;
String actn_on;
int rmnd_ind;
double prty;
String colr;
String sts;
int id;
String cre_date;
String cre_by;
String mod_date;
String mod_by;
int txn_id;
int delete_ind;
NoteModel({
this.note_id,
this.cust_id,
this.note,
this.actn_on,
this.rmnd_ind,
this.prty,
this.colr,
this.sts,
this.id,
this.cre_date,
this.cre_by,
this.mod_date,
this.mod_by,
this.txn_id,
this.delete_ind
});
static NoteModel fromMap(Map<String, dynamic> map) {
return NoteModel(
note_id: map["note_id"],
cust_id: map['cust_id'],
note: map['note'].toString(),
actn_on: map['actn_on'].toString(),
rmnd_ind: map['rmnd_ind'],
prty: map['prty'],
colr: map['colr'].toString(),
sts: map['sts'].toString(),
id: map['id'],
cre_date: map['cre_date'].toString(),
cre_by: map['cre_by'].toString(),
mod_date: map['mod_date'].toString(),
mod_by: map['mod_by'].toString(),
txn_id: map['txn_id'],
delete_ind: map['delete_ind'],
);
}
Map<String, dynamic> toMap() {
Map<String, dynamic> map = {
'note_id': note_id,
'cust_id': cust_id,
'note':note,
'actn_on': actn_on,
'rmnd_ind': rmnd_ind,
'prty': prty,
'colr': colr,
'sts':sts,
'id': id,
'cre_date': cre_date,
'cre_by': cre_by,
'mod_date':mod_date,
'mod_by':mod_by,
'txn_id':txn_id,
'delete_ind': delete_ind
};
if (note_id != null) {
map['note_id'] = note_id;
}
return map;
}
}
db_service.dart
import 'package:vers2cts/models/note_model.dart';
import 'package:vers2cts/utils/db_helper.dart';
class DBService {
Future<int> insertNote(NoteModel note) async {
await DB.init();
var result = await DB.insert(NoteModel.table, note);
return result;
}
Future<List<Map<String, dynamic>>> getNoteMapList() async {
await DB.init();
var result = await DB.query(NoteModel.table);
return result;
}
Future<List<NoteModel>> getCustomerNotes(int customer) async {
await DB.init();
var res = await DB.rawQuery("note WHERE cust_id = '$customer'");
int count = res.length;
List<NoteModel> notelist = List<NoteModel>();
for (int i = 0; i < count; i++) {
notelist.add(NoteModel.fromMap(res[i]));
}
return notelist;
}
}
db_helper.dart actn_on saves the date and prty saves the priority
import 'dart:async';
import 'package:vers2cts/models/model.dart';
import 'package:path/path.dart' as p;
import 'package:sqflite/sqflite.dart';
abstract class DB {
static Database _db;
static int get _version => 1;
static Future<Database> init() async {
if (_db != null) {
return _db;
}
try {
var databasesPath = await getDatabasesPath();
String _path = p.join(databasesPath, 'CTS.db');
_db = await openDatabase(_path, version: _version, onCreate: onCreate);
print('db location:'+_path);
} catch (ex) {
print(ex);
}
}
static void onCreate(Database db, int version) async {
await db.execute(
'CREATE TABLE note (note_id INTEGER PRIMARY KEY,cust_id INTEGER, '
'note TEXT, '
'actn_on TEXT, rmnd_ind INTEGER, prty REAL, colr TEXT,'
'sts TEXT,'
'id INTEGER, cre_date TEXT,cre_by TEXT, mod_date TEXT,mod_by TEXT, txn_id INTEGER, delete_ind INTEGER)');
}
static Future<List<Map<String, dynamic>>> query(String table) async =>
_db.query(table);
static Future<int> insert(String table, Model model) async =>
await _db.insert(table, model.toMap());
static Future<List<Map<String, dynamic>>> rawQuery(String table) async =>
_db.query(table);
}
Thankyou DarShan I got my answer I just had to use ORDER BY in my query
Future<List<NoteModel>> getCustomerNotes(int customer) async {
await DB.init();
var res = await DB.rawQuery("note WHERE cust_id = '$customer' ORDER BY actn_on ASC,prty DESC;");
int count = res.length;
List<NoteModel> notelist = List<NoteModel>();
// For loop to create a 'Note List' from a 'Map List'
for (int i = 0; i < count; i++) {
notelist.add(NoteModel.fromMap(res[i]));
}
return notelist;
}