marco.pms.mobileapp/lib/model/directory/edit_bucket_bottom_sheet.dart

197 lines
6.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:collection/collection.dart';
import 'package:on_field_work/controller/directory/manage_bucket_controller.dart';
import 'package:on_field_work/controller/directory/directory_controller.dart';
import 'package:on_field_work/helpers/utils/base_bottom_sheet.dart';
import 'package:on_field_work/helpers/widgets/my_text.dart';
import 'package:on_field_work/helpers/widgets/my_spacing.dart';
import 'package:on_field_work/helpers/widgets/my_snackbar.dart';
import 'package:on_field_work/model/employees/employee_model.dart';
import 'package:on_field_work/model/directory/contact_bucket_list_model.dart';
import 'package:on_field_work/model/employees/multiple_select_bottomsheet.dart';
class EditBucketBottomSheet {
static void show(
BuildContext context,
ContactBucket bucket,
List<EmployeeModel> allEmployees, {
required String ownerId,
}) {
final ManageBucketController controller = Get.find();
final nameController = TextEditingController(text: bucket.name);
final descController = TextEditingController(text: bucket.description);
final selectedIds = RxSet<String>({...bucket.employeeIds});
InputDecoration _inputDecoration(String label) {
return InputDecoration(
labelText: label,
filled: true,
fillColor: Colors.grey.shade100,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.grey.shade300),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: Colors.grey.shade300),
),
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
borderSide: BorderSide(color: Colors.blueAccent, width: 1.5),
),
contentPadding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
isDense: true,
);
}
Future<void> _handleSubmit() async {
final newName = nameController.text.trim();
final newDesc = descController.text.trim();
final newEmployeeIds = selectedIds.toList()..sort();
final originalEmployeeIds = [...bucket.employeeIds]..sort();
final nameChanged = newName != bucket.name;
final descChanged = newDesc != bucket.description;
final employeeChanged =
!(const ListEquality().equals(newEmployeeIds, originalEmployeeIds));
if (!nameChanged && !descChanged && !employeeChanged) {
showAppSnackbar(
title: "No Changes",
message: "No changes were made to update the bucket.",
type: SnackbarType.warning,
);
return;
}
final success = await controller.updateBucket(
id: bucket.id,
name: newName,
description: newDesc,
employeeIds: newEmployeeIds,
originalEmployeeIds: originalEmployeeIds,
);
if (success) {
final directoryController = Get.find<DirectoryController>();
await directoryController.fetchBuckets();
Navigator.of(context).pop();
}
}
Future<void> _handleSubmitBottomSheet(BuildContext sheetContext) async {
await _handleSubmit();
// close bottom sheet safely
if (Navigator.of(sheetContext).canPop()) {
Navigator.of(sheetContext).pop();
}
}
Widget _formContent() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
controller: nameController,
decoration: _inputDecoration('Bucket Name'),
),
MySpacing.height(16),
TextField(
controller: descController,
maxLines: 2,
decoration: _inputDecoration('Description'),
),
MySpacing.height(20),
MyText.labelLarge('Shared With', fontWeight: 600),
MySpacing.height(8),
Obx(() {
if (selectedIds.isEmpty) return const SizedBox.shrink();
final selectedEmployees =
allEmployees.where((e) => selectedIds.contains(e.id)).toList();
return Wrap(
spacing: 8,
children: selectedEmployees.map((emp) {
final fullName = '${emp.firstName} ${emp.lastName}'.trim();
return Chip(
label: Text(fullName),
onDeleted: emp.id == ownerId
? null
: () => selectedIds.remove(emp.id),
);
}).toList(),
);
}),
MySpacing.height(8),
// --- Open new EmployeeSelectionBottomSheet ---
GestureDetector(
onTap: () async {
final initiallySelected = allEmployees
.where((e) => selectedIds.contains(e.id))
.toList();
final result = await showModalBottomSheet<List<EmployeeModel>>(
context: context,
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(22)),
),
builder: (_) => EmployeeSelectionBottomSheet(
initiallySelected: initiallySelected,
multipleSelection: true,
title: "Shared With",
),
);
if (result != null) {
selectedIds
..clear()
..addAll(result.map((e) => e.id));
}
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey.shade300),
),
child: Row(
children: const [
Icon(Icons.search, color: Colors.grey),
SizedBox(width: 8),
Expanded(child: Text("Search & Select Employees")),
],
),
),
),
MySpacing.height(8),
const SizedBox.shrink(),
],
);
}
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) {
return BaseBottomSheet(
title: "Edit Bucket",
onCancel: () => Navigator.pop(context),
onSubmit: () => _handleSubmitBottomSheet(context),
child: _formContent(),
);
},
);
}
}