I'm trying to change the status of the 'TaskCard' from false to true after pressing on the 'ElevatedButton' in 'task*-details-page*.dart' I tried solving this problem without using riverpod as well, but to no avail. I never really used extra in the GoRouter package, but I noticed that it was used in the 'routes.dart' file. (I'm not working on this alone that's why it was used) I'd rather not use it if complicates things for achieving the goal I mentioned.
routes.dart
GoRoute(
path: "/${NamedRoutes.taskDetails}",
name: NamedRoutes.taskDetails,
pageBuilder: (context, state) {
// Retrieve the TaskModel object passed as an extra parameter
final task = state.extra as TaskModel;
return NoTransitionPage(
key: state.pageKey,
child: TaskDetails(
taskModel: task),
);
},
),
task_model.dart
class TaskModel {
final String id;
final String taskTitle;
final String taskDescription;
final bool taskStatus;
final Timestamp? timestamp;
final String projectId;
TaskModel({
required this.id,
required this.taskTitle,
required this.taskDescription,
required this.taskStatus,
this.timestamp,
required this.projectId,
});
task_repository.dart
class TasksRepo {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<void> createTask({
required String taskTitle,
required String taskDescription,
required bool taskStatus,
required String projectId,
}) async {
try {
DocumentReference documentReference =
_firestore.collection('tasks').doc();
TaskModel createTask = TaskModel(
projectId: projectId,
id: documentReference.id,
taskDescription: taskDescription,
taskStatus: false,
taskTitle: taskTitle,
timestamp: Timestamp.now(),
);
await documentReference.set(createTask.toMap());
printSuccess('Task added successfully!');
} catch (e) {
printError('Error adding task: $e');
throw ('Error adding task: $e');
}
}
Future<void> changeTaskstatus({
required String taskId,
required bool taskStatus,
}) async {
try {
DocumentReference documentReference =
_firestore.collection('tasks').doc(taskId);
// Update only the taskStatus field
await documentReference.update({'taskStatus': !taskStatus});
printSuccess('Task status changed successfully!');
} catch (e) {
printError('Error changing task status: $e');
throw ('Error changing task status: $e');
}
}
Future<TaskModel?> getTasksById({required String taskId}) async {
try {
DocumentSnapshot projectSnapshot =
await _firestore.collection('tasks').doc(taskId).get();
if (projectSnapshot.exists) {
return TaskModel.fromMap(
projectSnapshot.data() as Map<String, dynamic>);
} else {
return null;
}
} catch (e) {
throw ('Error getting project by ID: $e');
}
}
}
task_state.dart (just in case it's needed)
import 'package:flutter_riverpod/flutter_riverpod.dart';
class TasksState {
// Add a provider container to manage the state of each task
final ProviderContainer container = ProviderContainer();
// Your existing state properties
final bool isLoading;
final String error;
TasksState({
this.isLoading = false,
this.error = '',
});
TasksState copyWith({
bool? isLoading,
String? error,
}) {
return TasksState(
isLoading: isLoading ?? this.isLoading,
error: error ?? this.error,
);
}
}
task_controller.dart
class TaskController extends StateNotifier<TasksState> {
final TasksRepo _tasksRepo;
TaskController(super.state, this._tasksRepo);
Future<void> createTask({
required String taskTitle,
required String taskDescription,
required bool taskStatus,
required projectId,
// required DateTime dateTime,
// required Color color,
}) async {
state = state.copyWith(isLoading: true);
try {
await _tasksRepo.createTask(
taskDescription: taskDescription,
taskStatus: false,
taskTitle: taskTitle,
projectId: projectId);
state = state.copyWith(
isLoading: false,
);
} catch (e) {
state = state.copyWith(isLoading: false, error: e.toString());
}
}
Future<void> changeTaskStatus(
{required String taskId,
required String taskTitle,
required String taskDescription,
required bool taskStatus,
required String projectId}) async {
try {
state = state.copyWith(isLoading: true);
await _tasksRepo.changeTaskstatus(
taskId: taskId,
taskStatus: taskStatus,
);
print(taskStatus.toString());
state = state.copyWith(
isLoading: false,
);
} catch (e) {
state = state.copyWith(isLoading: false, error: e.toString());
}
}
}
task_provider.dart
import 'package:capstone_project/app/modules/tasks/domain/providers/controllers/task_controller.dart';
import 'package:capstone_project/app/modules/tasks/domain/providers/state/task_state.dart';
import 'package:capstone_project/app/modules/tasks/domain/providers/repository/task_repo.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
final taskRepoProvider = Provider<TasksRepo>((ref) {
return TasksRepo();
});
final tasksStateNotifierProvider =
StateNotifierProvider<TaskController, TasksState>(
(ref) => TaskController(
TasksState(),
ref.read(
taskRepoProvider,
),
),
);
taskdetailspage.dart
import 'package:capstone_project/app/modules/tasks/domain/models/task_model.dart';
import 'package:capstone_project/app/modules/tasks/domain/providers/task_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class TaskDetails extends ConsumerWidget {
final TaskModel taskModel;
TaskDetails({required this.taskModel});
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(
title: Text(taskModel.taskTitle), // Display the task title
),
body: Column(
children: [
Text("description: ${taskModel.taskDescription}"),
SizedBox(
height: 20,
),
Text("task status: ${taskModel.taskStatus}"),
ElevatedButton(
onPressed: () {
final taskRepoProviders =
ref.read(tasksStateNotifierProvider.notifier);
taskRepoProviders.changeTaskStatus(
taskId: taskModel.id,
taskTitle: taskModel.taskTitle,
taskDescription: taskModel.taskDescription,
taskStatus: taskModel.taskStatus,
projectId: taskModel.projectId);
},
child: Text("Please")),
],
),
);
}
}
part of the code inside task_page.dart (the page before task_details.dart which contains the ElevatedButton that switch the bool from false to true)
StreamBuilder<List<TaskModel>>(
stream: ref
.watch(taskRepoProvider)
.fetchTasks(projectId: projectModel.projectID),
builder: (context, snapshot) {
if (snapshot.hasData) {
listTasks = snapshot.data!;
return ListView.builder(
padding: EdgeInsets.only(
left: context.screenWidth * 0.015,
right: context.screenWidth * 0.015,
bottom: context.screenHeight * 0.05,
top: context.screenHeight * 0.01),
itemCount: listTasks.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () => {
context.pushNamed(
NamedRoutes.taskDetails,
extra: listTasks[index],
)
},
child: TaskCardWithTimelineWidget(
task: listTasks[index],
firstItem: index,
lastItem: index,
projectModel: projectModel,
),
);
},
);
I tried using riverpod in many different ways, I looked different articles and examples, but no luck solving the issue, I'm not sure if it's because using extra in the 'routes.dart' file, but it making things a bit more complicated, or maybe not compatible with the way I'm doing things. I wouldn't mind using the regular Provider package, but solving this would be a big help.