reworked operation (#12)

Reviewed-on: #12
Co-authored-by: Mark M2 Macbook <marco@catelli.it>
Co-committed-by: Mark M2 Macbook <marco@catelli.it>
This commit is contained in:
2026-05-04 15:36:42 +02:00
committed by brontomark
parent 9f57207a39
commit 94ad524bae
110 changed files with 5831 additions and 5306 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

@@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:flux/core/utils/string_extensions.dart';
import 'package:flux/core/utils/extensions.dart';
class BrandModel extends Equatable {
final String? id;

View File

@@ -1,5 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:flux/core/utils/string_extensions.dart';
import 'package:flux/core/utils/extensions.dart';
class ModelModel extends Equatable {
final String? id;

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(),
);