In the job_details.dart file I want to listen to changes in the timestamp field when the start time or end time button is pressed and add the corresponding table row. But currently, I am getting value for my current job by listening to changes in my Jobs class and fetching the particular job using its ID. Therefore a new Table row does not get rendered when I tap on the Start time or End time button. How do I implement the above scenario to listen to changes in my Job class whenever a new timestamp is added to the _timestamps list and render a new Table row correspondingly?
job.dart
class Job with ChangeNotifier{
final int jobID;
final String name;
final String startTime = DateTime.now().toString();
String expectedDeliveryDate;
final List<String> _progressImagesUrl = [];
bool isCompleted = false;
final List<Map<String, DateTime?>> _timestamps = [];
Job({required this.jobID, required this.name, this.expectedDeliveryDate = ""});
void editExpectedDeliveryDate(DateTime dt){
expectedDeliveryDate = dt.toString();
notifyListeners();
}
List<String> get progressImagesUrl{
return [..._progressImagesUrl];
}
List<Map<String, DateTime?>> get timestamps{
return [..._timestamps];
}
void addStartTime(){
if(_timestamps.isNotEmpty && _timestamps.last["endTime"] == null){
print("error");
throw Exception("Provide end time first");
}
print("added start time");
_timestamps.add({"startTime": DateTime.now(), "endTime": null});
notifyListeners();
}
void addEndTime(){
if(_timestamps.isEmpty || _timestamps.last["endTime"] != null){
throw Exception("Provide start time first");
}
print("added end time");
_timestamps.last["endTime"] = DateTime.now();
notifyListeners();
}
void addImage(String imageUrl){
_progressImagesUrl.add(imageUrl);
notifyListeners();
}
void toggleIsCompleted(){
isCompleted != isCompleted;
notifyListeners();
}
}
jobs.dart
import 'package:flutter/material.dart';
import 'job.dart';
class Jobs with ChangeNotifier{
final List<Job> _items = [
Job(
jobID: 1,
name: 'firstProduct',
expectedDeliveryDate: DateTime.now().toString(),
),
Job(
jobID: 2,
name: 'second product',
expectedDeliveryDate: DateTime.now().toString(),
),
Job(
jobID: 3,
name: 'third product',
expectedDeliveryDate: DateTime.now().toString(),
),
Job(
jobID: 4,
name: 'fourth product',
expectedDeliveryDate: DateTime.now().toString(),
),
];
List<Job> get items{
return [..._items];
}
void addJob(String name, String endTime){
Job newJob = Job(jobID: name.length, name: name, expectedDeliveryDate: endTime);
_items.add(newJob);
notifyListeners();
}
Job findById(int id){
return _items.firstWhere((element) => element.jobID == id);
}
List<Job> get completedJobs{
return _items.where((element) => element.isCompleted).toList();
}
}
job_details.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:rupa_creation/provider/jobs.dart';
import '../provider/job.dart';
class JobDetailsScreen extends StatelessWidget {
const JobDetailsScreen({Key? key}) : super(key: key);
static const routeName = '/product-detail';
@override
Widget build(BuildContext context) {
final jobId = ModalRoute.of(context)?.settings.arguments as int;
final loadedJob = Provider.of<Jobs>(
context,
).findById(jobId);
List<TableRow> createTimeStampTable(List<Map<String, DateTime?>> items) {
List<TableRow> itemProperties = [];
itemProperties.add(const TableRow(children: [
TableCell(child: Text("Start Time")),
TableCell(child: Text("End Time"))
]));
for (int i = 0; i < items.length; ++i) {
itemProperties.add(TableRow(children: [
TableCell(child: Text("${items[i]["startTime"]?.hour}:${items[i]["startTime"]?.minute}")),
TableCell(child: Text("${items[i]["endTime"]?.hour}:${items[i]["endTime"]?.minute}")),
]));
}
return itemProperties;
}
return Scaffold(
appBar: AppBar(
title: Text(loadedJob.name),
),
body: Container(
child: Column(
children: [
Row(
children: [
TextButton(
onPressed: () {
try {
loadedJob.addStartTime();
// Navigator.of(context).pushReplacementNamed(JobDetailsScreen.routeName, arguments: jobId);
} on Exception catch (e) {
AlertDialog(
title: Text(e.toString()),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Container(
color: Colors.green,
padding: const EdgeInsets.all(14),
child: const Text("okay"),
),
),
],
);
}
},
child: const Text("Start")),
TextButton(
onPressed: () {
try {
loadedJob.addEndTime();
// Navigator.of(context).pushReplacementNamed(JobDetailsScreen.routeName, arguments: jobId);
} on Exception catch (e) {
print("here");
AlertDialog(
title: Text(e.toString()),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Container(
color: Colors.green,
padding: const EdgeInsets.all(14),
child: const Text("okay"),
),
),
],
);
}
},
child: const Text("Stop")),
],
),
Table(
children: createTimeStampTable(loadedJob.timestamps),
)
],
),
),
);
}
}
job_overview.dart
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:rupa_creation/provider/job.dart';
import '../screens/job_details.dart';
class JobOverview extends StatelessWidget {
const JobOverview({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final job = Provider.of<Job>(context);
DateTime startDateTime = DateTime.parse(job.startTime);
DateTime endDateTime = DateTime.parse(job.expectedDeliveryDate);
return Card(
child: ListTile(
tileColor: Colors.black12,
// contentPadding: EdgeInsets.all(10),
leading: Icon(Icons.ac_unit),
title: Text(job.name, textScaleFactor: 1.2,),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Start Date: ${DateFormat("dd-MM-yyyy").format(startDateTime)}"),
Text("Expected Delivery Date: ${DateFormat("dd-MM-yyyy").format(endDateTime)}"),
],
),
onTap: (){
Navigator.of(context).pushNamed(JobDetailsScreen.routeName, arguments: job.jobID);
},
),
);
}
}