import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flux/core/blocs/session/session_cubit.dart'; import 'package:flux/features/operations/data/operations_repository.dart'; import 'package:flux/features/operations/models/operation_model.dart'; import 'package:get_it/get_it.dart'; part 'operation_list_state.dart'; class OperationListCubit extends Cubit { final OperationsRepository _repository = GetIt.I(); final SessionCubit _sessionCubit = GetIt.I(); OperationListCubit() : super(const OperationListState()); // 🥷 MOTORE 1: DESKTOP (Sostituisce la lista) Future loadSpecificPageDesktop(int page) async { if (state.status == OperationListStatus.loading) return; emit(state.copyWith(status: OperationListStatus.loading)); try { final companyId = _sessionCubit.state.company?.id; final paginatedData = await _repository.fetchPaginatedOperations( companyId: companyId!, page: page, itemsPerPage: state.itemsPerPage, ); emit( state.copyWith( status: OperationListStatus.success, operations: paginatedData.operations, // 🎯 SOSTITUISCE I DATI totalItems: paginatedData.totalCount, currentPage: page, hasReachedMax: paginatedData.operations.length < state.itemsPerPage, ), ); } catch (e) { emit( state.copyWith( status: OperationListStatus.failure, errorMessage: e.toString(), ), ); } } // 🥷 MOTORE 2: MOBILE (Accoda alla lista) Future loadNextPageMobile({bool refresh = false}) async { if (state.status == OperationListStatus.loading) return; if (state.hasReachedMax && !refresh) return; // Se stiamo pullando verso il basso (refresh), ripartiamo da pagina 1 final targetPage = refresh ? 1 : state.currentPage + 1; // Mostriamo il loading solo se è un refresh totale, altrimenti manteniamo lo stato success // per non far sparire la UI mentre carica in fondo if (refresh) emit(state.copyWith(status: OperationListStatus.loading)); try { final companyId = _sessionCubit.state.company?.id; final paginatedData = await _repository.fetchPaginatedOperations( companyId: companyId!, page: targetPage, itemsPerPage: state.itemsPerPage, ); emit( state.copyWith( status: OperationListStatus.success, // 🎯 ACCODA I DATI SE NON È REFRESH, ALTRIMENTI SOSTITUISCE operations: refresh ? paginatedData.operations : List.of(state.operations) ..addAll(paginatedData.operations), totalItems: paginatedData.totalCount, currentPage: targetPage, hasReachedMax: paginatedData.operations.length < state.itemsPerPage, ), ); } catch (e) { emit( state.copyWith( status: OperationListStatus.failure, errorMessage: e.toString(), ), ); } } void updateFilters({String? text, DateTimeRange? range}) { emit( state.copyWith( // 🥷 FORZIAMO IL TIPO: Diciamo a Dart che il risultato del ternario è proprio una funzione searchTerm: text != null ? () => text : null, dateRange: range != null ? () => range : null, currentPage: 1, // Reset obbligatorio alla prima pagina hasReachedMax: false, ), ); // Ricarichiamo la pagina 1 con i nuovi filtri applicati loadSpecificPageDesktop(1); } void clearFilters() { // Invece di un const vuoto che potrebbe bruciarti l'impostazione itemsPerPage, // creiamo uno stato pulito ma manteniamo la preferenza di paginazione. emit(OperationListState(itemsPerPage: state.itemsPerPage)); loadSpecificPageDesktop(1); } }