243 lines
7.6 KiB
Dart
243 lines
7.6 KiB
Dart
// Updated AddContactController to support multiple emails and phones
|
|
|
|
import 'package:get/get.dart';
|
|
import 'package:marco/helpers/services/api_service.dart';
|
|
import 'package:marco/helpers/services/app_logger.dart';
|
|
import 'package:marco/helpers/widgets/my_snackbar.dart';
|
|
|
|
class AddContactController extends GetxController {
|
|
final RxList<String> categories = <String>[].obs;
|
|
final RxList<String> buckets = <String>[].obs;
|
|
final RxList<String> globalProjects = <String>[].obs;
|
|
final RxList<String> tags = <String>[].obs;
|
|
|
|
final RxString selectedCategory = ''.obs;
|
|
final RxString selectedBucket = ''.obs;
|
|
final RxString selectedProject = ''.obs;
|
|
|
|
final RxList<String> enteredTags = <String>[].obs;
|
|
final RxList<String> filteredSuggestions = <String>[].obs;
|
|
final RxList<String> organizationNames = <String>[].obs;
|
|
final RxList<String> filteredOrgSuggestions = <String>[].obs;
|
|
|
|
final RxMap<String, String> categoriesMap = <String, String>{}.obs;
|
|
final RxMap<String, String> bucketsMap = <String, String>{}.obs;
|
|
final RxMap<String, String> projectsMap = <String, String>{}.obs;
|
|
final RxMap<String, String> tagsMap = <String, String>{}.obs;
|
|
|
|
@override
|
|
void onInit() {
|
|
super.onInit();
|
|
logSafe("AddContactController initialized", level: LogLevel.debug);
|
|
fetchInitialData();
|
|
}
|
|
|
|
Future<void> fetchInitialData() async {
|
|
logSafe("Fetching initial dropdown data", level: LogLevel.debug);
|
|
await Future.wait([
|
|
fetchBuckets(),
|
|
fetchGlobalProjects(),
|
|
fetchTags(),
|
|
fetchCategories(),
|
|
fetchOrganizationNames(),
|
|
]);
|
|
}
|
|
|
|
void resetForm() {
|
|
selectedCategory.value = '';
|
|
selectedProject.value = '';
|
|
selectedBucket.value = '';
|
|
enteredTags.clear();
|
|
filteredSuggestions.clear();
|
|
filteredOrgSuggestions.clear();
|
|
}
|
|
|
|
Future<void> fetchBuckets() async {
|
|
try {
|
|
final response = await ApiService.getContactBucketList();
|
|
if (response != null && response['data'] is List) {
|
|
final names = <String>[];
|
|
for (var item in response['data']) {
|
|
if (item['name'] != null && item['id'] != null) {
|
|
bucketsMap[item['name']] = item['id'].toString();
|
|
names.add(item['name']);
|
|
}
|
|
}
|
|
buckets.assignAll(names);
|
|
logSafe("Fetched \${names.length} buckets");
|
|
}
|
|
} catch (e) {
|
|
logSafe("Failed to fetch buckets: \$e", level: LogLevel.error);
|
|
}
|
|
}
|
|
|
|
Future<void> fetchOrganizationNames() async {
|
|
try {
|
|
final orgs = await ApiService.getOrganizationList();
|
|
organizationNames.assignAll(orgs);
|
|
logSafe("Fetched \${orgs.length} organization names");
|
|
} catch (e) {
|
|
logSafe("Failed to load organization names: \$e", level: LogLevel.error);
|
|
}
|
|
}
|
|
|
|
Future<void> submitContact({
|
|
required String name,
|
|
required String organization,
|
|
required List<Map<String, String>> emails,
|
|
required List<Map<String, String>> phones,
|
|
required String address,
|
|
required String description,
|
|
}) async {
|
|
try {
|
|
final categoryId = categoriesMap[selectedCategory.value];
|
|
final bucketId = bucketsMap[selectedBucket.value];
|
|
final projectId = projectsMap[selectedProject.value];
|
|
|
|
final tagObjects = enteredTags.map((tagName) {
|
|
final tagId = tagsMap[tagName];
|
|
return tagId != null ? {"id": tagId, "name": tagName} : {"name": tagName};
|
|
}).toList();
|
|
|
|
final body = {
|
|
"name": name,
|
|
"organization": organization,
|
|
"contactCategoryId": categoryId,
|
|
"projectIds": projectId != null ? [projectId] : [],
|
|
"bucketIds": bucketId != null ? [bucketId] : [],
|
|
"tags": tagObjects,
|
|
"contactEmails": emails,
|
|
"contactPhones": phones,
|
|
"address": address,
|
|
"description": description,
|
|
};
|
|
|
|
logSafe("Submitting contact", sensitive: true);
|
|
|
|
final response = await ApiService.createContact(body);
|
|
if (response == true) {
|
|
logSafe("Contact creation succeeded");
|
|
Get.back(result: true);
|
|
showAppSnackbar(
|
|
title: "Success",
|
|
message: "Contact created successfully",
|
|
type: SnackbarType.success,
|
|
);
|
|
} else {
|
|
logSafe("Contact creation failed", level: LogLevel.error);
|
|
showAppSnackbar(
|
|
title: "Error",
|
|
message: "Failed to create contact",
|
|
type: SnackbarType.error,
|
|
);
|
|
}
|
|
} catch (e) {
|
|
logSafe("Contact creation error: \$e", level: LogLevel.error);
|
|
showAppSnackbar(
|
|
title: "Error",
|
|
message: "Something went wrong",
|
|
type: SnackbarType.error,
|
|
);
|
|
}
|
|
}
|
|
|
|
void filterOrganizationSuggestions(String query) {
|
|
if (query.trim().isEmpty) {
|
|
filteredOrgSuggestions.clear();
|
|
return;
|
|
}
|
|
|
|
final lower = query.toLowerCase();
|
|
filteredOrgSuggestions.assignAll(
|
|
organizationNames.where((name) => name.toLowerCase().contains(lower)).toList(),
|
|
);
|
|
logSafe("Filtered organization suggestions for: \$query", level: LogLevel.debug);
|
|
}
|
|
|
|
Future<void> fetchGlobalProjects() async {
|
|
try {
|
|
final response = await ApiService.getGlobalProjects();
|
|
if (response != null) {
|
|
final names = <String>[];
|
|
for (var item in response) {
|
|
final name = item['name']?.toString().trim();
|
|
final id = item['id']?.toString().trim();
|
|
if (name != null && id != null && name.isNotEmpty) {
|
|
projectsMap[name] = id;
|
|
names.add(name);
|
|
}
|
|
}
|
|
globalProjects.assignAll(names);
|
|
logSafe("Fetched \${names.length} global projects");
|
|
}
|
|
} catch (e) {
|
|
logSafe("Failed to fetch global projects: \$e", level: LogLevel.error);
|
|
}
|
|
}
|
|
|
|
Future<void> fetchTags() async {
|
|
try {
|
|
final response = await ApiService.getContactTagList();
|
|
if (response != null && response['data'] is List) {
|
|
tags.assignAll(List<String>.from(
|
|
response['data'].map((e) => e['name'] ?? '').where((e) => e != ''),
|
|
));
|
|
logSafe("Fetched \${tags.length} tags");
|
|
}
|
|
} catch (e) {
|
|
logSafe("Failed to fetch tags: \$e", level: LogLevel.error);
|
|
}
|
|
}
|
|
|
|
void filterSuggestions(String query) {
|
|
if (query.trim().isEmpty) {
|
|
filteredSuggestions.clear();
|
|
return;
|
|
}
|
|
|
|
final lower = query.toLowerCase();
|
|
filteredSuggestions.assignAll(
|
|
tags.where((tag) => tag.toLowerCase().contains(lower) && !enteredTags.contains(tag)).toList(),
|
|
);
|
|
logSafe("Filtered tag suggestions for: \$query", level: LogLevel.debug);
|
|
}
|
|
|
|
void clearSuggestions() {
|
|
filteredSuggestions.clear();
|
|
logSafe("Cleared tag suggestions", level: LogLevel.debug);
|
|
}
|
|
|
|
Future<void> fetchCategories() async {
|
|
try {
|
|
final response = await ApiService.getContactCategoryList();
|
|
if (response != null && response['data'] is List) {
|
|
final names = <String>[];
|
|
for (var item in response['data']) {
|
|
final name = item['name']?.toString().trim();
|
|
final id = item['id']?.toString().trim();
|
|
if (name != null && id != null && name.isNotEmpty) {
|
|
categoriesMap[name] = id;
|
|
names.add(name);
|
|
}
|
|
}
|
|
categories.assignAll(names);
|
|
logSafe("Fetched \${names.length} contact categories");
|
|
}
|
|
} catch (e) {
|
|
logSafe("Failed to fetch categories: \$e", level: LogLevel.error);
|
|
}
|
|
}
|
|
|
|
void addEnteredTag(String tag) {
|
|
if (tag.trim().isNotEmpty && !enteredTags.contains(tag.trim())) {
|
|
enteredTags.add(tag.trim());
|
|
logSafe("Added tag: \$tag", level: LogLevel.debug);
|
|
}
|
|
}
|
|
|
|
void removeEnteredTag(String tag) {
|
|
enteredTags.remove(tag);
|
|
logSafe("Removed tag: \$tag", level: LogLevel.debug);
|
|
}
|
|
}
|