263 lines
8.1 KiB
Dart
263 lines
8.1 KiB
Dart
import 'package:url_launcher/url_launcher.dart';
|
|
import '../services/api_service.dart';
|
|
import 'snackbar_util.dart';
|
|
|
|
/// WhatsApp Integration Utility
|
|
/// Handles WhatsApp sharing and communication
|
|
class WhatsAppUtil {
|
|
static final _apiService = ApiService();
|
|
/// Open WhatsApp with a pre-filled message
|
|
static Future<bool> openWhatsApp(String phone, String message) async {
|
|
try {
|
|
// Clean phone number
|
|
final cleanPhone = phone.replaceAll(RegExp(r'\D'), '');
|
|
|
|
// Add country code if not present (91 for India)
|
|
final formattedPhone = cleanPhone.startsWith('91')
|
|
? cleanPhone
|
|
: '91$cleanPhone';
|
|
|
|
// Encode message
|
|
final encodedMessage = Uri.encodeComponent(message);
|
|
|
|
// Create WhatsApp URL
|
|
final url = 'https://wa.me/$formattedPhone?text=$encodedMessage';
|
|
|
|
// Launch URL
|
|
final uri = Uri.parse(url);
|
|
if (await canLaunchUrl(uri)) {
|
|
return await launchUrl(
|
|
uri,
|
|
mode: LaunchMode.externalApplication,
|
|
);
|
|
} else {
|
|
SnackbarUtil.showError('Could not open WhatsApp');
|
|
return false;
|
|
}
|
|
} catch (e) {
|
|
SnackbarUtil.showError('Error opening WhatsApp: ${e.toString()}');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Share payment receipt via WhatsApp
|
|
static Future<bool> sharePaymentReceipt(String paymentId) async {
|
|
try {
|
|
SnackbarUtil.showLoading('Generating receipt...');
|
|
|
|
final response = await _apiService.post(
|
|
'/share/payment-receipt',
|
|
{'paymentId': paymentId},
|
|
);
|
|
|
|
SnackbarUtil.dismiss();
|
|
|
|
if (response['success'] == true) {
|
|
final whatsappUrl = response['data']['whatsappUrl'];
|
|
final uri = Uri.parse(whatsappUrl);
|
|
|
|
if (await canLaunchUrl(uri)) {
|
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
|
SnackbarUtil.showSuccess('Opening WhatsApp...');
|
|
return true;
|
|
} else {
|
|
SnackbarUtil.showError('Could not open WhatsApp');
|
|
return false;
|
|
}
|
|
} else {
|
|
SnackbarUtil.showError(response['message'] ?? 'Failed to generate receipt');
|
|
return false;
|
|
}
|
|
} catch (e) {
|
|
SnackbarUtil.dismiss();
|
|
SnackbarUtil.showError('Error sharing receipt: ${e.toString()}');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Fetch the permanent public URL for a completed draw (manager auth).
|
|
static Future<String?> getDrawPublicShareUrl(String drawId) async {
|
|
try {
|
|
final response = await _apiService.post('/share/draw-link', {'drawId': drawId});
|
|
if (response['success'] == true && response['data'] != null) {
|
|
return response['data']['shareUrl']?.toString();
|
|
}
|
|
return null;
|
|
} catch (_) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// Share draw result via WhatsApp
|
|
static Future<bool> shareDrawResult(String drawId, {String? recipientPhone}) async {
|
|
try {
|
|
SnackbarUtil.showLoading('Generating share link...');
|
|
|
|
final response = await _apiService.post('/share/draw-link', {'drawId': drawId});
|
|
|
|
SnackbarUtil.dismiss();
|
|
|
|
if (response['success'] == true) {
|
|
final message = response['data']['message']?.toString() ?? '';
|
|
if (message.isEmpty) {
|
|
SnackbarUtil.showError('Share message was empty');
|
|
return false;
|
|
}
|
|
return await shareText(message, phone: recipientPhone);
|
|
} else {
|
|
SnackbarUtil.showError(response['message'] ?? 'Failed to generate result');
|
|
return false;
|
|
}
|
|
} catch (e) {
|
|
SnackbarUtil.dismiss();
|
|
SnackbarUtil.showError('Error sharing result: ${e.toString()}');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Share group invitation via WhatsApp
|
|
static Future<bool> shareGroupInvite(String groupId, String recipientPhone) async {
|
|
try {
|
|
if (recipientPhone.isEmpty) {
|
|
SnackbarUtil.showError('Please provide recipient phone number');
|
|
return false;
|
|
}
|
|
|
|
SnackbarUtil.showLoading('Generating invitation...');
|
|
|
|
final response = await _apiService.post(
|
|
'/share/group-invite',
|
|
{
|
|
'groupId': groupId,
|
|
'recipientPhone': recipientPhone,
|
|
},
|
|
);
|
|
|
|
SnackbarUtil.dismiss();
|
|
|
|
if (response['success'] == true) {
|
|
final whatsappUrl = response['data']['whatsappUrl'];
|
|
final uri = Uri.parse(whatsappUrl);
|
|
|
|
if (await canLaunchUrl(uri)) {
|
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
|
SnackbarUtil.showSuccess('Opening WhatsApp...');
|
|
return true;
|
|
} else {
|
|
SnackbarUtil.showError('Could not open WhatsApp');
|
|
return false;
|
|
}
|
|
} else {
|
|
SnackbarUtil.showError(response['message'] ?? 'Failed to generate invitation');
|
|
return false;
|
|
}
|
|
} catch (e) {
|
|
SnackbarUtil.dismiss();
|
|
SnackbarUtil.showError('Error sharing invitation: ${e.toString()}');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Send payment reminder to specific member (Manager only)
|
|
static Future<bool> sendPaymentReminder(String groupId, String memberId) async {
|
|
try {
|
|
SnackbarUtil.showLoading('Generating reminder...');
|
|
|
|
final response = await _apiService.post(
|
|
'/share/payment-reminder',
|
|
{
|
|
'groupId': groupId,
|
|
'memberId': memberId,
|
|
},
|
|
);
|
|
|
|
SnackbarUtil.dismiss();
|
|
|
|
if (response['success'] == true) {
|
|
final whatsappUrl = response['data']['whatsappUrl'];
|
|
final uri = Uri.parse(whatsappUrl);
|
|
|
|
if (await canLaunchUrl(uri)) {
|
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
|
SnackbarUtil.showSuccess('Opening WhatsApp...');
|
|
return true;
|
|
} else {
|
|
SnackbarUtil.showError('Could not open WhatsApp');
|
|
return false;
|
|
}
|
|
} else {
|
|
SnackbarUtil.showError(response['message'] ?? 'Failed to generate reminder');
|
|
return false;
|
|
}
|
|
} catch (e) {
|
|
SnackbarUtil.dismiss();
|
|
SnackbarUtil.showError('Error sending reminder: ${e.toString()}');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Send bulk reminders to all unpaid members (Manager only)
|
|
static Future<Map<String, dynamic>?> sendBulkReminders(String groupId) async {
|
|
try {
|
|
SnackbarUtil.showLoading('Generating bulk reminders...');
|
|
|
|
final response = await _apiService.post(
|
|
'/share/bulk-reminders',
|
|
{'groupId': groupId},
|
|
);
|
|
|
|
SnackbarUtil.dismiss();
|
|
|
|
if (response['success'] == true) {
|
|
final reminderCount = response['data']['total_reminders'];
|
|
|
|
SnackbarUtil.showSuccess(
|
|
'Generated $reminderCount reminder(s)',
|
|
title: 'Reminders Ready',
|
|
duration: const Duration(seconds: 4),
|
|
);
|
|
|
|
// Return reminders list for batch opening
|
|
return response['data'];
|
|
} else {
|
|
SnackbarUtil.showError(response['message'] ?? 'Failed to generate reminders');
|
|
return null;
|
|
}
|
|
} catch (e) {
|
|
SnackbarUtil.dismiss();
|
|
SnackbarUtil.showError('Error generating reminders: ${e.toString()}');
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// Contact manager directly via WhatsApp
|
|
static Future<bool> contactManager(String managerPhone, {String? message}) async {
|
|
final defaultMessage = message ?? 'Hi, I have a question about my chit fund group.';
|
|
return await openWhatsApp(managerPhone, defaultMessage);
|
|
}
|
|
|
|
/// Quick share - Generic text sharing
|
|
static Future<bool> shareText(String text, {String? phone}) async {
|
|
if (phone != null) {
|
|
return await openWhatsApp(phone, text);
|
|
} else {
|
|
// Open WhatsApp without specific recipient
|
|
final encodedMessage = Uri.encodeComponent(text);
|
|
final url = 'https://wa.me/?text=$encodedMessage';
|
|
final uri = Uri.parse(url);
|
|
|
|
if (await canLaunchUrl(uri)) {
|
|
return await launchUrl(uri, mode: LaunchMode.externalApplication);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// Check if WhatsApp is installed
|
|
static Future<bool> isWhatsAppInstalled() async {
|
|
final uri = Uri.parse('https://wa.me/');
|
|
return await canLaunchUrl(uri);
|
|
}
|
|
}
|
|
|