new operation form almost ready

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-05-03 10:08:57 +02:00
parent 40ca1a9160
commit 4580173edf
15 changed files with 578 additions and 61 deletions

View File

@@ -9,19 +9,17 @@ import 'package:get_it/get_it.dart';
part 'product_state.dart';
class ProductCubit extends Cubit<ProductState> {
class ProductsCubit extends Cubit<ProductState> {
final ProductRepository _repository = GetIt.I<ProductRepository>();
final SessionCubit _sessionCubit = GetIt.I<SessionCubit>();
ProductCubit() : super(const ProductState());
ProductsCubit() : super(const ProductState());
// Caricamento iniziale dei Brand
Future<void> loadBrands() async {
emit(state.copyWith(status: ProductStatus.loading));
try {
final brands = await _repository.getBrands(
_sessionCubit.state.company!.id!,
);
final brands = await _repository.getBrands();
emit(state.copyWith(status: ProductStatus.success, brands: brands));
} catch (e) {
emit(
@@ -30,6 +28,27 @@ class ProductCubit extends Cubit<ProductState> {
}
}
Future<void> loadModels() async {
emit(state.copyWith(status: ProductStatus.loading));
try {
final models = await _repository.getModels();
emit(state.copyWith(status: ProductStatus.success, models: models));
} catch (e) {
emit(
state.copyWith(status: ProductStatus.error, errorMessage: e.toString()),
);
}
}
Future<void> refreshCubit() async {
if (state.selectedBrand != null) {
await selectBrand(state.selectedBrand);
} else {
emit(state.copyWith(status: ProductStatus.initial));
await loadBrands();
}
}
// Selezione Brand e caricamento Modelli
Future<void> selectBrand(BrandModel? brand) async {
if (brand == null) {

View File

@@ -1,3 +1,4 @@
import 'package:flux/core/blocs/session/session_cubit.dart';
import 'package:get_it/get_it.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import '../models/brand_model.dart';
@@ -5,16 +6,17 @@ import '../models/model_model.dart';
class ProductRepository {
final SupabaseClient _supabase = GetIt.I<SupabaseClient>();
final String _companyId = GetIt.I<SessionCubit>().state.company!.id!;
// --- BRAND ---
/// Recupera tutti i brand dell'azienda
Future<List<BrandModel>> getBrands(String companyId) async {
Future<List<BrandModel>> getBrands() async {
try {
final response = await _supabase
.from('brand')
.select()
.eq('company_id', companyId)
.eq('company_id', _companyId)
.eq('is_active', true)
.order('name');
@@ -57,6 +59,19 @@ class ProductRepository {
}
}
Future<List<ModelModel>> getModels() async {
try {
final response = await _supabase
.from('model')
.select()
.eq('is_active', true)
.order('name');
return (response as List).map((m) => ModelModel.fromJson(m)).toList();
} catch (e) {
throw '$e';
}
}
/// Crea o aggiorna un modello
/// NOTA: name_with_brand verrà gestito dal trigger SQL che hai lanciato!
Future<ModelModel> upsertModel(ModelModel model) async {

View File

@@ -33,7 +33,7 @@ class BrandSelector extends StatelessWidget {
return DropdownMenuItem(value: brand, child: Text(brand.name));
}).toList(),
onChanged: (brand) =>
context.read<ProductCubit>().selectBrand(brand),
context.read<ProductsCubit>().selectBrand(brand),
),
),
const SizedBox(width: 16),

View File

@@ -64,7 +64,7 @@ class ModelsList extends StatelessWidget {
color: model.isActive ? context.accent : Colors.grey,
),
onPressed: () => context
.read<ProductCubit>()
.read<ProductsCubit>()
.toggleStatus('model', model.id!, model.isActive),
),
],

View File

@@ -40,7 +40,7 @@ void _submitBrand(
BrandModel? brand,
) {
if (controller.text.trim().isNotEmpty) {
context.read<ProductCubit>().saveBrand(controller.text, id: brand?.id);
context.read<ProductsCubit>().saveBrand(controller.text, id: brand?.id);
Navigator.pop(context);
}
}
@@ -81,7 +81,7 @@ void _submitModel(
ModelModel? model,
) {
if (controller.text.isNotEmpty) {
context.read<ProductCubit>().saveModel(controller.text, id: model?.id);
context.read<ProductsCubit>().saveModel(controller.text, id: model?.id);
Navigator.pop(context);
}
}

View File

@@ -12,7 +12,7 @@ class ProductsScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Carichiamo i brand appena la pagina viene creata
context.read<ProductCubit>().loadBrands();
context.read<ProductsCubit>().loadBrands();
return Scaffold(
backgroundColor: context.background,
@@ -33,7 +33,7 @@ class ProductsScreen extends StatelessWidget {
),
),
),
body: BlocConsumer<ProductCubit, ProductState>(
body: BlocConsumer<ProductsCubit, ProductState>(
listener: (context, state) {
if (state.status == ProductStatus.error) {
ScaffoldMessenger.of(context).showSnackBar(

View File

@@ -23,7 +23,7 @@ class _QuickProductDialogState extends State<QuickProductDialog> {
setState(() => _isLoading = true);
final newModel = await context.read<ProductCubit>().quickCreateProduct(
final newModel = await context.read<ProductsCubit>().quickCreateProduct(
brandName: _selectedBrandName.trim(),
modelName: _modelCtrl.text.trim(),
);

View File

@@ -10,6 +10,7 @@ class ProviderModel extends Equatable {
final bool assicurazioni;
final bool intrattenimento;
final bool finanziamenti;
final bool telepass;
final bool altro;
final bool isActive;
final String companyId;
@@ -24,6 +25,7 @@ class ProviderModel extends Equatable {
required this.assicurazioni,
required this.intrattenimento,
required this.finanziamenti,
required this.telepass,
required this.altro,
required this.isActive,
required this.companyId,
@@ -51,6 +53,7 @@ class ProviderModel extends Equatable {
assicurazioni: map['assicurazioni'] ?? false,
intrattenimento: map['intrattenimento'] ?? false,
finanziamenti: map['finanziamenti'] ?? false,
telepass: map['telepass'] ?? false,
altro: map['altro'] ?? false,
isActive: map['is_active'] ?? true,
companyId: map['company_id'],
@@ -67,6 +70,7 @@ class ProviderModel extends Equatable {
'assicurazioni': assicurazioni,
'intrattenimento': intrattenimento,
'finanziamenti': finanziamenti,
'telepass': telepass,
'altro': altro,
'is_active': isActive,
'company_id': companyId,
@@ -89,6 +93,7 @@ class ProviderModel extends Equatable {
assicurazioni,
intrattenimento,
finanziamenti,
telepass,
altro,
isActive,
companyId,
@@ -104,6 +109,7 @@ class ProviderModel extends Equatable {
bool? assicurazioni,
bool? intrattenimento,
bool? finanziamenti,
bool? telepass,
bool? altro,
bool? isActive,
String? companyId,
@@ -118,6 +124,7 @@ class ProviderModel extends Equatable {
assicurazioni: assicurazioni ?? this.assicurazioni,
intrattenimento: intrattenimento ?? this.intrattenimento,
finanziamenti: finanziamenti ?? this.finanziamenti,
telepass: telepass ?? this.telepass,
altro: altro ?? this.altro,
isActive: isActive ?? this.isActive,
companyId: companyId ?? this.companyId,

View File

@@ -21,6 +21,7 @@ class _ProviderFormSheetState extends State<ProviderFormSheet> {
late bool _assicurazioni;
late bool _intrattenimento;
late bool _finanziamenti;
late bool _telepass;
late bool _altro;
late bool _isActive;
final List<String> _tempSelectedStoreIds =
@@ -40,6 +41,7 @@ class _ProviderFormSheetState extends State<ProviderFormSheet> {
_assicurazioni = p?.assicurazioni ?? false;
_intrattenimento = p?.intrattenimento ?? false;
_finanziamenti = p?.finanziamenti ?? false;
_telepass = p?.telepass ?? false;
_altro = p?.altro ?? false;
_isActive = p?.isActive ?? true;
}
@@ -64,6 +66,7 @@ class _ProviderFormSheetState extends State<ProviderFormSheet> {
assicurazioni: _assicurazioni,
intrattenimento: _intrattenimento,
finanziamenti: _finanziamenti,
telepass: _telepass,
altro: _altro,
isActive: _isActive,
companyId:
@@ -138,6 +141,11 @@ class _ProviderFormSheetState extends State<ProviderFormSheet> {
_finanziamenti,
(v) => setState(() => _finanziamenti = v),
),
_buildSwitch(
"Telepass",
_telepass,
(v) => setState(() => _telepass = v),
),
_buildSwitch(
"Altro/Accessori",
_altro,

View File

@@ -146,6 +146,8 @@ class _ProvidersMasterDataScreenState extends State<ProvidersMasterDataScreen> {
if (p.energia) _smallTag("⚡ Energy", Colors.orange),
if (p.assicurazioni) _smallTag("🛡️ Assic", Colors.teal),
if (p.intrattenimento) _smallTag("📺 Ent", Colors.red),
if (p.finanziamenti) _smallTag("💰 Fin", Colors.purple),
if (p.telepass) _smallTag("🏎️ Telepass", Colors.yellow),
if (p.altro) _smallTag("📦 Altro", Colors.grey),
],
);