757 lines
23 KiB
Dart
757 lines
23 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import '../../../../core/utils/column_search_paging.dart';
|
|
import '../../../../core/utils/table_search.dart';
|
|
|
|
import '../../../../shared/models/asset_model.dart';
|
|
import '../../../../shared/models/entity_attachment_model.dart';
|
|
import '../../../../shared/models/export_file_result.dart';
|
|
import '../../data/repositories/asset_repository_impl.dart';
|
|
import 'asset_categories_provider.dart';
|
|
|
|
class AssetsListState {
|
|
const AssetsListState({
|
|
this.assets = const [],
|
|
this.query = const AssetListQuery(limit: 20),
|
|
this.total = 0,
|
|
this.totalPages = 1,
|
|
this.isRefreshing = false,
|
|
this.isExporting = false,
|
|
this.actionError,
|
|
this.actionSuccess,
|
|
});
|
|
|
|
final List<AssetModel> assets;
|
|
final AssetListQuery query;
|
|
final int total;
|
|
final int totalPages;
|
|
final bool isRefreshing;
|
|
final bool isExporting;
|
|
final String? actionError;
|
|
final String? actionSuccess;
|
|
|
|
AssetsListState copyWith({
|
|
List<AssetModel>? assets,
|
|
AssetListQuery? query,
|
|
int? total,
|
|
int? totalPages,
|
|
bool? isRefreshing,
|
|
bool? isExporting,
|
|
String? actionError,
|
|
String? actionSuccess,
|
|
bool clearMessages = false,
|
|
}) {
|
|
return AssetsListState(
|
|
assets: assets ?? this.assets,
|
|
query: query ?? this.query,
|
|
total: total ?? this.total,
|
|
totalPages: totalPages ?? this.totalPages,
|
|
isRefreshing: isRefreshing ?? this.isRefreshing,
|
|
isExporting: isExporting ?? this.isExporting,
|
|
actionError: clearMessages ? null : actionError ?? this.actionError,
|
|
actionSuccess: clearMessages ? null : actionSuccess ?? this.actionSuccess,
|
|
);
|
|
}
|
|
}
|
|
|
|
final assetsListProvider =
|
|
AsyncNotifierProvider.autoDispose<AssetsListNotifier, AssetsListState>(
|
|
AssetsListNotifier.new,
|
|
);
|
|
|
|
class AssetsListNotifier extends AutoDisposeAsyncNotifier<AssetsListState> {
|
|
final _columnSearch = ColumnSearchPaging();
|
|
|
|
@override
|
|
Future<AssetsListState> build() async {
|
|
return _load(const AssetListQuery(limit: 20));
|
|
}
|
|
|
|
Future<AssetsListState> _load(AssetListQuery query) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.getAssets(query);
|
|
if (result.failure != null) throw result.failure!;
|
|
final page = result.data!;
|
|
var items = List<AssetModel>.from(page.items);
|
|
final search = TableSearch.normalize(query.search);
|
|
|
|
// API search often ignores category name — pull matching categories too.
|
|
if (search.isNotEmpty && query.itemCategoryId == null) {
|
|
final categories = await ref.read(itemCategoriesProvider.future);
|
|
var categoryMatches = 0;
|
|
for (final category in categories) {
|
|
if (!TableSearch.matches(search, [category.name])) continue;
|
|
if (++categoryMatches > 5) break;
|
|
final categoryId = int.tryParse(category.id);
|
|
if (categoryId == null) continue;
|
|
final byCategory = await repository.getAssets(
|
|
query.copyWith(search: null, itemCategoryId: categoryId),
|
|
);
|
|
if (byCategory.failure == null && byCategory.data != null) {
|
|
items = TableSearch.mergeById(
|
|
items,
|
|
byCategory.data!.items,
|
|
(asset) => asset.id,
|
|
);
|
|
}
|
|
}
|
|
|
|
// Keep API page results + enriched matches; pagination stays server-driven.
|
|
}
|
|
|
|
return AssetsListState(
|
|
assets: items,
|
|
query: query,
|
|
total: page.total,
|
|
totalPages: page.totalPages,
|
|
);
|
|
}
|
|
|
|
Future<void> refresh() async {
|
|
final current = state.valueOrNull ?? const AssetsListState();
|
|
state = AsyncData(current.copyWith(isRefreshing: true, clearMessages: true));
|
|
try {
|
|
state = AsyncData(await _load(current.query));
|
|
} catch (e, st) {
|
|
state = AsyncError(e, st);
|
|
}
|
|
}
|
|
|
|
Future<void> applyQuery(AssetListQuery query) async {
|
|
final previous = state.valueOrNull;
|
|
if (previous == null) {
|
|
state = const AsyncLoading();
|
|
}
|
|
try {
|
|
state = AsyncData(await _load(query));
|
|
} catch (e, st) {
|
|
state = AsyncError(e, st);
|
|
}
|
|
}
|
|
|
|
void setSearch(String search) {
|
|
final current = state.valueOrNull;
|
|
if (current == null) return;
|
|
applyQuery(
|
|
current.query.copyWith(search: TableSearch.normalize(search), page: 1),
|
|
);
|
|
}
|
|
|
|
Future<void> ensureColumnSearchDataset() async {
|
|
final current = state.valueOrNull;
|
|
if (current == null) return;
|
|
final limit = _columnSearch.beginFullDataset(
|
|
currentLimit: current.query.limit,
|
|
total: current.total,
|
|
);
|
|
if (limit == null) return;
|
|
await applyQuery(
|
|
current.query.copyWith(search: null, page: 1, limit: limit),
|
|
);
|
|
}
|
|
|
|
void clearColumnSearchDataset() {
|
|
final current = state.valueOrNull;
|
|
if (current == null) return;
|
|
final limit = _columnSearch.endFullDataset();
|
|
if (limit == null) return;
|
|
applyQuery(current.query.copyWith(search: null, page: 1, limit: limit));
|
|
}
|
|
|
|
void setStatusFilter(String? status) {
|
|
final current = state.valueOrNull;
|
|
if (current == null) return;
|
|
applyQuery(current.query.copyWith(status: status, page: 1));
|
|
}
|
|
|
|
void setCategoryFilter(int? itemCategoryId) {
|
|
final current = state.valueOrNull;
|
|
if (current == null) return;
|
|
applyQuery(current.query.copyWith(itemCategoryId: itemCategoryId, page: 1));
|
|
}
|
|
|
|
void setLocationFilter(int? locationId) {
|
|
final current = state.valueOrNull;
|
|
if (current == null) return;
|
|
applyQuery(current.query.copyWith(locationId: locationId, page: 1));
|
|
}
|
|
|
|
void setPage(int page) {
|
|
final current = state.valueOrNull;
|
|
if (current == null) return;
|
|
applyQuery(current.query.copyWith(page: page));
|
|
}
|
|
|
|
void setPageSize(int limit) {
|
|
final current = state.valueOrNull;
|
|
if (current == null) return;
|
|
applyQuery(current.query.copyWith(limit: limit, page: 1));
|
|
}
|
|
|
|
Future<ExportFileResult?> exportAssets() async {
|
|
final current = state.valueOrNull;
|
|
if (current == null) return null;
|
|
|
|
state = AsyncData(current.copyWith(isExporting: true, clearMessages: true));
|
|
|
|
final result =
|
|
await ref.read(assetRepositoryProvider).exportAssets(current.query);
|
|
final latest = state.valueOrNull ?? current;
|
|
|
|
if (result.failure != null) {
|
|
state = AsyncData(
|
|
latest.copyWith(
|
|
isExporting: false,
|
|
actionError: result.failure!.message,
|
|
),
|
|
);
|
|
return null;
|
|
}
|
|
|
|
state = AsyncData(latest.copyWith(isExporting: false));
|
|
return result.data;
|
|
}
|
|
|
|
Future<bool> deleteAsset(String id) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.deleteAsset(id);
|
|
if (result.failure != null) {
|
|
final current = state.valueOrNull;
|
|
if (current != null) {
|
|
state = AsyncData(current.copyWith(actionError: result.failure!.message));
|
|
}
|
|
return false;
|
|
}
|
|
await refresh();
|
|
ref.invalidate(myMaintenanceProvider);
|
|
final current = state.valueOrNull;
|
|
if (current != null) {
|
|
state = AsyncData(current.copyWith(actionSuccess: 'Asset deleted'));
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
final assetDetailProvider =
|
|
AsyncNotifierProvider.family<AssetDetailNotifier, AssetDetailState, String>(
|
|
AssetDetailNotifier.new,
|
|
);
|
|
|
|
class AssetDetailState {
|
|
const AssetDetailState({
|
|
required this.asset,
|
|
this.amcContracts = const [],
|
|
this.serviceVisits = const [],
|
|
this.insurancePolicies = const [],
|
|
this.attachments = const [],
|
|
});
|
|
|
|
final AssetModel asset;
|
|
final List<AmcContractModel> amcContracts;
|
|
final List<ServiceVisitModel> serviceVisits;
|
|
final List<InsurancePolicyModel> insurancePolicies;
|
|
final List<EntityAttachmentModel> attachments;
|
|
|
|
AssetDetailState copyWith({
|
|
AssetModel? asset,
|
|
List<AmcContractModel>? amcContracts,
|
|
List<ServiceVisitModel>? serviceVisits,
|
|
List<InsurancePolicyModel>? insurancePolicies,
|
|
List<EntityAttachmentModel>? attachments,
|
|
}) {
|
|
return AssetDetailState(
|
|
asset: asset ?? this.asset,
|
|
amcContracts: amcContracts ?? this.amcContracts,
|
|
serviceVisits: serviceVisits ?? this.serviceVisits,
|
|
insurancePolicies: insurancePolicies ?? this.insurancePolicies,
|
|
attachments: attachments ?? this.attachments,
|
|
);
|
|
}
|
|
}
|
|
|
|
class AssetDetailNotifier extends FamilyAsyncNotifier<AssetDetailState, String> {
|
|
@override
|
|
Future<AssetDetailState> build(String arg) async {
|
|
return _loadAll(arg);
|
|
}
|
|
|
|
Future<AssetDetailState> _loadAll(String assetId) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final assetResult = await repository.getAssetById(assetId);
|
|
if (assetResult.failure != null) throw assetResult.failure!;
|
|
|
|
final amcResult = await repository.getAmcContracts(assetId);
|
|
final visitsResult = await repository.getServiceVisits(assetId);
|
|
final insuranceResult = await repository.getInsurancePolicies(assetId);
|
|
final attachmentsResult = await repository.listAttachments(assetId);
|
|
|
|
return AssetDetailState(
|
|
asset: assetResult.data!,
|
|
amcContracts: amcResult.data ?? [],
|
|
serviceVisits: visitsResult.data ?? [],
|
|
insurancePolicies: insuranceResult.data ?? [],
|
|
attachments: attachmentsResult.data ?? [],
|
|
);
|
|
}
|
|
|
|
Future<void> reload() async {
|
|
state = const AsyncLoading();
|
|
state = AsyncData(await _loadAll(arg));
|
|
}
|
|
|
|
Future<EntityAttachmentModel> uploadAttachment({
|
|
required List<int> bytes,
|
|
required String filename,
|
|
String attachmentType = 'DOCUMENT',
|
|
}) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.uploadAttachment(
|
|
arg,
|
|
bytes: bytes,
|
|
filename: filename,
|
|
attachmentType: attachmentType,
|
|
);
|
|
if (result.failure != null) throw result.failure!;
|
|
final current = state.valueOrNull;
|
|
if (current == null) {
|
|
await reload();
|
|
} else {
|
|
state = AsyncData(
|
|
current.copyWith(
|
|
attachments: [...current.attachments, result.data!],
|
|
),
|
|
);
|
|
}
|
|
return result.data!;
|
|
}
|
|
|
|
Future<List<int>> downloadAttachment(String attachmentId) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.downloadAttachment(arg, attachmentId);
|
|
if (result.failure != null) throw result.failure!;
|
|
return result.data ?? [];
|
|
}
|
|
|
|
Future<void> deleteAttachment(String attachmentId) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.deleteAttachment(arg, attachmentId);
|
|
if (result.failure != null) throw result.failure!;
|
|
final current = state.valueOrNull;
|
|
if (current == null) {
|
|
await reload();
|
|
return;
|
|
}
|
|
state = AsyncData(
|
|
current.copyWith(
|
|
attachments: current.attachments
|
|
.where((a) => a.id != attachmentId)
|
|
.toList(),
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<AssetModel?> updateAsset(Map<String, dynamic> data) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.updateAsset(arg, data);
|
|
if (result.failure != null) throw result.failure!;
|
|
await reload();
|
|
ref.invalidate(assetsListProvider);
|
|
ref.invalidate(myMaintenanceProvider);
|
|
return result.data;
|
|
}
|
|
|
|
Future<bool> deleteAsset() async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.deleteAsset(arg);
|
|
if (result.failure != null) return false;
|
|
ref.invalidate(assetsListProvider);
|
|
ref.invalidate(myMaintenanceProvider);
|
|
return true;
|
|
}
|
|
|
|
Future<void> transferAsset(Map<String, dynamic> data) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.transferAsset(arg, data);
|
|
if (result.failure != null) throw result.failure!;
|
|
await reload();
|
|
ref.invalidate(assetsListProvider);
|
|
ref.invalidate(transferHistoryProvider(arg));
|
|
}
|
|
|
|
Future<AmcContractModel?> createAmc(Map<String, dynamic> data) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.createAmcContract(arg, data);
|
|
if (result.failure != null) throw result.failure!;
|
|
await reload();
|
|
return result.data;
|
|
}
|
|
|
|
Future<AmcContractModel?> updateAmc(
|
|
String contractId,
|
|
Map<String, dynamic> data,
|
|
) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.updateAmcContract(arg, contractId, data);
|
|
if (result.failure != null) throw result.failure!;
|
|
await reload();
|
|
return result.data;
|
|
}
|
|
|
|
Future<ServiceVisitModel?> logVisit(Map<String, dynamic> data) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.logServiceVisit(arg, data);
|
|
if (result.failure != null) throw result.failure!;
|
|
await reload();
|
|
return result.data;
|
|
}
|
|
|
|
Future<ServiceVisitModel?> updateVisit(
|
|
String visitId,
|
|
Map<String, dynamic> data,
|
|
) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.updateServiceVisit(arg, visitId, data);
|
|
if (result.failure != null) throw result.failure!;
|
|
await reload();
|
|
return result.data;
|
|
}
|
|
|
|
Future<InsurancePolicyModel?> createInsurance(Map<String, dynamic> data) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.createInsurancePolicy(arg, data);
|
|
if (result.failure != null) throw result.failure!;
|
|
await reload();
|
|
return result.data;
|
|
}
|
|
|
|
Future<InsurancePolicyModel?> updateInsurance(
|
|
String policyId,
|
|
Map<String, dynamic> data,
|
|
) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.updateInsurancePolicy(arg, policyId, data);
|
|
if (result.failure != null) throw result.failure!;
|
|
await reload();
|
|
return result.data;
|
|
}
|
|
}
|
|
|
|
typedef AmcContractFormParams = ({String assetId, String contractId});
|
|
|
|
final amcContractFormProvider = FutureProvider.autoDispose
|
|
.family<AmcContractModel, AmcContractFormParams>((ref, params) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.getAmcContractById(
|
|
params.assetId,
|
|
params.contractId,
|
|
);
|
|
if (result.failure != null) throw result.failure!;
|
|
return result.data!;
|
|
});
|
|
|
|
typedef ServiceVisitFormParams = ({String assetId, String visitId});
|
|
|
|
final serviceVisitFormProvider = FutureProvider.autoDispose
|
|
.family<ServiceVisitModel, ServiceVisitFormParams>((ref, params) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.getServiceVisitById(
|
|
params.assetId,
|
|
params.visitId,
|
|
);
|
|
if (result.failure != null) throw result.failure!;
|
|
return result.data!;
|
|
});
|
|
|
|
typedef InsurancePolicyFormParams = ({String assetId, String policyId});
|
|
|
|
final insurancePolicyFormProvider = FutureProvider.autoDispose
|
|
.family<InsurancePolicyModel, InsurancePolicyFormParams>((ref, params) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.getInsurancePolicyById(
|
|
params.assetId,
|
|
params.policyId,
|
|
);
|
|
if (result.failure != null) throw result.failure!;
|
|
return result.data!;
|
|
});
|
|
|
|
final transferHistoryProvider = FutureProvider.autoDispose
|
|
.family<List<AssetTransferHistoryModel>, String>((ref, assetId) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.getTransferHistory(assetId);
|
|
if (result.failure != null) throw result.failure!;
|
|
return result.data ?? const [];
|
|
});
|
|
|
|
final assetFormProvider =
|
|
AsyncNotifierProvider.family.autoDispose<AssetFormNotifier, AssetModel?, String?>(
|
|
AssetFormNotifier.new,
|
|
);
|
|
|
|
class AssetFormNotifier extends AutoDisposeFamilyAsyncNotifier<AssetModel?, String?> {
|
|
@override
|
|
Future<AssetModel?> build(String? arg) async {
|
|
if (arg == null) return null;
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.getAssetById(arg);
|
|
if (result.failure != null) throw result.failure!;
|
|
return result.data;
|
|
}
|
|
|
|
Future<AssetModel?> submitCreate(Map<String, dynamic> data) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.createAsset(data);
|
|
if (result.failure != null) throw result.failure!;
|
|
ref.invalidate(assetsListProvider);
|
|
ref.invalidate(myMaintenanceProvider);
|
|
return result.data;
|
|
}
|
|
|
|
Future<AssetModel?> submitUpdate(String id, Map<String, dynamic> data) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.updateAsset(id, data);
|
|
if (result.failure != null) throw result.failure!;
|
|
ref.invalidate(assetsListProvider);
|
|
ref.invalidate(assetDetailProvider(id));
|
|
ref.invalidate(myMaintenanceProvider);
|
|
|
|
final fresh = await repository.getAssetById(id);
|
|
final asset = fresh.data ?? result.data;
|
|
if (asset != null) {
|
|
state = AsyncData(asset);
|
|
}
|
|
return asset;
|
|
}
|
|
}
|
|
|
|
class AssetAlertsState {
|
|
const AssetAlertsState({
|
|
this.expiryAlerts = const [],
|
|
this.serviceAlerts = const [],
|
|
this.expiryDays = 30,
|
|
this.expiryType,
|
|
this.serviceStatus,
|
|
this.expiryPage = 1,
|
|
this.expiryTotalPages = 1,
|
|
this.isRefreshing = false,
|
|
});
|
|
|
|
final List<AssetAlertModel> expiryAlerts;
|
|
final List<AssetAlertModel> serviceAlerts;
|
|
final int expiryDays;
|
|
final String? expiryType;
|
|
final String? serviceStatus;
|
|
final int expiryPage;
|
|
final int expiryTotalPages;
|
|
final bool isRefreshing;
|
|
|
|
AssetAlertsState copyWith({
|
|
List<AssetAlertModel>? expiryAlerts,
|
|
List<AssetAlertModel>? serviceAlerts,
|
|
int? expiryDays,
|
|
String? expiryType,
|
|
String? serviceStatus,
|
|
int? expiryPage,
|
|
int? expiryTotalPages,
|
|
bool? isRefreshing,
|
|
bool clearExpiryType = false,
|
|
bool clearServiceStatus = false,
|
|
}) {
|
|
return AssetAlertsState(
|
|
expiryAlerts: expiryAlerts ?? this.expiryAlerts,
|
|
serviceAlerts: serviceAlerts ?? this.serviceAlerts,
|
|
expiryDays: expiryDays ?? this.expiryDays,
|
|
expiryType: clearExpiryType ? null : expiryType ?? this.expiryType,
|
|
serviceStatus: clearServiceStatus ? null : serviceStatus ?? this.serviceStatus,
|
|
expiryPage: expiryPage ?? this.expiryPage,
|
|
expiryTotalPages: expiryTotalPages ?? this.expiryTotalPages,
|
|
isRefreshing: isRefreshing ?? this.isRefreshing,
|
|
);
|
|
}
|
|
}
|
|
|
|
final assetAlertsProvider =
|
|
AsyncNotifierProvider<AssetAlertsNotifier, AssetAlertsState>(AssetAlertsNotifier.new);
|
|
|
|
class AssetAlertsNotifier extends AsyncNotifier<AssetAlertsState> {
|
|
@override
|
|
Future<AssetAlertsState> build() async {
|
|
return _load(const AssetAlertsState());
|
|
}
|
|
|
|
Future<AssetAlertsState> _load(AssetAlertsState filters) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final expiryResult = await repository.getExpiryAlerts(
|
|
days: filters.expiryDays,
|
|
type: filters.expiryType,
|
|
page: filters.expiryPage,
|
|
);
|
|
final serviceResult = await repository.getServiceAlerts(status: filters.serviceStatus);
|
|
|
|
if (expiryResult.failure != null) throw expiryResult.failure!;
|
|
|
|
final expiryPage = expiryResult.data!;
|
|
return AssetAlertsState(
|
|
expiryAlerts: expiryPage.items,
|
|
serviceAlerts: serviceResult.data ?? [],
|
|
expiryDays: filters.expiryDays,
|
|
expiryType: filters.expiryType,
|
|
serviceStatus: filters.serviceStatus,
|
|
expiryPage: expiryPage.page,
|
|
expiryTotalPages: expiryPage.totalPages,
|
|
);
|
|
}
|
|
|
|
Future<void> refresh() async {
|
|
final current = state.valueOrNull ?? const AssetAlertsState();
|
|
state = AsyncData(current.copyWith(isRefreshing: true));
|
|
try {
|
|
state = AsyncData(await _load(current));
|
|
} catch (e, st) {
|
|
state = AsyncError(e, st);
|
|
}
|
|
}
|
|
|
|
Future<void> setExpiryDays(int days) async {
|
|
final current = state.valueOrNull ?? const AssetAlertsState();
|
|
state = const AsyncLoading();
|
|
state = AsyncData(await _load(current.copyWith(expiryDays: days, expiryPage: 1)));
|
|
}
|
|
|
|
Future<void> setExpiryType(String? type) async {
|
|
final current = state.valueOrNull ?? const AssetAlertsState();
|
|
state = const AsyncLoading();
|
|
state = AsyncData(
|
|
await _load(
|
|
current.copyWith(
|
|
expiryType: type,
|
|
expiryPage: 1,
|
|
clearExpiryType: type == null,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> setServiceStatus(String? status) async {
|
|
final current = state.valueOrNull ?? const AssetAlertsState();
|
|
state = const AsyncLoading();
|
|
state = AsyncData(
|
|
await _load(
|
|
current.copyWith(
|
|
serviceStatus: status,
|
|
clearServiceStatus: status == null,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> setExpiryPage(int page) async {
|
|
final current = state.valueOrNull ?? const AssetAlertsState();
|
|
state = const AsyncLoading();
|
|
state = AsyncData(await _load(current.copyWith(expiryPage: page)));
|
|
}
|
|
}
|
|
|
|
class MyMaintenanceState {
|
|
const MyMaintenanceState({
|
|
this.assets = const [],
|
|
this.dueOnly = true,
|
|
this.page = 1,
|
|
this.limit = 20,
|
|
this.total = 0,
|
|
this.totalPages = 1,
|
|
this.isRefreshing = false,
|
|
});
|
|
|
|
final List<AssetModel> assets;
|
|
final bool dueOnly;
|
|
final int page;
|
|
final int limit;
|
|
final int total;
|
|
final int totalPages;
|
|
final bool isRefreshing;
|
|
|
|
MyMaintenanceState copyWith({
|
|
List<AssetModel>? assets,
|
|
bool? dueOnly,
|
|
int? page,
|
|
int? limit,
|
|
int? total,
|
|
int? totalPages,
|
|
bool? isRefreshing,
|
|
}) {
|
|
return MyMaintenanceState(
|
|
assets: assets ?? this.assets,
|
|
dueOnly: dueOnly ?? this.dueOnly,
|
|
page: page ?? this.page,
|
|
limit: limit ?? this.limit,
|
|
total: total ?? this.total,
|
|
totalPages: totalPages ?? this.totalPages,
|
|
isRefreshing: isRefreshing ?? this.isRefreshing,
|
|
);
|
|
}
|
|
}
|
|
|
|
final myMaintenanceProvider =
|
|
AsyncNotifierProvider.autoDispose<MyMaintenanceNotifier, MyMaintenanceState>(
|
|
MyMaintenanceNotifier.new,
|
|
);
|
|
|
|
class MyMaintenanceNotifier extends AutoDisposeAsyncNotifier<MyMaintenanceState> {
|
|
@override
|
|
Future<MyMaintenanceState> build() async {
|
|
return _load(const MyMaintenanceState());
|
|
}
|
|
|
|
Future<MyMaintenanceState> _load(MyMaintenanceState filters) async {
|
|
final repository = ref.read(assetRepositoryProvider);
|
|
final result = await repository.getMyMaintenanceAssets(
|
|
dueOnly: filters.dueOnly,
|
|
page: filters.page,
|
|
limit: filters.limit,
|
|
);
|
|
if (result.failure != null) throw result.failure!;
|
|
final page = result.data!;
|
|
return MyMaintenanceState(
|
|
assets: page.items,
|
|
dueOnly: filters.dueOnly,
|
|
page: page.page,
|
|
limit: filters.limit,
|
|
total: page.total,
|
|
totalPages: page.totalPages,
|
|
);
|
|
}
|
|
|
|
Future<void> refresh() async {
|
|
final current = state.valueOrNull ?? const MyMaintenanceState();
|
|
state = AsyncData(current.copyWith(isRefreshing: true));
|
|
try {
|
|
state = AsyncData(await _load(current));
|
|
} catch (e, st) {
|
|
state = AsyncError(e, st);
|
|
}
|
|
}
|
|
|
|
Future<void> setDueOnly(bool dueOnly) async {
|
|
final current = state.valueOrNull ?? const MyMaintenanceState();
|
|
state = const AsyncLoading();
|
|
state = AsyncData(
|
|
await _load(current.copyWith(dueOnly: dueOnly, page: 1)),
|
|
);
|
|
}
|
|
|
|
Future<void> setPage(int page) async {
|
|
final current = state.valueOrNull ?? const MyMaintenanceState();
|
|
state = const AsyncLoading();
|
|
state = AsyncData(await _load(current.copyWith(page: page)));
|
|
}
|
|
|
|
Future<void> setPageSize(int limit) async {
|
|
final current = state.valueOrNull ?? const MyMaintenanceState();
|
|
state = const AsyncLoading();
|
|
state = AsyncData(
|
|
await _load(current.copyWith(limit: limit, page: 1)),
|
|
);
|
|
}
|
|
}
|