marco.pms.mobileapp/lib/view/employees/assign_employee_bottom_sheet.dart

193 lines
6.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:marco/helpers/widgets/my_spacing.dart';
import 'package:marco/helpers/widgets/my_text.dart';
import 'package:marco/helpers/widgets/my_snackbar.dart';
import 'package:marco/controller/employee/assign_projects_controller.dart';
import 'package:marco/model/global_project_model.dart';
import 'package:marco/helpers/utils/base_bottom_sheet.dart';
class AssignProjectBottomSheet extends StatefulWidget {
final String employeeId;
final String jobRoleId;
const AssignProjectBottomSheet({
super.key,
required this.employeeId,
required this.jobRoleId,
});
@override
State<AssignProjectBottomSheet> createState() =>
_AssignProjectBottomSheetState();
}
class _AssignProjectBottomSheetState extends State<AssignProjectBottomSheet> {
late final AssignProjectController assignController;
final ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
assignController = Get.put(
AssignProjectController(
employeeId: widget.employeeId,
jobRoleId: widget.jobRoleId,
),
tag: '${widget.employeeId}_${widget.jobRoleId}',
);
}
@override
Widget build(BuildContext context) {
return GetBuilder<AssignProjectController>(
tag: '${widget.employeeId}_${widget.jobRoleId}',
builder: (_) {
return BaseBottomSheet(
title: "Assign to Project",
onCancel: () => Navigator.pop(context),
onSubmit: _handleAssign,
submitText: "Assign",
child: Obx(() {
if (assignController.isLoading.value) {
return const Center(child: CircularProgressIndicator());
}
final projects = assignController.allProjects;
if (projects.isEmpty) {
return const Center(child: Text('No projects available.'));
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
MyText.bodySmall(
'Select the projects to assign this employee.',
color: Colors.grey[600],
),
MySpacing.height(8),
// Select All
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Projects (${projects.length})',
style: const TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16,
),
),
TextButton(
onPressed: () {
assignController.toggleSelectAll();
},
child: Obx(() {
return Text(
assignController.areAllSelected()
? 'Deselect All'
: 'Select All',
style: const TextStyle(
color: Colors.blueAccent,
fontWeight: FontWeight.w600,
),
);
}),
),
],
),
// List of Projects
SizedBox(
height: 300,
child: ListView.builder(
controller: _scrollController,
itemCount: projects.length,
itemBuilder: (context, index) {
final GlobalProjectModel project = projects[index];
return Obx(() {
final bool isSelected =
assignController.isProjectSelected(
project.id.toString(),
);
return Theme(
data: Theme.of(context).copyWith(
checkboxTheme: CheckboxThemeData(
fillColor: WidgetStateProperty.resolveWith<Color>(
(states) => states.contains(WidgetState.selected)
? Colors.blueAccent
: Colors.white,
),
side: const BorderSide(
color: Colors.black,
width: 2,
),
checkColor:
WidgetStateProperty.all(Colors.white),
),
),
child: CheckboxListTile(
dense: true,
value: isSelected,
title: Text(
project.name,
style: const TextStyle(
fontWeight: FontWeight.w500,
fontSize: 14,
),
),
onChanged: (checked) {
assignController.toggleProjectSelection(
project.id.toString(),
checked ?? false,
);
},
activeColor: Colors.blueAccent,
controlAffinity: ListTileControlAffinity.leading,
contentPadding: EdgeInsets.zero,
visualDensity: const VisualDensity(
horizontal: -4,
vertical: -4,
),
),
);
});
},
),
),
],
);
}),
);
},
);
}
Future<void> _handleAssign() async {
if (assignController.selectedProjects.isEmpty) {
showAppSnackbar(
title: "Error",
message: "Please select at least one project.",
type: SnackbarType.error,
);
return;
}
final success = await assignController.assignProjectsToEmployee();
if (success) {
Get.back();
showAppSnackbar(
title: "Success",
message: "Employee assigned to selected projects.",
type: SnackbarType.success,
);
} else {
showAppSnackbar(
title: "Error",
message: "Failed to assign employee.",
type: SnackbarType.error,
);
}
}
}