feature aggiunta

This commit is contained in:
2026-04-20 11:18:22 +02:00
parent 023665ae58
commit 78012fdbf3
13 changed files with 631 additions and 80 deletions

View File

@@ -1,10 +1,15 @@
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flux/core/blocs/session/session_bloc.dart';
import 'package:flux/core/utils/string_extensions.dart';
import 'package:flux/features/services/models/service_file_model.dart';
import 'package:get_it/get_it.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import '../models/service_model.dart';
class ServicesRepository {
final _supabase = Supabase.instance.client;
final companyId = GetIt.I.get<SessionBloc>().state.company!.id;
// --- RECUPERO SINGOLO SERVIZIO CON JOIN COMPLETO ---
Future<ServiceModel> fetchServiceById(String id) async {
@@ -16,7 +21,8 @@ class ServicesRepository {
customer(nome),
energy_service(*),
fin_service(*),
entertainment_service(*)
entertainment_service(*),
service_file(*)
''')
.eq('id', id)
.single();
@@ -44,7 +50,8 @@ class ServicesRepository {
customer(nome),
energy_service(*),
fin_service(*),
entertainment_service(*)
entertainment_service(*),
service_file(*)
''')
.eq('company_id', companyId);
@@ -75,7 +82,10 @@ class ServicesRepository {
}
// --- SALVATAGGIO COMPLETO (PRIMA PADRE, POI FIGLI) ---
Future<void> saveFullService(ServiceModel service) async {
Future<void> saveFullService(
ServiceModel service,
List<PlatformFile> localFiles,
) async {
try {
// 1. Upsert del record principale
final serviceData = await _supabase
@@ -142,6 +152,63 @@ class ServicesRepository {
if (insertTasks.isNotEmpty) {
await Future.wait(insertTasks);
}
if (localFiles.isNotEmpty) {
final List<Future> uploadTasks = [];
for (var file in localFiles) {
// Puliamo il nome del file per evitare problemi con spazi o caratteri strani
final cleanFileName = file.name.replaceAll(
RegExp(r'[^a-zA-Z0-9\.\-]'),
'_',
);
final storagePath =
'$companyId/services/$newId/${DateTime.now().millisecondsSinceEpoch}_$cleanFileName';
final int fileSize = file.size;
final fileToSave = ServiceFileModel(
name: cleanFileName.fileNameWithoutExtension(),
extension: cleanFileName.fileExtension(),
url: '',
serviceId: newId,
fileSize: fileSize,
);
// Creiamo una funzione asincrona per caricare file e scrivere nel DB
Future<void> uploadAndLink() async {
// Determiniamo il MIME type corretto in base all'estensione
final String mimeType = fileToSave.extension.toLowerCase() == 'pdf'
? 'application/pdf'
: 'image/${fileToSave.extension}';
// A. Upload nel Bucket Storage (usiamo i bytes così funziona anche su Web!)
await _supabase.storage
.from('documents')
.uploadBinary(
storagePath,
file.bytes!,
fileOptions: FileOptions(
contentType:
mimeType, // Diciamo a Supabase esattamente cos'è!
upsert:
true, // Opzionale: sovrascrive se esiste già un file con lo stesso nome
),
);
// B. Otteniamo l'URL pubblico e scriviamo il record del file nel DB
final String publicUrl = _supabase.storage
.from('documents')
.getPublicUrl(storagePath);
await _supabase
.from('service_file')
.insert(fileToSave.copyWith(url: publicUrl).toMap());
}
uploadTasks.add(uploadAndLink());
}
// Eseguiamo tutti gli upload in parallelo per la massima velocità
await Future.wait(uploadTasks);
}
} catch (e) {
// Qui potresti aggiungere una logica di "rollback manuale" se necessario
throw Exception('Errore durante il salvataggio corazzato: $e');
@@ -188,28 +255,4 @@ class ServicesRepository {
]; // Fallback se non c'è ancora storia
}
}
Future<void> uploadAttachment({
required String serviceId,
required String fileName,
required Uint8List fileBytes,
}) async {
try {
// 1. Upload fisico nel bucket 'service_documents'
final path = '$serviceId/$fileName';
await _supabase.storage
.from('service_documents')
.uploadBinary(path, fileBytes);
// 2. Registriamo l'esistenza del file nel database
await _supabase.from('service_attachment').insert({
'service_id': serviceId,
'file_path': path,
'file_name': fileName,
'created_at': DateTime.now().toIso8601String(),
});
} catch (e) {
throw "Errore upload: $e";
}
}
}