Files
SIB/old/lib/services/taxi_service.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
}
}
}