160 lines
4.7 KiB
Dart
160 lines
4.7 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:file_picker/file_picker.dart';
|
|
import 'package:flux/features/customers/models/customer_file_model.dart';
|
|
import 'package:get_it/get_it.dart';
|
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
|
import '../models/customer_model.dart';
|
|
|
|
class CustomerRepository {
|
|
final SupabaseClient _client = GetIt.I<SupabaseClient>();
|
|
|
|
// Crea un nuovo cliente
|
|
Future<CustomerModel> saveCustomer(CustomerModel customer) async {
|
|
try {
|
|
final response = await _client
|
|
.from('customer')
|
|
.upsert(customer.toJson())
|
|
.select()
|
|
.single();
|
|
return CustomerModel.fromJson(response);
|
|
} catch (e) {
|
|
throw 'Errore durante il salvataggio del cliente: $e';
|
|
}
|
|
}
|
|
|
|
Future<CustomerModel> updateCustomer(CustomerModel customer) async {
|
|
try {
|
|
final response = await _client
|
|
.from('customer')
|
|
.update(customer.toJson())
|
|
.eq('id', customer.id!)
|
|
.select()
|
|
.single();
|
|
return CustomerModel.fromJson(response);
|
|
} catch (e) {
|
|
throw 'Errore durante la modifica del cliente: $e';
|
|
}
|
|
}
|
|
|
|
// Recupera tutti i clienti dell'azienda
|
|
Future<List<CustomerModel>> getCustomers(String companyId) async {
|
|
try {
|
|
final response = await _client
|
|
.from('customer')
|
|
.select('*, customer_file(count)')
|
|
.eq('company_id', companyId)
|
|
.eq('is_active', true)
|
|
.order('nome');
|
|
|
|
return (response as List).map((c) => CustomerModel.fromJson(c)).toList();
|
|
} catch (e) {
|
|
throw 'Errore nel recupero clienti';
|
|
}
|
|
}
|
|
|
|
// Ricerca clienti per nome o telefono (fondamentale per la UX)
|
|
Future<List<CustomerModel>> searchCustomers(
|
|
String companyId,
|
|
String query,
|
|
) async {
|
|
try {
|
|
final response = await _client
|
|
.from('customer')
|
|
.select()
|
|
.eq('company_id', companyId)
|
|
.or('nome.ilike.%$query%,telefono.ilike.%$query%')
|
|
.limit(10);
|
|
|
|
return (response as List).map((c) => CustomerModel.fromJson(c)).toList();
|
|
} catch (e) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/// Recupera i file di un cliente specifico
|
|
Future<List<CustomerFileModel>> getCustomerFiles(String customerId) async {
|
|
try {
|
|
final response = await _client
|
|
.from('customer_file')
|
|
.select()
|
|
.eq('customer_id', customerId);
|
|
|
|
return (response as List)
|
|
.map((f) => CustomerFileModel.fromJson(f))
|
|
.toList();
|
|
} catch (e) {
|
|
throw 'Errore recupero file: $e';
|
|
}
|
|
}
|
|
|
|
/// Salva il riferimento del file nel DB
|
|
Future<void> saveFileReference(CustomerFileModel file) async {
|
|
await _client.from('customer_file').insert(file.toJson());
|
|
}
|
|
|
|
/// Carica un file e salva il riferimento nel database
|
|
Future<CustomerFileModel> uploadAndRegisterFile({
|
|
required String customerId,
|
|
required PlatformFile pickedFile,
|
|
}) async {
|
|
try {
|
|
final user = _client.auth.currentUser;
|
|
if (user == null) throw 'Utente non autenticato';
|
|
|
|
final fileName = pickedFile.name;
|
|
final extension = pickedFile.extension ?? '';
|
|
final path =
|
|
'${user.id}/$customerId/${DateTime.now().millisecondsSinceEpoch}_$fileName';
|
|
|
|
// Usiamo bytes invece del path per massima compatibilità
|
|
if (pickedFile.bytes == null && pickedFile.path == null) {
|
|
throw 'Impossibile leggere il contenuto del file';
|
|
}
|
|
|
|
// Se siamo su desktop/mobile abbiamo il path, su web abbiamo i bytes
|
|
if (pickedFile.bytes != null) {
|
|
await _client.storage
|
|
.from('documents')
|
|
.uploadBinary(path, pickedFile.bytes!);
|
|
} else {
|
|
final file = File(pickedFile.path!);
|
|
await _client.storage.from('documents').upload(path, file);
|
|
}
|
|
|
|
final String publicUrl = _client.storage
|
|
.from('documents')
|
|
.getPublicUrl(path);
|
|
|
|
final fileRecord = CustomerFileModel(
|
|
customerId: customerId,
|
|
name: fileName,
|
|
url: publicUrl,
|
|
extension: extension,
|
|
);
|
|
|
|
final response = await _client
|
|
.from('customer_file')
|
|
.insert(fileRecord.toJson())
|
|
.select()
|
|
.single();
|
|
|
|
return CustomerFileModel.fromJson(response);
|
|
} catch (e) {
|
|
throw 'Errore durante l\'upload: $e';
|
|
}
|
|
}
|
|
|
|
/// Aggiorna la lista degli URL nel database
|
|
Future<void> updateCustomerDocuments(int id, List<String> urls) async {
|
|
await _client.from('customer').update({'document_urls': urls}).eq('id', id);
|
|
}
|
|
|
|
/// Elimina un file dallo storage
|
|
Future<void> deleteDocument(String fullPath) async {
|
|
// Il path dovrebbe essere ricavato dall'URL
|
|
final path = fullPath.split('documents/').last;
|
|
await _client.storage.from('documents').remove([path]);
|
|
}
|
|
}
|