providers-in-store (#4)

Reviewed-on: http://catelliub.zapto.org:3000/brontomark/flux/pulls/4
Co-authored-by: mark-cachy <marco@catelli.it>
Co-committed-by: mark-cachy <marco@catelli.it>
This commit is contained in:
2026-04-17 15:37:14 +02:00
committed by brontomark
parent c1b6c9e7ac
commit 667bbf6404
14 changed files with 688 additions and 335 deletions

View File

@@ -40,29 +40,22 @@ class ProviderRepository {
// Recupera tutti i provider di una company (per la lista generale)
Future<List<ProviderModel>> fetchAllCompanyProviders(String companyId) async {
try {
// La magia è qui: selezioniamo tutto e chiediamo il conteggio (count)
// della tabella pivot providers_in_stores
final response = await _supabase
.from('provider')
.select('''
*,
providers_in_stores(count)
associated_stores:providers_in_stores (
store (
*
)
)
''')
.eq('company_id', companyId)
.order('nome');
return (response as List).map((m) {
// Estraiamo il conteggio dalla struttura restituita da Supabase
// La risposta per ogni riga sarà tipo: { "id": "...", "providers_in_stores": [{"count": 5}] }
final storesList = m['providers_in_stores'] as List?;
final count = (storesList != null && storesList.isNotEmpty)
? storesList[0]['count'] as int
: 0;
return ProviderModel.fromMap(m).copyWith(storesCount: count);
}).toList();
return (response as List).map((m) => ProviderModel.fromMap(m)).toList();
} catch (e) {
throw Exception('Errore fetch all providers: $e');
throw 'Errore fetch providers: $e';
}
}

View File

@@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:flux/features/master_data/store/models/store_model.dart';
class ProviderModel extends Equatable {
final String? id;
@@ -11,7 +12,7 @@ class ProviderModel extends Equatable {
final bool altro;
final bool isActive;
final String companyId;
final int storesCount;
final List<StoreModel> associatedStores;
const ProviderModel({
this.id,
@@ -24,10 +25,21 @@ class ProviderModel extends Equatable {
required this.altro,
required this.isActive,
required this.companyId,
this.storesCount = 0, // Numero di store associati, default a 0
this.associatedStores = const [],
});
factory ProviderModel.fromMap(Map<String, dynamic> map) {
// Estraiamo la lista dalla pivot e poi prendiamo l'oggetto 'store' annidato
final pivotList = map['associated_stores'] as List?;
List<StoreModel> stores = [];
if (pivotList != null) {
stores = pivotList
.where((item) => item['store'] != null) // Sicurezza
.map(
(item) => StoreModel.fromMap(item['store'] as Map<String, dynamic>),
)
.toList();
}
return ProviderModel(
id: map['id'],
nome: map['nome'],
@@ -39,11 +51,7 @@ class ProviderModel extends Equatable {
altro: map['altro'] ?? false,
isActive: map['is_active'] ?? true,
companyId: map['company_id'],
storesCount:
map['providers_in_stores'] != null &&
map['providers_in_stores'].isNotEmpty
? map['providers_in_stores'][0]['count'] as int
: 0, // Assumiamo che l'API possa restituire questo campo
associatedStores: stores,
);
}
@@ -79,7 +87,7 @@ class ProviderModel extends Equatable {
altro,
isActive,
companyId,
storesCount,
associatedStores,
];
ProviderModel copyWith({
@@ -93,7 +101,7 @@ class ProviderModel extends Equatable {
bool? altro,
bool? isActive,
String? companyId,
int? storesCount,
List<StoreModel>? associatedStores,
}) {
return ProviderModel(
id: id ?? this.id,
@@ -106,7 +114,7 @@ class ProviderModel extends Equatable {
altro: altro ?? this.altro,
isActive: isActive ?? this.isActive,
companyId: companyId ?? this.companyId,
storesCount: storesCount ?? this.storesCount,
associatedStores: associatedStores ?? this.associatedStores,
);
}
}

View File

@@ -29,6 +29,9 @@ class _ProviderFormSheetState extends State<ProviderFormSheet> {
void initState() {
super.initState();
final p = widget.initialProvider;
for (final store in p?.associatedStores ?? []) {
_tempSelectedStoreIds.add(store.id!);
}
_nameController = TextEditingController(text: p?.nome ?? '');
_telefoniaFissa = p?.telefoniaFissa ?? false;
_telefoniaMobile = p?.telefoniaMobile ?? false;

View File

@@ -17,8 +17,6 @@ class _ProvidersMasterDataScreenState extends State<ProvidersMasterDataScreen> {
@override
void initState() {
super.initState();
// Carichiamo i provider della company (senza store specifico per ora)
context.read<ProvidersCubit>().loadProviders(null);
}
@override
@@ -126,7 +124,7 @@ class _ProvidersMasterDataScreenState extends State<ProvidersMasterDataScreen> {
// Un piccolo testo che indica il numero di store associati
// Nota: Dovrai assicurarti che il Cubit carichi queste info
return Text(
"Disponibile in ${provider.storesCount} negozi",
"Disponibile in ${provider.associatedStores.length} negozi",
style: TextStyle(
fontSize: 11,
color: Colors.indigo.withValues(alpha: 0.7),