243 lines
7.1 KiB
Dart
243 lines
7.1 KiB
Dart
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
|
|
|
import '../models/taxi_model.dart';
|
|
import './supabase_service.dart';
|
|
|
|
/// Service for managing taxi data and favorites functionality
|
|
class TaxiService {
|
|
static TaxiService? _instance;
|
|
static TaxiService get instance => _instance ??= TaxiService._();
|
|
TaxiService._();
|
|
|
|
final SupabaseClient _client = SupabaseService.client;
|
|
static const String _favoritesKey = 'favorite_taxi_ids';
|
|
|
|
/// Get distinct corregimientos from active taxis
|
|
Future<List<String>> getCorregimientos() async {
|
|
try {
|
|
final response = await _client
|
|
.from('taxis')
|
|
.select('corregimiento')
|
|
.eq('is_active', true)
|
|
.order('corregimiento');
|
|
|
|
if (response.isEmpty) return [];
|
|
|
|
// Extract unique corregimientos
|
|
final Set<String> uniqueCorregimientos = {};
|
|
for (final item in response) {
|
|
final corregimiento = item['corregimiento'] as String?;
|
|
if (corregimiento != null && corregimiento.isNotEmpty) {
|
|
uniqueCorregimientos.add(corregimiento);
|
|
}
|
|
}
|
|
|
|
return uniqueCorregimientos.toList()..sort();
|
|
} catch (e) {
|
|
throw Exception('Failed to fetch corregimientos: $e');
|
|
}
|
|
}
|
|
|
|
/// Get available shifts
|
|
List<String> getShifts() {
|
|
return ['Day', 'Evening', 'Night'];
|
|
}
|
|
|
|
/// Search taxis with optional corregimiento, shift, and text filters
|
|
Future<List<TaxiModel>> searchTaxis({
|
|
String? selectedCorregimiento,
|
|
String? selectedShift,
|
|
String? searchText,
|
|
}) async {
|
|
try {
|
|
var query = _client.from('taxis').select('*').eq('is_active', true);
|
|
|
|
// Apply corregimiento filter
|
|
if (selectedCorregimiento != null && selectedCorregimiento.isNotEmpty) {
|
|
query = query.eq('corregimiento', selectedCorregimiento);
|
|
}
|
|
|
|
// Apply shift filter
|
|
if (selectedShift != null && selectedShift.isNotEmpty) {
|
|
// Convert display name to database value
|
|
String dbShift = selectedShift.toLowerCase();
|
|
query = query.eq('shift', dbShift);
|
|
}
|
|
|
|
// Apply text search filter
|
|
if (searchText != null && searchText.isNotEmpty) {
|
|
query = query.or('name.ilike.%$searchText%,phone.ilike.%$searchText%');
|
|
}
|
|
|
|
final response = await query.order('name');
|
|
|
|
return response
|
|
.map<TaxiModel>((json) => TaxiModel.fromJson(json))
|
|
.toList();
|
|
} catch (e) {
|
|
throw Exception('Failed to search taxis: $e');
|
|
}
|
|
}
|
|
|
|
/// Get user's favorite taxi IDs (from Supabase or local storage)
|
|
Future<List<String>> getFavoriteTaxiIds() async {
|
|
try {
|
|
// Check if user is authenticated
|
|
final user = _client.auth.currentUser;
|
|
if (user != null) {
|
|
// Get favorites from Supabase
|
|
final response = await _client
|
|
.from('favorite_taxis')
|
|
.select('taxi_id')
|
|
.eq('user_id', user.id);
|
|
|
|
return response
|
|
.map<String>((item) => item['taxi_id'] as String)
|
|
.toList();
|
|
} else {
|
|
// Get favorites from local storage
|
|
return await _getLocalFavorites();
|
|
}
|
|
} catch (e) {
|
|
// Fallback to local storage if Supabase fails
|
|
return await _getLocalFavorites();
|
|
}
|
|
}
|
|
|
|
/// Toggle favorite status for a taxi
|
|
Future<bool> toggleFavorite(String taxiId) async {
|
|
try {
|
|
final user = _client.auth.currentUser;
|
|
|
|
if (user != null) {
|
|
// Handle Supabase favorites
|
|
return await _toggleSupabaseFavorite(user.id, taxiId);
|
|
} else {
|
|
// Handle local storage favorites
|
|
return await _toggleLocalFavorite(taxiId);
|
|
}
|
|
} catch (e) {
|
|
// Fallback to local storage
|
|
return await _toggleLocalFavorite(taxiId);
|
|
}
|
|
}
|
|
|
|
/// Check if taxi is favorited
|
|
Future<bool> isFavorite(String taxiId) async {
|
|
final favorites = await getFavoriteTaxiIds();
|
|
return favorites.contains(taxiId);
|
|
}
|
|
|
|
/// Handle Supabase favorite toggle
|
|
Future<bool> _toggleSupabaseFavorite(String userId, String taxiId) async {
|
|
try {
|
|
// Check if favorite exists
|
|
final existing =
|
|
await _client
|
|
.from('favorite_taxis')
|
|
.select('id')
|
|
.eq('user_id', userId)
|
|
.eq('taxi_id', taxiId)
|
|
.maybeSingle();
|
|
|
|
if (existing != null) {
|
|
// Remove favorite
|
|
await _client
|
|
.from('favorite_taxis')
|
|
.delete()
|
|
.eq('user_id', userId)
|
|
.eq('taxi_id', taxiId);
|
|
return false;
|
|
} else {
|
|
// Add favorite
|
|
await _client.from('favorite_taxis').insert({
|
|
'user_id': userId,
|
|
'taxi_id': taxiId,
|
|
});
|
|
return true;
|
|
}
|
|
} catch (e) {
|
|
throw Exception('Failed to toggle Supabase favorite: $e');
|
|
}
|
|
}
|
|
|
|
/// Handle local storage favorite toggle
|
|
Future<bool> _toggleLocalFavorite(String taxiId) async {
|
|
try {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final favorites = prefs.getStringList(_favoritesKey) ?? [];
|
|
|
|
if (favorites.contains(taxiId)) {
|
|
favorites.remove(taxiId);
|
|
await prefs.setStringList(_favoritesKey, favorites);
|
|
return false;
|
|
} else {
|
|
favorites.add(taxiId);
|
|
await prefs.setStringList(_favoritesKey, favorites);
|
|
return true;
|
|
}
|
|
} catch (e) {
|
|
throw Exception('Failed to toggle local favorite: $e');
|
|
}
|
|
}
|
|
|
|
/// Get favorites from local storage
|
|
Future<List<String>> _getLocalFavorites() async {
|
|
try {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
return prefs.getStringList(_favoritesKey) ?? [];
|
|
} catch (e) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/// Clear all local favorites (for testing/reset)
|
|
Future<void> clearLocalFavorites() async {
|
|
try {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.remove(_favoritesKey);
|
|
} catch (e) {
|
|
// Silent fail for clearing favorites
|
|
}
|
|
}
|
|
|
|
/// Sync local favorites to Supabase when user authenticates
|
|
Future<void> syncLocalFavoritesToSupabase() async {
|
|
try {
|
|
final user = _client.auth.currentUser;
|
|
if (user == null) return;
|
|
|
|
final localFavorites = await _getLocalFavorites();
|
|
if (localFavorites.isEmpty) return;
|
|
|
|
// Get existing Supabase favorites
|
|
final supabaseFavorites = await _client
|
|
.from('favorite_taxis')
|
|
.select('taxi_id')
|
|
.eq('user_id', user.id);
|
|
|
|
final existingIds =
|
|
supabaseFavorites
|
|
.map<String>((item) => item['taxi_id'] as String)
|
|
.toSet();
|
|
|
|
// Add local favorites that don't exist in Supabase
|
|
final toAdd = localFavorites.where((id) => !existingIds.contains(id));
|
|
|
|
if (toAdd.isNotEmpty) {
|
|
final insertData =
|
|
toAdd
|
|
.map((taxiId) => {'user_id': user.id, 'taxi_id': taxiId})
|
|
.toList();
|
|
|
|
await _client.from('favorite_taxis').insert(insertData);
|
|
}
|
|
|
|
// Clear local favorites after successful sync
|
|
await clearLocalFavorites();
|
|
} catch (e) {
|
|
// Silent fail for sync operation
|
|
}
|
|
}
|
|
} |