Related
I am a learner and new to Flutter.
I want help with the followings
I need to get a list of items with checkboxes from and API
I should be able to select a single or multiple checkboxes
If I select a checkbox its should display the total amount selected
if I select two checkboxes, its should sum the total of the two for me and display it.
Below is what I have done so far.
I will greatly appreciate your solutions
here is my code
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:liquid_pull_to_refresh/liquid_pull_to_refresh.dart';
import 'dart:convert';
import 'dart:ffi';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:stachup/models/TeamModel.dart';
import 'package:stachup/models/newStaches.dart';
import 'package:stachup/models/TeamModel.dart';
class Stash extends StatefulWidget {
String first_name;
String token;
String referalcode;
String last_name;
Stash(
{Key? key,
required this.first_name,
required this.token,
required this.last_name,
required this.referalcode})
: super(key: key);
#override
State<Stash> createState() => _StashState();
}
class _StashState extends State<Stash> {
bool isChecked = false;
String? first_name;
String? token;
String? last_name;
String? referalcode;
bool setup = false;
String? setupError;
bool _isChecked = false;
late SharedPreferences logindata;
userData() async {
logindata = await SharedPreferences.getInstance();
first_name = logindata.getString('first_name')!;
last_name = logindata.getString('last_name')!;
referalcode = logindata.getString('referalcode')!;
token = logindata.getString('token')!;
setState(() {});
}
List<Team> teams = [];
Future getData() async {
var response = await http.get(Uri.https(
'incoming.isplitpay.com', 'api/durationlist', {'token': token}));
var jsonData = jsonDecode(response.body);
print(token);
for (var eachTeam in jsonData) {
var datetime = DateTime.parse(eachTeam["paid_date"]);
final team = Team(
id_pes: eachTeam['id_pes'],
amount: eachTeam['amount'],
paid_date: datetime,
);
teams.add(team);
}
// print(teams.length);
}
#override
void initState() {
super.initState();
userData();
}
#override
Widget build(BuildContext context) {
//getData();
return Scaffold(
backgroundColor: Colors.blue.shade50,
body: FutureBuilder(
future: getData(),
builder: ((context, snapshot) {
//if done loading show data
if (snapshot.connectionState == ConnectionState.done) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
),
child: ListView.builder(
itemCount: teams.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 80,
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
),
color: Colors.grey[50],
borderRadius: BorderRadius.circular(12),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Checkbox(
checkColor: Colors.white,
value: _isChecked,
onChanged: (bool? value) {
setState(() {
_isChecked = value!;
});
print(value);
},
),
Text(
'GHS ' + teams[index].amount,
style: GoogleFonts.lato(
fontSize: 16,
),
),
Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Text(
'Savings for',
style: GoogleFonts.lato(
fontSize: 16,
),
),
),
Text(
"${teams[index].paid_date.day.toString().padLeft(2, '0')}-${teams[index].paid_date.month.toString().padLeft(2, '0')}-${teams[index].paid_date.year}",
style: GoogleFonts.lato(
fontSize: 16,
),
),
],
)
],
),
),
);
}),
);
//else show circule progress bar
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}),
),
);
}
}
My Model
import 'package:flutter/material.dart';
class Team {
final String id_pes;
final String amount;
final DateTime paid_date;
Team({
required this.id_pes,
required this.amount,
required this.paid_date,
});
}
class UserProgress {
final int goaldays;
final double progress;
UserProgress({
required this.goaldays,
required this.progress,
});
}
You can add a variable inside the Class Team to control the CheckBox.
The checked list can be filtered out through the List.where() function.
I added the Tooltip() Widget to show the expected effect.
import 'package:flutter/material.dart';
class MyWidget extends StatefulWidget {
const MyWidget({super.key});
#override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
List<Team> dataList = [
Team(id_pes: '1', amount: '10', paid_date: DateTime.now()),
Team(id_pes: '2', amount: '20', paid_date: DateTime.now()),
Team(id_pes: '3', amount: '30', paid_date: DateTime.now()),
Team(id_pes: '4', amount: '40', paid_date: DateTime.now()),
Team(id_pes: '5', amount: '50', paid_date: DateTime.now()),
Team(id_pes: '6', amount: '60', paid_date: DateTime.now()),
];
Widget _buildListItem(int index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 80,
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
),
color: Colors.grey[50],
borderRadius: BorderRadius.circular(12),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Checkbox(
checkColor: Colors.white,
value: dataList[index].isChecked ?? false,
onChanged: (bool? value) {
setState(() {
dataList[index].isChecked = value;
});
print(value);
},
),
Text(
'GHS ' + dataList[index].amount,
),
],
),
),
);
}
#override
Widget build(BuildContext context) {
var checkedList = dataList.where((data) => data.isChecked ?? false);
var totalAmount = checkedList.isNotEmpty
? 'TotalAmount:${checkedList.reduce((before, after) => Team(amount: '${double.parse(before.amount) + double.parse(after.amount)}', id_pes: '_', paid_date: DateTime.now())).amount} '
: '';
return Scaffold(
body: ListView.builder(
shrinkWrap: true,
itemCount: dataList.length,
itemBuilder: (context, index) {
return Tooltip(
message: totalAmount, child: _buildListItem(index));
}));
}
}
class Team {
final String id_pes;
final String amount;
final DateTime paid_date;
bool? isChecked;
Team({
required this.id_pes,
required this.amount,
required this.paid_date,
this.isChecked,
});
}
So i'm pretty lost trying to get my app to fetch not only the desired text from firestore but also the image i placed there. I know the error "Bad state: field does not exist within the DocumentSnapshotPlatform" implies that either I'm missing field or there's something wrong with at least one of those fields. There's only four things I'm trying to fetch from firestore "imgUrl, title, desc, organizer" i have checked for spelling and order and i can't figure it out. I have also checked firestore to see if the order and spelling was correct and i dont see what's the issue. Please help, Thank you so much in advanced.
////////////////////////////// News Class Starts\\\\\\\\\\\\\\
import 'package:myfuji/screens/CrudMethods.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'CrudMethods.dart';
import 'add_blog.dart';
class News extends StatefulWidget {
#override
_NewsState createState() => _NewsState();
}
class _NewsState extends State<News> {
CrudMethods crudMethods = CrudMethods();
late QuerySnapshot blogSnapshot;
#override
void initState() {
crudMethods.getData().then((result) {
blogSnapshot = result;
setState(() {});
});
super.initState();
}
Widget blogsList() {
return ListView.builder(
padding: const EdgeInsets.only(top: 24),
itemCount: blogSnapshot.docs.length,
itemBuilder: (context, index) {
return BlogTile(
organizer: blogSnapshot.docs[index].get('Organizer'),
desc: blogSnapshot.docs[index].get('desc'),
imgUrl: blogSnapshot.docs[index].get('imgUrl'),
title: blogSnapshot.docs[index].get('title'),
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Events"),
),
body: Container(
child: blogSnapshot != null
? blogsList()
: const Center(
child: CircularProgressIndicator(),
)),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => AddBlog()));
},
),
);
}
}
class BlogTile extends StatelessWidget {
final String imgUrl, title, desc, organizer;
const BlogTile(
{required this.organizer,
required this.desc,
required this.imgUrl,
required this.title});
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(bottom: 24, right: 16, left: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: Image.network(
imgUrl,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
height: 200,
),
),
),
const SizedBox(height: 16),
Text(
title,
style: const TextStyle(fontSize: 17),
),
const SizedBox(height: 2),
Text(
'$desc - By $organizer',
style: const TextStyle(fontSize: 14),
)
],
),
);
}
}
///////////////////////////////////////////// class AddBlog begins here \\\\\\\\\\\
import 'dart:io';
import 'package:myfuji/screens/CrudMethods.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:random_string/random_string.dart';
class AddBlog extends StatefulWidget {
#override
_AddBlogState createState() => _AddBlogState();
}
class _AddBlogState extends State<AddBlog> {
//
late File selectedImage;
final picker = ImagePicker();
bool isLoading = false;
CrudMethods crudMethods = new CrudMethods();
Future getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
if (pickedFile != null) {
selectedImage = File(pickedFile.path);
} else {
print('No image selected.');
}
});
}
Future<void> uploadBlog() async {
if (selectedImage != null) {
// upload the image
setState(() {
isLoading = true;
});
Reference firebaseStorageRef = FirebaseStorage.instance
.ref()
.child("events/")
.child("${randomAlphaNumeric(9)}.jpg");
final UploadTask task = firebaseStorageRef.putFile(selectedImage);
var imageUrl;
await task.whenComplete(() async {
try {
imageUrl = await firebaseStorageRef.getDownloadURL();
} catch (onError) {
print("Error");
}
print(imageUrl);
});
// print(downloadUrl);
Map<String, dynamic> blogData = {
"imgUrl": imageUrl,
"Organizer": authorTextEditingController.text,
"title": titleTextEditingController.text,
"desc": descTextEditingController.text
};
crudMethods.addData(blogData).then((value) {
setState(() {
isLoading = false;
});
Navigator.pop(context);
});
// upload the blog info
}
}
//
TextEditingController titleTextEditingController =
new TextEditingController();
TextEditingController descTextEditingController = new TextEditingController();
TextEditingController authorTextEditingController =
new TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Create Blog"),
actions: [
GestureDetector(
onTap: () {
uploadBlog();
},
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Icon(Icons.file_upload)),
)
],
),
body: isLoading
? Container(
child: Center(
child: CircularProgressIndicator(),
))
: SingleChildScrollView(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 16),
child: Column(
children: [
GestureDetector(
onTap: () {
getImage();
},
child: selectedImage != null
? Container(
height: 150,
margin: EdgeInsets.symmetric(vertical: 24),
width: MediaQuery.of(context).size.width,
child: ClipRRect(
borderRadius:
BorderRadius.all(Radius.circular(8)),
child: Image.file(
selectedImage,
fit: BoxFit.cover,
),
),
)
: Container(
height: 150,
decoration: BoxDecoration(
color: Colors.grey,
borderRadius:
BorderRadius.all(Radius.circular(8))),
margin: EdgeInsets.symmetric(vertical: 24),
width: MediaQuery.of(context).size.width,
child: Icon(
Icons.camera_alt,
color: Colors.white,
),
),
),
TextField(
controller: titleTextEditingController,
decoration: InputDecoration(hintText: "enter title"),
),
TextField(
controller: descTextEditingController,
decoration: InputDecoration(hintText: "enter desc"),
),
TextField(
controller: authorTextEditingController,
decoration:
InputDecoration(hintText: "enter author name"),
),
],
)),
),
);
}
}
///////////////////////////////////////////// class CrudMethods begins here \\\\\\\\\\\
import 'package:cloud_firestore/cloud_firestore.dart';
class CrudMethods {
Future<void> addData(blogData) async {
print(blogData);
FirebaseFirestore.instance
.collection("events/")
.add(blogData)
.then((value) => print(value))
.catchError((e) {
print(e);
});
}
getData() async {
return await FirebaseFirestore.instance.collection("events/").get();
}
}
/////////////////////////////////////////////firestore\\\\\\\\\\\\\
This maybe related to having “/“ after collection name here:
.collection("events/")
Instead try this:
.collection("events")
Also it may be best to change child to collection here:
Reference firebaseStorageRef = FirebaseStorage.instance
.ref()
.child("events/")
Try to see if you get data back by running this:
itemCount: blogSnapshot.docs.length,
itemBuilder: (context, index) {
QuerySnapshot snap = blogSnapshot.data; // Snapshot
List<DocumentSnapshot> items = snap.documents; // List of Documents
DocumentSnapshot item = items[index]; Specific Document
return BlogTile(
organizer: item.data['Organizer'],
desc: item.data['desc'],
imgUrl: item.data['imgUrl'],
title: item.data['title'],
);
},
I think you need to utilize a QueryDocumentSnapshot to access the data in the document.
So I have two screens:
-Book_screen to display all the books(click on any book to go to article_screen)
-article_screen to display articles
In article_screen, I can click on article to save it as favorites.
but when I go back to book_screen then come back to article_screen, those favorited articles doesn't show the favorited status(icon red heart).
this is my article screen code:
class ArticleENPage extends ConsumerStatefulWidget{
final String bookName;
const ArticleENPage({Key? key,#PathParam() required this.bookName,}) : super(key: key);
#override
ArticleENScreen createState()=> ArticleENScreen();
}
class ArticleENScreen extends ConsumerState<ArticleENPage> {
late Future<List<Code>> codes;
#override
void initState() {
super.initState();
codes = fetchCodes();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.bookName,style: const TextStyle(fontSize: 24,fontWeight: FontWeight.bold),),backgroundColor: Colors.white,foregroundColor: Colors.black,elevation: 0,),
body: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//SizedBox(height: 10),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0),
child: Container(
margin: const EdgeInsets.only(top:10),
height: 43,
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 2),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
border: Border.all(
color: Colors.black.withOpacity(0.32),
),
),
child: Consumer(
builder: (context,ref,_) {
return TextField(
onChanged: (value) {
searchStringController controller = ref.read(searchStringProvider.notifier);
controller.setText(value.toLowerCase());
},
decoration: const InputDecoration(
border: InputBorder.none,
icon: Icon(Icons.search,size:18),
hintText: "Search Here",
hintStyle: TextStyle(color: Color.fromRGBO(128,128, 128, 1)),
),
);
}
),
),
),
const SizedBox(height: 10),
Expanded(
child: FutureBuilder(
builder: (context, AsyncSnapshot<List<Code>> snapshot) {
if (snapshot.hasData) {
return Center(
child: Consumer(
builder: (context,ref,child) {
final searchString = ref.watch(searchStringProvider);
return ListView.separated(
padding: const EdgeInsets.all(8),
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int index) {
return snapshot.data![index].name
.toLowerCase()
.contains(searchString) ||
snapshot.data![index].description
.toLowerCase()
.contains(searchString)
? Consumer(
builder: (context,ref,child) {
final favlist = ref.watch(FavoriteListController.favoriteListProvider);
print(favlist);
final alreadySaved = favlist.contains(snapshot.data![index]);
return Card(
child:Padding(
padding: const EdgeInsets.all(10),
child:ExpandableNotifier(
child: ScrollOnExpand(
child: ExpandablePanel(
theme: const ExpandableThemeData(hasIcon: true),
header: RichText(text: TextSpan(children: highlight(snapshot.data![index].name, searchString,'title')),),
collapsed: RichText(text: TextSpan(children: highlight(snapshot.data![index].description, searchString,'content')), softWrap: true, maxLines: 3, overflow: TextOverflow.ellipsis,),
expanded: Column(
children: [
RichText(text: TextSpan(children: highlight(snapshot.data![index].description, searchString,'content')), softWrap: true ),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
icon: Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
semanticLabel: alreadySaved ? 'Remove from saved' : 'Save',
),
onPressed: () {
FavoriteListController controller = ref.read(FavoriteListController.favoriteListProvider.notifier);
if (alreadySaved) {
controller.toggle(snapshot.data![index]);
} else {
controller.toggle(snapshot.data![index]);
}
},
),
IconButton(
icon: const Icon(Icons.content_copy),
onPressed: () {
setState(() {
Clipboard.setData(ClipboardData(text: snapshot.data![index].name+"\n"+snapshot.data![index].description))
.then((value) {
ScaffoldMessenger.of(context).showSnackBar(new SnackBar(content: Text('Copied')));
},);
});
},
),],),],)),),)));})
: Container();
},
separatorBuilder: (BuildContext context, int index) {
return snapshot.data![index].name
.toLowerCase()
.contains(searchString) ||
snapshot.data![index].description
.toLowerCase()
.contains(searchString)
? Divider()
: Container();
},
);
}
),
);
} else if (snapshot.hasError) {
return const Center(child: Text('Something went wrong :('));
}
return const Align(alignment:Alignment.topCenter,child:CircularProgressIndicator());
},
future: codes,
),
),
],
),
);
}
//read from files
Future<List<Code>> fetchCodes() async {
final response =
await rootBundle.loadString('assets/articles.json');
var CodeJson = json.decode(response)[widget.bookName] as List<dynamic>;
return CodeJson.map((code) => Code.fromJson(code)).toList();
}
}
I tried using riverpod for provider and save to sharedpreference the list of code that I favorited.
final sharedPrefs =
FutureProvider<SharedPreferences>((_) async => await SharedPreferences.getInstance());
class FavoriteListController extends StateNotifier<List<Code>>{
FavoriteListController(this.pref) : super(Code.decode(pref?.getString("favcode")??""));
static final favoriteListProvider = StateNotifierProvider<FavoriteListController, List<Code>>((ref) {
final pref = ref.watch(sharedPrefs).maybeWhen(
data: (value) => value,
orElse: () => null,
);
print(pref?.getString("favcode"));
return FavoriteListController(pref);
});
final SharedPreferences? pref;
void toggle(Code code) {
if (state.contains(code)) {
state = state.where((id) => id != code).toList();
} else {
state = [...state, code];
}
final String encodedData = Code.encode(state);
pref!.setString("favcode", encodedData);
}
}
I am not sure what is the cause of this but I think it might be because of futurebuilder? I am confused to how to solve this issue...
I am stuck in a dead end so any help or advice would be really appreciated
edit 1-
this is my source code in case I have not include all the necessary codes
https://github.com/sopheareachte/LawCode
edit-2
do I need to change "late Future<List> codes;" that fetch all the codes for futurebuilder to riverpod futureprovider too for it to work?
Maybe the problem is, that you define a static provider inside of your controller class. Try this code:
final sharedPrefs = FutureProvider<SharedPreferences>((_) async => await SharedPreferences.getInstance());
final favoriteListProvider = StateNotifierProvider<FavoriteListController, List<Code>>((ref) {
final pref = ref.watch(sharedPrefs).maybeWhen(
data: (value) => value,
orElse: () => null,
);
print(pref?.getString("favcode"));
return FavoriteListController(pref);
});
class FavoriteListController extends StateNotifier<List<Code>>{
FavoriteListController(this.pref) : super(Code.decode(pref?.getString("favcode")??""));
final SharedPreferences? pref;
void toggle(Code code) {
if (state.contains(code)) {
state = state.where((id) => id != code).toList();
} else {
state = [...state, code];
}
final String encodedData = Code.encode(state);
pref!.setString("favcode", encodedData);
}
}
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;
}
I try to create an onTap function on ChatRoomListTile which navigates me to the chatscreen where the id is = chatRoomId. Unfortunately I don't know how to deliver the ID.
Unfortunately I am very unexperienced in flutter and I made this app via tutorial... It works nice but I am still learning, so a big big big thanks!
my Database.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:signal/helperfunctions/sharedpref_helper.dart';
class DatabaseMethods{
Future addUserInfoToDB(String userId, Map<String, dynamic>userInfoMap)
async {
return FirebaseFirestore.instance
.collection("users")
.doc(userId)
.set(userInfoMap);
}
Future<Stream<QuerySnapshot>> getUserByUserName(String username) async{
return FirebaseFirestore.instance
.collection("users")
.where("username", isEqualTo: username)
.snapshots();
}
Future addMessage(String chatRoomId, String messageId, Map messageInfoMap) async {
return FirebaseFirestore.instance
.collection ("chatrooms")
.doc(chatRoomId)
.collection("chats")
.doc(messageId)
.set(messageInfoMap);
}
updateLastMessageSend(String chatRoomId, Map lastMessageInfoMap){
return FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.update(lastMessageInfoMap);
}
createChatRoom(String chatRoomId, Map chatRoomInfoMap) async{
final snapShot = await FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.get();
if(snapShot.exists){
//chatroom already exists
return true;
}else{
//chatroom does not exists
return FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.set(chatRoomInfoMap);
}
}
Future<Stream<QuerySnapshot>> getChatRoomMessages(chatRoomId) async {
return FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.collection("chats")
.orderBy("ts", descending: true)
.snapshots();
}
// Future<Stream<QuerySnapshot>> openChatRoom(String chatRoomId) async{
// return FirebaseFirestore.instance
// .collection("chatrooms")
// .doc(chatRoomId)
// .collection("chats")
// .snapshots();
// }
Future<Stream<QuerySnapshot>> getChatRooms() async {
String myUsername = await SharedPreferenceHelper().getUserName();
return FirebaseFirestore.instance
.collection("chatrooms")
.orderBy("lastMessageSendTs", descending: true)
.where("users",arrayContains: myUsername)
.snapshots();
}
Future<QuerySnapshot> getUserInfo(String username) async {
return await FirebaseFirestore.instance
.collection("users")
.where("username", isEqualTo: username)
.get();
}
}
and my home.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:signal/helperfunctions/sharedpref_helper.dart';
import 'package:signal/services/auth.dart';
import 'package:signal/services/database.dart';
import 'package:signal/views/signin.dart';
import 'services/colorpicker.dart';
import 'chatscreen.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
bool isSearching = false;
String myName, myProfilePic, myUserName, myEmail, messageSentTs;
Stream usersStream, chatRoomsStream;
TextEditingController searchUsernameEditingController =
TextEditingController();
getMyInfoFromSharedPreference() async{
myName = await SharedPreferenceHelper().getDisplayName();
myProfilePic = await SharedPreferenceHelper().getUserProfileUrl();
myUserName = await SharedPreferenceHelper().getUserName();
myEmail = await SharedPreferenceHelper().getUserEmail();
}
//dieser string sollte eigentlich aus sicherheitsgründen random generiert werden
getChatRoomIdByUsernames(String a, String b){
if(a.substring(0,1).codeUnitAt(0) > b.substring(0,1).codeUnitAt(0)){
return "$b\_$a";
}else{
return "$a\_$b";
}
}
onSearchBtnClick() async {
isSearching = true;
setState(() {});
usersStream = await DatabaseMethods()
.getUserByUserName(searchUsernameEditingController.text);
setState(() {});
}
Widget chatRoomsList(){
return StreamBuilder(
stream: chatRoomsStream,
builder: (context, snapshot){
return snapshot.hasData
? ListView.builder(
itemCount: snapshot.data.docs.length,
shrinkWrap: true,
itemBuilder: (context, index){
DocumentSnapshot ds = snapshot.data.docs[index];
return ChatRoomListTile(ds["lastMessage"], ds.id,myUserName);
})
: Center(child: CircularProgressIndicator());
},
);
}
// print("this is the values we have $myUserName $username"));
// Chatroom ID Kontrolle ( achtung beim randomisen der CRId)
Widget searchUserListTile({String profileUrl, name, username, email}){
return GestureDetector(
onTap: (){
var chatRoomId = getChatRoomIdByUsernames(myUserName, username);
Map<String, dynamic> chatRoomInfoMap = {
"users" : [myUserName, username]
};
DatabaseMethods().createChatRoom(chatRoomId, chatRoomInfoMap);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChatScreen(username, name)
)
);
},
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(30),
child: Image.network(
profileUrl,
height: 20,
width: 20,
),
),
SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children:[
Text(name),
Text(email),
],
)
],
),
);
}
Widget searchUsersList(){
return StreamBuilder(
stream: usersStream,
builder: (context, snapshot){
return snapshot.hasData
? ListView.builder(
itemCount: snapshot.data.docs.length,
shrinkWrap: true,
itemBuilder: (context, index){
DocumentSnapshot ds = snapshot.data.docs[index];
return searchUserListTile(
profileUrl: ds["imgUrl"],
name: ds["name"],
username: ds["username"],
email: ds["email"]
);
},
) : Center(child: CircularProgressIndicator(),);
}
);
}
getChatRooms() async {
chatRoomsStream = await DatabaseMethods().getChatRooms();
setState(() {});
}
onScreenLoaded() async {
await getMyInfoFromSharedPreference();
getChatRooms();
}
#override
void initState() {
onScreenLoaded();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color.fromRGBO(233, 240, 244, 1),
appBar: AppBar(
title: Image.asset('assets/images/logo.png', width: 40,),
elevation: 0.0,
backgroundColor: Colors.white,
actions: [
InkWell(
onTap: (){
AuthMethods().signOut().then((s) {
Navigator.pushReplacement(context, MaterialPageRoute
(builder: (context) => SignIn()));
});
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Icon(Icons.exit_to_app)),
)
],
),
body: Container(
margin: EdgeInsets.symmetric(horizontal: 20),
child: Column(
children: [
Row(
children: [
isSearching
? GestureDetector(
onTap: (){
isSearching = false;
searchUsernameEditingController.text = "";
setState(() {});
},
child: Padding(
padding: EdgeInsets.only(right: 12),
child: Icon(Icons.arrow_back)),
) : Container(),
Expanded(
child: Container(
// Disable Searchbar
width: 0,
height: 0,
margin: EdgeInsets.symmetric(vertical: 16),
padding: EdgeInsets.symmetric(horizontal:16),
decoration: BoxDecoration
(border: Border.all(
color: Colors.black87,
width: 1,
style: BorderStyle.solid), borderRadius: BorderRadius.circular(24)),
child: Row(
children: [
Expanded(
child: TextField(
controller: searchUsernameEditingController,
decoration: InputDecoration(
border: InputBorder.none, hintText: "Finde einen Freund"),
)),
GestureDetector(
onTap:(){
if(searchUsernameEditingController.text != ""){
onSearchBtnClick();
}
},
// Disable Search Icon
// child: Icon(Icons.search),
)
],
),
),
)
]
),
isSearching ? searchUsersList() : chatRoomsList()
],
),
),
);
}
}
class ChatRoomListTile extends StatefulWidget {
final String lastMessage, chatRoomId, myUsername;
ChatRoomListTile(this.lastMessage, this.chatRoomId, this.myUsername);
#override
_ChatRoomListTileState createState() => _ChatRoomListTileState();
}
class _ChatRoomListTileState extends State<ChatRoomListTile> {
String profilePicUrl ="", name="", username="";
getThisUserInfo() async {
username = widget.chatRoomId.replaceAll(widget.myUsername, "").replaceAll("_", "");
QuerySnapshot querySnapshot = await DatabaseMethods().getUserInfo(username);
name = "${querySnapshot.docs[0]["name"]}";
profilePicUrl = "${querySnapshot.docs[0]["imgUrl"]}";
setState(() {});
}
#override
void initState() {
getThisUserInfo();
super.initState();
}
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(vertical: 2, horizontal: 0,),
padding: EdgeInsets.symmetric(horizontal:12,vertical: 20,),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.network(
profilePicUrl,
height: 35,
width: 35,
),
),
SizedBox(width: 15),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name,
style: TextStyle(
fontSize: 14,
fontFamily: 'Roboto',
color: Color.fromRGBO(57, 59, 85, 0.8),
fontWeight: FontWeight.w500,
),
),
SizedBox(height: 5),
Container(
width: (MediaQuery.of(context).size.width) - 150,
child: Text(
widget.lastMessage,
style: new TextStyle(
fontSize: 13.0,
fontFamily: 'Roboto',
color: Color.fromRGBO(171, 183, 201, 1),
fontWeight: FontWeight.w400,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
],
)
],
),
);
}
}
you can pass the id as a constructor from the listTile,
Navigator.of(context).push.... ChatScreen(id: chatRoomId)
as so, and in ChatScreen you can receive it like so
class ChatScreenextends StatefulWidget {
final String id;
ChatScreen({requried this.id});
#override
_ChatScreenState createState() => _ChatScreenState ();
}
class _ChatScreenState extends State<ChatScreen> {
if it is a stateless Widget class you can directly access the id as id, if it is a stateful Widget then widget.id ,
Another way of doing this is passing as Navigator argument you can check the docs for more info Flutter Docs
Hello and thank you very much for your time ... i tried to implement it but unfortunate i get an error. here the GestureDetector i added to my home.dart ::: I also tried to change id: chatRoomId to this.Id or just chatRoomId .. but it keeps underlined and erroring :
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => ChatScreen(id: chatRoomId)));
},
child: Container(
margin: EdgeInsets.symmetric(vertical: 2, horizontal: 0,),
padding: EdgeInsets.symmetric(horizontal:12,vertical: 20,),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
),
and here the update of the chatscreen.dart
class ChatScreen extends StatefulWidget {
final String chatWidthUsername, name, id;
ChatScreen(this.chatWidthUsername, this.name, {this.id});
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
String chatRoomId, messageId = "";
Stream messageStream;
String myName, myProfilePic, myUserName, myEmail;
TextEditingController messageTextEditingController = TextEditingController();
thanks again so much !
greetings
alex