diff --git a/lib/core/constants/api_endpoints.dart b/lib/core/constants/api_endpoints.dart index 83b4e87..420f00f 100644 --- a/lib/core/constants/api_endpoints.dart +++ b/lib/core/constants/api_endpoints.dart @@ -73,25 +73,16 @@ class ApiEndpoints { // Assets static const String assets = '/assets'; static String assetById(String id) => '/assets/$id'; - static String assetQrCode(String id) => '/assets/$id/qr-code'; - static const String assetSearch = '/assets/search'; - - // Asset Allocations - static const String assetAllocations = '/asset-allocations'; - static String assetAllocationById(String id) => '/asset-allocations/$id'; - static String returnAsset(String id) => '/asset-allocations/$id/return'; - static String reassignAsset(String id) => '/asset-allocations/$id/reassign'; - static String transferAsset(String id) => '/asset-allocations/$id/transfer'; - static const String allocationHistory = '/asset-allocations/history'; - - // Asset Maintenance - static const String assetMaintenance = '/asset-maintenance'; - static String maintenanceById(String id) => '/asset-maintenance/$id'; - - // Asset Disposal - static const String assetDisposal = '/asset-disposal'; - static String disposalById(String id) => '/asset-disposal/$id'; - static String approveDisposal(String id) => '/asset-disposal/$id/approve'; + static String assetTransfer(String id) => '/assets/$id/transfer'; + static const String assetAlertsExpiry = '/assets/alerts/expiry'; + static const String assetAlertsService = '/assets/alerts/service'; + static String assetAmc(String assetId) => '/assets/$assetId/amc'; + static String assetAmcRenew(String assetId, String contractId) => + '/assets/$assetId/amc/$contractId/renew'; + static String assetServiceVisits(String assetId) => '/assets/$assetId/service-visits'; + static String assetInsurance(String assetId) => '/assets/$assetId/insurance'; + static String assetInsuranceRenew(String assetId, String policyId) => + '/assets/$assetId/insurance/$policyId/renew'; // Dashboard static const String dashboardKpis = '/dashboard/kpis'; diff --git a/lib/core/constants/route_constants.dart b/lib/core/constants/route_constants.dart index 3335ecf..7e95fe6 100644 --- a/lib/core/constants/route_constants.dart +++ b/lib/core/constants/route_constants.dart @@ -45,11 +45,7 @@ class RouteConstants { static const String assetEdit = '/assets/:id/edit'; static const String assetDetail = '/assets/:id'; static const String assetCategories = '/assets/categories'; - static const String assetAllocations = '/assets/allocations'; - static const String assetMaintenance = '/assets/maintenance'; - static const String assetDisposal = '/assets/disposal'; - static const String assetQrScan = '/assets/qr-scan'; - static const String assetQrGenerate = '/assets/qr-generate'; + static const String assetAlerts = '/assets/alerts'; // Master Data static const String masterData = '/master-data'; diff --git a/lib/modules/assets/data/datasources/asset_remote_data_source.dart b/lib/modules/assets/data/datasources/asset_remote_data_source.dart new file mode 100644 index 0000000..36ffeea --- /dev/null +++ b/lib/modules/assets/data/datasources/asset_remote_data_source.dart @@ -0,0 +1,213 @@ +import 'package:dio/dio.dart'; + +import '../../../../core/constants/api_endpoints.dart'; +import '../../../../shared/models/api_response.dart'; +import '../../../../shared/models/asset_model.dart'; + +class AssetRemoteDataSource { + AssetRemoteDataSource({required this.dio}); + + final Dio dio; + + Future> getAssets(PaginationParams params) async { + final response = await dio.get( + ApiEndpoints.assets, + queryParameters: { + 'page': params.page, + 'limit': params.limit, + if (params.search != null && params.search!.isNotEmpty) 'search': params.search, + }, + ); + return _parsePaginated(response.data, AssetModel.fromJson); + } + + Future getAssetById(String id) async { + final response = await dio.get(ApiEndpoints.assetById(id)); + return AssetModel.fromJson(response.data['data'] as Map); + } + + Future createAsset(Map data) async { + final response = await dio.post(ApiEndpoints.assets, data: data); + return AssetModel.fromJson(response.data['data'] as Map); + } + + Future updateAsset(String id, Map data) async { + final response = await dio.put(ApiEndpoints.assetById(id), data: data); + return AssetModel.fromJson(response.data['data'] as Map); + } + + Future deleteAsset(String id) async { + await dio.delete(ApiEndpoints.assetById(id)); + } + + Future transferAsset(String id, Map data) async { + final response = await dio.post(ApiEndpoints.assetTransfer(id), data: data); + return AssetModel.fromJson(response.data['data'] as Map); + } + + Future> getCategories() async { + final response = await dio.get( + ApiEndpoints.assetCategories, + queryParameters: const {'limit': 100, 'is_active': true}, + ); + return _parseList(response.data, AssetCategoryModel.fromJson); + } + + Future> getExpiryAlerts({ + int? days, + String? type, + int page = 1, + int limit = 20, + }) async { + final response = await dio.get( + ApiEndpoints.assetAlertsExpiry, + queryParameters: { + 'page': page, + 'limit': limit, + if (days != null) 'days': days, + if (type != null) 'type': type, + }, + ); + return _parsePaginated(response.data, AssetAlertModel.fromJson); + } + + Future> getServiceAlerts({String? status}) async { + final response = await dio.get( + ApiEndpoints.assetAlertsService, + queryParameters: {if (status != null) 'status': status}, + ); + return _parseList(response.data, AssetAlertModel.fromJson); + } + + Future> getAmcContracts(String assetId) async { + final response = await dio.get(ApiEndpoints.assetAmc(assetId)); + return _parseList(response.data, AmcContractModel.fromJson); + } + + Future createAmcContract( + String assetId, + Map data, + ) async { + final response = await dio.post(ApiEndpoints.assetAmc(assetId), data: data); + return AmcContractModel.fromJson(response.data['data'] as Map); + } + + Future renewAmcContract( + String assetId, + String contractId, + Map data, + ) async { + final response = await dio.patch( + ApiEndpoints.assetAmcRenew(assetId, contractId), + data: data, + ); + return AmcContractModel.fromJson(response.data['data'] as Map); + } + + Future> getServiceVisits(String assetId) async { + final response = await dio.get(ApiEndpoints.assetServiceVisits(assetId)); + return _parseList(response.data, ServiceVisitModel.fromJson); + } + + Future logServiceVisit( + String assetId, + Map data, + ) async { + final response = await dio.post(ApiEndpoints.assetServiceVisits(assetId), data: data); + return ServiceVisitModel.fromJson(response.data['data'] as Map); + } + + Future> getInsurancePolicies(String assetId) async { + final response = await dio.get(ApiEndpoints.assetInsurance(assetId)); + return _parseList(response.data, InsurancePolicyModel.fromJson); + } + + Future createInsurancePolicy( + String assetId, + Map data, + ) async { + final response = await dio.post(ApiEndpoints.assetInsurance(assetId), data: data); + return InsurancePolicyModel.fromJson( + response.data['data'] as Map, + ); + } + + Future renewInsurancePolicy( + String assetId, + String policyId, + Map data, + ) async { + final response = await dio.patch( + ApiEndpoints.assetInsuranceRenew(assetId, policyId), + data: data, + ); + return InsurancePolicyModel.fromJson( + response.data['data'] as Map, + ); + } + + List _parseList( + dynamic body, + T Function(Map) fromJson, + ) { + if (body is! Map) return []; + final raw = body['data']; + if (raw is List) { + return raw + .whereType>() + .map(fromJson) + .toList(); + } + if (raw is Map) { + final items = raw['items']; + if (items is List) { + return items + .whereType>() + .map(fromJson) + .toList(); + } + } + return []; + } + + PaginatedResponse _parsePaginated( + dynamic body, + T Function(Map) fromJson, + ) { + if (body is! Map) { + return const PaginatedResponse( + items: [], + page: 1, + limit: 20, + total: 0, + totalPages: 1, + ); + } + + final raw = body['data']; + final meta = body['meta'] as Map? ?? {}; + + if (raw is List) { + final items = raw.whereType>().map(fromJson).toList(); + return PaginatedResponse( + items: items, + page: (meta['page'] as num?)?.toInt() ?? 1, + limit: (meta['limit'] as num?)?.toInt() ?? items.length, + total: (meta['total'] as num?)?.toInt() ?? items.length, + totalPages: (meta['totalPages'] as num?)?.toInt() ?? 1, + ); + } + + if (raw is Map) { + return PaginatedResponse.fromJson(raw, (json) => fromJson(json! as Map)); + } + + return const PaginatedResponse( + items: [], + page: 1, + limit: 20, + total: 0, + totalPages: 1, + ); + } +} diff --git a/lib/modules/assets/data/repositories/asset_repository_impl.dart b/lib/modules/assets/data/repositories/asset_repository_impl.dart index 0720ce1..3e3d290 100644 --- a/lib/modules/assets/data/repositories/asset_repository_impl.dart +++ b/lib/modules/assets/data/repositories/asset_repository_impl.dart @@ -1,129 +1,131 @@ -import 'package:dio/dio.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import '../../../../core/constants/api_endpoints.dart'; import '../../../../core/network/api_handler.dart'; import '../../../../core/network/dio_client.dart'; import '../../../../shared/models/api_response.dart'; import '../../../../shared/models/asset_model.dart'; import '../../domain/repositories/asset_repository.dart'; +import '../datasources/asset_remote_data_source.dart'; + +final assetRemoteDataSourceProvider = Provider((ref) { + return AssetRemoteDataSource(dio: ref.watch(dioProvider)); +}); final assetRepositoryProvider = Provider((ref) { - return AssetRepositoryImpl(dio: ref.watch(dioProvider)); + return AssetRepositoryImpl(dataSource: ref.watch(assetRemoteDataSourceProvider)); }); class AssetRepositoryImpl implements AssetRepository { - AssetRepositoryImpl({required this.dio}); + AssetRepositoryImpl({required this.dataSource}); - final Dio dio; + final AssetRemoteDataSource dataSource; @override - Future>> getAssets(PaginationParams params) async { - return safeApiCall(() async { - final response = await dio.get(ApiEndpoints.assets, queryParameters: { - 'page': params.page, - 'limit': params.limit, - if (params.search != null) 'search': params.search, - }); - return PaginatedResponse.fromJson( - response.data['data'] as Map, - (json) => AssetModel.fromJson(json! as Map), - ); - }); + Future>> getAssets(PaginationParams params) { + return safeApiCall(() => dataSource.getAssets(params)); } @override - Future> getAssetById(String id) async { - return safeApiCall(() async { - final response = await dio.get(ApiEndpoints.assetById(id)); - return AssetModel.fromJson(response.data['data'] as Map); - }); + Future> getAssetById(String id) { + return safeApiCall(() => dataSource.getAssetById(id)); } @override - Future> createAsset(Map data) async { - return safeApiCall(() async { - final response = await dio.post(ApiEndpoints.assets, data: data); - return AssetModel.fromJson(response.data['data'] as Map); - }); + Future> createAsset(Map data) { + return safeApiCall(() => dataSource.createAsset(data)); } @override - Future> updateAsset(String id, Map data) async { - return safeApiCall(() async { - final response = await dio.put(ApiEndpoints.assetById(id), data: data); - return AssetModel.fromJson(response.data['data'] as Map); - }); + Future> updateAsset(String id, Map data) { + return safeApiCall(() => dataSource.updateAsset(id, data)); } @override - Future>> getCategories() async { - return safeApiCall(() async { - final response = await dio.get(ApiEndpoints.assetCategories); - final rawData = response.data['data']; - final list = rawData is List - ? rawData - : (rawData is Map ? rawData['items'] as List? : null) ?? - []; - return list - .map((e) => AssetCategoryModel.fromJson(e as Map)) - .toList(); - }); + Future> deleteAsset(String id) { + return safeApiCall(() => dataSource.deleteAsset(id)); } @override - Future>> getAllocations( - PaginationParams params, - ) async { - return safeApiCall(() async { - final response = await dio.get(ApiEndpoints.assetAllocations, queryParameters: { - 'page': params.page, - 'limit': params.limit, - }); - return PaginatedResponse.fromJson( - response.data['data'] as Map, - (json) => AssetAllocationModel.fromJson(json! as Map), - ); - }); + Future> transferAsset(String id, Map data) { + return safeApiCall(() => dataSource.transferAsset(id, data)); } @override - Future>> getMaintenance( - PaginationParams params, - ) async { - return safeApiCall(() async { - final response = await dio.get(ApiEndpoints.assetMaintenance, queryParameters: { - 'page': params.page, - 'limit': params.limit, - }); - return PaginatedResponse.fromJson( - response.data['data'] as Map, - (json) => AssetMaintenanceModel.fromJson(json! as Map), - ); - }); + Future>> getCategories() { + return safeApiCall(() => dataSource.getCategories()); } @override - Future>> getDisposals( - PaginationParams params, - ) async { - return safeApiCall(() async { - final response = await dio.get(ApiEndpoints.assetDisposal, queryParameters: { - 'page': params.page, - 'limit': params.limit, - }); - return PaginatedResponse.fromJson( - response.data['data'] as Map, - (json) => AssetDisposalModel.fromJson(json! as Map), - ); - }); + Future>> getExpiryAlerts({ + int? days, + String? type, + int page = 1, + int limit = 20, + }) { + return safeApiCall( + () => dataSource.getExpiryAlerts(days: days, type: type, page: page, limit: limit), + ); } @override - Future> searchByQrCode(String code) async { - return safeApiCall(() async { - final response = await dio.get(ApiEndpoints.assetSearch, queryParameters: {'q': code}); - return AssetModel.fromJson(response.data['data'] as Map); - }); + Future>> getServiceAlerts({String? status}) { + return safeApiCall(() => dataSource.getServiceAlerts(status: status)); + } + + @override + Future>> getAmcContracts(String assetId) { + return safeApiCall(() => dataSource.getAmcContracts(assetId)); + } + + @override + Future> createAmcContract( + String assetId, + Map data, + ) { + return safeApiCall(() => dataSource.createAmcContract(assetId, data)); + } + + @override + Future> renewAmcContract( + String assetId, + String contractId, + Map data, + ) { + return safeApiCall(() => dataSource.renewAmcContract(assetId, contractId, data)); + } + + @override + Future>> getServiceVisits(String assetId) { + return safeApiCall(() => dataSource.getServiceVisits(assetId)); + } + + @override + Future> logServiceVisit( + String assetId, + Map data, + ) { + return safeApiCall(() => dataSource.logServiceVisit(assetId, data)); + } + + @override + Future>> getInsurancePolicies(String assetId) { + return safeApiCall(() => dataSource.getInsurancePolicies(assetId)); + } + + @override + Future> createInsurancePolicy( + String assetId, + Map data, + ) { + return safeApiCall(() => dataSource.createInsurancePolicy(assetId, data)); + } + + @override + Future> renewInsurancePolicy( + String assetId, + String policyId, + Map data, + ) { + return safeApiCall(() => dataSource.renewInsurancePolicy(assetId, policyId, data)); } } diff --git a/lib/modules/assets/domain/repositories/asset_repository.dart b/lib/modules/assets/domain/repositories/asset_repository.dart index a7089b5..d3b2cfc 100644 --- a/lib/modules/assets/domain/repositories/asset_repository.dart +++ b/lib/modules/assets/domain/repositories/asset_repository.dart @@ -1,4 +1,3 @@ -import '../../../../core/errors/failure.dart'; import '../../../../core/network/api_handler.dart'; import '../../../../shared/models/api_response.dart'; import '../../../../shared/models/asset_model.dart'; @@ -8,9 +7,39 @@ abstract class AssetRepository { Future> getAssetById(String id); Future> createAsset(Map data); Future> updateAsset(String id, Map data); + Future> deleteAsset(String id); + Future> transferAsset(String id, Map data); Future>> getCategories(); - Future>> getAllocations(PaginationParams params); - Future>> getMaintenance(PaginationParams params); - Future>> getDisposals(PaginationParams params); - Future> searchByQrCode(String code); + Future>> getExpiryAlerts({ + int? days, + String? type, + int page, + int limit, + }); + Future>> getServiceAlerts({String? status}); + Future>> getAmcContracts(String assetId); + Future> createAmcContract( + String assetId, + Map data, + ); + Future> renewAmcContract( + String assetId, + String contractId, + Map data, + ); + Future>> getServiceVisits(String assetId); + Future> logServiceVisit( + String assetId, + Map data, + ); + Future>> getInsurancePolicies(String assetId); + Future> createInsurancePolicy( + String assetId, + Map data, + ); + Future> renewInsurancePolicy( + String assetId, + String policyId, + Map data, + ); } diff --git a/lib/modules/assets/presentation/providers/assets_provider.dart b/lib/modules/assets/presentation/providers/assets_provider.dart new file mode 100644 index 0000000..984d422 --- /dev/null +++ b/lib/modules/assets/presentation/providers/assets_provider.dart @@ -0,0 +1,408 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../shared/models/api_response.dart'; +import '../../../../shared/models/asset_model.dart'; +import '../../data/repositories/asset_repository_impl.dart'; + +class AssetsListState { + const AssetsListState({ + this.assets = const [], + this.query = const PaginationParams(limit: 20), + this.total = 0, + this.totalPages = 1, + this.isRefreshing = false, + this.actionError, + this.actionSuccess, + }); + + final List assets; + final PaginationParams query; + final int total; + final int totalPages; + final bool isRefreshing; + final String? actionError; + final String? actionSuccess; + + AssetsListState copyWith({ + List? assets, + PaginationParams? query, + int? total, + int? totalPages, + bool? isRefreshing, + 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, + actionError: clearMessages ? null : actionError ?? this.actionError, + actionSuccess: clearMessages ? null : actionSuccess ?? this.actionSuccess, + ); + } +} + +final assetsListProvider = + AsyncNotifierProvider.autoDispose( + AssetsListNotifier.new, +); + +class AssetsListNotifier extends AutoDisposeAsyncNotifier { + @override + Future build() async { + return _load(const PaginationParams(limit: 20)); + } + + Future _load(PaginationParams query) async { + final repository = ref.read(assetRepositoryProvider); + final result = await repository.getAssets(query); + if (result.failure != null) throw result.failure!; + final page = result.data!; + return AssetsListState( + assets: page.items, + query: query, + total: page.total, + totalPages: page.totalPages, + ); + } + + Future 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 applyQuery(PaginationParams 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: search, 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 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(); + final current = state.valueOrNull; + if (current != null) { + state = AsyncData(current.copyWith(actionSuccess: 'Asset deleted')); + } + return true; + } +} + +final assetDetailProvider = + AsyncNotifierProvider.family( + AssetDetailNotifier.new, +); + +class AssetDetailState { + const AssetDetailState({ + required this.asset, + this.amcContracts = const [], + this.serviceVisits = const [], + this.insurancePolicies = const [], + }); + + final AssetModel asset; + final List amcContracts; + final List serviceVisits; + final List insurancePolicies; + + AssetDetailState copyWith({ + AssetModel? asset, + List? amcContracts, + List? serviceVisits, + List? insurancePolicies, + }) { + return AssetDetailState( + asset: asset ?? this.asset, + amcContracts: amcContracts ?? this.amcContracts, + serviceVisits: serviceVisits ?? this.serviceVisits, + insurancePolicies: insurancePolicies ?? this.insurancePolicies, + ); + } +} + +class AssetDetailNotifier extends FamilyAsyncNotifier { + @override + Future build(String arg) async { + return _loadAll(arg); + } + + Future _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); + + return AssetDetailState( + asset: assetResult.data!, + amcContracts: amcResult.data ?? [], + serviceVisits: visitsResult.data ?? [], + insurancePolicies: insuranceResult.data ?? [], + ); + } + + Future reload() async { + state = const AsyncLoading(); + state = AsyncData(await _loadAll(arg)); + } + + Future updateAsset(Map 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); + return result.data; + } + + Future deleteAsset() async { + final repository = ref.read(assetRepositoryProvider); + final result = await repository.deleteAsset(arg); + if (result.failure != null) return false; + ref.invalidate(assetsListProvider); + return true; + } + + Future transferAsset(Map 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); + return result.data; + } + + Future createAmc(Map 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 logVisit(Map 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 createInsurance(Map 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; + } +} + +final assetFormProvider = + AsyncNotifierProvider.family.autoDispose( + AssetFormNotifier.new, +); + +class AssetFormNotifier extends AutoDisposeFamilyAsyncNotifier { + @override + Future 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 submitCreate(Map data) async { + final repository = ref.read(assetRepositoryProvider); + final result = await repository.createAsset(data); + if (result.failure != null) throw result.failure!; + ref.invalidate(assetsListProvider); + return result.data; + } + + Future submitUpdate(String id, Map 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)); + + 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 expiryAlerts; + final List serviceAlerts; + final int expiryDays; + final String? expiryType; + final String? serviceStatus; + final int expiryPage; + final int expiryTotalPages; + final bool isRefreshing; + + AssetAlertsState copyWith({ + List? expiryAlerts, + List? 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.new); + +class AssetAlertsNotifier extends AsyncNotifier { + @override + Future build() async { + return _load(const AssetAlertsState()); + } + + Future _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 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 setExpiryDays(int days) async { + final current = state.valueOrNull ?? const AssetAlertsState(); + state = const AsyncLoading(); + state = AsyncData(await _load(current.copyWith(expiryDays: days, expiryPage: 1))); + } + + Future 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 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 setExpiryPage(int page) async { + final current = state.valueOrNull ?? const AssetAlertsState(); + state = const AsyncLoading(); + state = AsyncData(await _load(current.copyWith(expiryPage: page))); + } +} diff --git a/lib/modules/assets/presentation/screens/asset_alerts_screen.dart b/lib/modules/assets/presentation/screens/asset_alerts_screen.dart new file mode 100644 index 0000000..d885fff --- /dev/null +++ b/lib/modules/assets/presentation/screens/asset_alerts_screen.dart @@ -0,0 +1,271 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:intl/intl.dart'; + +import '../../../../core/constants/route_constants.dart'; +import '../../../../core/errors/failure.dart'; +import '../../../../shared/models/asset_model.dart'; +import '../../../../shared/widgets/app_card.dart'; +import '../../../../shared/widgets/app_dropdown.dart'; +import '../../../../shared/widgets/app_empty_state.dart'; +import '../../../../shared/widgets/app_loading_view.dart'; +import '../../../../shared/widgets/app_pagination.dart'; +import '../../../../shared/widgets/error_view.dart'; +import '../../../../shared/widgets/page_header.dart'; +import '../providers/assets_provider.dart'; + +class AssetAlertsScreen extends ConsumerWidget { + const AssetAlertsScreen({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final alertsAsync = ref.watch(assetAlertsProvider); + + return Padding( + padding: const EdgeInsets.all(24), + child: alertsAsync.when( + loading: () => const AppLoadingView(message: 'Loading alerts...'), + error: (e, _) => ErrorView.fromFailure( + e is Failure ? e : Failure.unknown(message: e.toString()), + onRetry: () => ref.invalidate(assetAlertsProvider), + ), + data: (state) => DefaultTabController( + length: 2, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + PageHeader( + title: 'Asset Alerts', + subtitle: 'Expiry and service due notifications', + actions: [ + OutlinedButton.icon( + onPressed: () => context.go(RouteConstants.assets), + icon: const Icon(Icons.inventory_2_outlined), + label: const Text('Asset Master'), + ), + ], + ), + const SizedBox(height: 16), + const TabBar( + tabs: [ + Tab(text: 'Expiry Alerts'), + Tab(text: 'Service Alerts'), + ], + ), + const SizedBox(height: 16), + Expanded( + child: TabBarView( + children: [ + _ExpiryAlertsTab(state: state), + _ServiceAlertsTab(state: state), + ], + ), + ), + ], + ), + ), + ), + ); + } +} + +class _ExpiryAlertsTab extends ConsumerWidget { + const _ExpiryAlertsTab({required this.state}); + + final AssetAlertsState state; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final notifier = ref.read(assetAlertsProvider.notifier); + final dateFormat = DateFormat('dd MMM yyyy'); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Wrap( + spacing: 12, + runSpacing: 8, + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + SizedBox( + width: 160, + child: AppDropdown( + label: 'Days ahead', + value: state.expiryDays, + options: const [7, 15, 30, 60, 90] + .map((d) => AppDropdownOption(value: d, label: '$d days')) + .toList(), + onChanged: (v) { + if (v != null) notifier.setExpiryDays(v); + }, + ), + ), + SizedBox( + width: 180, + child: AppDropdown( + label: 'Type', + value: state.expiryType, + options: const [ + AppDropdownOption(value: null, label: 'All'), + AppDropdownOption(value: 'AMC', label: 'AMC'), + AppDropdownOption(value: 'INSURANCE', label: 'Insurance'), + AppDropdownOption(value: 'WARRANTY', label: 'Warranty'), + ], + onChanged: notifier.setExpiryType, + ), + ), + IconButton( + onPressed: () => notifier.refresh(), + icon: const Icon(Icons.refresh), + tooltip: 'Refresh', + ), + ], + ), + const SizedBox(height: 16), + Expanded( + child: state.expiryAlerts.isEmpty + ? const AppEmptyState( + title: 'No expiry alerts', + description: 'No AMC, insurance or warranty expiries in this window.', + icon: Icons.event_available_outlined, + ) + : ListView.separated( + itemCount: state.expiryAlerts.length, + separatorBuilder: (_, __) => const SizedBox(height: 8), + itemBuilder: (context, index) { + final alert = state.expiryAlerts[index]; + return _AlertCard( + alert: alert, + dateLabel: alert.expiryDate != null + ? dateFormat.format(alert.expiryDate!) + : null, + onTap: alert.assetId != null + ? () => context.push('${RouteConstants.assets}/${alert.assetId}') + : null, + ); + }, + ), + ), + AppPagination( + currentPage: state.expiryPage, + totalPages: state.expiryTotalPages, + totalItems: state.expiryAlerts.length, + pageSize: 20, + onPageChanged: notifier.setExpiryPage, + onPageSizeChanged: (_) {}, + ), + ], + ); + } +} + +class _ServiceAlertsTab extends ConsumerWidget { + const _ServiceAlertsTab({required this.state}); + + final AssetAlertsState state; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final notifier = ref.read(assetAlertsProvider.notifier); + final dateFormat = DateFormat('dd MMM yyyy'); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Wrap( + spacing: 12, + runSpacing: 8, + children: [ + SizedBox( + width: 200, + child: AppDropdown( + label: 'Status', + value: state.serviceStatus, + options: const [ + AppDropdownOption(value: null, label: 'All'), + AppDropdownOption(value: 'OVERDUE', label: 'Overdue'), + AppDropdownOption(value: 'DUE_THIS_WEEK', label: 'Due This Week'), + AppDropdownOption(value: 'DUE_THIS_MONTH', label: 'Due This Month'), + AppDropdownOption(value: 'UPCOMING', label: 'Upcoming'), + ], + onChanged: notifier.setServiceStatus, + ), + ), + IconButton( + onPressed: () => notifier.refresh(), + icon: const Icon(Icons.refresh), + tooltip: 'Refresh', + ), + ], + ), + const SizedBox(height: 16), + Expanded( + child: state.serviceAlerts.isEmpty + ? const AppEmptyState( + title: 'No service alerts', + description: 'All services are up to date.', + icon: Icons.build_circle_outlined, + ) + : ListView.separated( + itemCount: state.serviceAlerts.length, + separatorBuilder: (_, __) => const SizedBox(height: 8), + itemBuilder: (context, index) { + final alert = state.serviceAlerts[index]; + return _AlertCard( + alert: alert, + dateLabel: alert.dueDate != null + ? dateFormat.format(alert.dueDate!) + : null, + onTap: alert.assetId != null + ? () => context.push('${RouteConstants.assets}/${alert.assetId}') + : null, + ); + }, + ), + ), + ], + ); + } +} + +class _AlertCard extends StatelessWidget { + const _AlertCard({ + required this.alert, + this.dateLabel, + this.onTap, + }); + + final AssetAlertModel alert; + final String? dateLabel; + final VoidCallback? onTap; + + @override + Widget build(BuildContext context) { + return AppCard( + child: ListTile( + onTap: onTap, + leading: Icon( + alert.type?.toUpperCase() == 'AMC' + ? Icons.handshake_outlined + : alert.type?.toUpperCase() == 'INSURANCE' + ? Icons.shield_outlined + : Icons.notifications_outlined, + ), + title: Text(alert.assetName ?? alert.title ?? 'Asset ${alert.assetId ?? ''}'), + subtitle: Text( + [ + if (alert.assetCode != null) alert.assetCode, + if (alert.type != null) alert.type, + if (alert.plantName != null) alert.plantName, + if (dateLabel != null) 'Due: $dateLabel', + if (alert.daysRemaining != null) '${alert.daysRemaining} days', + ].whereType().join(' · '), + ), + trailing: alert.status != null + ? Chip(label: Text(alert.status!, style: const TextStyle(fontSize: 11))) + : null, + ), + ); + } +} diff --git a/lib/modules/assets/presentation/screens/asset_categories_screen.dart b/lib/modules/assets/presentation/screens/asset_categories_screen.dart index 4a523f8..222d20b 100644 --- a/lib/modules/assets/presentation/screens/asset_categories_screen.dart +++ b/lib/modules/assets/presentation/screens/asset_categories_screen.dart @@ -36,7 +36,10 @@ class AssetCategoriesScreen extends ConsumerWidget { child: ListTile( leading: const Icon(Icons.category_outlined), title: Text(category.name), - subtitle: Text(category.slug), + subtitle: Text( + '${category.code}' + '${category.defaultDepreciationMethod != null ? ' · ${category.defaultDepreciationMethod}' : ''}', + ), ), ); }, diff --git a/lib/modules/assets/presentation/screens/asset_detail_screen.dart b/lib/modules/assets/presentation/screens/asset_detail_screen.dart index bd51651..34b35eb 100644 --- a/lib/modules/assets/presentation/screens/asset_detail_screen.dart +++ b/lib/modules/assets/presentation/screens/asset_detail_screen.dart @@ -1,77 +1,422 @@ -import '../../../../shared/widgets/app_card.dart'; import 'package:flutter/material.dart'; -import 'package:qr_flutter/qr_flutter.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:intl/intl.dart'; +import '../../../../core/constants/enums.dart'; +import '../../../../core/constants/route_constants.dart'; +import '../../../../core/errors/failure.dart'; +import '../../../../shared/models/asset_model.dart'; +import '../../../../shared/providers/permissions_provider.dart'; +import '../../../../shared/widgets/app_card.dart'; +import '../../../../shared/widgets/app_confirmation_dialog.dart'; +import '../../../../shared/widgets/app_loading_view.dart'; +import '../../../../shared/widgets/app_status_chip.dart'; +import '../../../../shared/widgets/can_permission.dart'; +import '../../../../shared/widgets/error_view.dart'; import '../../../../shared/widgets/page_header.dart'; +import '../../../../shared/widgets/app_side_panel.dart'; +import '../providers/assets_provider.dart'; +import '../widgets/asset_form_panel.dart'; +import '../widgets/asset_side_panels.dart'; -class AssetDetailScreen extends StatelessWidget { +class AssetDetailScreen extends ConsumerStatefulWidget { const AssetDetailScreen({super.key, required this.assetId}); final String assetId; + @override + ConsumerState createState() => _AssetDetailScreenState(); +} + +class _AssetDetailScreenState extends ConsumerState + with SingleTickerProviderStateMixin { + late final TabController _tabController; + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 4, vsync: this); + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { - return SingleChildScrollView( - padding: const EdgeInsets.all(24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - PageHeader( - title: 'Asset Details', - subtitle: 'ID: $assetId', - ), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - flex: 2, - child: AppCard( - child: Padding( - padding: const EdgeInsets.all(24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _DetailRow(label: 'Asset Name', value: '—'), - _DetailRow(label: 'Asset Code', value: '—'), - _DetailRow(label: 'Category', value: '—'), - _DetailRow(label: 'Serial Number', value: '—'), - _DetailRow(label: 'Status', value: '—'), - _DetailRow(label: 'Branch', value: '—'), - ], - ), + final detailAsync = ref.watch(assetDetailProvider(widget.assetId)); + final canEdit = ref.can('assets', PermissionAction.update); + final canDelete = ref.can('assets', PermissionAction.delete); + + return detailAsync.when( + loading: () => const AppLoadingView(message: 'Loading asset details...'), + error: (e, _) => ErrorView.fromFailure( + e is Failure ? e : Failure.unknown(message: e.toString()), + onRetry: () => ref.invalidate(assetDetailProvider(widget.assetId)), + ), + data: (state) => Padding( + padding: const EdgeInsets.all(24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + PageHeader( + title: state.asset.assetName, + subtitle: state.asset.assetCode ?? 'Asset ID: ${state.asset.id}', + actions: [ + if (canEdit) + OutlinedButton.icon( + onPressed: () => + openAssetFormPanel(context, ref, assetId: widget.assetId), + icon: const Icon(Icons.edit_outlined), + label: const Text('Edit'), ), - ), + if (canEdit) ...[ + const SizedBox(width: 8), + OutlinedButton.icon( + onPressed: () => _showTransferDialog(state.asset), + icon: const Icon(Icons.swap_horiz), + label: const Text('Transfer'), + ), + ], + if (canDelete) ...[ + const SizedBox(width: 8), + OutlinedButton.icon( + onPressed: _deleteAsset, + icon: const Icon(Icons.delete_outline), + label: const Text('Delete'), + ), + ], + ], + ), + const SizedBox(height: 16), + TabBar( + controller: _tabController, + tabs: const [ + Tab(text: 'Overview'), + Tab(text: 'AMC'), + Tab(text: 'Service Visits'), + Tab(text: 'Insurance'), + ], + ), + const SizedBox(height: 16), + Expanded( + child: TabBarView( + controller: _tabController, + children: [ + _OverviewTab(asset: state.asset), + _AmcTab(assetId: widget.assetId, contracts: state.amcContracts), + _ServiceVisitsTab(assetId: widget.assetId, visits: state.serviceVisits), + _InsuranceTab(assetId: widget.assetId, policies: state.insurancePolicies), + ], ), - const SizedBox(width: 24), - AppCard( - child: Padding( - padding: const EdgeInsets.all(24), - child: Column( - children: [ - const Text('QR Code'), - const SizedBox(height: 16), - QrImageView( - data: assetId, - version: QrVersions.auto, - size: 160, - ), - ], - ), - ), + ), + ], + ), + ), + ); + } + + Future _deleteAsset() async { + final confirmed = await showAppConfirmationDialog( + context: context, + title: 'Delete Asset', + message: 'Soft delete this asset?', + confirmLabel: 'Delete', + isDestructive: true, + ); + if (confirmed != true || !mounted) return; + + final deleted = await ref.read(assetDetailProvider(widget.assetId).notifier).deleteAsset(); + if (deleted && mounted) context.go(RouteConstants.assets); + } + + Future _showTransferDialog(AssetModel asset) async { + final plantIdController = TextEditingController(text: asset.plantId?.toString() ?? ''); + final confirmed = await showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('Transfer Asset'), + content: TextField( + controller: plantIdController, + decoration: const InputDecoration( + labelText: 'Target Plant ID', + helperText: 'Enter the plant ID to transfer this asset to', + ), + keyboardType: TextInputType.number, + ), + actions: [ + TextButton(onPressed: () => Navigator.pop(context, false), child: const Text('Cancel')), + ElevatedButton(onPressed: () => Navigator.pop(context, true), child: const Text('Transfer')), + ], + ), + ); + if (confirmed != true || !mounted) return; + + final plantId = int.tryParse(plantIdController.text.trim()); + if (plantId == null) return; + + try { + await ref.read(assetDetailProvider(widget.assetId).notifier).transferAsset({ + 'plant_id': plantId, + }); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Asset transferred')), + ); + } + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(e.toString()))); + } + } + } +} + +class _OverviewTab extends StatelessWidget { + const _OverviewTab({required this.asset}); + + final AssetModel asset; + + @override + Widget build(BuildContext context) { + final dateFormat = DateFormat('dd MMM yyyy'); + + return SingleChildScrollView( + child: AppCard( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + children: [ + _DetailRow(label: 'Asset Name', value: asset.assetName), + _DetailRow(label: 'Asset Code', value: asset.assetCode ?? '—'), + _DetailRow(label: 'Category', value: asset.assetCategoryName ?? '—'), + _DetailRow(label: 'Plant', value: asset.plantName ?? '—'), + _DetailRow( + label: 'Warranty Expiry', + value: asset.warrantyExpiryDate != null + ? dateFormat.format(asset.warrantyExpiryDate!) + : '—', + ), + _DetailRow( + label: 'Purchase Cost', + value: asset.purchaseCost != null ? '₹${asset.purchaseCost}' : '—', + ), + _DetailRow( + label: 'Status', + valueWidget: AppStatusChip(status: asset.status ?? 'active'), ), ], ), - ], + ), ), ); } } +class _AmcTab extends ConsumerWidget { + const _AmcTab({required this.assetId, required this.contracts}); + + final String assetId; + final List contracts; + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CanPermission( + module: 'assets', + action: PermissionAction.create, + child: Align( + alignment: Alignment.centerRight, + child: ElevatedButton.icon( + onPressed: () => _openAddAmcPanel(context, ref), + icon: const Icon(Icons.add), + label: const Text('Add AMC'), + ), + ), + ), + const SizedBox(height: 12), + Expanded( + child: contracts.isEmpty + ? const Center(child: Text('No AMC contracts')) + : ListView.separated( + itemCount: contracts.length, + separatorBuilder: (_, __) => const SizedBox(height: 8), + itemBuilder: (context, index) { + final c = contracts[index]; + return AppCard( + child: ListTile( + title: Text(c.contractNo ?? 'AMC #${c.id}'), + subtitle: Text( + '${c.vendorName ?? 'Vendor ${c.vendorId ?? '—'}'} · ' + '${DateFormat('dd MMM yyyy').format(c.startDate)} – ' + '${DateFormat('dd MMM yyyy').format(c.endDate)}', + ), + trailing: c.annualCost != null ? Text('₹${c.annualCost}') : null, + ), + ); + }, + ), + ), + ], + ); + } + + Future _openAddAmcPanel(BuildContext context, WidgetRef ref) async { + final saved = await showSidePanel( + context, + AddAmcPanel(assetId: assetId), + width: 520, + ); + if (saved == true && context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('AMC contract created')), + ); + } + } +} + +class _ServiceVisitsTab extends ConsumerWidget { + const _ServiceVisitsTab({required this.assetId, required this.visits}); + + final String assetId; + final List visits; + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CanPermission( + module: 'assets', + action: PermissionAction.create, + child: Align( + alignment: Alignment.centerRight, + child: ElevatedButton.icon( + onPressed: () => _openLogVisitPanel(context, ref), + icon: const Icon(Icons.add), + label: const Text('Log Visit'), + ), + ), + ), + const SizedBox(height: 12), + Expanded( + child: visits.isEmpty + ? const Center(child: Text('No service visits')) + : ListView.separated( + itemCount: visits.length, + separatorBuilder: (_, __) => const SizedBox(height: 8), + itemBuilder: (context, index) { + final v = visits[index]; + return AppCard( + child: ListTile( + title: Text(v.visitType), + subtitle: Text( + '${DateFormat('dd MMM yyyy').format(v.visitDate)}' + '${v.workDone != null ? ' · ${v.workDone}' : ''}', + ), + trailing: AppStatusChip(status: v.status, compact: true), + ), + ); + }, + ), + ), + ], + ); + } + + Future _openLogVisitPanel(BuildContext context, WidgetRef ref) async { + final saved = await showSidePanel( + context, + LogServiceVisitPanel(assetId: assetId), + width: 520, + ); + if (saved == true && context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Service visit logged')), + ); + } + } +} + +class _InsuranceTab extends ConsumerWidget { + const _InsuranceTab({required this.assetId, required this.policies}); + + final String assetId; + final List policies; + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CanPermission( + module: 'assets', + action: PermissionAction.create, + child: Align( + alignment: Alignment.centerRight, + child: ElevatedButton.icon( + onPressed: () => _openAddInsurancePanel(context, ref), + icon: const Icon(Icons.add), + label: const Text('Add Policy'), + ), + ), + ), + const SizedBox(height: 12), + Expanded( + child: policies.isEmpty + ? const Center(child: Text('No insurance policies')) + : ListView.separated( + itemCount: policies.length, + separatorBuilder: (_, __) => const SizedBox(height: 8), + itemBuilder: (context, index) { + final p = policies[index]; + return AppCard( + child: ListTile( + title: Text(p.policyNo), + subtitle: Text( + '${p.insurerName} · ' + '${DateFormat('dd MMM yyyy').format(p.policyStartDate)} – ' + '${DateFormat('dd MMM yyyy').format(p.policyEndDate)}', + ), + trailing: p.sumInsured != null ? Text('₹${p.sumInsured}') : null, + ), + ); + }, + ), + ), + ], + ); + } + + Future _openAddInsurancePanel(BuildContext context, WidgetRef ref) async { + final saved = await showSidePanel( + context, + AddInsurancePanel(assetId: assetId), + width: 520, + ); + if (saved == true && context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Insurance policy created')), + ); + } + } +} + class _DetailRow extends StatelessWidget { - const _DetailRow({required this.label, required this.value}); + const _DetailRow({ + required this.label, + this.value, + this.valueWidget, + }); final String label; - final String value; + final String? value; + final Widget? valueWidget; @override Widget build(BuildContext context) { @@ -80,7 +425,7 @@ class _DetailRow extends StatelessWidget { child: Row( children: [ SizedBox( - width: 140, + width: 160, child: Text( label, style: Theme.of(context).textTheme.bodyMedium?.copyWith( @@ -88,7 +433,9 @@ class _DetailRow extends StatelessWidget { ), ), ), - Expanded(child: Text(value, style: Theme.of(context).textTheme.bodyLarge)), + Expanded( + child: valueWidget ?? Text(value ?? '—', style: Theme.of(context).textTheme.bodyLarge), + ), ], ), ); diff --git a/lib/modules/assets/presentation/screens/asset_form_screen.dart b/lib/modules/assets/presentation/screens/asset_form_screen.dart deleted file mode 100644 index eb60504..0000000 --- a/lib/modules/assets/presentation/screens/asset_form_screen.dart +++ /dev/null @@ -1,114 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../../../core/constants/enums.dart'; -import '../../../../core/utils/validators.dart'; -import '../../../../shared/widgets/app_button.dart'; -import '../../../../shared/widgets/app_text_field.dart'; - -class AssetFormScreen extends StatefulWidget { - const AssetFormScreen({super.key, this.assetId}); - - final String? assetId; - - @override - State createState() => _AssetFormScreenState(); -} - -class _AssetFormScreenState extends State { - final _formKey = GlobalKey(); - final _nameController = TextEditingController(); - final _codeController = TextEditingController(); - final _brandController = TextEditingController(); - final _modelController = TextEditingController(); - final _serialController = TextEditingController(); - final _vendorController = TextEditingController(); - final _costController = TextEditingController(); - AssetCategoryType _category = AssetCategoryType.laptop; - AssetStatus _status = AssetStatus.available; - - bool get isEditing => widget.assetId != null; - - @override - void dispose() { - _nameController.dispose(); - _codeController.dispose(); - _brandController.dispose(); - _modelController.dispose(); - _serialController.dispose(); - _vendorController.dispose(); - _costController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: Text(isEditing ? 'Edit Asset' : 'Add Asset')), - body: SingleChildScrollView( - padding: const EdgeInsets.all(24), - child: Center( - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 600), - child: Form( - key: _formKey, - child: Column( - children: [ - AppTextField( - controller: _nameController, - label: 'Asset Name', - validator: (v) => Validators.required(v, fieldName: 'Asset name'), - ), - const SizedBox(height: 16), - AppTextField( - controller: _codeController, - label: 'Asset Code', - validator: (v) => Validators.required(v, fieldName: 'Asset code'), - ), - const SizedBox(height: 16), - DropdownButtonFormField( - value: _category, - decoration: const InputDecoration(labelText: 'Category'), - items: AssetCategoryType.values - .map((c) => DropdownMenuItem(value: c, child: Text(c.label))) - .toList(), - onChanged: (v) => setState(() => _category = v!), - ), - const SizedBox(height: 16), - AppTextField(controller: _brandController, label: 'Brand'), - const SizedBox(height: 16), - AppTextField(controller: _modelController, label: 'Model'), - const SizedBox(height: 16), - AppTextField(controller: _serialController, label: 'Serial Number'), - const SizedBox(height: 16), - AppTextField( - controller: _costController, - label: 'Purchase Cost', - keyboardType: TextInputType.number, - ), - const SizedBox(height: 16), - AppTextField(controller: _vendorController, label: 'Vendor'), - const SizedBox(height: 16), - DropdownButtonFormField( - value: _status, - decoration: const InputDecoration(labelText: 'Status'), - items: AssetStatus.values - .map((s) => DropdownMenuItem(value: s, child: Text(s.label))) - .toList(), - onChanged: (v) => setState(() => _status = v!), - ), - const SizedBox(height: 24), - AppButton( - label: isEditing ? 'Update Asset' : 'Create Asset', - onPressed: () { - if (_formKey.currentState!.validate()) Navigator.of(context).pop(); - }, - ), - ], - ), - ), - ), - ), - ), - ); - } -} diff --git a/lib/modules/assets/presentation/screens/asset_list_screen.dart b/lib/modules/assets/presentation/screens/asset_list_screen.dart index dd5a6d8..b9b7863 100644 --- a/lib/modules/assets/presentation/screens/asset_list_screen.dart +++ b/lib/modules/assets/presentation/screens/asset_list_screen.dart @@ -1,46 +1,802 @@ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; +import '../../../../core/constants/enums.dart'; import '../../../../core/constants/route_constants.dart'; +import '../../../../core/errors/failure.dart'; +import '../../../../core/utils/formatters.dart'; +import '../../../../core/utils/responsive_utils.dart'; +import '../../../../shared/models/asset_model.dart'; +import '../../../../shared/providers/permissions_provider.dart'; +import '../../../../shared/widgets/app_card.dart'; +import '../../../../shared/widgets/app_confirmation_dialog.dart'; +import '../../../../shared/widgets/app_dropdown.dart'; +import '../../../../shared/widgets/app_empty_state.dart'; +import '../../../../shared/widgets/app_loading_view.dart'; +import '../../../../shared/widgets/app_searchable_dropdown.dart'; +import '../../../../shared/widgets/can_permission.dart'; import '../../../../shared/widgets/error_view.dart'; import '../../../../shared/widgets/page_header.dart'; +import '../../../rbac/presentation/widgets/rbac_widgets.dart'; +import '../providers/asset_categories_provider.dart'; +import '../providers/assets_provider.dart'; +import '../widgets/asset_form_panel.dart'; -class AssetListScreen extends StatelessWidget { +class AssetListScreen extends ConsumerStatefulWidget { const AssetListScreen({super.key}); + @override + ConsumerState createState() => _AssetListScreenState(); +} + +class _AssetListScreenState extends ConsumerState { + static const _tableMinWidth = 1040.0; + + String? _selectedCategory; + String? _selectedPlant; + String? _selectedStatus; + @override Widget build(BuildContext context) { + final assetsAsync = ref.watch(assetsListProvider); + final canEdit = ref.can('assets', PermissionAction.update); + final canDelete = ref.can('assets', PermissionAction.delete); + + ref.listen(assetsListProvider, (prev, next) { + final error = next.valueOrNull?.actionError; + final success = next.valueOrNull?.actionSuccess; + if (error != null && error != prev?.valueOrNull?.actionError) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(error))); + } + if (success != null && success != prev?.valueOrNull?.actionSuccess) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(success))); + } + }); + return Padding( padding: const EdgeInsets.all(24), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - PageHeader( - title: 'Asset Master', - subtitle: 'Manage all company assets', - actions: [ - OutlinedButton.icon( - onPressed: () => context.go(RouteConstants.assetQrScan), - icon: const Icon(Icons.qr_code_scanner), - label: const Text('QR Scan'), + child: assetsAsync.when( + loading: () => const AppLoadingView(message: 'Loading assets...'), + error: (error, _) => ErrorView.fromFailure( + error is Failure ? error : Failure.unknown(message: error.toString()), + onRetry: () => ref.invalidate(assetsListProvider), + ), + data: (state) { + final allCategories = ref.watch(assetCategoriesProvider).valueOrNull ?? []; + final filteredAssets = _filterAssets(state.assets); + final categories = _categoryOptions(state.assets, allCategories); + final plants = _plantOptions(state.assets); + final statuses = _statusOptions(); + final categoryFilter = _selectedCategory ?? 'All categories'; + final plantFilter = _selectedPlant ?? 'All plants'; + final statusFilter = _selectedStatus ?? 'All statuses'; + final page = state.query.page; + final pageSize = state.query.limit; + final total = state.total; + final start = total == 0 ? 0 : ((page - 1) * pageSize) + 1; + final end = (page * pageSize).clamp(0, total); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + PageHeader( + title: 'Asset Master', + subtitle: 'Manage plant assets, AMC, service & insurance', + actions: [ + OutlinedButton.icon( + onPressed: () => context.go(RouteConstants.assetAlerts), + icon: const Icon(Icons.notifications_outlined), + label: const Text('Alerts'), + ), + const SizedBox(width: 8), + CanPermission( + module: 'assets', + action: PermissionAction.create, + child: ElevatedButton.icon( + onPressed: () => openAssetFormPanel(context, ref), + icon: const Icon(Icons.add), + label: const Text('Add Asset'), + ), + ), + ], ), - const SizedBox(width: 8), - ElevatedButton.icon( - onPressed: () => context.push('${RouteConstants.assets}/add'), - icon: const Icon(Icons.add), - label: const Text('Add Asset'), + const SizedBox(height: 16), + Expanded( + child: RefreshIndicator( + onRefresh: () => ref.read(assetsListProvider.notifier).refresh(), + child: context.isMobile + ? _AssetMobileList( + assets: filteredAssets, + onView: _viewAsset, + onEdit: canEdit ? _editAsset : null, + onDelete: canDelete ? _deleteAsset : null, + ) + : AppCard( + enableHover: false, + clipBehavior: Clip.none, + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + side: BorderSide( + color: Theme.of(context) + .colorScheme + .outline + .withValues(alpha: 0.12), + ), + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return _AssetsFilterBar( + wrapped: constraints.maxWidth < 1000, + categoryFilter: categoryFilter, + plantFilter: plantFilter, + statusFilter: statusFilter, + categories: categories, + plants: plants, + statuses: statuses, + onSearch: + ref.read(assetsListProvider.notifier).setSearch, + onCategoryChanged: (value) { + setState(() { + _selectedCategory = + value == 'All categories' ? null : value; + }); + }, + onPlantChanged: (value) { + setState(() { + _selectedPlant = + value == 'All plants' ? null : value; + }); + }, + onStatusChanged: (value) { + setState(() { + _selectedStatus = + value == 'All statuses' ? null : value; + }); + }, + ); + }, + ), + ), + const Divider(height: 1), + if (filteredAssets.isEmpty) + Expanded( + child: Center( + child: Text( + 'No assets found', + style: Theme.of(context) + .textTheme + .bodyLarge + ?.copyWith( + color: Theme.of(context) + .colorScheme + .onSurfaceVariant, + ), + ), + ), + ) + else + Expanded( + child: LayoutBuilder( + builder: (context, constraints) { + final tableWidth = + constraints.maxWidth < _tableMinWidth + ? _tableMinWidth + : constraints.maxWidth; + + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + padding: + const EdgeInsets.symmetric(horizontal: 4), + child: ConstrainedBox( + constraints: + BoxConstraints(minWidth: tableWidth), + child: DataTable( + horizontalMargin: 20, + columnSpacing: 16, + headingRowColor: WidgetStateProperty.all( + Theme.of(context) + .colorScheme + .surfaceContainerHighest + .withValues(alpha: 0.4), + ), + columns: const [ + DataColumn(label: Text('ASSET')), + DataColumn(label: Text('CATEGORY')), + DataColumn(label: Text('PLANT')), + DataColumn(label: Text('WARRANTY')), + DataColumn(label: Text('STATUS')), + DataColumn( + label: _AssetTableActionsHeader(), + ), + ], + rows: filteredAssets.map((asset) { + final status = + assetStatusDisplay(asset.status); + return DataRow( + cells: [ + DataCell( + Row( + children: [ + UserAvatarChip( + name: asset.assetName, + initials: + assetInitials(asset), + ), + const SizedBox(width: 10), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Text( + asset.assetName, + style: const TextStyle( + fontWeight: + FontWeight.w600, + ), + ), + Text( + asset.assetCode ?? '—', + style: Theme.of(context) + .textTheme + .bodySmall, + ), + ], + ), + ], + ), + ), + DataCell( + RoleBadge( + label: asset.assetCategoryName ?? + '—', + ), + ), + DataCell( + Text(asset.plantName ?? '—'), + ), + DataCell( + Text( + DateFormatter.displayDate( + asset.warrantyExpiryDate, + ), + ), + ), + DataCell( + StatusBadge( + label: status.label, + color: status.color, + ), + ), + DataCell( + _AssetTableActionsCell( + child: _AssetTableActions( + canView: true, + canEdit: canEdit, + canDelete: canDelete, + onView: () => _viewAsset(asset), + onEdit: () => _editAsset(asset), + onDelete: () => + _deleteAsset(asset), + ), + ), + ), + ], + ); + }).toList(), + ), + ), + ); + }, + ), + ), + const Divider(height: 1), + Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Text( + 'Showing $start–$end of $total assets', + style: Theme.of(context).textTheme.bodySmall, + ), + const Spacer(), + TextButton( + onPressed: page > 1 + ? () => ref + .read(assetsListProvider.notifier) + .setPage(page - 1) + : null, + child: const Text('Previous'), + ), + ...List.generate(state.totalPages.clamp(0, 4), (i) { + final pageIndex = i + 1; + final selected = page == pageIndex; + return Padding( + padding: + const EdgeInsets.symmetric(horizontal: 2), + child: Material( + color: selected + ? Theme.of(context).colorScheme.primary + : Colors.transparent, + shape: const CircleBorder(), + child: InkWell( + customBorder: const CircleBorder(), + onTap: () => ref + .read(assetsListProvider.notifier) + .setPage(pageIndex), + child: SizedBox( + width: 36, + height: 36, + child: Center( + child: Text( + '$pageIndex', + style: TextStyle( + color: selected + ? Theme.of(context) + .colorScheme + .onPrimary + : null, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ), + ), + ); + }), + TextButton( + onPressed: page < state.totalPages + ? () => ref + .read(assetsListProvider.notifier) + .setPage(page + 1) + : null, + child: const Text('Next'), + ), + ], + ), + ), + ], + ), + ), + ), ), ], - ), - const Expanded( - child: EmptyStateView( - title: 'No assets yet', - description: 'Add assets to start tracking laptops, devices, furniture, and more.', - icon: Icons.inventory_2_outlined, - ), - ), + ); + }, + ), + ); + } + + List _filterAssets(List assets) { + return assets.where((asset) { + if (_selectedCategory != null && + asset.assetCategoryName != _selectedCategory) { + return false; + } + if (_selectedPlant != null && asset.plantName != _selectedPlant) { + return false; + } + if (_selectedStatus != null) { + final label = assetStatusDisplay(asset.status).label; + if (label != _selectedStatus) return false; + } + return true; + }).toList(); + } + + List _categoryOptions( + List assets, + List allCategories, + ) { + final names = {}; + for (final asset in assets) { + final name = asset.assetCategoryName; + if (name != null && name.isNotEmpty) names.add(name); + } + for (final category in allCategories) { + names.add(category.name); + } + final sorted = names.toList()..sort(); + return ['All categories', ...sorted]; + } + + List _plantOptions(List assets) { + final names = assets + .map((a) => a.plantName) + .whereType() + .where((n) => n.isNotEmpty) + .toSet() + .toList() + ..sort(); + return ['All plants', ...names]; + } + + List _statusOptions() { + return [ + 'All statuses', + 'In Use', + 'Available', + 'Under Maintenance', + 'Disposed', + 'Inactive', + ]; + } + + void _viewAsset(AssetModel asset) { + context.push('${RouteConstants.assets}/${asset.id}'); + } + + void _editAsset(AssetModel asset) { + openAssetFormPanel(context, ref, assetId: asset.id); + } + + Future _deleteAsset(AssetModel asset) async { + final confirmed = await showAppConfirmationDialog( + context: context, + title: 'Delete Asset', + message: 'Soft delete "${asset.assetName}"?', + confirmLabel: 'Delete', + isDestructive: true, + ); + if (confirmed == true && mounted) { + await ref.read(assetsListProvider.notifier).deleteAsset(asset.id); + } + } +} + +String assetInitials(AssetModel asset) { + final code = asset.assetCode; + if (code != null && code.isNotEmpty) { + return code.length >= 2 ? code.substring(0, 2).toUpperCase() : code.toUpperCase(); + } + if (asset.assetName.isNotEmpty) { + final parts = asset.assetName.trim().split(RegExp(r'\s+')); + if (parts.length >= 2) { + return '${parts[0][0]}${parts[1][0]}'.toUpperCase(); + } + return asset.assetName[0].toUpperCase(); + } + return 'A'; +} + +({String label, Color color}) assetStatusDisplay(String? status) { + return switch (status?.toUpperCase().replaceAll(' ', '_')) { + 'IN_USE' => (label: 'In Use', color: const Color(0xFF16A34A)), + 'AVAILABLE' => (label: 'Available', color: const Color(0xFF2563EB)), + 'UNDER_MAINTENANCE' => ( + label: 'Under Maintenance', + color: const Color(0xFFCA8A04), + ), + 'DISPOSED' => (label: 'Disposed', color: const Color(0xFF6B7280)), + 'INACTIVE' => (label: 'Inactive', color: const Color(0xFFDC2626)), + _ when status != null && status.isNotEmpty => ( + label: status.replaceAll('_', ' '), + color: const Color(0xFF16A34A), + ), + _ => (label: 'Active', color: const Color(0xFF16A34A)), + }; +} + +class _AssetsFilterBar extends StatelessWidget { + const _AssetsFilterBar({ + required this.wrapped, + required this.categoryFilter, + required this.plantFilter, + required this.statusFilter, + required this.categories, + required this.plants, + required this.statuses, + required this.onSearch, + required this.onCategoryChanged, + required this.onPlantChanged, + required this.onStatusChanged, + }); + + final bool wrapped; + final String categoryFilter; + final String plantFilter; + final String statusFilter; + final List categories; + final List plants; + final List statuses; + final ValueChanged onSearch; + final ValueChanged onCategoryChanged; + final ValueChanged onPlantChanged; + final ValueChanged onStatusChanged; + + @override + Widget build(BuildContext context) { + final searchField = TextField( + decoration: const InputDecoration( + hintText: 'Search by name, code, category...', + prefixIcon: Icon(Icons.search, size: 20), + isDense: true, + ), + onChanged: onSearch, + ); + + final filters = [ + _AssetFilterDropdown( + value: categoryFilter, + label: 'Category', + items: categories, + onChanged: onCategoryChanged, + ), + _AssetFilterDropdown( + value: plantFilter, + label: 'Plant', + items: plants, + onChanged: onPlantChanged, + ), + _AssetFilterDropdown( + value: statusFilter, + label: 'Status', + items: statuses, + onChanged: onStatusChanged, + ), + ]; + + if (wrapped) { + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + searchField, + const SizedBox(height: 12), + Wrap(spacing: 12, runSpacing: 12, children: filters), ], + ); + } + + return Row( + children: [ + Expanded(flex: 3, child: searchField), + const SizedBox(width: 12), + Expanded(flex: 2, child: filters[0]), + const SizedBox(width: 12), + Expanded(flex: 2, child: filters[1]), + const SizedBox(width: 12), + Expanded(child: filters[2]), + ], + ); + } +} + +class _AssetFilterDropdown extends StatelessWidget { + const _AssetFilterDropdown({ + required this.value, + required this.label, + required this.items, + required this.onChanged, + }); + + final String value; + final String label; + final List items; + final ValueChanged onChanged; + + @override + Widget build(BuildContext context) { + return AppSearchableDropdown( + label: label, + value: value, + isDense: true, + searchHint: 'Search $label...', + options: items + .map((item) => AppDropdownOption(value: item, label: item)) + .toList(), + onChanged: (v) { + if (v != null) onChanged(v); + }, + ); + } +} + +class _AssetTableActions extends StatelessWidget { + const _AssetTableActions({ + required this.onView, + required this.onEdit, + required this.onDelete, + this.canView = true, + this.canEdit = true, + this.canDelete = true, + }); + + static const columnWidth = 108.0; + + final VoidCallback onView; + final VoidCallback onEdit; + final VoidCallback onDelete; + final bool canView; + final bool canEdit; + final bool canDelete; + + @override + Widget build(BuildContext context) { + final muted = Theme.of(context).colorScheme.onSurfaceVariant; + + return Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + if (canView) + _AssetActionIcon( + tooltip: 'View asset', + icon: Icons.visibility_outlined, + color: muted, + onPressed: onView, + ), + if (canEdit) + _AssetActionIcon( + tooltip: 'Edit asset', + icon: Icons.edit_outlined, + color: muted, + onPressed: onEdit, + ), + if (canDelete) + _AssetActionIcon( + tooltip: 'Delete asset', + icon: Icons.delete_outline, + color: muted, + onPressed: onDelete, + ), + ], + ); + } +} + +class _AssetTableActionsHeader extends StatelessWidget { + const _AssetTableActionsHeader(); + + @override + Widget build(BuildContext context) { + return const SizedBox( + width: _AssetTableActions.columnWidth, + child: Align( + alignment: Alignment.centerRight, + child: Text('ACTIONS'), ), ); } } + +class _AssetTableActionsCell extends StatelessWidget { + const _AssetTableActionsCell({required this.child}); + + final Widget child; + + @override + Widget build(BuildContext context) { + return SizedBox( + width: _AssetTableActions.columnWidth, + child: Align( + alignment: Alignment.centerRight, + child: Padding( + padding: const EdgeInsets.only(right: 4), + child: child, + ), + ), + ); + } +} + +class _AssetActionIcon extends StatelessWidget { + const _AssetActionIcon({ + required this.tooltip, + required this.icon, + required this.color, + required this.onPressed, + }); + + final String tooltip; + final IconData icon; + final Color color; + final VoidCallback onPressed; + + @override + Widget build(BuildContext context) { + return Tooltip( + message: tooltip, + child: InkWell( + onTap: onPressed, + borderRadius: BorderRadius.circular(6), + child: Padding( + padding: const EdgeInsets.all(6), + child: Icon(icon, size: 18, color: color), + ), + ), + ); + } +} + +class _AssetMobileList extends StatelessWidget { + const _AssetMobileList({ + required this.assets, + required this.onView, + this.onEdit, + this.onDelete, + }); + + final List assets; + final void Function(AssetModel) onView; + final void Function(AssetModel)? onEdit; + final void Function(AssetModel)? onDelete; + + @override + Widget build(BuildContext context) { + if (assets.isEmpty) { + return ListView( + children: const [ + AppEmptyState( + title: 'No assets found', + description: 'Add assets or adjust your search.', + icon: Icons.inventory_2_outlined, + ), + ], + ); + } + + return ListView.separated( + itemCount: assets.length, + separatorBuilder: (_, __) => const SizedBox(height: 8), + itemBuilder: (context, index) { + final asset = assets[index]; + final status = assetStatusDisplay(asset.status); + + return AppCard( + child: ListTile( + onTap: () => onView(asset), + leading: UserAvatarChip( + name: asset.assetName, + initials: assetInitials(asset), + ), + title: Text( + asset.assetName, + style: const TextStyle(fontWeight: FontWeight.w600), + ), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(asset.assetCode ?? '—'), + const SizedBox(height: 4), + Row( + children: [ + Flexible( + child: RoleBadge( + label: asset.assetCategoryName ?? '—', + ), + ), + const SizedBox(width: 8), + StatusBadge(label: status.label, color: status.color), + ], + ), + ], + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (onEdit != null) + IconButton( + icon: const Icon(Icons.edit_outlined), + onPressed: () => onEdit!(asset), + ), + if (onDelete != null) + IconButton( + icon: const Icon(Icons.delete_outline), + onPressed: () => onDelete!(asset), + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/lib/modules/assets/presentation/widgets/asset_form_panel.dart b/lib/modules/assets/presentation/widgets/asset_form_panel.dart new file mode 100644 index 0000000..fa519c9 --- /dev/null +++ b/lib/modules/assets/presentation/widgets/asset_form_panel.dart @@ -0,0 +1,326 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:intl/intl.dart'; + +import '../../../../core/errors/failure.dart'; +import '../../../../core/utils/formatters.dart'; +import '../../../../core/utils/validators.dart'; +import '../../../../shared/models/asset_model.dart'; +import '../../../../shared/models/user_management_models.dart' show FilterOptionModel; +import '../../../../shared/widgets/app_button.dart'; +import '../../../../shared/widgets/app_loading_view.dart'; +import '../../../../shared/widgets/app_side_panel.dart'; +import '../../../../shared/widgets/app_text_field.dart'; +import '../../../../shared/widgets/error_view.dart'; +import '../../../masters/data/datasources/master_remote_data_source.dart'; +import '../providers/asset_categories_provider.dart'; +import '../providers/assets_provider.dart'; + +Future openAssetFormPanel( + BuildContext context, + WidgetRef ref, { + String? assetId, +}) async { + ref.invalidate(assetFormProvider(assetId)); + final saved = await showSidePanel( + context, + AssetFormPanel(assetId: assetId), + width: 520, + ); + if (saved == true && context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + assetId == null + ? 'Asset created successfully' + : 'Asset updated successfully', + ), + ), + ); + } +} + +class AssetFormPanel extends ConsumerStatefulWidget { + const AssetFormPanel({super.key, this.assetId}); + + final String? assetId; + + bool get isEditing => assetId != null; + + @override + ConsumerState createState() => _AssetFormPanelState(); +} + +class _AssetFormPanelState extends ConsumerState { + final _formKey = GlobalKey(); + final _nameController = TextEditingController(); + final _costController = TextEditingController(); + int? _categoryId; + int? _plantId; + DateTime? _warrantyExpiry; + bool _isSubmitting = false; + String? _populatedSignature; + + @override + void dispose() { + _nameController.dispose(); + _costController.dispose(); + super.dispose(); + } + + String _assetSignature(AssetModel asset) => + '${asset.id}:${asset.assetCategoryId}:${asset.plantId}:' + '${asset.warrantyExpiryDate?.toIso8601String()}:' + '${asset.purchaseCost}:${asset.assetName}'; + + int? _dropdownValue(int? selected, Iterable validIds) { + if (selected == null) return null; + return validIds.contains(selected) ? selected : null; + } + + void _populateFromAsset(AssetModel asset) { + setState(() { + _nameController.text = asset.assetName; + _categoryId = asset.assetCategoryId; + _plantId = asset.plantId; + _warrantyExpiry = asset.warrantyExpiryDate; + if (asset.purchaseCost != null) { + _costController.text = asset.purchaseCost!.toStringAsFixed( + asset.purchaseCost! % 1 == 0 ? 0 : 2, + ); + } else { + _costController.clear(); + } + }); + } + + Map _buildPayload() { + return { + 'asset_name': _nameController.text.trim(), + 'asset_category_id': _categoryId, + 'plant_id': _plantId, + if (_warrantyExpiry != null) + 'warranty_expiry_date': DateFormat('yyyy-MM-dd').format(_warrantyExpiry!), + if (_costController.text.trim().isNotEmpty) + 'purchase_cost': double.tryParse(_costController.text.trim()), + }; + } + + Future _pickWarrantyDate() async { + final picked = await showDatePicker( + context: context, + initialDate: _warrantyExpiry ?? DateTime.now(), + firstDate: DateTime(2000), + lastDate: DateTime(2100), + ); + if (picked != null) setState(() => _warrantyExpiry = picked); + } + + Future _submit() async { + if (!_formKey.currentState!.validate()) return; + if (_categoryId == null || _plantId == null) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Please select category and plant')), + ); + return; + } + + setState(() => _isSubmitting = true); + try { + final notifier = ref.read(assetFormProvider(widget.assetId).notifier); + final payload = _buildPayload(); + if (widget.isEditing) { + await notifier.submitUpdate(widget.assetId!, payload); + } else { + await notifier.submitCreate(payload); + } + if (mounted) Navigator.of(context, rootNavigator: true).pop(true); + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(e.toString())), + ); + } + } finally { + if (mounted) setState(() => _isSubmitting = false); + } + } + + @override + Widget build(BuildContext context) { + final categoriesAsync = ref.watch(assetCategoriesProvider); + final plantsAsync = ref.watch(assetPlantsProvider); + + if (widget.isEditing) { + ref.listen(assetFormProvider(widget.assetId), (prev, next) { + next.whenData((asset) { + if (asset == null || !mounted) return; + final signature = _assetSignature(asset); + if (_populatedSignature != signature) { + _populatedSignature = signature; + _populateFromAsset(asset); + } + }); + }); + } + + final formAsync = + widget.isEditing ? ref.watch(assetFormProvider(widget.assetId)) : null; + + return SidePanelScaffold( + title: widget.isEditing ? 'Edit asset' : 'Add asset', + footer: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + OutlinedButton( + onPressed: _isSubmitting + ? null + : () => Navigator.of(context, rootNavigator: true).pop(), + child: const Text('Cancel'), + ), + const SizedBox(width: 12), + AppButton( + label: widget.isEditing ? 'Update asset' : 'Save asset', + expand: false, + icon: Icons.check, + isLoading: _isSubmitting, + onPressed: _isSubmitting ? null : _submit, + ), + ], + ), + child: widget.isEditing && formAsync != null + ? formAsync.when( + loading: () => const AppLoadingView(message: 'Loading asset...'), + error: (e, _) => ErrorView.fromFailure( + e is Failure ? e : Failure.unknown(message: e.toString()), + onRetry: () => ref.invalidate(assetFormProvider(widget.assetId)), + ), + data: (_) => _buildForm(categoriesAsync, plantsAsync), + ) + : _buildForm(categoriesAsync, plantsAsync), + ); + } + + Widget _buildForm( + AsyncValue> categoriesAsync, + AsyncValue> plantsAsync, + ) { + return Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + AppTextField( + controller: _nameController, + label: 'Asset Name *', + validator: (v) => Validators.required(v, fieldName: 'Asset name'), + ), + const SizedBox(height: 12), + SidePanelFormRow( + left: categoriesAsync.when( + loading: () => const LinearProgressIndicator(), + error: (_, __) => const Text('Failed to load categories'), + data: (categories) => _categoryDropdown(categories), + ), + right: plantsAsync.when( + loading: () => const LinearProgressIndicator(), + error: (_, __) => const Text('Failed to load plants'), + data: (plants) => _plantDropdown(plants), + ), + ), + SidePanelFormRow( + left: _AssetFormDateField( + label: 'Warranty Expiry Date', + value: _warrantyExpiry, + onPick: _pickWarrantyDate, + ), + right: AppTextField( + controller: _costController, + label: 'Purchase Cost', + keyboardType: TextInputType.number, + ), + ), + ], + ), + ); + } + + Widget _categoryDropdown(List categories) { + final categoryIds = categories + .map((c) => int.tryParse(c.id)) + .whereType() + .toList(); + return DropdownButtonFormField( + value: _dropdownValue(_categoryId, categoryIds), + isExpanded: true, + decoration: const InputDecoration(labelText: 'Category *'), + items: categories + .map( + (c) => DropdownMenuItem( + value: int.tryParse(c.id), + child: Text('${c.code} — ${c.name}'), + ), + ) + .where((item) => item.value != null) + .toList(), + onChanged: (v) => setState(() => _categoryId = v), + validator: (v) => v == null ? 'Category is required' : null, + ); + } + + Widget _plantDropdown(List plants) { + final plantIds = plants + .map((p) => int.tryParse(p.id)) + .whereType() + .toList(); + return DropdownButtonFormField( + value: _dropdownValue(_plantId, plantIds), + isExpanded: true, + decoration: const InputDecoration(labelText: 'Plant *'), + items: plants + .map( + (p) => DropdownMenuItem( + value: int.tryParse(p.id), + child: Text(p.name), + ), + ) + .where((item) => item.value != null) + .toList(), + onChanged: (v) => setState(() => _plantId = v), + validator: (v) => v == null ? 'Plant is required' : null, + ); + } +} + +class _AssetFormDateField extends StatelessWidget { + const _AssetFormDateField({ + required this.label, + required this.value, + required this.onPick, + }); + + final String label; + final DateTime? value; + final VoidCallback onPick; + + @override + Widget build(BuildContext context) { + final displayText = value != null ? DateFormatter.displayDate(value) : ''; + + return TextFormField( + readOnly: true, + onTap: onPick, + decoration: InputDecoration( + labelText: label, + hintText: 'Select date', + suffixIcon: const Icon(Icons.calendar_today_outlined, size: 20), + ), + controller: TextEditingController(text: displayText), + ); + } +} + +final assetPlantsProvider = FutureProvider>((ref) async { + final dataSource = ref.watch(masterRemoteDataSourceProvider); + return dataSource.listPlants(); +}); diff --git a/lib/modules/assets/presentation/widgets/asset_side_panels.dart b/lib/modules/assets/presentation/widgets/asset_side_panels.dart new file mode 100644 index 0000000..fa100eb --- /dev/null +++ b/lib/modules/assets/presentation/widgets/asset_side_panels.dart @@ -0,0 +1,500 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../../../core/utils/formatters.dart'; +import '../../../../core/utils/validators.dart'; +import '../../../../shared/widgets/app_button.dart'; +import '../../../../shared/widgets/app_side_panel.dart'; +import '../../../../shared/widgets/app_text_field.dart'; +import '../providers/assets_provider.dart'; + +class AddAmcPanel extends ConsumerStatefulWidget { + const AddAmcPanel({super.key, required this.assetId}); + + final String assetId; + + @override + ConsumerState createState() => _AddAmcPanelState(); +} + +class _AddAmcPanelState extends ConsumerState { + final _formKey = GlobalKey(); + final _vendorIdController = TextEditingController(); + final _contractNoController = TextEditingController(); + final _annualCostController = TextEditingController(); + DateTime? _startDate; + DateTime? _endDate; + String _contractType = 'COMPREHENSIVE'; + bool _isSubmitting = false; + + @override + void dispose() { + _vendorIdController.dispose(); + _contractNoController.dispose(); + _annualCostController.dispose(); + super.dispose(); + } + + Future _pickDate({required bool isStart}) async { + final picked = await showDatePicker( + context: context, + initialDate: (isStart ? _startDate : _endDate) ?? DateTime.now(), + firstDate: DateTime(2000), + lastDate: DateTime(2100), + ); + if (picked != null) { + setState(() { + if (isStart) { + _startDate = picked; + } else { + _endDate = picked; + } + }); + } + } + + Future _save() async { + if (!_formKey.currentState!.validate()) return; + if (_startDate == null || _endDate == null) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Please select start and end dates')), + ); + return; + } + + final vendorId = int.tryParse(_vendorIdController.text.trim()); + if (vendorId == null) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Please enter a valid vendor ID')), + ); + return; + } + + setState(() => _isSubmitting = true); + try { + await ref.read(assetDetailProvider(widget.assetId).notifier).createAmc({ + 'vendor_id': vendorId, + if (_contractNoController.text.isNotEmpty) + 'contract_no': _contractNoController.text.trim(), + 'contract_type': _contractType, + 'start_date': DateFormatter.toApiDate(_startDate!), + 'end_date': DateFormatter.toApiDate(_endDate!), + if (_annualCostController.text.isNotEmpty) + 'annual_cost': double.tryParse(_annualCostController.text), + }); + if (mounted) Navigator.of(context, rootNavigator: true).pop(true); + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(e.toString()))); + } + } finally { + if (mounted) setState(() => _isSubmitting = false); + } + } + + @override + Widget build(BuildContext context) { + return SidePanelScaffold( + title: 'Add AMC Contract', + footer: _panelFooter( + context, + isSubmitting: _isSubmitting, + saveLabel: 'Save contract', + onSave: _save, + ), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SidePanelFormRow( + left: AppTextField( + controller: _vendorIdController, + label: 'Vendor ID *', + keyboardType: TextInputType.number, + validator: (v) => Validators.required(v, fieldName: 'Vendor ID'), + ), + right: AppTextField( + controller: _contractNoController, + label: 'Contract No', + ), + ), + DropdownButtonFormField( + value: _contractType, + isExpanded: true, + decoration: const InputDecoration(labelText: 'Contract Type'), + items: const [ + 'COMPREHENSIVE', + 'LABOUR_ONLY', + 'PARTS_ONLY', + 'PREVENTIVE_ONLY', + ] + .map((t) => DropdownMenuItem(value: t, child: Text(t))) + .toList(), + onChanged: (v) { + if (v != null) setState(() => _contractType = v); + }, + ), + const SizedBox(height: 12), + SidePanelFormRow( + left: _SidePanelDateField( + label: 'Start Date', + isRequired: true, + value: _startDate, + onPick: () => _pickDate(isStart: true), + ), + right: _SidePanelDateField( + label: 'End Date', + isRequired: true, + value: _endDate, + onPick: () => _pickDate(isStart: false), + ), + ), + AppTextField( + controller: _annualCostController, + label: 'Annual Cost', + keyboardType: TextInputType.number, + ), + ], + ), + ), + ); + } +} + +class LogServiceVisitPanel extends ConsumerStatefulWidget { + const LogServiceVisitPanel({super.key, required this.assetId}); + + final String assetId; + + @override + ConsumerState createState() => _LogServiceVisitPanelState(); +} + +class _LogServiceVisitPanelState extends ConsumerState { + final _formKey = GlobalKey(); + final _workDoneController = TextEditingController(); + DateTime? _visitDate = DateTime.now(); + String _visitType = 'PREVENTIVE'; + String _status = 'COMPLETED'; + bool _isSubmitting = false; + + @override + void dispose() { + _workDoneController.dispose(); + super.dispose(); + } + + Future _pickVisitDate() async { + final picked = await showDatePicker( + context: context, + initialDate: _visitDate ?? DateTime.now(), + firstDate: DateTime(2000), + lastDate: DateTime(2100), + ); + if (picked != null) setState(() => _visitDate = picked); + } + + Future _save() async { + if (_visitDate == null) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Please select visit date')), + ); + return; + } + + setState(() => _isSubmitting = true); + try { + await ref.read(assetDetailProvider(widget.assetId).notifier).logVisit({ + 'visit_type': _visitType, + 'visit_date': DateFormatter.toApiDate(_visitDate!), + if (_workDoneController.text.isNotEmpty) + 'work_done': _workDoneController.text.trim(), + 'status': _status, + }); + if (mounted) Navigator.of(context, rootNavigator: true).pop(true); + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(e.toString()))); + } + } finally { + if (mounted) setState(() => _isSubmitting = false); + } + } + + @override + Widget build(BuildContext context) { + return SidePanelScaffold( + title: 'Log Service Visit', + footer: _panelFooter( + context, + isSubmitting: _isSubmitting, + saveLabel: 'Save visit', + onSave: _save, + ), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SidePanelFormRow( + left: DropdownButtonFormField( + value: _visitType, + isExpanded: true, + decoration: const InputDecoration(labelText: 'Visit Type *'), + items: const [ + 'PREVENTIVE', + 'BREAKDOWN', + 'INSPECTION', + 'INSTALLATION', + 'CALIBRATION', + 'OTHER', + ] + .map((t) => DropdownMenuItem(value: t, child: Text(t))) + .toList(), + onChanged: (v) { + if (v != null) setState(() => _visitType = v); + }, + ), + right: DropdownButtonFormField( + value: _status, + isExpanded: true, + decoration: const InputDecoration(labelText: 'Status'), + items: const [ + 'SCHEDULED', + 'IN_PROGRESS', + 'COMPLETED', + 'CANCELLED', + 'PENDING_PARTS', + ] + .map((t) => DropdownMenuItem(value: t, child: Text(t))) + .toList(), + onChanged: (v) { + if (v != null) setState(() => _status = v); + }, + ), + ), + _SidePanelDateField( + label: 'Visit Date', + isRequired: true, + value: _visitDate, + onPick: _pickVisitDate, + ), + const SizedBox(height: 12), + AppTextField( + controller: _workDoneController, + label: 'Work Done', + maxLines: 4, + ), + ], + ), + ), + ); + } +} + +class AddInsurancePanel extends ConsumerStatefulWidget { + const AddInsurancePanel({super.key, required this.assetId}); + + final String assetId; + + @override + ConsumerState createState() => _AddInsurancePanelState(); +} + +class _AddInsurancePanelState extends ConsumerState { + final _formKey = GlobalKey(); + final _policyNoController = TextEditingController(); + final _insurerNameController = TextEditingController(); + final _sumInsuredController = TextEditingController(); + DateTime? _startDate; + DateTime? _endDate; + String _policyType = 'COMPREHENSIVE'; + bool _isSubmitting = false; + + @override + void dispose() { + _policyNoController.dispose(); + _insurerNameController.dispose(); + _sumInsuredController.dispose(); + super.dispose(); + } + + Future _pickDate({required bool isStart}) async { + final picked = await showDatePicker( + context: context, + initialDate: (isStart ? _startDate : _endDate) ?? DateTime.now(), + firstDate: DateTime(2000), + lastDate: DateTime(2100), + ); + if (picked != null) { + setState(() { + if (isStart) { + _startDate = picked; + } else { + _endDate = picked; + } + }); + } + } + + Future _save() async { + if (!_formKey.currentState!.validate()) return; + if (_startDate == null || _endDate == null) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Please select start and end dates')), + ); + return; + } + + setState(() => _isSubmitting = true); + try { + await ref.read(assetDetailProvider(widget.assetId).notifier).createInsurance({ + 'policy_no': _policyNoController.text.trim(), + 'insurer_name': _insurerNameController.text.trim(), + 'policy_type': _policyType, + if (_sumInsuredController.text.isNotEmpty) + 'sum_insured': double.tryParse(_sumInsuredController.text), + 'policy_start_date': DateFormatter.toApiDate(_startDate!), + 'policy_end_date': DateFormatter.toApiDate(_endDate!), + }); + if (mounted) Navigator.of(context, rootNavigator: true).pop(true); + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(e.toString()))); + } + } finally { + if (mounted) setState(() => _isSubmitting = false); + } + } + + @override + Widget build(BuildContext context) { + return SidePanelScaffold( + title: 'Add Insurance Policy', + footer: _panelFooter( + context, + isSubmitting: _isSubmitting, + saveLabel: 'Save policy', + onSave: _save, + ), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SidePanelFormRow( + left: AppTextField( + controller: _policyNoController, + label: 'Policy No *', + validator: (v) => Validators.required(v, fieldName: 'Policy no'), + ), + right: AppTextField( + controller: _insurerNameController, + label: 'Insurer Name *', + validator: (v) => Validators.required(v, fieldName: 'Insurer name'), + ), + ), + SidePanelFormRow( + left: DropdownButtonFormField( + value: _policyType, + isExpanded: true, + decoration: const InputDecoration(labelText: 'Policy Type'), + items: const [ + 'FIRE_AND_ALLIED', + 'MACHINERY_BREAKDOWN', + 'COMPREHENSIVE', + 'THIRD_PARTY', + 'VEHICLE', + 'OTHER', + ] + .map((t) => DropdownMenuItem(value: t, child: Text(t))) + .toList(), + onChanged: (v) { + if (v != null) setState(() => _policyType = v); + }, + ), + right: AppTextField( + controller: _sumInsuredController, + label: 'Sum Insured', + keyboardType: TextInputType.number, + ), + ), + SidePanelFormRow( + left: _SidePanelDateField( + label: 'Start Date', + isRequired: true, + value: _startDate, + onPick: () => _pickDate(isStart: true), + ), + right: _SidePanelDateField( + label: 'End Date', + isRequired: true, + value: _endDate, + onPick: () => _pickDate(isStart: false), + ), + ), + ], + ), + ), + ); + } +} + +Widget _panelFooter( + BuildContext context, { + required bool isSubmitting, + required String saveLabel, + required VoidCallback onSave, +}) { + return Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + OutlinedButton( + onPressed: isSubmitting + ? null + : () => Navigator.of(context, rootNavigator: true).pop(), + child: const Text('Cancel'), + ), + const SizedBox(width: 12), + AppButton( + label: saveLabel, + expand: false, + icon: Icons.check, + isLoading: isSubmitting, + onPressed: isSubmitting ? null : onSave, + ), + ], + ); +} + +class _SidePanelDateField extends StatelessWidget { + const _SidePanelDateField({ + required this.label, + required this.value, + required this.onPick, + this.isRequired = false, + }); + + final String label; + final DateTime? value; + final VoidCallback onPick; + final bool isRequired; + + @override + Widget build(BuildContext context) { + final labelText = isRequired ? '$label *' : label; + final displayText = value != null ? DateFormatter.displayDate(value) : ''; + + return TextFormField( + readOnly: true, + onTap: onPick, + decoration: InputDecoration( + labelText: labelText, + hintText: 'Select date', + suffixIcon: const Icon(Icons.calendar_today_outlined, size: 20), + ), + controller: TextEditingController(text: displayText), + ); + } +} diff --git a/lib/modules/dev/presentation/screens/screen_gallery_screen.dart b/lib/modules/dev/presentation/screens/screen_gallery_screen.dart index 68cf414..4ec922f 100644 --- a/lib/modules/dev/presentation/screens/screen_gallery_screen.dart +++ b/lib/modules/dev/presentation/screens/screen_gallery_screen.dart @@ -77,15 +77,10 @@ final _entries = [ ), // Assets _GalleryEntry(title: 'Asset List', route: RouteConstants.assets, group: 'Assets'), - _GalleryEntry(title: 'Add Asset', route: RouteConstants.assetAdd, group: 'Assets'), - _GalleryEntry(title: 'Edit Asset', route: '/assets/demo-asset/edit', group: 'Assets'), _GalleryEntry(title: 'Asset Detail', route: '/assets/demo-asset', group: 'Assets'), _GalleryEntry(title: 'Asset Categories', route: RouteConstants.assetCategories, group: 'Assets'), - _GalleryEntry(title: 'Allocations', route: RouteConstants.assetAllocations, group: 'Assets'), - _GalleryEntry(title: 'Maintenance', route: RouteConstants.assetMaintenance, group: 'Assets'), - _GalleryEntry(title: 'Disposal', route: RouteConstants.assetDisposal, group: 'Assets'), - _GalleryEntry(title: 'QR Scan', route: RouteConstants.assetQrScan, group: 'Assets'), - _GalleryEntry(title: 'QR Generate', route: RouteConstants.assetQrGenerate, group: 'Assets'), + _GalleryEntry(title: 'Categories', route: RouteConstants.assetCategories, group: 'Assets'), + _GalleryEntry(title: 'Alerts', route: RouteConstants.assetAlerts, group: 'Assets'), // Master data _GalleryEntry(title: 'Master Data Hub', route: RouteConstants.masterData, group: 'Master Data'), ...masterDefinitions.map( diff --git a/lib/shared/models/asset_model.dart b/lib/shared/models/asset_model.dart index 4a07f1d..56e4d73 100644 --- a/lib/shared/models/asset_model.dart +++ b/lib/shared/models/asset_model.dart @@ -3,15 +3,80 @@ import 'package:freezed_annotation/freezed_annotation.dart'; part 'asset_model.freezed.dart'; part 'asset_model.g.dart'; +String _idFromJson(Object? value) => value?.toString() ?? ''; + +int? _intFromJsonNullable(Object? value) { + if (value == null) return null; + if (value is int) return value; + if (value is num) return value.toInt(); + return int.tryParse(value.toString()); +} + +double? _doubleFromJsonNullable(Object? value) { + if (value == null) return null; + if (value is double) return value; + if (value is num) return value.toDouble(); + return double.tryParse(value.toString()); +} + +DateTime _dateFromJson(Object? value) { + if (value is DateTime) return value; + return DateTime.parse(value.toString()); +} + +DateTime? _dateFromJsonNullable(Object? value) { + if (value == null) return null; + if (value is DateTime) return value; + return DateTime.tryParse(value.toString()); +} + +Object? _readNestedName(Map json, String nestedKey) { + final nested = json[nestedKey]; + if (nested is Map) return nested['name']; + return null; +} + +Object? _readAssetCategoryName(Map json, String key) { + final flat = json['asset_category_name']; + if (flat is String && flat.isNotEmpty) return flat; + return _readNestedName(json, 'asset_category'); +} + +Object? _readPlantName(Map json, String key) { + final flat = json['plant_name']; + if (flat is String && flat.isNotEmpty) return flat; + return _readNestedName(json, 'plant'); +} + +Object? _readAssetCategoryId(Map json, String key) { + final flat = json['asset_category_id']; + if (flat != null) return flat; + final nested = json['asset_category']; + if (nested is Map) return nested['id']; + return null; +} + +Object? _readPlantId(Map json, String key) { + final flat = json['plant_id']; + if (flat != null) return flat; + final nested = json['plant']; + if (nested is Map) return nested['id']; + return null; +} + @freezed class AssetCategoryModel with _$AssetCategoryModel { const factory AssetCategoryModel({ - required String id, + @JsonKey(fromJson: _idFromJson) required String id, + required String code, required String name, - required String slug, - String? description, - @JsonKey(name: 'company_id') String? companyId, + @JsonKey(name: 'code_prefix') String? codePrefix, + @JsonKey(name: 'default_useful_life_years', fromJson: _intFromJsonNullable) + int? defaultUsefulLifeYears, + @JsonKey(name: 'default_depreciation_method') String? defaultDepreciationMethod, + @JsonKey(name: 'is_active') @Default(true) bool isActive, DateTime? createdAt, + DateTime? updatedAt, }) = _AssetCategoryModel; factory AssetCategoryModel.fromJson(Map json) => @@ -21,85 +86,108 @@ class AssetCategoryModel with _$AssetCategoryModel { @freezed class AssetModel with _$AssetModel { const factory AssetModel({ - required String id, - required String name, - @JsonKey(name: 'asset_code') required String assetCode, - @JsonKey(name: 'category_id') required String categoryId, - @JsonKey(name: 'category_name') String? categoryName, - String? brand, - String? model, - @JsonKey(name: 'serial_number') String? serialNumber, - @JsonKey(name: 'purchase_date') DateTime? purchaseDate, - @JsonKey(name: 'purchase_cost') double? purchaseCost, - String? vendor, - @JsonKey(name: 'warranty_start') DateTime? warrantyStart, - @JsonKey(name: 'warranty_end') DateTime? warrantyEnd, - @Default('available') String status, - @JsonKey(name: 'branch_id') String? branchId, - @JsonKey(name: 'branch_name') String? branchName, - @JsonKey(name: 'company_id') String? companyId, - @JsonKey(name: 'qr_code_url') String? qrCodeUrl, - DateTime? createdAt, - DateTime? updatedAt, + @JsonKey(fromJson: _idFromJson) required String id, + @JsonKey(name: 'asset_name') required String assetName, + @JsonKey(name: 'asset_code') String? assetCode, + @JsonKey( + name: 'asset_category_id', + readValue: _readAssetCategoryId, + fromJson: _intFromJsonNullable, + ) + int? assetCategoryId, + @JsonKey(name: 'asset_category_name', readValue: _readAssetCategoryName) + String? assetCategoryName, + @JsonKey(name: 'plant_id', readValue: _readPlantId, fromJson: _intFromJsonNullable) + int? plantId, + @JsonKey(name: 'plant_name', readValue: _readPlantName) String? plantName, + @JsonKey(name: 'warranty_expiry_date', fromJson: _dateFromJsonNullable) + DateTime? warrantyExpiryDate, + @JsonKey(name: 'purchase_cost', fromJson: _doubleFromJsonNullable) double? purchaseCost, + String? status, + @JsonKey(name: 'is_active') @Default(true) bool isActive, + @JsonKey(name: 'created_at', fromJson: _dateFromJsonNullable) DateTime? createdAt, + @JsonKey(name: 'updated_at', fromJson: _dateFromJsonNullable) DateTime? updatedAt, }) = _AssetModel; factory AssetModel.fromJson(Map json) => _$AssetModelFromJson(json); } @freezed -class AssetAllocationModel with _$AssetAllocationModel { - const factory AssetAllocationModel({ - required String id, - @JsonKey(name: 'asset_id') required String assetId, - @JsonKey(name: 'asset_name') String? assetName, - @JsonKey(name: 'employee_id') required String employeeId, - @JsonKey(name: 'employee_name') String? employeeName, - @JsonKey(name: 'assigned_date') required DateTime assignedDate, - @JsonKey(name: 'returned_date') DateTime? returnedDate, - String? remarks, +class AmcContractModel with _$AmcContractModel { + const factory AmcContractModel({ + @JsonKey(fromJson: _idFromJson) required String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) String? assetId, + @JsonKey(name: 'vendor_id', fromJson: _intFromJsonNullable) int? vendorId, + @JsonKey(name: 'vendor_name') String? vendorName, + @JsonKey(name: 'contract_no') String? contractNo, + @JsonKey(name: 'contract_type') String? contractType, + @JsonKey(name: 'start_date', fromJson: _dateFromJson) required DateTime startDate, + @JsonKey(name: 'end_date', fromJson: _dateFromJson) required DateTime endDate, + @JsonKey(name: 'annual_cost', fromJson: _doubleFromJsonNullable) double? annualCost, @Default('active') String status, DateTime? createdAt, - }) = _AssetAllocationModel; + }) = _AmcContractModel; - factory AssetAllocationModel.fromJson(Map json) => - _$AssetAllocationModelFromJson(json); + factory AmcContractModel.fromJson(Map json) => + _$AmcContractModelFromJson(json); } @freezed -class AssetMaintenanceModel with _$AssetMaintenanceModel { - const factory AssetMaintenanceModel({ - required String id, - @JsonKey(name: 'asset_id') required String assetId, - @JsonKey(name: 'asset_name') String? assetName, - required String description, - @JsonKey(name: 'service_vendor') String? serviceVendor, - double? cost, - @Default('open') String status, - @JsonKey(name: 'requested_by') String? requestedBy, - @JsonKey(name: 'completed_date') DateTime? completedDate, +class ServiceVisitModel with _$ServiceVisitModel { + const factory ServiceVisitModel({ + @JsonKey(fromJson: _idFromJson) required String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) String? assetId, + @JsonKey(name: 'visit_type') required String visitType, + @JsonKey(name: 'visit_date', fromJson: _dateFromJson) required DateTime visitDate, + @JsonKey(name: 'complaint_no') String? complaintNo, + @JsonKey(name: 'work_done') String? workDone, + @JsonKey(name: 'next_service_date', fromJson: _dateFromJsonNullable) + DateTime? nextServiceDate, + @Default('COMPLETED') String status, DateTime? createdAt, - DateTime? updatedAt, - }) = _AssetMaintenanceModel; + }) = _ServiceVisitModel; - factory AssetMaintenanceModel.fromJson(Map json) => - _$AssetMaintenanceModelFromJson(json); + factory ServiceVisitModel.fromJson(Map json) => + _$ServiceVisitModelFromJson(json); } @freezed -class AssetDisposalModel with _$AssetDisposalModel { - const factory AssetDisposalModel({ - required String id, - @JsonKey(name: 'asset_id') required String assetId, - @JsonKey(name: 'asset_name') String? assetName, - @JsonKey(name: 'disposal_reason') required String disposalReason, - @JsonKey(name: 'disposal_date') DateTime? disposalDate, - @Default('pending') String status, - @JsonKey(name: 'requested_by') String? requestedBy, - @JsonKey(name: 'approved_by') String? approvedBy, +class InsurancePolicyModel with _$InsurancePolicyModel { + const factory InsurancePolicyModel({ + @JsonKey(fromJson: _idFromJson) required String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) String? assetId, + @JsonKey(name: 'policy_no') required String policyNo, + @JsonKey(name: 'insurer_name') required String insurerName, + @JsonKey(name: 'policy_type') String? policyType, + @JsonKey(name: 'sum_insured', fromJson: _doubleFromJsonNullable) double? sumInsured, + @JsonKey(name: 'policy_start_date', fromJson: _dateFromJson) + required DateTime policyStartDate, + @JsonKey(name: 'policy_end_date', fromJson: _dateFromJson) required DateTime policyEndDate, + @Default('active') String status, DateTime? createdAt, - DateTime? updatedAt, - }) = _AssetDisposalModel; + }) = _InsurancePolicyModel; - factory AssetDisposalModel.fromJson(Map json) => - _$AssetDisposalModelFromJson(json); + factory InsurancePolicyModel.fromJson(Map json) => + _$InsurancePolicyModelFromJson(json); +} + +@freezed +class AssetAlertModel with _$AssetAlertModel { + const factory AssetAlertModel({ + @JsonKey(fromJson: _idFromJson) required String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) String? assetId, + @JsonKey(name: 'asset_name') String? assetName, + @JsonKey(name: 'asset_code') String? assetCode, + String? type, + String? title, + String? message, + @JsonKey(name: 'expiry_date', fromJson: _dateFromJsonNullable) DateTime? expiryDate, + @JsonKey(name: 'due_date', fromJson: _dateFromJsonNullable) DateTime? dueDate, + @JsonKey(name: 'days_remaining', fromJson: _intFromJsonNullable) int? daysRemaining, + String? status, + @JsonKey(name: 'plant_name') String? plantName, + }) = _AssetAlertModel; + + factory AssetAlertModel.fromJson(Map json) => + _$AssetAlertModelFromJson(json); } diff --git a/lib/shared/models/asset_model.freezed.dart b/lib/shared/models/asset_model.freezed.dart index 1cb8027..00ba61d 100644 --- a/lib/shared/models/asset_model.freezed.dart +++ b/lib/shared/models/asset_model.freezed.dart @@ -21,13 +21,20 @@ AssetCategoryModel _$AssetCategoryModelFromJson(Map json) { /// @nodoc mixin _$AssetCategoryModel { + @JsonKey(fromJson: _idFromJson) String get id => throw _privateConstructorUsedError; + String get code => throw _privateConstructorUsedError; String get name => throw _privateConstructorUsedError; - String get slug => throw _privateConstructorUsedError; - String? get description => throw _privateConstructorUsedError; - @JsonKey(name: 'company_id') - String? get companyId => throw _privateConstructorUsedError; + @JsonKey(name: 'code_prefix') + String? get codePrefix => throw _privateConstructorUsedError; + @JsonKey(name: 'default_useful_life_years', fromJson: _intFromJsonNullable) + int? get defaultUsefulLifeYears => throw _privateConstructorUsedError; + @JsonKey(name: 'default_depreciation_method') + String? get defaultDepreciationMethod => throw _privateConstructorUsedError; + @JsonKey(name: 'is_active') + bool get isActive => throw _privateConstructorUsedError; DateTime? get createdAt => throw _privateConstructorUsedError; + DateTime? get updatedAt => throw _privateConstructorUsedError; /// Serializes this AssetCategoryModel to a JSON map. Map toJson() => throw _privateConstructorUsedError; @@ -47,12 +54,17 @@ abstract class $AssetCategoryModelCopyWith<$Res> { ) = _$AssetCategoryModelCopyWithImpl<$Res, AssetCategoryModel>; @useResult $Res call({ - String id, + @JsonKey(fromJson: _idFromJson) String id, + String code, String name, - String slug, - String? description, - @JsonKey(name: 'company_id') String? companyId, + @JsonKey(name: 'code_prefix') String? codePrefix, + @JsonKey(name: 'default_useful_life_years', fromJson: _intFromJsonNullable) + int? defaultUsefulLifeYears, + @JsonKey(name: 'default_depreciation_method') + String? defaultDepreciationMethod, + @JsonKey(name: 'is_active') bool isActive, DateTime? createdAt, + DateTime? updatedAt, }); } @@ -72,11 +84,14 @@ class _$AssetCategoryModelCopyWithImpl<$Res, $Val extends AssetCategoryModel> @override $Res call({ Object? id = null, + Object? code = null, Object? name = null, - Object? slug = null, - Object? description = freezed, - Object? companyId = freezed, + Object? codePrefix = freezed, + Object? defaultUsefulLifeYears = freezed, + Object? defaultDepreciationMethod = freezed, + Object? isActive = null, Object? createdAt = freezed, + Object? updatedAt = freezed, }) { return _then( _value.copyWith( @@ -84,26 +99,38 @@ class _$AssetCategoryModelCopyWithImpl<$Res, $Val extends AssetCategoryModel> ? _value.id : id // ignore: cast_nullable_to_non_nullable as String, + code: null == code + ? _value.code + : code // ignore: cast_nullable_to_non_nullable + as String, name: null == name ? _value.name : name // ignore: cast_nullable_to_non_nullable as String, - slug: null == slug - ? _value.slug - : slug // ignore: cast_nullable_to_non_nullable - as String, - description: freezed == description - ? _value.description - : description // ignore: cast_nullable_to_non_nullable + codePrefix: freezed == codePrefix + ? _value.codePrefix + : codePrefix // ignore: cast_nullable_to_non_nullable as String?, - companyId: freezed == companyId - ? _value.companyId - : companyId // ignore: cast_nullable_to_non_nullable + defaultUsefulLifeYears: freezed == defaultUsefulLifeYears + ? _value.defaultUsefulLifeYears + : defaultUsefulLifeYears // ignore: cast_nullable_to_non_nullable + as int?, + defaultDepreciationMethod: freezed == defaultDepreciationMethod + ? _value.defaultDepreciationMethod + : defaultDepreciationMethod // ignore: cast_nullable_to_non_nullable as String?, + isActive: null == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool, createdAt: freezed == createdAt ? _value.createdAt : createdAt // ignore: cast_nullable_to_non_nullable as DateTime?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, ) as $Val, ); @@ -120,12 +147,17 @@ abstract class _$$AssetCategoryModelImplCopyWith<$Res> @override @useResult $Res call({ - String id, + @JsonKey(fromJson: _idFromJson) String id, + String code, String name, - String slug, - String? description, - @JsonKey(name: 'company_id') String? companyId, + @JsonKey(name: 'code_prefix') String? codePrefix, + @JsonKey(name: 'default_useful_life_years', fromJson: _intFromJsonNullable) + int? defaultUsefulLifeYears, + @JsonKey(name: 'default_depreciation_method') + String? defaultDepreciationMethod, + @JsonKey(name: 'is_active') bool isActive, DateTime? createdAt, + DateTime? updatedAt, }); } @@ -144,11 +176,14 @@ class __$$AssetCategoryModelImplCopyWithImpl<$Res> @override $Res call({ Object? id = null, + Object? code = null, Object? name = null, - Object? slug = null, - Object? description = freezed, - Object? companyId = freezed, + Object? codePrefix = freezed, + Object? defaultUsefulLifeYears = freezed, + Object? defaultDepreciationMethod = freezed, + Object? isActive = null, Object? createdAt = freezed, + Object? updatedAt = freezed, }) { return _then( _$AssetCategoryModelImpl( @@ -156,26 +191,38 @@ class __$$AssetCategoryModelImplCopyWithImpl<$Res> ? _value.id : id // ignore: cast_nullable_to_non_nullable as String, + code: null == code + ? _value.code + : code // ignore: cast_nullable_to_non_nullable + as String, name: null == name ? _value.name : name // ignore: cast_nullable_to_non_nullable as String, - slug: null == slug - ? _value.slug - : slug // ignore: cast_nullable_to_non_nullable - as String, - description: freezed == description - ? _value.description - : description // ignore: cast_nullable_to_non_nullable + codePrefix: freezed == codePrefix + ? _value.codePrefix + : codePrefix // ignore: cast_nullable_to_non_nullable as String?, - companyId: freezed == companyId - ? _value.companyId - : companyId // ignore: cast_nullable_to_non_nullable + defaultUsefulLifeYears: freezed == defaultUsefulLifeYears + ? _value.defaultUsefulLifeYears + : defaultUsefulLifeYears // ignore: cast_nullable_to_non_nullable + as int?, + defaultDepreciationMethod: freezed == defaultDepreciationMethod + ? _value.defaultDepreciationMethod + : defaultDepreciationMethod // ignore: cast_nullable_to_non_nullable as String?, + isActive: null == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool, createdAt: freezed == createdAt ? _value.createdAt : createdAt // ignore: cast_nullable_to_non_nullable as DateTime?, + updatedAt: freezed == updatedAt + ? _value.updatedAt + : updatedAt // ignore: cast_nullable_to_non_nullable + as DateTime?, ), ); } @@ -185,34 +232,49 @@ class __$$AssetCategoryModelImplCopyWithImpl<$Res> @JsonSerializable() class _$AssetCategoryModelImpl implements _AssetCategoryModel { const _$AssetCategoryModelImpl({ - required this.id, + @JsonKey(fromJson: _idFromJson) required this.id, + required this.code, required this.name, - required this.slug, - this.description, - @JsonKey(name: 'company_id') this.companyId, + @JsonKey(name: 'code_prefix') this.codePrefix, + @JsonKey(name: 'default_useful_life_years', fromJson: _intFromJsonNullable) + this.defaultUsefulLifeYears, + @JsonKey(name: 'default_depreciation_method') + this.defaultDepreciationMethod, + @JsonKey(name: 'is_active') this.isActive = true, this.createdAt, + this.updatedAt, }); factory _$AssetCategoryModelImpl.fromJson(Map json) => _$$AssetCategoryModelImplFromJson(json); @override + @JsonKey(fromJson: _idFromJson) final String id; @override + final String code; + @override final String name; @override - final String slug; + @JsonKey(name: 'code_prefix') + final String? codePrefix; @override - final String? description; + @JsonKey(name: 'default_useful_life_years', fromJson: _intFromJsonNullable) + final int? defaultUsefulLifeYears; @override - @JsonKey(name: 'company_id') - final String? companyId; + @JsonKey(name: 'default_depreciation_method') + final String? defaultDepreciationMethod; + @override + @JsonKey(name: 'is_active') + final bool isActive; @override final DateTime? createdAt; + @override + final DateTime? updatedAt; @override String toString() { - return 'AssetCategoryModel(id: $id, name: $name, slug: $slug, description: $description, companyId: $companyId, createdAt: $createdAt)'; + return 'AssetCategoryModel(id: $id, code: $code, name: $name, codePrefix: $codePrefix, defaultUsefulLifeYears: $defaultUsefulLifeYears, defaultDepreciationMethod: $defaultDepreciationMethod, isActive: $isActive, createdAt: $createdAt, updatedAt: $updatedAt)'; } @override @@ -221,14 +283,23 @@ class _$AssetCategoryModelImpl implements _AssetCategoryModel { (other.runtimeType == runtimeType && other is _$AssetCategoryModelImpl && (identical(other.id, id) || other.id == id) && + (identical(other.code, code) || other.code == code) && (identical(other.name, name) || other.name == name) && - (identical(other.slug, slug) || other.slug == slug) && - (identical(other.description, description) || - other.description == description) && - (identical(other.companyId, companyId) || - other.companyId == companyId) && + (identical(other.codePrefix, codePrefix) || + other.codePrefix == codePrefix) && + (identical(other.defaultUsefulLifeYears, defaultUsefulLifeYears) || + other.defaultUsefulLifeYears == defaultUsefulLifeYears) && + (identical( + other.defaultDepreciationMethod, + defaultDepreciationMethod, + ) || + other.defaultDepreciationMethod == defaultDepreciationMethod) && + (identical(other.isActive, isActive) || + other.isActive == isActive) && (identical(other.createdAt, createdAt) || - other.createdAt == createdAt)); + other.createdAt == createdAt) && + (identical(other.updatedAt, updatedAt) || + other.updatedAt == updatedAt)); } @JsonKey(includeFromJson: false, includeToJson: false) @@ -236,11 +307,14 @@ class _$AssetCategoryModelImpl implements _AssetCategoryModel { int get hashCode => Object.hash( runtimeType, id, + code, name, - slug, - description, - companyId, + codePrefix, + defaultUsefulLifeYears, + defaultDepreciationMethod, + isActive, createdAt, + updatedAt, ); /// Create a copy of AssetCategoryModel @@ -262,30 +336,45 @@ class _$AssetCategoryModelImpl implements _AssetCategoryModel { abstract class _AssetCategoryModel implements AssetCategoryModel { const factory _AssetCategoryModel({ - required final String id, + @JsonKey(fromJson: _idFromJson) required final String id, + required final String code, required final String name, - required final String slug, - final String? description, - @JsonKey(name: 'company_id') final String? companyId, + @JsonKey(name: 'code_prefix') final String? codePrefix, + @JsonKey(name: 'default_useful_life_years', fromJson: _intFromJsonNullable) + final int? defaultUsefulLifeYears, + @JsonKey(name: 'default_depreciation_method') + final String? defaultDepreciationMethod, + @JsonKey(name: 'is_active') final bool isActive, final DateTime? createdAt, + final DateTime? updatedAt, }) = _$AssetCategoryModelImpl; factory _AssetCategoryModel.fromJson(Map json) = _$AssetCategoryModelImpl.fromJson; @override + @JsonKey(fromJson: _idFromJson) String get id; @override + String get code; + @override String get name; @override - String get slug; + @JsonKey(name: 'code_prefix') + String? get codePrefix; @override - String? get description; + @JsonKey(name: 'default_useful_life_years', fromJson: _intFromJsonNullable) + int? get defaultUsefulLifeYears; @override - @JsonKey(name: 'company_id') - String? get companyId; + @JsonKey(name: 'default_depreciation_method') + String? get defaultDepreciationMethod; + @override + @JsonKey(name: 'is_active') + bool get isActive; @override DateTime? get createdAt; + @override + DateTime? get updatedAt; /// Create a copy of AssetCategoryModel /// with the given fields replaced by the non-null parameter values. @@ -301,37 +390,38 @@ AssetModel _$AssetModelFromJson(Map json) { /// @nodoc mixin _$AssetModel { + @JsonKey(fromJson: _idFromJson) String get id => throw _privateConstructorUsedError; - String get name => throw _privateConstructorUsedError; + @JsonKey(name: 'asset_name') + String get assetName => throw _privateConstructorUsedError; @JsonKey(name: 'asset_code') - String get assetCode => throw _privateConstructorUsedError; - @JsonKey(name: 'category_id') - String get categoryId => throw _privateConstructorUsedError; - @JsonKey(name: 'category_name') - String? get categoryName => throw _privateConstructorUsedError; - String? get brand => throw _privateConstructorUsedError; - String? get model => throw _privateConstructorUsedError; - @JsonKey(name: 'serial_number') - String? get serialNumber => throw _privateConstructorUsedError; - @JsonKey(name: 'purchase_date') - DateTime? get purchaseDate => throw _privateConstructorUsedError; - @JsonKey(name: 'purchase_cost') + String? get assetCode => throw _privateConstructorUsedError; + @JsonKey( + name: 'asset_category_id', + readValue: _readAssetCategoryId, + fromJson: _intFromJsonNullable, + ) + int? get assetCategoryId => throw _privateConstructorUsedError; + @JsonKey(name: 'asset_category_name', readValue: _readAssetCategoryName) + String? get assetCategoryName => throw _privateConstructorUsedError; + @JsonKey( + name: 'plant_id', + readValue: _readPlantId, + fromJson: _intFromJsonNullable, + ) + int? get plantId => throw _privateConstructorUsedError; + @JsonKey(name: 'plant_name', readValue: _readPlantName) + String? get plantName => throw _privateConstructorUsedError; + @JsonKey(name: 'warranty_expiry_date', fromJson: _dateFromJsonNullable) + DateTime? get warrantyExpiryDate => throw _privateConstructorUsedError; + @JsonKey(name: 'purchase_cost', fromJson: _doubleFromJsonNullable) double? get purchaseCost => throw _privateConstructorUsedError; - String? get vendor => throw _privateConstructorUsedError; - @JsonKey(name: 'warranty_start') - DateTime? get warrantyStart => throw _privateConstructorUsedError; - @JsonKey(name: 'warranty_end') - DateTime? get warrantyEnd => throw _privateConstructorUsedError; - String get status => throw _privateConstructorUsedError; - @JsonKey(name: 'branch_id') - String? get branchId => throw _privateConstructorUsedError; - @JsonKey(name: 'branch_name') - String? get branchName => throw _privateConstructorUsedError; - @JsonKey(name: 'company_id') - String? get companyId => throw _privateConstructorUsedError; - @JsonKey(name: 'qr_code_url') - String? get qrCodeUrl => throw _privateConstructorUsedError; + String? get status => throw _privateConstructorUsedError; + @JsonKey(name: 'is_active') + bool get isActive => throw _privateConstructorUsedError; + @JsonKey(name: 'created_at', fromJson: _dateFromJsonNullable) DateTime? get createdAt => throw _privateConstructorUsedError; + @JsonKey(name: 'updated_at', fromJson: _dateFromJsonNullable) DateTime? get updatedAt => throw _privateConstructorUsedError; /// Serializes this AssetModel to a JSON map. @@ -352,25 +442,33 @@ abstract class $AssetModelCopyWith<$Res> { ) = _$AssetModelCopyWithImpl<$Res, AssetModel>; @useResult $Res call({ - String id, - String name, - @JsonKey(name: 'asset_code') String assetCode, - @JsonKey(name: 'category_id') String categoryId, - @JsonKey(name: 'category_name') String? categoryName, - String? brand, - String? model, - @JsonKey(name: 'serial_number') String? serialNumber, - @JsonKey(name: 'purchase_date') DateTime? purchaseDate, - @JsonKey(name: 'purchase_cost') double? purchaseCost, - String? vendor, - @JsonKey(name: 'warranty_start') DateTime? warrantyStart, - @JsonKey(name: 'warranty_end') DateTime? warrantyEnd, - String status, - @JsonKey(name: 'branch_id') String? branchId, - @JsonKey(name: 'branch_name') String? branchName, - @JsonKey(name: 'company_id') String? companyId, - @JsonKey(name: 'qr_code_url') String? qrCodeUrl, + @JsonKey(fromJson: _idFromJson) String id, + @JsonKey(name: 'asset_name') String assetName, + @JsonKey(name: 'asset_code') String? assetCode, + @JsonKey( + name: 'asset_category_id', + readValue: _readAssetCategoryId, + fromJson: _intFromJsonNullable, + ) + int? assetCategoryId, + @JsonKey(name: 'asset_category_name', readValue: _readAssetCategoryName) + String? assetCategoryName, + @JsonKey( + name: 'plant_id', + readValue: _readPlantId, + fromJson: _intFromJsonNullable, + ) + int? plantId, + @JsonKey(name: 'plant_name', readValue: _readPlantName) String? plantName, + @JsonKey(name: 'warranty_expiry_date', fromJson: _dateFromJsonNullable) + DateTime? warrantyExpiryDate, + @JsonKey(name: 'purchase_cost', fromJson: _doubleFromJsonNullable) + double? purchaseCost, + String? status, + @JsonKey(name: 'is_active') bool isActive, + @JsonKey(name: 'created_at', fromJson: _dateFromJsonNullable) DateTime? createdAt, + @JsonKey(name: 'updated_at', fromJson: _dateFromJsonNullable) DateTime? updatedAt, }); } @@ -391,23 +489,16 @@ class _$AssetModelCopyWithImpl<$Res, $Val extends AssetModel> @override $Res call({ Object? id = null, - Object? name = null, - Object? assetCode = null, - Object? categoryId = null, - Object? categoryName = freezed, - Object? brand = freezed, - Object? model = freezed, - Object? serialNumber = freezed, - Object? purchaseDate = freezed, + Object? assetName = null, + Object? assetCode = freezed, + Object? assetCategoryId = freezed, + Object? assetCategoryName = freezed, + Object? plantId = freezed, + Object? plantName = freezed, + Object? warrantyExpiryDate = freezed, Object? purchaseCost = freezed, - Object? vendor = freezed, - Object? warrantyStart = freezed, - Object? warrantyEnd = freezed, - Object? status = null, - Object? branchId = freezed, - Object? branchName = freezed, - Object? companyId = freezed, - Object? qrCodeUrl = freezed, + Object? status = freezed, + Object? isActive = null, Object? createdAt = freezed, Object? updatedAt = freezed, }) { @@ -417,74 +508,46 @@ class _$AssetModelCopyWithImpl<$Res, $Val extends AssetModel> ? _value.id : id // ignore: cast_nullable_to_non_nullable as String, - name: null == name - ? _value.name - : name // ignore: cast_nullable_to_non_nullable + assetName: null == assetName + ? _value.assetName + : assetName // ignore: cast_nullable_to_non_nullable as String, - assetCode: null == assetCode + assetCode: freezed == assetCode ? _value.assetCode : assetCode // ignore: cast_nullable_to_non_nullable - as String, - categoryId: null == categoryId - ? _value.categoryId - : categoryId // ignore: cast_nullable_to_non_nullable - as String, - categoryName: freezed == categoryName - ? _value.categoryName - : categoryName // ignore: cast_nullable_to_non_nullable as String?, - brand: freezed == brand - ? _value.brand - : brand // ignore: cast_nullable_to_non_nullable + assetCategoryId: freezed == assetCategoryId + ? _value.assetCategoryId + : assetCategoryId // ignore: cast_nullable_to_non_nullable + as int?, + assetCategoryName: freezed == assetCategoryName + ? _value.assetCategoryName + : assetCategoryName // ignore: cast_nullable_to_non_nullable as String?, - model: freezed == model - ? _value.model - : model // ignore: cast_nullable_to_non_nullable + plantId: freezed == plantId + ? _value.plantId + : plantId // ignore: cast_nullable_to_non_nullable + as int?, + plantName: freezed == plantName + ? _value.plantName + : plantName // ignore: cast_nullable_to_non_nullable as String?, - serialNumber: freezed == serialNumber - ? _value.serialNumber - : serialNumber // ignore: cast_nullable_to_non_nullable - as String?, - purchaseDate: freezed == purchaseDate - ? _value.purchaseDate - : purchaseDate // ignore: cast_nullable_to_non_nullable + warrantyExpiryDate: freezed == warrantyExpiryDate + ? _value.warrantyExpiryDate + : warrantyExpiryDate // ignore: cast_nullable_to_non_nullable as DateTime?, purchaseCost: freezed == purchaseCost ? _value.purchaseCost : purchaseCost // ignore: cast_nullable_to_non_nullable as double?, - vendor: freezed == vendor - ? _value.vendor - : vendor // ignore: cast_nullable_to_non_nullable - as String?, - warrantyStart: freezed == warrantyStart - ? _value.warrantyStart - : warrantyStart // ignore: cast_nullable_to_non_nullable - as DateTime?, - warrantyEnd: freezed == warrantyEnd - ? _value.warrantyEnd - : warrantyEnd // ignore: cast_nullable_to_non_nullable - as DateTime?, - status: null == status + status: freezed == status ? _value.status : status // ignore: cast_nullable_to_non_nullable - as String, - branchId: freezed == branchId - ? _value.branchId - : branchId // ignore: cast_nullable_to_non_nullable - as String?, - branchName: freezed == branchName - ? _value.branchName - : branchName // ignore: cast_nullable_to_non_nullable - as String?, - companyId: freezed == companyId - ? _value.companyId - : companyId // ignore: cast_nullable_to_non_nullable - as String?, - qrCodeUrl: freezed == qrCodeUrl - ? _value.qrCodeUrl - : qrCodeUrl // ignore: cast_nullable_to_non_nullable as String?, + isActive: null == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool, createdAt: freezed == createdAt ? _value.createdAt : createdAt // ignore: cast_nullable_to_non_nullable @@ -509,25 +572,33 @@ abstract class _$$AssetModelImplCopyWith<$Res> @override @useResult $Res call({ - String id, - String name, - @JsonKey(name: 'asset_code') String assetCode, - @JsonKey(name: 'category_id') String categoryId, - @JsonKey(name: 'category_name') String? categoryName, - String? brand, - String? model, - @JsonKey(name: 'serial_number') String? serialNumber, - @JsonKey(name: 'purchase_date') DateTime? purchaseDate, - @JsonKey(name: 'purchase_cost') double? purchaseCost, - String? vendor, - @JsonKey(name: 'warranty_start') DateTime? warrantyStart, - @JsonKey(name: 'warranty_end') DateTime? warrantyEnd, - String status, - @JsonKey(name: 'branch_id') String? branchId, - @JsonKey(name: 'branch_name') String? branchName, - @JsonKey(name: 'company_id') String? companyId, - @JsonKey(name: 'qr_code_url') String? qrCodeUrl, + @JsonKey(fromJson: _idFromJson) String id, + @JsonKey(name: 'asset_name') String assetName, + @JsonKey(name: 'asset_code') String? assetCode, + @JsonKey( + name: 'asset_category_id', + readValue: _readAssetCategoryId, + fromJson: _intFromJsonNullable, + ) + int? assetCategoryId, + @JsonKey(name: 'asset_category_name', readValue: _readAssetCategoryName) + String? assetCategoryName, + @JsonKey( + name: 'plant_id', + readValue: _readPlantId, + fromJson: _intFromJsonNullable, + ) + int? plantId, + @JsonKey(name: 'plant_name', readValue: _readPlantName) String? plantName, + @JsonKey(name: 'warranty_expiry_date', fromJson: _dateFromJsonNullable) + DateTime? warrantyExpiryDate, + @JsonKey(name: 'purchase_cost', fromJson: _doubleFromJsonNullable) + double? purchaseCost, + String? status, + @JsonKey(name: 'is_active') bool isActive, + @JsonKey(name: 'created_at', fromJson: _dateFromJsonNullable) DateTime? createdAt, + @JsonKey(name: 'updated_at', fromJson: _dateFromJsonNullable) DateTime? updatedAt, }); } @@ -547,23 +618,16 @@ class __$$AssetModelImplCopyWithImpl<$Res> @override $Res call({ Object? id = null, - Object? name = null, - Object? assetCode = null, - Object? categoryId = null, - Object? categoryName = freezed, - Object? brand = freezed, - Object? model = freezed, - Object? serialNumber = freezed, - Object? purchaseDate = freezed, + Object? assetName = null, + Object? assetCode = freezed, + Object? assetCategoryId = freezed, + Object? assetCategoryName = freezed, + Object? plantId = freezed, + Object? plantName = freezed, + Object? warrantyExpiryDate = freezed, Object? purchaseCost = freezed, - Object? vendor = freezed, - Object? warrantyStart = freezed, - Object? warrantyEnd = freezed, - Object? status = null, - Object? branchId = freezed, - Object? branchName = freezed, - Object? companyId = freezed, - Object? qrCodeUrl = freezed, + Object? status = freezed, + Object? isActive = null, Object? createdAt = freezed, Object? updatedAt = freezed, }) { @@ -573,74 +637,46 @@ class __$$AssetModelImplCopyWithImpl<$Res> ? _value.id : id // ignore: cast_nullable_to_non_nullable as String, - name: null == name - ? _value.name - : name // ignore: cast_nullable_to_non_nullable + assetName: null == assetName + ? _value.assetName + : assetName // ignore: cast_nullable_to_non_nullable as String, - assetCode: null == assetCode + assetCode: freezed == assetCode ? _value.assetCode : assetCode // ignore: cast_nullable_to_non_nullable - as String, - categoryId: null == categoryId - ? _value.categoryId - : categoryId // ignore: cast_nullable_to_non_nullable - as String, - categoryName: freezed == categoryName - ? _value.categoryName - : categoryName // ignore: cast_nullable_to_non_nullable as String?, - brand: freezed == brand - ? _value.brand - : brand // ignore: cast_nullable_to_non_nullable + assetCategoryId: freezed == assetCategoryId + ? _value.assetCategoryId + : assetCategoryId // ignore: cast_nullable_to_non_nullable + as int?, + assetCategoryName: freezed == assetCategoryName + ? _value.assetCategoryName + : assetCategoryName // ignore: cast_nullable_to_non_nullable as String?, - model: freezed == model - ? _value.model - : model // ignore: cast_nullable_to_non_nullable + plantId: freezed == plantId + ? _value.plantId + : plantId // ignore: cast_nullable_to_non_nullable + as int?, + plantName: freezed == plantName + ? _value.plantName + : plantName // ignore: cast_nullable_to_non_nullable as String?, - serialNumber: freezed == serialNumber - ? _value.serialNumber - : serialNumber // ignore: cast_nullable_to_non_nullable - as String?, - purchaseDate: freezed == purchaseDate - ? _value.purchaseDate - : purchaseDate // ignore: cast_nullable_to_non_nullable + warrantyExpiryDate: freezed == warrantyExpiryDate + ? _value.warrantyExpiryDate + : warrantyExpiryDate // ignore: cast_nullable_to_non_nullable as DateTime?, purchaseCost: freezed == purchaseCost ? _value.purchaseCost : purchaseCost // ignore: cast_nullable_to_non_nullable as double?, - vendor: freezed == vendor - ? _value.vendor - : vendor // ignore: cast_nullable_to_non_nullable - as String?, - warrantyStart: freezed == warrantyStart - ? _value.warrantyStart - : warrantyStart // ignore: cast_nullable_to_non_nullable - as DateTime?, - warrantyEnd: freezed == warrantyEnd - ? _value.warrantyEnd - : warrantyEnd // ignore: cast_nullable_to_non_nullable - as DateTime?, - status: null == status + status: freezed == status ? _value.status : status // ignore: cast_nullable_to_non_nullable - as String, - branchId: freezed == branchId - ? _value.branchId - : branchId // ignore: cast_nullable_to_non_nullable - as String?, - branchName: freezed == branchName - ? _value.branchName - : branchName // ignore: cast_nullable_to_non_nullable - as String?, - companyId: freezed == companyId - ? _value.companyId - : companyId // ignore: cast_nullable_to_non_nullable - as String?, - qrCodeUrl: freezed == qrCodeUrl - ? _value.qrCodeUrl - : qrCodeUrl // ignore: cast_nullable_to_non_nullable as String?, + isActive: null == isActive + ? _value.isActive + : isActive // ignore: cast_nullable_to_non_nullable + as bool, createdAt: freezed == createdAt ? _value.createdAt : createdAt // ignore: cast_nullable_to_non_nullable @@ -658,25 +694,33 @@ class __$$AssetModelImplCopyWithImpl<$Res> @JsonSerializable() class _$AssetModelImpl implements _AssetModel { const _$AssetModelImpl({ - required this.id, - required this.name, - @JsonKey(name: 'asset_code') required this.assetCode, - @JsonKey(name: 'category_id') required this.categoryId, - @JsonKey(name: 'category_name') this.categoryName, - this.brand, - this.model, - @JsonKey(name: 'serial_number') this.serialNumber, - @JsonKey(name: 'purchase_date') this.purchaseDate, - @JsonKey(name: 'purchase_cost') this.purchaseCost, - this.vendor, - @JsonKey(name: 'warranty_start') this.warrantyStart, - @JsonKey(name: 'warranty_end') this.warrantyEnd, - this.status = 'available', - @JsonKey(name: 'branch_id') this.branchId, - @JsonKey(name: 'branch_name') this.branchName, - @JsonKey(name: 'company_id') this.companyId, - @JsonKey(name: 'qr_code_url') this.qrCodeUrl, + @JsonKey(fromJson: _idFromJson) required this.id, + @JsonKey(name: 'asset_name') required this.assetName, + @JsonKey(name: 'asset_code') this.assetCode, + @JsonKey( + name: 'asset_category_id', + readValue: _readAssetCategoryId, + fromJson: _intFromJsonNullable, + ) + this.assetCategoryId, + @JsonKey(name: 'asset_category_name', readValue: _readAssetCategoryName) + this.assetCategoryName, + @JsonKey( + name: 'plant_id', + readValue: _readPlantId, + fromJson: _intFromJsonNullable, + ) + this.plantId, + @JsonKey(name: 'plant_name', readValue: _readPlantName) this.plantName, + @JsonKey(name: 'warranty_expiry_date', fromJson: _dateFromJsonNullable) + this.warrantyExpiryDate, + @JsonKey(name: 'purchase_cost', fromJson: _doubleFromJsonNullable) + this.purchaseCost, + this.status, + @JsonKey(name: 'is_active') this.isActive = true, + @JsonKey(name: 'created_at', fromJson: _dateFromJsonNullable) this.createdAt, + @JsonKey(name: 'updated_at', fromJson: _dateFromJsonNullable) this.updatedAt, }); @@ -684,62 +728,55 @@ class _$AssetModelImpl implements _AssetModel { _$$AssetModelImplFromJson(json); @override + @JsonKey(fromJson: _idFromJson) final String id; @override - final String name; + @JsonKey(name: 'asset_name') + final String assetName; @override @JsonKey(name: 'asset_code') - final String assetCode; + final String? assetCode; @override - @JsonKey(name: 'category_id') - final String categoryId; + @JsonKey( + name: 'asset_category_id', + readValue: _readAssetCategoryId, + fromJson: _intFromJsonNullable, + ) + final int? assetCategoryId; @override - @JsonKey(name: 'category_name') - final String? categoryName; + @JsonKey(name: 'asset_category_name', readValue: _readAssetCategoryName) + final String? assetCategoryName; @override - final String? brand; + @JsonKey( + name: 'plant_id', + readValue: _readPlantId, + fromJson: _intFromJsonNullable, + ) + final int? plantId; @override - final String? model; + @JsonKey(name: 'plant_name', readValue: _readPlantName) + final String? plantName; @override - @JsonKey(name: 'serial_number') - final String? serialNumber; + @JsonKey(name: 'warranty_expiry_date', fromJson: _dateFromJsonNullable) + final DateTime? warrantyExpiryDate; @override - @JsonKey(name: 'purchase_date') - final DateTime? purchaseDate; - @override - @JsonKey(name: 'purchase_cost') + @JsonKey(name: 'purchase_cost', fromJson: _doubleFromJsonNullable) final double? purchaseCost; @override - final String? vendor; + final String? status; @override - @JsonKey(name: 'warranty_start') - final DateTime? warrantyStart; - @override - @JsonKey(name: 'warranty_end') - final DateTime? warrantyEnd; - @override - @JsonKey() - final String status; - @override - @JsonKey(name: 'branch_id') - final String? branchId; - @override - @JsonKey(name: 'branch_name') - final String? branchName; - @override - @JsonKey(name: 'company_id') - final String? companyId; - @override - @JsonKey(name: 'qr_code_url') - final String? qrCodeUrl; + @JsonKey(name: 'is_active') + final bool isActive; @override + @JsonKey(name: 'created_at', fromJson: _dateFromJsonNullable) final DateTime? createdAt; @override + @JsonKey(name: 'updated_at', fromJson: _dateFromJsonNullable) final DateTime? updatedAt; @override String toString() { - return 'AssetModel(id: $id, name: $name, assetCode: $assetCode, categoryId: $categoryId, categoryName: $categoryName, brand: $brand, model: $model, serialNumber: $serialNumber, purchaseDate: $purchaseDate, purchaseCost: $purchaseCost, vendor: $vendor, warrantyStart: $warrantyStart, warrantyEnd: $warrantyEnd, status: $status, branchId: $branchId, branchName: $branchName, companyId: $companyId, qrCodeUrl: $qrCodeUrl, createdAt: $createdAt, updatedAt: $updatedAt)'; + return 'AssetModel(id: $id, assetName: $assetName, assetCode: $assetCode, assetCategoryId: $assetCategoryId, assetCategoryName: $assetCategoryName, plantId: $plantId, plantName: $plantName, warrantyExpiryDate: $warrantyExpiryDate, purchaseCost: $purchaseCost, status: $status, isActive: $isActive, createdAt: $createdAt, updatedAt: $updatedAt)'; } @override @@ -748,35 +785,24 @@ class _$AssetModelImpl implements _AssetModel { (other.runtimeType == runtimeType && other is _$AssetModelImpl && (identical(other.id, id) || other.id == id) && - (identical(other.name, name) || other.name == name) && + (identical(other.assetName, assetName) || + other.assetName == assetName) && (identical(other.assetCode, assetCode) || other.assetCode == assetCode) && - (identical(other.categoryId, categoryId) || - other.categoryId == categoryId) && - (identical(other.categoryName, categoryName) || - other.categoryName == categoryName) && - (identical(other.brand, brand) || other.brand == brand) && - (identical(other.model, model) || other.model == model) && - (identical(other.serialNumber, serialNumber) || - other.serialNumber == serialNumber) && - (identical(other.purchaseDate, purchaseDate) || - other.purchaseDate == purchaseDate) && + (identical(other.assetCategoryId, assetCategoryId) || + other.assetCategoryId == assetCategoryId) && + (identical(other.assetCategoryName, assetCategoryName) || + other.assetCategoryName == assetCategoryName) && + (identical(other.plantId, plantId) || other.plantId == plantId) && + (identical(other.plantName, plantName) || + other.plantName == plantName) && + (identical(other.warrantyExpiryDate, warrantyExpiryDate) || + other.warrantyExpiryDate == warrantyExpiryDate) && (identical(other.purchaseCost, purchaseCost) || other.purchaseCost == purchaseCost) && - (identical(other.vendor, vendor) || other.vendor == vendor) && - (identical(other.warrantyStart, warrantyStart) || - other.warrantyStart == warrantyStart) && - (identical(other.warrantyEnd, warrantyEnd) || - other.warrantyEnd == warrantyEnd) && (identical(other.status, status) || other.status == status) && - (identical(other.branchId, branchId) || - other.branchId == branchId) && - (identical(other.branchName, branchName) || - other.branchName == branchName) && - (identical(other.companyId, companyId) || - other.companyId == companyId) && - (identical(other.qrCodeUrl, qrCodeUrl) || - other.qrCodeUrl == qrCodeUrl) && + (identical(other.isActive, isActive) || + other.isActive == isActive) && (identical(other.createdAt, createdAt) || other.createdAt == createdAt) && (identical(other.updatedAt, updatedAt) || @@ -785,29 +811,22 @@ class _$AssetModelImpl implements _AssetModel { @JsonKey(includeFromJson: false, includeToJson: false) @override - int get hashCode => Object.hashAll([ + int get hashCode => Object.hash( runtimeType, id, - name, + assetName, assetCode, - categoryId, - categoryName, - brand, - model, - serialNumber, - purchaseDate, + assetCategoryId, + assetCategoryName, + plantId, + plantName, + warrantyExpiryDate, purchaseCost, - vendor, - warrantyStart, - warrantyEnd, status, - branchId, - branchName, - companyId, - qrCodeUrl, + isActive, createdAt, updatedAt, - ]); + ); /// Create a copy of AssetModel /// with the given fields replaced by the non-null parameter values. @@ -825,25 +844,34 @@ class _$AssetModelImpl implements _AssetModel { abstract class _AssetModel implements AssetModel { const factory _AssetModel({ - required final String id, - required final String name, - @JsonKey(name: 'asset_code') required final String assetCode, - @JsonKey(name: 'category_id') required final String categoryId, - @JsonKey(name: 'category_name') final String? categoryName, - final String? brand, - final String? model, - @JsonKey(name: 'serial_number') final String? serialNumber, - @JsonKey(name: 'purchase_date') final DateTime? purchaseDate, - @JsonKey(name: 'purchase_cost') final double? purchaseCost, - final String? vendor, - @JsonKey(name: 'warranty_start') final DateTime? warrantyStart, - @JsonKey(name: 'warranty_end') final DateTime? warrantyEnd, - final String status, - @JsonKey(name: 'branch_id') final String? branchId, - @JsonKey(name: 'branch_name') final String? branchName, - @JsonKey(name: 'company_id') final String? companyId, - @JsonKey(name: 'qr_code_url') final String? qrCodeUrl, + @JsonKey(fromJson: _idFromJson) required final String id, + @JsonKey(name: 'asset_name') required final String assetName, + @JsonKey(name: 'asset_code') final String? assetCode, + @JsonKey( + name: 'asset_category_id', + readValue: _readAssetCategoryId, + fromJson: _intFromJsonNullable, + ) + final int? assetCategoryId, + @JsonKey(name: 'asset_category_name', readValue: _readAssetCategoryName) + final String? assetCategoryName, + @JsonKey( + name: 'plant_id', + readValue: _readPlantId, + fromJson: _intFromJsonNullable, + ) + final int? plantId, + @JsonKey(name: 'plant_name', readValue: _readPlantName) + final String? plantName, + @JsonKey(name: 'warranty_expiry_date', fromJson: _dateFromJsonNullable) + final DateTime? warrantyExpiryDate, + @JsonKey(name: 'purchase_cost', fromJson: _doubleFromJsonNullable) + final double? purchaseCost, + final String? status, + @JsonKey(name: 'is_active') final bool isActive, + @JsonKey(name: 'created_at', fromJson: _dateFromJsonNullable) final DateTime? createdAt, + @JsonKey(name: 'updated_at', fromJson: _dateFromJsonNullable) final DateTime? updatedAt, }) = _$AssetModelImpl; @@ -851,56 +879,50 @@ abstract class _AssetModel implements AssetModel { _$AssetModelImpl.fromJson; @override + @JsonKey(fromJson: _idFromJson) String get id; @override - String get name; + @JsonKey(name: 'asset_name') + String get assetName; @override @JsonKey(name: 'asset_code') - String get assetCode; + String? get assetCode; @override - @JsonKey(name: 'category_id') - String get categoryId; + @JsonKey( + name: 'asset_category_id', + readValue: _readAssetCategoryId, + fromJson: _intFromJsonNullable, + ) + int? get assetCategoryId; @override - @JsonKey(name: 'category_name') - String? get categoryName; + @JsonKey(name: 'asset_category_name', readValue: _readAssetCategoryName) + String? get assetCategoryName; @override - String? get brand; + @JsonKey( + name: 'plant_id', + readValue: _readPlantId, + fromJson: _intFromJsonNullable, + ) + int? get plantId; @override - String? get model; + @JsonKey(name: 'plant_name', readValue: _readPlantName) + String? get plantName; @override - @JsonKey(name: 'serial_number') - String? get serialNumber; + @JsonKey(name: 'warranty_expiry_date', fromJson: _dateFromJsonNullable) + DateTime? get warrantyExpiryDate; @override - @JsonKey(name: 'purchase_date') - DateTime? get purchaseDate; - @override - @JsonKey(name: 'purchase_cost') + @JsonKey(name: 'purchase_cost', fromJson: _doubleFromJsonNullable) double? get purchaseCost; @override - String? get vendor; + String? get status; @override - @JsonKey(name: 'warranty_start') - DateTime? get warrantyStart; - @override - @JsonKey(name: 'warranty_end') - DateTime? get warrantyEnd; - @override - String get status; - @override - @JsonKey(name: 'branch_id') - String? get branchId; - @override - @JsonKey(name: 'branch_name') - String? get branchName; - @override - @JsonKey(name: 'company_id') - String? get companyId; - @override - @JsonKey(name: 'qr_code_url') - String? get qrCodeUrl; + @JsonKey(name: 'is_active') + bool get isActive; @override + @JsonKey(name: 'created_at', fromJson: _dateFromJsonNullable) DateTime? get createdAt; @override + @JsonKey(name: 'updated_at', fromJson: _dateFromJsonNullable) DateTime? get updatedAt; /// Create a copy of AssetModel @@ -911,86 +933,90 @@ abstract class _AssetModel implements AssetModel { throw _privateConstructorUsedError; } -AssetAllocationModel _$AssetAllocationModelFromJson(Map json) { - return _AssetAllocationModel.fromJson(json); +AmcContractModel _$AmcContractModelFromJson(Map json) { + return _AmcContractModel.fromJson(json); } /// @nodoc -mixin _$AssetAllocationModel { +mixin _$AmcContractModel { + @JsonKey(fromJson: _idFromJson) String get id => throw _privateConstructorUsedError; - @JsonKey(name: 'asset_id') - String get assetId => throw _privateConstructorUsedError; - @JsonKey(name: 'asset_name') - String? get assetName => throw _privateConstructorUsedError; - @JsonKey(name: 'employee_id') - String get employeeId => throw _privateConstructorUsedError; - @JsonKey(name: 'employee_name') - String? get employeeName => throw _privateConstructorUsedError; - @JsonKey(name: 'assigned_date') - DateTime get assignedDate => throw _privateConstructorUsedError; - @JsonKey(name: 'returned_date') - DateTime? get returnedDate => throw _privateConstructorUsedError; - String? get remarks => throw _privateConstructorUsedError; + @JsonKey(name: 'asset_id', fromJson: _idFromJson) + String? get assetId => throw _privateConstructorUsedError; + @JsonKey(name: 'vendor_id', fromJson: _intFromJsonNullable) + int? get vendorId => throw _privateConstructorUsedError; + @JsonKey(name: 'vendor_name') + String? get vendorName => throw _privateConstructorUsedError; + @JsonKey(name: 'contract_no') + String? get contractNo => throw _privateConstructorUsedError; + @JsonKey(name: 'contract_type') + String? get contractType => throw _privateConstructorUsedError; + @JsonKey(name: 'start_date', fromJson: _dateFromJson) + DateTime get startDate => throw _privateConstructorUsedError; + @JsonKey(name: 'end_date', fromJson: _dateFromJson) + DateTime get endDate => throw _privateConstructorUsedError; + @JsonKey(name: 'annual_cost', fromJson: _doubleFromJsonNullable) + double? get annualCost => throw _privateConstructorUsedError; String get status => throw _privateConstructorUsedError; DateTime? get createdAt => throw _privateConstructorUsedError; - /// Serializes this AssetAllocationModel to a JSON map. + /// Serializes this AmcContractModel to a JSON map. Map toJson() => throw _privateConstructorUsedError; - /// Create a copy of AssetAllocationModel + /// Create a copy of AmcContractModel /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) - $AssetAllocationModelCopyWith get copyWith => + $AmcContractModelCopyWith get copyWith => throw _privateConstructorUsedError; } /// @nodoc -abstract class $AssetAllocationModelCopyWith<$Res> { - factory $AssetAllocationModelCopyWith( - AssetAllocationModel value, - $Res Function(AssetAllocationModel) then, - ) = _$AssetAllocationModelCopyWithImpl<$Res, AssetAllocationModel>; +abstract class $AmcContractModelCopyWith<$Res> { + factory $AmcContractModelCopyWith( + AmcContractModel value, + $Res Function(AmcContractModel) then, + ) = _$AmcContractModelCopyWithImpl<$Res, AmcContractModel>; @useResult $Res call({ - String id, - @JsonKey(name: 'asset_id') String assetId, - @JsonKey(name: 'asset_name') String? assetName, - @JsonKey(name: 'employee_id') String employeeId, - @JsonKey(name: 'employee_name') String? employeeName, - @JsonKey(name: 'assigned_date') DateTime assignedDate, - @JsonKey(name: 'returned_date') DateTime? returnedDate, - String? remarks, + @JsonKey(fromJson: _idFromJson) String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) String? assetId, + @JsonKey(name: 'vendor_id', fromJson: _intFromJsonNullable) int? vendorId, + @JsonKey(name: 'vendor_name') String? vendorName, + @JsonKey(name: 'contract_no') String? contractNo, + @JsonKey(name: 'contract_type') String? contractType, + @JsonKey(name: 'start_date', fromJson: _dateFromJson) DateTime startDate, + @JsonKey(name: 'end_date', fromJson: _dateFromJson) DateTime endDate, + @JsonKey(name: 'annual_cost', fromJson: _doubleFromJsonNullable) + double? annualCost, String status, DateTime? createdAt, }); } /// @nodoc -class _$AssetAllocationModelCopyWithImpl< - $Res, - $Val extends AssetAllocationModel -> - implements $AssetAllocationModelCopyWith<$Res> { - _$AssetAllocationModelCopyWithImpl(this._value, this._then); +class _$AmcContractModelCopyWithImpl<$Res, $Val extends AmcContractModel> + implements $AmcContractModelCopyWith<$Res> { + _$AmcContractModelCopyWithImpl(this._value, this._then); // ignore: unused_field final $Val _value; // ignore: unused_field final $Res Function($Val) _then; - /// Create a copy of AssetAllocationModel + /// Create a copy of AmcContractModel /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ Object? id = null, - Object? assetId = null, - Object? assetName = freezed, - Object? employeeId = null, - Object? employeeName = freezed, - Object? assignedDate = null, - Object? returnedDate = freezed, - Object? remarks = freezed, + Object? assetId = freezed, + Object? vendorId = freezed, + Object? vendorName = freezed, + Object? contractNo = freezed, + Object? contractType = freezed, + Object? startDate = null, + Object? endDate = null, + Object? annualCost = freezed, Object? status = null, Object? createdAt = freezed, }) { @@ -1000,34 +1026,38 @@ class _$AssetAllocationModelCopyWithImpl< ? _value.id : id // ignore: cast_nullable_to_non_nullable as String, - assetId: null == assetId + assetId: freezed == assetId ? _value.assetId : assetId // ignore: cast_nullable_to_non_nullable - as String, - assetName: freezed == assetName - ? _value.assetName - : assetName // ignore: cast_nullable_to_non_nullable as String?, - employeeId: null == employeeId - ? _value.employeeId - : employeeId // ignore: cast_nullable_to_non_nullable - as String, - employeeName: freezed == employeeName - ? _value.employeeName - : employeeName // ignore: cast_nullable_to_non_nullable + vendorId: freezed == vendorId + ? _value.vendorId + : vendorId // ignore: cast_nullable_to_non_nullable + as int?, + vendorName: freezed == vendorName + ? _value.vendorName + : vendorName // ignore: cast_nullable_to_non_nullable as String?, - assignedDate: null == assignedDate - ? _value.assignedDate - : assignedDate // ignore: cast_nullable_to_non_nullable + contractNo: freezed == contractNo + ? _value.contractNo + : contractNo // ignore: cast_nullable_to_non_nullable + as String?, + contractType: freezed == contractType + ? _value.contractType + : contractType // ignore: cast_nullable_to_non_nullable + as String?, + startDate: null == startDate + ? _value.startDate + : startDate // ignore: cast_nullable_to_non_nullable as DateTime, - returnedDate: freezed == returnedDate - ? _value.returnedDate - : returnedDate // ignore: cast_nullable_to_non_nullable - as DateTime?, - remarks: freezed == remarks - ? _value.remarks - : remarks // ignore: cast_nullable_to_non_nullable - as String?, + endDate: null == endDate + ? _value.endDate + : endDate // ignore: cast_nullable_to_non_nullable + as DateTime, + annualCost: freezed == annualCost + ? _value.annualCost + : annualCost // ignore: cast_nullable_to_non_nullable + as double?, status: null == status ? _value.status : status // ignore: cast_nullable_to_non_nullable @@ -1043,87 +1073,94 @@ class _$AssetAllocationModelCopyWithImpl< } /// @nodoc -abstract class _$$AssetAllocationModelImplCopyWith<$Res> - implements $AssetAllocationModelCopyWith<$Res> { - factory _$$AssetAllocationModelImplCopyWith( - _$AssetAllocationModelImpl value, - $Res Function(_$AssetAllocationModelImpl) then, - ) = __$$AssetAllocationModelImplCopyWithImpl<$Res>; +abstract class _$$AmcContractModelImplCopyWith<$Res> + implements $AmcContractModelCopyWith<$Res> { + factory _$$AmcContractModelImplCopyWith( + _$AmcContractModelImpl value, + $Res Function(_$AmcContractModelImpl) then, + ) = __$$AmcContractModelImplCopyWithImpl<$Res>; @override @useResult $Res call({ - String id, - @JsonKey(name: 'asset_id') String assetId, - @JsonKey(name: 'asset_name') String? assetName, - @JsonKey(name: 'employee_id') String employeeId, - @JsonKey(name: 'employee_name') String? employeeName, - @JsonKey(name: 'assigned_date') DateTime assignedDate, - @JsonKey(name: 'returned_date') DateTime? returnedDate, - String? remarks, + @JsonKey(fromJson: _idFromJson) String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) String? assetId, + @JsonKey(name: 'vendor_id', fromJson: _intFromJsonNullable) int? vendorId, + @JsonKey(name: 'vendor_name') String? vendorName, + @JsonKey(name: 'contract_no') String? contractNo, + @JsonKey(name: 'contract_type') String? contractType, + @JsonKey(name: 'start_date', fromJson: _dateFromJson) DateTime startDate, + @JsonKey(name: 'end_date', fromJson: _dateFromJson) DateTime endDate, + @JsonKey(name: 'annual_cost', fromJson: _doubleFromJsonNullable) + double? annualCost, String status, DateTime? createdAt, }); } /// @nodoc -class __$$AssetAllocationModelImplCopyWithImpl<$Res> - extends _$AssetAllocationModelCopyWithImpl<$Res, _$AssetAllocationModelImpl> - implements _$$AssetAllocationModelImplCopyWith<$Res> { - __$$AssetAllocationModelImplCopyWithImpl( - _$AssetAllocationModelImpl _value, - $Res Function(_$AssetAllocationModelImpl) _then, +class __$$AmcContractModelImplCopyWithImpl<$Res> + extends _$AmcContractModelCopyWithImpl<$Res, _$AmcContractModelImpl> + implements _$$AmcContractModelImplCopyWith<$Res> { + __$$AmcContractModelImplCopyWithImpl( + _$AmcContractModelImpl _value, + $Res Function(_$AmcContractModelImpl) _then, ) : super(_value, _then); - /// Create a copy of AssetAllocationModel + /// Create a copy of AmcContractModel /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ Object? id = null, - Object? assetId = null, - Object? assetName = freezed, - Object? employeeId = null, - Object? employeeName = freezed, - Object? assignedDate = null, - Object? returnedDate = freezed, - Object? remarks = freezed, + Object? assetId = freezed, + Object? vendorId = freezed, + Object? vendorName = freezed, + Object? contractNo = freezed, + Object? contractType = freezed, + Object? startDate = null, + Object? endDate = null, + Object? annualCost = freezed, Object? status = null, Object? createdAt = freezed, }) { return _then( - _$AssetAllocationModelImpl( + _$AmcContractModelImpl( id: null == id ? _value.id : id // ignore: cast_nullable_to_non_nullable as String, - assetId: null == assetId + assetId: freezed == assetId ? _value.assetId : assetId // ignore: cast_nullable_to_non_nullable - as String, - assetName: freezed == assetName - ? _value.assetName - : assetName // ignore: cast_nullable_to_non_nullable as String?, - employeeId: null == employeeId - ? _value.employeeId - : employeeId // ignore: cast_nullable_to_non_nullable - as String, - employeeName: freezed == employeeName - ? _value.employeeName - : employeeName // ignore: cast_nullable_to_non_nullable + vendorId: freezed == vendorId + ? _value.vendorId + : vendorId // ignore: cast_nullable_to_non_nullable + as int?, + vendorName: freezed == vendorName + ? _value.vendorName + : vendorName // ignore: cast_nullable_to_non_nullable as String?, - assignedDate: null == assignedDate - ? _value.assignedDate - : assignedDate // ignore: cast_nullable_to_non_nullable + contractNo: freezed == contractNo + ? _value.contractNo + : contractNo // ignore: cast_nullable_to_non_nullable + as String?, + contractType: freezed == contractType + ? _value.contractType + : contractType // ignore: cast_nullable_to_non_nullable + as String?, + startDate: null == startDate + ? _value.startDate + : startDate // ignore: cast_nullable_to_non_nullable as DateTime, - returnedDate: freezed == returnedDate - ? _value.returnedDate - : returnedDate // ignore: cast_nullable_to_non_nullable - as DateTime?, - remarks: freezed == remarks - ? _value.remarks - : remarks // ignore: cast_nullable_to_non_nullable - as String?, + endDate: null == endDate + ? _value.endDate + : endDate // ignore: cast_nullable_to_non_nullable + as DateTime, + annualCost: freezed == annualCost + ? _value.annualCost + : annualCost // ignore: cast_nullable_to_non_nullable + as double?, status: null == status ? _value.status : status // ignore: cast_nullable_to_non_nullable @@ -1139,45 +1176,53 @@ class __$$AssetAllocationModelImplCopyWithImpl<$Res> /// @nodoc @JsonSerializable() -class _$AssetAllocationModelImpl implements _AssetAllocationModel { - const _$AssetAllocationModelImpl({ - required this.id, - @JsonKey(name: 'asset_id') required this.assetId, - @JsonKey(name: 'asset_name') this.assetName, - @JsonKey(name: 'employee_id') required this.employeeId, - @JsonKey(name: 'employee_name') this.employeeName, - @JsonKey(name: 'assigned_date') required this.assignedDate, - @JsonKey(name: 'returned_date') this.returnedDate, - this.remarks, +class _$AmcContractModelImpl implements _AmcContractModel { + const _$AmcContractModelImpl({ + @JsonKey(fromJson: _idFromJson) required this.id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) this.assetId, + @JsonKey(name: 'vendor_id', fromJson: _intFromJsonNullable) this.vendorId, + @JsonKey(name: 'vendor_name') this.vendorName, + @JsonKey(name: 'contract_no') this.contractNo, + @JsonKey(name: 'contract_type') this.contractType, + @JsonKey(name: 'start_date', fromJson: _dateFromJson) + required this.startDate, + @JsonKey(name: 'end_date', fromJson: _dateFromJson) required this.endDate, + @JsonKey(name: 'annual_cost', fromJson: _doubleFromJsonNullable) + this.annualCost, this.status = 'active', this.createdAt, }); - factory _$AssetAllocationModelImpl.fromJson(Map json) => - _$$AssetAllocationModelImplFromJson(json); + factory _$AmcContractModelImpl.fromJson(Map json) => + _$$AmcContractModelImplFromJson(json); @override + @JsonKey(fromJson: _idFromJson) final String id; @override - @JsonKey(name: 'asset_id') - final String assetId; + @JsonKey(name: 'asset_id', fromJson: _idFromJson) + final String? assetId; @override - @JsonKey(name: 'asset_name') - final String? assetName; + @JsonKey(name: 'vendor_id', fromJson: _intFromJsonNullable) + final int? vendorId; @override - @JsonKey(name: 'employee_id') - final String employeeId; + @JsonKey(name: 'vendor_name') + final String? vendorName; @override - @JsonKey(name: 'employee_name') - final String? employeeName; + @JsonKey(name: 'contract_no') + final String? contractNo; @override - @JsonKey(name: 'assigned_date') - final DateTime assignedDate; + @JsonKey(name: 'contract_type') + final String? contractType; @override - @JsonKey(name: 'returned_date') - final DateTime? returnedDate; + @JsonKey(name: 'start_date', fromJson: _dateFromJson) + final DateTime startDate; @override - final String? remarks; + @JsonKey(name: 'end_date', fromJson: _dateFromJson) + final DateTime endDate; + @override + @JsonKey(name: 'annual_cost', fromJson: _doubleFromJsonNullable) + final double? annualCost; @override @JsonKey() final String status; @@ -1186,27 +1231,29 @@ class _$AssetAllocationModelImpl implements _AssetAllocationModel { @override String toString() { - return 'AssetAllocationModel(id: $id, assetId: $assetId, assetName: $assetName, employeeId: $employeeId, employeeName: $employeeName, assignedDate: $assignedDate, returnedDate: $returnedDate, remarks: $remarks, status: $status, createdAt: $createdAt)'; + return 'AmcContractModel(id: $id, assetId: $assetId, vendorId: $vendorId, vendorName: $vendorName, contractNo: $contractNo, contractType: $contractType, startDate: $startDate, endDate: $endDate, annualCost: $annualCost, status: $status, createdAt: $createdAt)'; } @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _$AssetAllocationModelImpl && + other is _$AmcContractModelImpl && (identical(other.id, id) || other.id == id) && (identical(other.assetId, assetId) || other.assetId == assetId) && - (identical(other.assetName, assetName) || - other.assetName == assetName) && - (identical(other.employeeId, employeeId) || - other.employeeId == employeeId) && - (identical(other.employeeName, employeeName) || - other.employeeName == employeeName) && - (identical(other.assignedDate, assignedDate) || - other.assignedDate == assignedDate) && - (identical(other.returnedDate, returnedDate) || - other.returnedDate == returnedDate) && - (identical(other.remarks, remarks) || other.remarks == remarks) && + (identical(other.vendorId, vendorId) || + other.vendorId == vendorId) && + (identical(other.vendorName, vendorName) || + other.vendorName == vendorName) && + (identical(other.contractNo, contractNo) || + other.contractNo == contractNo) && + (identical(other.contractType, contractType) || + other.contractType == contractType) && + (identical(other.startDate, startDate) || + other.startDate == startDate) && + (identical(other.endDate, endDate) || other.endDate == endDate) && + (identical(other.annualCost, annualCost) || + other.annualCost == annualCost) && (identical(other.status, status) || other.status == status) && (identical(other.createdAt, createdAt) || other.createdAt == createdAt)); @@ -1218,172 +1265,554 @@ class _$AssetAllocationModelImpl implements _AssetAllocationModel { runtimeType, id, assetId, - assetName, - employeeId, - employeeName, - assignedDate, - returnedDate, - remarks, + vendorId, + vendorName, + contractNo, + contractType, + startDate, + endDate, + annualCost, status, createdAt, ); - /// Create a copy of AssetAllocationModel + /// Create a copy of AmcContractModel /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @override @pragma('vm:prefer-inline') - _$$AssetAllocationModelImplCopyWith<_$AssetAllocationModelImpl> - get copyWith => - __$$AssetAllocationModelImplCopyWithImpl<_$AssetAllocationModelImpl>( + _$$AmcContractModelImplCopyWith<_$AmcContractModelImpl> get copyWith => + __$$AmcContractModelImplCopyWithImpl<_$AmcContractModelImpl>( this, _$identity, ); @override Map toJson() { - return _$$AssetAllocationModelImplToJson(this); + return _$$AmcContractModelImplToJson(this); } } -abstract class _AssetAllocationModel implements AssetAllocationModel { - const factory _AssetAllocationModel({ - required final String id, - @JsonKey(name: 'asset_id') required final String assetId, - @JsonKey(name: 'asset_name') final String? assetName, - @JsonKey(name: 'employee_id') required final String employeeId, - @JsonKey(name: 'employee_name') final String? employeeName, - @JsonKey(name: 'assigned_date') required final DateTime assignedDate, - @JsonKey(name: 'returned_date') final DateTime? returnedDate, - final String? remarks, +abstract class _AmcContractModel implements AmcContractModel { + const factory _AmcContractModel({ + @JsonKey(fromJson: _idFromJson) required final String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) final String? assetId, + @JsonKey(name: 'vendor_id', fromJson: _intFromJsonNullable) + final int? vendorId, + @JsonKey(name: 'vendor_name') final String? vendorName, + @JsonKey(name: 'contract_no') final String? contractNo, + @JsonKey(name: 'contract_type') final String? contractType, + @JsonKey(name: 'start_date', fromJson: _dateFromJson) + required final DateTime startDate, + @JsonKey(name: 'end_date', fromJson: _dateFromJson) + required final DateTime endDate, + @JsonKey(name: 'annual_cost', fromJson: _doubleFromJsonNullable) + final double? annualCost, final String status, final DateTime? createdAt, - }) = _$AssetAllocationModelImpl; + }) = _$AmcContractModelImpl; - factory _AssetAllocationModel.fromJson(Map json) = - _$AssetAllocationModelImpl.fromJson; + factory _AmcContractModel.fromJson(Map json) = + _$AmcContractModelImpl.fromJson; @override + @JsonKey(fromJson: _idFromJson) String get id; @override - @JsonKey(name: 'asset_id') - String get assetId; + @JsonKey(name: 'asset_id', fromJson: _idFromJson) + String? get assetId; @override - @JsonKey(name: 'asset_name') - String? get assetName; + @JsonKey(name: 'vendor_id', fromJson: _intFromJsonNullable) + int? get vendorId; @override - @JsonKey(name: 'employee_id') - String get employeeId; + @JsonKey(name: 'vendor_name') + String? get vendorName; @override - @JsonKey(name: 'employee_name') - String? get employeeName; + @JsonKey(name: 'contract_no') + String? get contractNo; @override - @JsonKey(name: 'assigned_date') - DateTime get assignedDate; + @JsonKey(name: 'contract_type') + String? get contractType; @override - @JsonKey(name: 'returned_date') - DateTime? get returnedDate; + @JsonKey(name: 'start_date', fromJson: _dateFromJson) + DateTime get startDate; @override - String? get remarks; + @JsonKey(name: 'end_date', fromJson: _dateFromJson) + DateTime get endDate; + @override + @JsonKey(name: 'annual_cost', fromJson: _doubleFromJsonNullable) + double? get annualCost; @override String get status; @override DateTime? get createdAt; - /// Create a copy of AssetAllocationModel + /// Create a copy of AmcContractModel /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) - _$$AssetAllocationModelImplCopyWith<_$AssetAllocationModelImpl> - get copyWith => throw _privateConstructorUsedError; + _$$AmcContractModelImplCopyWith<_$AmcContractModelImpl> get copyWith => + throw _privateConstructorUsedError; } -AssetMaintenanceModel _$AssetMaintenanceModelFromJson( - Map json, -) { - return _AssetMaintenanceModel.fromJson(json); +ServiceVisitModel _$ServiceVisitModelFromJson(Map json) { + return _ServiceVisitModel.fromJson(json); } /// @nodoc -mixin _$AssetMaintenanceModel { +mixin _$ServiceVisitModel { + @JsonKey(fromJson: _idFromJson) String get id => throw _privateConstructorUsedError; - @JsonKey(name: 'asset_id') - String get assetId => throw _privateConstructorUsedError; - @JsonKey(name: 'asset_name') - String? get assetName => throw _privateConstructorUsedError; - String get description => throw _privateConstructorUsedError; - @JsonKey(name: 'service_vendor') - String? get serviceVendor => throw _privateConstructorUsedError; - double? get cost => throw _privateConstructorUsedError; + @JsonKey(name: 'asset_id', fromJson: _idFromJson) + String? get assetId => throw _privateConstructorUsedError; + @JsonKey(name: 'visit_type') + String get visitType => throw _privateConstructorUsedError; + @JsonKey(name: 'visit_date', fromJson: _dateFromJson) + DateTime get visitDate => throw _privateConstructorUsedError; + @JsonKey(name: 'complaint_no') + String? get complaintNo => throw _privateConstructorUsedError; + @JsonKey(name: 'work_done') + String? get workDone => throw _privateConstructorUsedError; + @JsonKey(name: 'next_service_date', fromJson: _dateFromJsonNullable) + DateTime? get nextServiceDate => throw _privateConstructorUsedError; String get status => throw _privateConstructorUsedError; - @JsonKey(name: 'requested_by') - String? get requestedBy => throw _privateConstructorUsedError; - @JsonKey(name: 'completed_date') - DateTime? get completedDate => throw _privateConstructorUsedError; DateTime? get createdAt => throw _privateConstructorUsedError; - DateTime? get updatedAt => throw _privateConstructorUsedError; - /// Serializes this AssetMaintenanceModel to a JSON map. + /// Serializes this ServiceVisitModel to a JSON map. Map toJson() => throw _privateConstructorUsedError; - /// Create a copy of AssetMaintenanceModel + /// Create a copy of ServiceVisitModel /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) - $AssetMaintenanceModelCopyWith get copyWith => + $ServiceVisitModelCopyWith get copyWith => throw _privateConstructorUsedError; } /// @nodoc -abstract class $AssetMaintenanceModelCopyWith<$Res> { - factory $AssetMaintenanceModelCopyWith( - AssetMaintenanceModel value, - $Res Function(AssetMaintenanceModel) then, - ) = _$AssetMaintenanceModelCopyWithImpl<$Res, AssetMaintenanceModel>; +abstract class $ServiceVisitModelCopyWith<$Res> { + factory $ServiceVisitModelCopyWith( + ServiceVisitModel value, + $Res Function(ServiceVisitModel) then, + ) = _$ServiceVisitModelCopyWithImpl<$Res, ServiceVisitModel>; @useResult $Res call({ - String id, - @JsonKey(name: 'asset_id') String assetId, - @JsonKey(name: 'asset_name') String? assetName, - String description, - @JsonKey(name: 'service_vendor') String? serviceVendor, - double? cost, + @JsonKey(fromJson: _idFromJson) String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) String? assetId, + @JsonKey(name: 'visit_type') String visitType, + @JsonKey(name: 'visit_date', fromJson: _dateFromJson) DateTime visitDate, + @JsonKey(name: 'complaint_no') String? complaintNo, + @JsonKey(name: 'work_done') String? workDone, + @JsonKey(name: 'next_service_date', fromJson: _dateFromJsonNullable) + DateTime? nextServiceDate, String status, - @JsonKey(name: 'requested_by') String? requestedBy, - @JsonKey(name: 'completed_date') DateTime? completedDate, DateTime? createdAt, - DateTime? updatedAt, }); } /// @nodoc -class _$AssetMaintenanceModelCopyWithImpl< +class _$ServiceVisitModelCopyWithImpl<$Res, $Val extends ServiceVisitModel> + implements $ServiceVisitModelCopyWith<$Res> { + _$ServiceVisitModelCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of ServiceVisitModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? assetId = freezed, + Object? visitType = null, + Object? visitDate = null, + Object? complaintNo = freezed, + Object? workDone = freezed, + Object? nextServiceDate = freezed, + Object? status = null, + Object? createdAt = freezed, + }) { + return _then( + _value.copyWith( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + assetId: freezed == assetId + ? _value.assetId + : assetId // ignore: cast_nullable_to_non_nullable + as String?, + visitType: null == visitType + ? _value.visitType + : visitType // ignore: cast_nullable_to_non_nullable + as String, + visitDate: null == visitDate + ? _value.visitDate + : visitDate // ignore: cast_nullable_to_non_nullable + as DateTime, + complaintNo: freezed == complaintNo + ? _value.complaintNo + : complaintNo // ignore: cast_nullable_to_non_nullable + as String?, + workDone: freezed == workDone + ? _value.workDone + : workDone // ignore: cast_nullable_to_non_nullable + as String?, + nextServiceDate: freezed == nextServiceDate + ? _value.nextServiceDate + : nextServiceDate // ignore: cast_nullable_to_non_nullable + as DateTime?, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$ServiceVisitModelImplCopyWith<$Res> + implements $ServiceVisitModelCopyWith<$Res> { + factory _$$ServiceVisitModelImplCopyWith( + _$ServiceVisitModelImpl value, + $Res Function(_$ServiceVisitModelImpl) then, + ) = __$$ServiceVisitModelImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + @JsonKey(fromJson: _idFromJson) String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) String? assetId, + @JsonKey(name: 'visit_type') String visitType, + @JsonKey(name: 'visit_date', fromJson: _dateFromJson) DateTime visitDate, + @JsonKey(name: 'complaint_no') String? complaintNo, + @JsonKey(name: 'work_done') String? workDone, + @JsonKey(name: 'next_service_date', fromJson: _dateFromJsonNullable) + DateTime? nextServiceDate, + String status, + DateTime? createdAt, + }); +} + +/// @nodoc +class __$$ServiceVisitModelImplCopyWithImpl<$Res> + extends _$ServiceVisitModelCopyWithImpl<$Res, _$ServiceVisitModelImpl> + implements _$$ServiceVisitModelImplCopyWith<$Res> { + __$$ServiceVisitModelImplCopyWithImpl( + _$ServiceVisitModelImpl _value, + $Res Function(_$ServiceVisitModelImpl) _then, + ) : super(_value, _then); + + /// Create a copy of ServiceVisitModel + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = null, + Object? assetId = freezed, + Object? visitType = null, + Object? visitDate = null, + Object? complaintNo = freezed, + Object? workDone = freezed, + Object? nextServiceDate = freezed, + Object? status = null, + Object? createdAt = freezed, + }) { + return _then( + _$ServiceVisitModelImpl( + id: null == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String, + assetId: freezed == assetId + ? _value.assetId + : assetId // ignore: cast_nullable_to_non_nullable + as String?, + visitType: null == visitType + ? _value.visitType + : visitType // ignore: cast_nullable_to_non_nullable + as String, + visitDate: null == visitDate + ? _value.visitDate + : visitDate // ignore: cast_nullable_to_non_nullable + as DateTime, + complaintNo: freezed == complaintNo + ? _value.complaintNo + : complaintNo // ignore: cast_nullable_to_non_nullable + as String?, + workDone: freezed == workDone + ? _value.workDone + : workDone // ignore: cast_nullable_to_non_nullable + as String?, + nextServiceDate: freezed == nextServiceDate + ? _value.nextServiceDate + : nextServiceDate // ignore: cast_nullable_to_non_nullable + as DateTime?, + status: null == status + ? _value.status + : status // ignore: cast_nullable_to_non_nullable + as String, + createdAt: freezed == createdAt + ? _value.createdAt + : createdAt // ignore: cast_nullable_to_non_nullable + as DateTime?, + ), + ); + } +} + +/// @nodoc +@JsonSerializable() +class _$ServiceVisitModelImpl implements _ServiceVisitModel { + const _$ServiceVisitModelImpl({ + @JsonKey(fromJson: _idFromJson) required this.id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) this.assetId, + @JsonKey(name: 'visit_type') required this.visitType, + @JsonKey(name: 'visit_date', fromJson: _dateFromJson) + required this.visitDate, + @JsonKey(name: 'complaint_no') this.complaintNo, + @JsonKey(name: 'work_done') this.workDone, + @JsonKey(name: 'next_service_date', fromJson: _dateFromJsonNullable) + this.nextServiceDate, + this.status = 'COMPLETED', + this.createdAt, + }); + + factory _$ServiceVisitModelImpl.fromJson(Map json) => + _$$ServiceVisitModelImplFromJson(json); + + @override + @JsonKey(fromJson: _idFromJson) + final String id; + @override + @JsonKey(name: 'asset_id', fromJson: _idFromJson) + final String? assetId; + @override + @JsonKey(name: 'visit_type') + final String visitType; + @override + @JsonKey(name: 'visit_date', fromJson: _dateFromJson) + final DateTime visitDate; + @override + @JsonKey(name: 'complaint_no') + final String? complaintNo; + @override + @JsonKey(name: 'work_done') + final String? workDone; + @override + @JsonKey(name: 'next_service_date', fromJson: _dateFromJsonNullable) + final DateTime? nextServiceDate; + @override + @JsonKey() + final String status; + @override + final DateTime? createdAt; + + @override + String toString() { + return 'ServiceVisitModel(id: $id, assetId: $assetId, visitType: $visitType, visitDate: $visitDate, complaintNo: $complaintNo, workDone: $workDone, nextServiceDate: $nextServiceDate, status: $status, createdAt: $createdAt)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ServiceVisitModelImpl && + (identical(other.id, id) || other.id == id) && + (identical(other.assetId, assetId) || other.assetId == assetId) && + (identical(other.visitType, visitType) || + other.visitType == visitType) && + (identical(other.visitDate, visitDate) || + other.visitDate == visitDate) && + (identical(other.complaintNo, complaintNo) || + other.complaintNo == complaintNo) && + (identical(other.workDone, workDone) || + other.workDone == workDone) && + (identical(other.nextServiceDate, nextServiceDate) || + other.nextServiceDate == nextServiceDate) && + (identical(other.status, status) || other.status == status) && + (identical(other.createdAt, createdAt) || + other.createdAt == createdAt)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + assetId, + visitType, + visitDate, + complaintNo, + workDone, + nextServiceDate, + status, + createdAt, + ); + + /// Create a copy of ServiceVisitModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$ServiceVisitModelImplCopyWith<_$ServiceVisitModelImpl> get copyWith => + __$$ServiceVisitModelImplCopyWithImpl<_$ServiceVisitModelImpl>( + this, + _$identity, + ); + + @override + Map toJson() { + return _$$ServiceVisitModelImplToJson(this); + } +} + +abstract class _ServiceVisitModel implements ServiceVisitModel { + const factory _ServiceVisitModel({ + @JsonKey(fromJson: _idFromJson) required final String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) final String? assetId, + @JsonKey(name: 'visit_type') required final String visitType, + @JsonKey(name: 'visit_date', fromJson: _dateFromJson) + required final DateTime visitDate, + @JsonKey(name: 'complaint_no') final String? complaintNo, + @JsonKey(name: 'work_done') final String? workDone, + @JsonKey(name: 'next_service_date', fromJson: _dateFromJsonNullable) + final DateTime? nextServiceDate, + final String status, + final DateTime? createdAt, + }) = _$ServiceVisitModelImpl; + + factory _ServiceVisitModel.fromJson(Map json) = + _$ServiceVisitModelImpl.fromJson; + + @override + @JsonKey(fromJson: _idFromJson) + String get id; + @override + @JsonKey(name: 'asset_id', fromJson: _idFromJson) + String? get assetId; + @override + @JsonKey(name: 'visit_type') + String get visitType; + @override + @JsonKey(name: 'visit_date', fromJson: _dateFromJson) + DateTime get visitDate; + @override + @JsonKey(name: 'complaint_no') + String? get complaintNo; + @override + @JsonKey(name: 'work_done') + String? get workDone; + @override + @JsonKey(name: 'next_service_date', fromJson: _dateFromJsonNullable) + DateTime? get nextServiceDate; + @override + String get status; + @override + DateTime? get createdAt; + + /// Create a copy of ServiceVisitModel + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$ServiceVisitModelImplCopyWith<_$ServiceVisitModelImpl> get copyWith => + throw _privateConstructorUsedError; +} + +InsurancePolicyModel _$InsurancePolicyModelFromJson(Map json) { + return _InsurancePolicyModel.fromJson(json); +} + +/// @nodoc +mixin _$InsurancePolicyModel { + @JsonKey(fromJson: _idFromJson) + String get id => throw _privateConstructorUsedError; + @JsonKey(name: 'asset_id', fromJson: _idFromJson) + String? get assetId => throw _privateConstructorUsedError; + @JsonKey(name: 'policy_no') + String get policyNo => throw _privateConstructorUsedError; + @JsonKey(name: 'insurer_name') + String get insurerName => throw _privateConstructorUsedError; + @JsonKey(name: 'policy_type') + String? get policyType => throw _privateConstructorUsedError; + @JsonKey(name: 'sum_insured', fromJson: _doubleFromJsonNullable) + double? get sumInsured => throw _privateConstructorUsedError; + @JsonKey(name: 'policy_start_date', fromJson: _dateFromJson) + DateTime get policyStartDate => throw _privateConstructorUsedError; + @JsonKey(name: 'policy_end_date', fromJson: _dateFromJson) + DateTime get policyEndDate => throw _privateConstructorUsedError; + String get status => throw _privateConstructorUsedError; + DateTime? get createdAt => throw _privateConstructorUsedError; + + /// Serializes this InsurancePolicyModel to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of InsurancePolicyModel + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $InsurancePolicyModelCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $InsurancePolicyModelCopyWith<$Res> { + factory $InsurancePolicyModelCopyWith( + InsurancePolicyModel value, + $Res Function(InsurancePolicyModel) then, + ) = _$InsurancePolicyModelCopyWithImpl<$Res, InsurancePolicyModel>; + @useResult + $Res call({ + @JsonKey(fromJson: _idFromJson) String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) String? assetId, + @JsonKey(name: 'policy_no') String policyNo, + @JsonKey(name: 'insurer_name') String insurerName, + @JsonKey(name: 'policy_type') String? policyType, + @JsonKey(name: 'sum_insured', fromJson: _doubleFromJsonNullable) + double? sumInsured, + @JsonKey(name: 'policy_start_date', fromJson: _dateFromJson) + DateTime policyStartDate, + @JsonKey(name: 'policy_end_date', fromJson: _dateFromJson) + DateTime policyEndDate, + String status, + DateTime? createdAt, + }); +} + +/// @nodoc +class _$InsurancePolicyModelCopyWithImpl< $Res, - $Val extends AssetMaintenanceModel + $Val extends InsurancePolicyModel > - implements $AssetMaintenanceModelCopyWith<$Res> { - _$AssetMaintenanceModelCopyWithImpl(this._value, this._then); + implements $InsurancePolicyModelCopyWith<$Res> { + _$InsurancePolicyModelCopyWithImpl(this._value, this._then); // ignore: unused_field final $Val _value; // ignore: unused_field final $Res Function($Val) _then; - /// Create a copy of AssetMaintenanceModel + /// Create a copy of InsurancePolicyModel /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ Object? id = null, - Object? assetId = null, - Object? assetName = freezed, - Object? description = null, - Object? serviceVendor = freezed, - Object? cost = freezed, + Object? assetId = freezed, + Object? policyNo = null, + Object? insurerName = null, + Object? policyType = freezed, + Object? sumInsured = freezed, + Object? policyStartDate = null, + Object? policyEndDate = null, Object? status = null, - Object? requestedBy = freezed, - Object? completedDate = freezed, Object? createdAt = freezed, - Object? updatedAt = freezed, }) { return _then( _value.copyWith( @@ -1391,46 +1820,42 @@ class _$AssetMaintenanceModelCopyWithImpl< ? _value.id : id // ignore: cast_nullable_to_non_nullable as String, - assetId: null == assetId + assetId: freezed == assetId ? _value.assetId : assetId // ignore: cast_nullable_to_non_nullable - as String, - assetName: freezed == assetName - ? _value.assetName - : assetName // ignore: cast_nullable_to_non_nullable as String?, - description: null == description - ? _value.description - : description // ignore: cast_nullable_to_non_nullable + policyNo: null == policyNo + ? _value.policyNo + : policyNo // ignore: cast_nullable_to_non_nullable as String, - serviceVendor: freezed == serviceVendor - ? _value.serviceVendor - : serviceVendor // ignore: cast_nullable_to_non_nullable + insurerName: null == insurerName + ? _value.insurerName + : insurerName // ignore: cast_nullable_to_non_nullable + as String, + policyType: freezed == policyType + ? _value.policyType + : policyType // ignore: cast_nullable_to_non_nullable as String?, - cost: freezed == cost - ? _value.cost - : cost // ignore: cast_nullable_to_non_nullable + sumInsured: freezed == sumInsured + ? _value.sumInsured + : sumInsured // ignore: cast_nullable_to_non_nullable as double?, + policyStartDate: null == policyStartDate + ? _value.policyStartDate + : policyStartDate // ignore: cast_nullable_to_non_nullable + as DateTime, + policyEndDate: null == policyEndDate + ? _value.policyEndDate + : policyEndDate // ignore: cast_nullable_to_non_nullable + as DateTime, status: null == status ? _value.status : status // ignore: cast_nullable_to_non_nullable as String, - requestedBy: freezed == requestedBy - ? _value.requestedBy - : requestedBy // ignore: cast_nullable_to_non_nullable - as String?, - completedDate: freezed == completedDate - ? _value.completedDate - : completedDate // ignore: cast_nullable_to_non_nullable - as DateTime?, createdAt: freezed == createdAt ? _value.createdAt : createdAt // ignore: cast_nullable_to_non_nullable as DateTime?, - updatedAt: freezed == updatedAt - ? _value.updatedAt - : updatedAt // ignore: cast_nullable_to_non_nullable - as DateTime?, ) as $Val, ); @@ -1438,102 +1863,98 @@ class _$AssetMaintenanceModelCopyWithImpl< } /// @nodoc -abstract class _$$AssetMaintenanceModelImplCopyWith<$Res> - implements $AssetMaintenanceModelCopyWith<$Res> { - factory _$$AssetMaintenanceModelImplCopyWith( - _$AssetMaintenanceModelImpl value, - $Res Function(_$AssetMaintenanceModelImpl) then, - ) = __$$AssetMaintenanceModelImplCopyWithImpl<$Res>; +abstract class _$$InsurancePolicyModelImplCopyWith<$Res> + implements $InsurancePolicyModelCopyWith<$Res> { + factory _$$InsurancePolicyModelImplCopyWith( + _$InsurancePolicyModelImpl value, + $Res Function(_$InsurancePolicyModelImpl) then, + ) = __$$InsurancePolicyModelImplCopyWithImpl<$Res>; @override @useResult $Res call({ - String id, - @JsonKey(name: 'asset_id') String assetId, - @JsonKey(name: 'asset_name') String? assetName, - String description, - @JsonKey(name: 'service_vendor') String? serviceVendor, - double? cost, + @JsonKey(fromJson: _idFromJson) String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) String? assetId, + @JsonKey(name: 'policy_no') String policyNo, + @JsonKey(name: 'insurer_name') String insurerName, + @JsonKey(name: 'policy_type') String? policyType, + @JsonKey(name: 'sum_insured', fromJson: _doubleFromJsonNullable) + double? sumInsured, + @JsonKey(name: 'policy_start_date', fromJson: _dateFromJson) + DateTime policyStartDate, + @JsonKey(name: 'policy_end_date', fromJson: _dateFromJson) + DateTime policyEndDate, String status, - @JsonKey(name: 'requested_by') String? requestedBy, - @JsonKey(name: 'completed_date') DateTime? completedDate, DateTime? createdAt, - DateTime? updatedAt, }); } /// @nodoc -class __$$AssetMaintenanceModelImplCopyWithImpl<$Res> - extends - _$AssetMaintenanceModelCopyWithImpl<$Res, _$AssetMaintenanceModelImpl> - implements _$$AssetMaintenanceModelImplCopyWith<$Res> { - __$$AssetMaintenanceModelImplCopyWithImpl( - _$AssetMaintenanceModelImpl _value, - $Res Function(_$AssetMaintenanceModelImpl) _then, +class __$$InsurancePolicyModelImplCopyWithImpl<$Res> + extends _$InsurancePolicyModelCopyWithImpl<$Res, _$InsurancePolicyModelImpl> + implements _$$InsurancePolicyModelImplCopyWith<$Res> { + __$$InsurancePolicyModelImplCopyWithImpl( + _$InsurancePolicyModelImpl _value, + $Res Function(_$InsurancePolicyModelImpl) _then, ) : super(_value, _then); - /// Create a copy of AssetMaintenanceModel + /// Create a copy of InsurancePolicyModel /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ Object? id = null, - Object? assetId = null, - Object? assetName = freezed, - Object? description = null, - Object? serviceVendor = freezed, - Object? cost = freezed, + Object? assetId = freezed, + Object? policyNo = null, + Object? insurerName = null, + Object? policyType = freezed, + Object? sumInsured = freezed, + Object? policyStartDate = null, + Object? policyEndDate = null, Object? status = null, - Object? requestedBy = freezed, - Object? completedDate = freezed, Object? createdAt = freezed, - Object? updatedAt = freezed, }) { return _then( - _$AssetMaintenanceModelImpl( + _$InsurancePolicyModelImpl( id: null == id ? _value.id : id // ignore: cast_nullable_to_non_nullable as String, - assetId: null == assetId + assetId: freezed == assetId ? _value.assetId : assetId // ignore: cast_nullable_to_non_nullable - as String, - assetName: freezed == assetName - ? _value.assetName - : assetName // ignore: cast_nullable_to_non_nullable as String?, - description: null == description - ? _value.description - : description // ignore: cast_nullable_to_non_nullable + policyNo: null == policyNo + ? _value.policyNo + : policyNo // ignore: cast_nullable_to_non_nullable as String, - serviceVendor: freezed == serviceVendor - ? _value.serviceVendor - : serviceVendor // ignore: cast_nullable_to_non_nullable + insurerName: null == insurerName + ? _value.insurerName + : insurerName // ignore: cast_nullable_to_non_nullable + as String, + policyType: freezed == policyType + ? _value.policyType + : policyType // ignore: cast_nullable_to_non_nullable as String?, - cost: freezed == cost - ? _value.cost - : cost // ignore: cast_nullable_to_non_nullable + sumInsured: freezed == sumInsured + ? _value.sumInsured + : sumInsured // ignore: cast_nullable_to_non_nullable as double?, + policyStartDate: null == policyStartDate + ? _value.policyStartDate + : policyStartDate // ignore: cast_nullable_to_non_nullable + as DateTime, + policyEndDate: null == policyEndDate + ? _value.policyEndDate + : policyEndDate // ignore: cast_nullable_to_non_nullable + as DateTime, status: null == status ? _value.status : status // ignore: cast_nullable_to_non_nullable as String, - requestedBy: freezed == requestedBy - ? _value.requestedBy - : requestedBy // ignore: cast_nullable_to_non_nullable - as String?, - completedDate: freezed == completedDate - ? _value.completedDate - : completedDate // ignore: cast_nullable_to_non_nullable - as DateTime?, createdAt: freezed == createdAt ? _value.createdAt : createdAt // ignore: cast_nullable_to_non_nullable as DateTime?, - updatedAt: freezed == updatedAt - ? _value.updatedAt - : updatedAt // ignore: cast_nullable_to_non_nullable - as DateTime?, ), ); } @@ -1541,81 +1962,83 @@ class __$$AssetMaintenanceModelImplCopyWithImpl<$Res> /// @nodoc @JsonSerializable() -class _$AssetMaintenanceModelImpl implements _AssetMaintenanceModel { - const _$AssetMaintenanceModelImpl({ - required this.id, - @JsonKey(name: 'asset_id') required this.assetId, - @JsonKey(name: 'asset_name') this.assetName, - required this.description, - @JsonKey(name: 'service_vendor') this.serviceVendor, - this.cost, - this.status = 'open', - @JsonKey(name: 'requested_by') this.requestedBy, - @JsonKey(name: 'completed_date') this.completedDate, +class _$InsurancePolicyModelImpl implements _InsurancePolicyModel { + const _$InsurancePolicyModelImpl({ + @JsonKey(fromJson: _idFromJson) required this.id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) this.assetId, + @JsonKey(name: 'policy_no') required this.policyNo, + @JsonKey(name: 'insurer_name') required this.insurerName, + @JsonKey(name: 'policy_type') this.policyType, + @JsonKey(name: 'sum_insured', fromJson: _doubleFromJsonNullable) + this.sumInsured, + @JsonKey(name: 'policy_start_date', fromJson: _dateFromJson) + required this.policyStartDate, + @JsonKey(name: 'policy_end_date', fromJson: _dateFromJson) + required this.policyEndDate, + this.status = 'active', this.createdAt, - this.updatedAt, }); - factory _$AssetMaintenanceModelImpl.fromJson(Map json) => - _$$AssetMaintenanceModelImplFromJson(json); + factory _$InsurancePolicyModelImpl.fromJson(Map json) => + _$$InsurancePolicyModelImplFromJson(json); @override + @JsonKey(fromJson: _idFromJson) final String id; @override - @JsonKey(name: 'asset_id') - final String assetId; + @JsonKey(name: 'asset_id', fromJson: _idFromJson) + final String? assetId; @override - @JsonKey(name: 'asset_name') - final String? assetName; + @JsonKey(name: 'policy_no') + final String policyNo; @override - final String description; + @JsonKey(name: 'insurer_name') + final String insurerName; @override - @JsonKey(name: 'service_vendor') - final String? serviceVendor; + @JsonKey(name: 'policy_type') + final String? policyType; @override - final double? cost; + @JsonKey(name: 'sum_insured', fromJson: _doubleFromJsonNullable) + final double? sumInsured; + @override + @JsonKey(name: 'policy_start_date', fromJson: _dateFromJson) + final DateTime policyStartDate; + @override + @JsonKey(name: 'policy_end_date', fromJson: _dateFromJson) + final DateTime policyEndDate; @override @JsonKey() final String status; @override - @JsonKey(name: 'requested_by') - final String? requestedBy; - @override - @JsonKey(name: 'completed_date') - final DateTime? completedDate; - @override final DateTime? createdAt; - @override - final DateTime? updatedAt; @override String toString() { - return 'AssetMaintenanceModel(id: $id, assetId: $assetId, assetName: $assetName, description: $description, serviceVendor: $serviceVendor, cost: $cost, status: $status, requestedBy: $requestedBy, completedDate: $completedDate, createdAt: $createdAt, updatedAt: $updatedAt)'; + return 'InsurancePolicyModel(id: $id, assetId: $assetId, policyNo: $policyNo, insurerName: $insurerName, policyType: $policyType, sumInsured: $sumInsured, policyStartDate: $policyStartDate, policyEndDate: $policyEndDate, status: $status, createdAt: $createdAt)'; } @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _$AssetMaintenanceModelImpl && + other is _$InsurancePolicyModelImpl && (identical(other.id, id) || other.id == id) && (identical(other.assetId, assetId) || other.assetId == assetId) && - (identical(other.assetName, assetName) || - other.assetName == assetName) && - (identical(other.description, description) || - other.description == description) && - (identical(other.serviceVendor, serviceVendor) || - other.serviceVendor == serviceVendor) && - (identical(other.cost, cost) || other.cost == cost) && + (identical(other.policyNo, policyNo) || + other.policyNo == policyNo) && + (identical(other.insurerName, insurerName) || + other.insurerName == insurerName) && + (identical(other.policyType, policyType) || + other.policyType == policyType) && + (identical(other.sumInsured, sumInsured) || + other.sumInsured == sumInsured) && + (identical(other.policyStartDate, policyStartDate) || + other.policyStartDate == policyStartDate) && + (identical(other.policyEndDate, policyEndDate) || + other.policyEndDate == policyEndDate) && (identical(other.status, status) || other.status == status) && - (identical(other.requestedBy, requestedBy) || - other.requestedBy == requestedBy) && - (identical(other.completedDate, completedDate) || - other.completedDate == completedDate) && (identical(other.createdAt, createdAt) || - other.createdAt == createdAt) && - (identical(other.updatedAt, updatedAt) || - other.updatedAt == updatedAt)); + other.createdAt == createdAt)); } @JsonKey(includeFromJson: false, includeToJson: false) @@ -1624,168 +2047,181 @@ class _$AssetMaintenanceModelImpl implements _AssetMaintenanceModel { runtimeType, id, assetId, - assetName, - description, - serviceVendor, - cost, + policyNo, + insurerName, + policyType, + sumInsured, + policyStartDate, + policyEndDate, status, - requestedBy, - completedDate, createdAt, - updatedAt, ); - /// Create a copy of AssetMaintenanceModel + /// Create a copy of InsurancePolicyModel /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @override @pragma('vm:prefer-inline') - _$$AssetMaintenanceModelImplCopyWith<_$AssetMaintenanceModelImpl> + _$$InsurancePolicyModelImplCopyWith<_$InsurancePolicyModelImpl> get copyWith => - __$$AssetMaintenanceModelImplCopyWithImpl<_$AssetMaintenanceModelImpl>( + __$$InsurancePolicyModelImplCopyWithImpl<_$InsurancePolicyModelImpl>( this, _$identity, ); @override Map toJson() { - return _$$AssetMaintenanceModelImplToJson(this); + return _$$InsurancePolicyModelImplToJson(this); } } -abstract class _AssetMaintenanceModel implements AssetMaintenanceModel { - const factory _AssetMaintenanceModel({ - required final String id, - @JsonKey(name: 'asset_id') required final String assetId, - @JsonKey(name: 'asset_name') final String? assetName, - required final String description, - @JsonKey(name: 'service_vendor') final String? serviceVendor, - final double? cost, +abstract class _InsurancePolicyModel implements InsurancePolicyModel { + const factory _InsurancePolicyModel({ + @JsonKey(fromJson: _idFromJson) required final String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) final String? assetId, + @JsonKey(name: 'policy_no') required final String policyNo, + @JsonKey(name: 'insurer_name') required final String insurerName, + @JsonKey(name: 'policy_type') final String? policyType, + @JsonKey(name: 'sum_insured', fromJson: _doubleFromJsonNullable) + final double? sumInsured, + @JsonKey(name: 'policy_start_date', fromJson: _dateFromJson) + required final DateTime policyStartDate, + @JsonKey(name: 'policy_end_date', fromJson: _dateFromJson) + required final DateTime policyEndDate, final String status, - @JsonKey(name: 'requested_by') final String? requestedBy, - @JsonKey(name: 'completed_date') final DateTime? completedDate, final DateTime? createdAt, - final DateTime? updatedAt, - }) = _$AssetMaintenanceModelImpl; + }) = _$InsurancePolicyModelImpl; - factory _AssetMaintenanceModel.fromJson(Map json) = - _$AssetMaintenanceModelImpl.fromJson; + factory _InsurancePolicyModel.fromJson(Map json) = + _$InsurancePolicyModelImpl.fromJson; @override + @JsonKey(fromJson: _idFromJson) String get id; @override - @JsonKey(name: 'asset_id') - String get assetId; + @JsonKey(name: 'asset_id', fromJson: _idFromJson) + String? get assetId; @override - @JsonKey(name: 'asset_name') - String? get assetName; + @JsonKey(name: 'policy_no') + String get policyNo; @override - String get description; + @JsonKey(name: 'insurer_name') + String get insurerName; @override - @JsonKey(name: 'service_vendor') - String? get serviceVendor; + @JsonKey(name: 'policy_type') + String? get policyType; @override - double? get cost; + @JsonKey(name: 'sum_insured', fromJson: _doubleFromJsonNullable) + double? get sumInsured; + @override + @JsonKey(name: 'policy_start_date', fromJson: _dateFromJson) + DateTime get policyStartDate; + @override + @JsonKey(name: 'policy_end_date', fromJson: _dateFromJson) + DateTime get policyEndDate; @override String get status; @override - @JsonKey(name: 'requested_by') - String? get requestedBy; - @override - @JsonKey(name: 'completed_date') - DateTime? get completedDate; - @override DateTime? get createdAt; - @override - DateTime? get updatedAt; - /// Create a copy of AssetMaintenanceModel + /// Create a copy of InsurancePolicyModel /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) - _$$AssetMaintenanceModelImplCopyWith<_$AssetMaintenanceModelImpl> + _$$InsurancePolicyModelImplCopyWith<_$InsurancePolicyModelImpl> get copyWith => throw _privateConstructorUsedError; } -AssetDisposalModel _$AssetDisposalModelFromJson(Map json) { - return _AssetDisposalModel.fromJson(json); +AssetAlertModel _$AssetAlertModelFromJson(Map json) { + return _AssetAlertModel.fromJson(json); } /// @nodoc -mixin _$AssetDisposalModel { +mixin _$AssetAlertModel { + @JsonKey(fromJson: _idFromJson) String get id => throw _privateConstructorUsedError; - @JsonKey(name: 'asset_id') - String get assetId => throw _privateConstructorUsedError; + @JsonKey(name: 'asset_id', fromJson: _idFromJson) + String? get assetId => throw _privateConstructorUsedError; @JsonKey(name: 'asset_name') String? get assetName => throw _privateConstructorUsedError; - @JsonKey(name: 'disposal_reason') - String get disposalReason => throw _privateConstructorUsedError; - @JsonKey(name: 'disposal_date') - DateTime? get disposalDate => throw _privateConstructorUsedError; - String get status => throw _privateConstructorUsedError; - @JsonKey(name: 'requested_by') - String? get requestedBy => throw _privateConstructorUsedError; - @JsonKey(name: 'approved_by') - String? get approvedBy => throw _privateConstructorUsedError; - DateTime? get createdAt => throw _privateConstructorUsedError; - DateTime? get updatedAt => throw _privateConstructorUsedError; + @JsonKey(name: 'asset_code') + String? get assetCode => throw _privateConstructorUsedError; + String? get type => throw _privateConstructorUsedError; + String? get title => throw _privateConstructorUsedError; + String? get message => throw _privateConstructorUsedError; + @JsonKey(name: 'expiry_date', fromJson: _dateFromJsonNullable) + DateTime? get expiryDate => throw _privateConstructorUsedError; + @JsonKey(name: 'due_date', fromJson: _dateFromJsonNullable) + DateTime? get dueDate => throw _privateConstructorUsedError; + @JsonKey(name: 'days_remaining', fromJson: _intFromJsonNullable) + int? get daysRemaining => throw _privateConstructorUsedError; + String? get status => throw _privateConstructorUsedError; + @JsonKey(name: 'plant_name') + String? get plantName => throw _privateConstructorUsedError; - /// Serializes this AssetDisposalModel to a JSON map. + /// Serializes this AssetAlertModel to a JSON map. Map toJson() => throw _privateConstructorUsedError; - /// Create a copy of AssetDisposalModel + /// Create a copy of AssetAlertModel /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) - $AssetDisposalModelCopyWith get copyWith => + $AssetAlertModelCopyWith get copyWith => throw _privateConstructorUsedError; } /// @nodoc -abstract class $AssetDisposalModelCopyWith<$Res> { - factory $AssetDisposalModelCopyWith( - AssetDisposalModel value, - $Res Function(AssetDisposalModel) then, - ) = _$AssetDisposalModelCopyWithImpl<$Res, AssetDisposalModel>; +abstract class $AssetAlertModelCopyWith<$Res> { + factory $AssetAlertModelCopyWith( + AssetAlertModel value, + $Res Function(AssetAlertModel) then, + ) = _$AssetAlertModelCopyWithImpl<$Res, AssetAlertModel>; @useResult $Res call({ - String id, - @JsonKey(name: 'asset_id') String assetId, + @JsonKey(fromJson: _idFromJson) String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) String? assetId, @JsonKey(name: 'asset_name') String? assetName, - @JsonKey(name: 'disposal_reason') String disposalReason, - @JsonKey(name: 'disposal_date') DateTime? disposalDate, - String status, - @JsonKey(name: 'requested_by') String? requestedBy, - @JsonKey(name: 'approved_by') String? approvedBy, - DateTime? createdAt, - DateTime? updatedAt, + @JsonKey(name: 'asset_code') String? assetCode, + String? type, + String? title, + String? message, + @JsonKey(name: 'expiry_date', fromJson: _dateFromJsonNullable) + DateTime? expiryDate, + @JsonKey(name: 'due_date', fromJson: _dateFromJsonNullable) + DateTime? dueDate, + @JsonKey(name: 'days_remaining', fromJson: _intFromJsonNullable) + int? daysRemaining, + String? status, + @JsonKey(name: 'plant_name') String? plantName, }); } /// @nodoc -class _$AssetDisposalModelCopyWithImpl<$Res, $Val extends AssetDisposalModel> - implements $AssetDisposalModelCopyWith<$Res> { - _$AssetDisposalModelCopyWithImpl(this._value, this._then); +class _$AssetAlertModelCopyWithImpl<$Res, $Val extends AssetAlertModel> + implements $AssetAlertModelCopyWith<$Res> { + _$AssetAlertModelCopyWithImpl(this._value, this._then); // ignore: unused_field final $Val _value; // ignore: unused_field final $Res Function($Val) _then; - /// Create a copy of AssetDisposalModel + /// Create a copy of AssetAlertModel /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ Object? id = null, - Object? assetId = null, + Object? assetId = freezed, Object? assetName = freezed, - Object? disposalReason = null, - Object? disposalDate = freezed, - Object? status = null, - Object? requestedBy = freezed, - Object? approvedBy = freezed, - Object? createdAt = freezed, - Object? updatedAt = freezed, + Object? assetCode = freezed, + Object? type = freezed, + Object? title = freezed, + Object? message = freezed, + Object? expiryDate = freezed, + Object? dueDate = freezed, + Object? daysRemaining = freezed, + Object? status = freezed, + Object? plantName = freezed, }) { return _then( _value.copyWith( @@ -1793,42 +2229,50 @@ class _$AssetDisposalModelCopyWithImpl<$Res, $Val extends AssetDisposalModel> ? _value.id : id // ignore: cast_nullable_to_non_nullable as String, - assetId: null == assetId + assetId: freezed == assetId ? _value.assetId : assetId // ignore: cast_nullable_to_non_nullable - as String, + as String?, assetName: freezed == assetName ? _value.assetName : assetName // ignore: cast_nullable_to_non_nullable as String?, - disposalReason: null == disposalReason - ? _value.disposalReason - : disposalReason // ignore: cast_nullable_to_non_nullable - as String, - disposalDate: freezed == disposalDate - ? _value.disposalDate - : disposalDate // ignore: cast_nullable_to_non_nullable + assetCode: freezed == assetCode + ? _value.assetCode + : assetCode // ignore: cast_nullable_to_non_nullable + as String?, + type: freezed == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as String?, + title: freezed == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable + as String?, + message: freezed == message + ? _value.message + : message // ignore: cast_nullable_to_non_nullable + as String?, + expiryDate: freezed == expiryDate + ? _value.expiryDate + : expiryDate // ignore: cast_nullable_to_non_nullable as DateTime?, - status: null == status + dueDate: freezed == dueDate + ? _value.dueDate + : dueDate // ignore: cast_nullable_to_non_nullable + as DateTime?, + daysRemaining: freezed == daysRemaining + ? _value.daysRemaining + : daysRemaining // ignore: cast_nullable_to_non_nullable + as int?, + status: freezed == status ? _value.status : status // ignore: cast_nullable_to_non_nullable - as String, - requestedBy: freezed == requestedBy - ? _value.requestedBy - : requestedBy // ignore: cast_nullable_to_non_nullable as String?, - approvedBy: freezed == approvedBy - ? _value.approvedBy - : approvedBy // ignore: cast_nullable_to_non_nullable + plantName: freezed == plantName + ? _value.plantName + : plantName // ignore: cast_nullable_to_non_nullable as String?, - createdAt: freezed == createdAt - ? _value.createdAt - : createdAt // ignore: cast_nullable_to_non_nullable - as DateTime?, - updatedAt: freezed == updatedAt - ? _value.updatedAt - : updatedAt // ignore: cast_nullable_to_non_nullable - as DateTime?, ) as $Val, ); @@ -1836,95 +2280,110 @@ class _$AssetDisposalModelCopyWithImpl<$Res, $Val extends AssetDisposalModel> } /// @nodoc -abstract class _$$AssetDisposalModelImplCopyWith<$Res> - implements $AssetDisposalModelCopyWith<$Res> { - factory _$$AssetDisposalModelImplCopyWith( - _$AssetDisposalModelImpl value, - $Res Function(_$AssetDisposalModelImpl) then, - ) = __$$AssetDisposalModelImplCopyWithImpl<$Res>; +abstract class _$$AssetAlertModelImplCopyWith<$Res> + implements $AssetAlertModelCopyWith<$Res> { + factory _$$AssetAlertModelImplCopyWith( + _$AssetAlertModelImpl value, + $Res Function(_$AssetAlertModelImpl) then, + ) = __$$AssetAlertModelImplCopyWithImpl<$Res>; @override @useResult $Res call({ - String id, - @JsonKey(name: 'asset_id') String assetId, + @JsonKey(fromJson: _idFromJson) String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) String? assetId, @JsonKey(name: 'asset_name') String? assetName, - @JsonKey(name: 'disposal_reason') String disposalReason, - @JsonKey(name: 'disposal_date') DateTime? disposalDate, - String status, - @JsonKey(name: 'requested_by') String? requestedBy, - @JsonKey(name: 'approved_by') String? approvedBy, - DateTime? createdAt, - DateTime? updatedAt, + @JsonKey(name: 'asset_code') String? assetCode, + String? type, + String? title, + String? message, + @JsonKey(name: 'expiry_date', fromJson: _dateFromJsonNullable) + DateTime? expiryDate, + @JsonKey(name: 'due_date', fromJson: _dateFromJsonNullable) + DateTime? dueDate, + @JsonKey(name: 'days_remaining', fromJson: _intFromJsonNullable) + int? daysRemaining, + String? status, + @JsonKey(name: 'plant_name') String? plantName, }); } /// @nodoc -class __$$AssetDisposalModelImplCopyWithImpl<$Res> - extends _$AssetDisposalModelCopyWithImpl<$Res, _$AssetDisposalModelImpl> - implements _$$AssetDisposalModelImplCopyWith<$Res> { - __$$AssetDisposalModelImplCopyWithImpl( - _$AssetDisposalModelImpl _value, - $Res Function(_$AssetDisposalModelImpl) _then, +class __$$AssetAlertModelImplCopyWithImpl<$Res> + extends _$AssetAlertModelCopyWithImpl<$Res, _$AssetAlertModelImpl> + implements _$$AssetAlertModelImplCopyWith<$Res> { + __$$AssetAlertModelImplCopyWithImpl( + _$AssetAlertModelImpl _value, + $Res Function(_$AssetAlertModelImpl) _then, ) : super(_value, _then); - /// Create a copy of AssetDisposalModel + /// Create a copy of AssetAlertModel /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override $Res call({ Object? id = null, - Object? assetId = null, + Object? assetId = freezed, Object? assetName = freezed, - Object? disposalReason = null, - Object? disposalDate = freezed, - Object? status = null, - Object? requestedBy = freezed, - Object? approvedBy = freezed, - Object? createdAt = freezed, - Object? updatedAt = freezed, + Object? assetCode = freezed, + Object? type = freezed, + Object? title = freezed, + Object? message = freezed, + Object? expiryDate = freezed, + Object? dueDate = freezed, + Object? daysRemaining = freezed, + Object? status = freezed, + Object? plantName = freezed, }) { return _then( - _$AssetDisposalModelImpl( + _$AssetAlertModelImpl( id: null == id ? _value.id : id // ignore: cast_nullable_to_non_nullable as String, - assetId: null == assetId + assetId: freezed == assetId ? _value.assetId : assetId // ignore: cast_nullable_to_non_nullable - as String, + as String?, assetName: freezed == assetName ? _value.assetName : assetName // ignore: cast_nullable_to_non_nullable as String?, - disposalReason: null == disposalReason - ? _value.disposalReason - : disposalReason // ignore: cast_nullable_to_non_nullable - as String, - disposalDate: freezed == disposalDate - ? _value.disposalDate - : disposalDate // ignore: cast_nullable_to_non_nullable + assetCode: freezed == assetCode + ? _value.assetCode + : assetCode // ignore: cast_nullable_to_non_nullable + as String?, + type: freezed == type + ? _value.type + : type // ignore: cast_nullable_to_non_nullable + as String?, + title: freezed == title + ? _value.title + : title // ignore: cast_nullable_to_non_nullable + as String?, + message: freezed == message + ? _value.message + : message // ignore: cast_nullable_to_non_nullable + as String?, + expiryDate: freezed == expiryDate + ? _value.expiryDate + : expiryDate // ignore: cast_nullable_to_non_nullable as DateTime?, - status: null == status + dueDate: freezed == dueDate + ? _value.dueDate + : dueDate // ignore: cast_nullable_to_non_nullable + as DateTime?, + daysRemaining: freezed == daysRemaining + ? _value.daysRemaining + : daysRemaining // ignore: cast_nullable_to_non_nullable + as int?, + status: freezed == status ? _value.status : status // ignore: cast_nullable_to_non_nullable - as String, - requestedBy: freezed == requestedBy - ? _value.requestedBy - : requestedBy // ignore: cast_nullable_to_non_nullable as String?, - approvedBy: freezed == approvedBy - ? _value.approvedBy - : approvedBy // ignore: cast_nullable_to_non_nullable + plantName: freezed == plantName + ? _value.plantName + : plantName // ignore: cast_nullable_to_non_nullable as String?, - createdAt: freezed == createdAt - ? _value.createdAt - : createdAt // ignore: cast_nullable_to_non_nullable - as DateTime?, - updatedAt: freezed == updatedAt - ? _value.updatedAt - : updatedAt // ignore: cast_nullable_to_non_nullable - as DateTime?, ), ); } @@ -1932,78 +2391,87 @@ class __$$AssetDisposalModelImplCopyWithImpl<$Res> /// @nodoc @JsonSerializable() -class _$AssetDisposalModelImpl implements _AssetDisposalModel { - const _$AssetDisposalModelImpl({ - required this.id, - @JsonKey(name: 'asset_id') required this.assetId, +class _$AssetAlertModelImpl implements _AssetAlertModel { + const _$AssetAlertModelImpl({ + @JsonKey(fromJson: _idFromJson) required this.id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) this.assetId, @JsonKey(name: 'asset_name') this.assetName, - @JsonKey(name: 'disposal_reason') required this.disposalReason, - @JsonKey(name: 'disposal_date') this.disposalDate, - this.status = 'pending', - @JsonKey(name: 'requested_by') this.requestedBy, - @JsonKey(name: 'approved_by') this.approvedBy, - this.createdAt, - this.updatedAt, + @JsonKey(name: 'asset_code') this.assetCode, + this.type, + this.title, + this.message, + @JsonKey(name: 'expiry_date', fromJson: _dateFromJsonNullable) + this.expiryDate, + @JsonKey(name: 'due_date', fromJson: _dateFromJsonNullable) this.dueDate, + @JsonKey(name: 'days_remaining', fromJson: _intFromJsonNullable) + this.daysRemaining, + this.status, + @JsonKey(name: 'plant_name') this.plantName, }); - factory _$AssetDisposalModelImpl.fromJson(Map json) => - _$$AssetDisposalModelImplFromJson(json); + factory _$AssetAlertModelImpl.fromJson(Map json) => + _$$AssetAlertModelImplFromJson(json); @override + @JsonKey(fromJson: _idFromJson) final String id; @override - @JsonKey(name: 'asset_id') - final String assetId; + @JsonKey(name: 'asset_id', fromJson: _idFromJson) + final String? assetId; @override @JsonKey(name: 'asset_name') final String? assetName; @override - @JsonKey(name: 'disposal_reason') - final String disposalReason; + @JsonKey(name: 'asset_code') + final String? assetCode; @override - @JsonKey(name: 'disposal_date') - final DateTime? disposalDate; + final String? type; @override - @JsonKey() - final String status; + final String? title; @override - @JsonKey(name: 'requested_by') - final String? requestedBy; + final String? message; @override - @JsonKey(name: 'approved_by') - final String? approvedBy; + @JsonKey(name: 'expiry_date', fromJson: _dateFromJsonNullable) + final DateTime? expiryDate; @override - final DateTime? createdAt; + @JsonKey(name: 'due_date', fromJson: _dateFromJsonNullable) + final DateTime? dueDate; @override - final DateTime? updatedAt; + @JsonKey(name: 'days_remaining', fromJson: _intFromJsonNullable) + final int? daysRemaining; + @override + final String? status; + @override + @JsonKey(name: 'plant_name') + final String? plantName; @override String toString() { - return 'AssetDisposalModel(id: $id, assetId: $assetId, assetName: $assetName, disposalReason: $disposalReason, disposalDate: $disposalDate, status: $status, requestedBy: $requestedBy, approvedBy: $approvedBy, createdAt: $createdAt, updatedAt: $updatedAt)'; + return 'AssetAlertModel(id: $id, assetId: $assetId, assetName: $assetName, assetCode: $assetCode, type: $type, title: $title, message: $message, expiryDate: $expiryDate, dueDate: $dueDate, daysRemaining: $daysRemaining, status: $status, plantName: $plantName)'; } @override bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && - other is _$AssetDisposalModelImpl && + other is _$AssetAlertModelImpl && (identical(other.id, id) || other.id == id) && (identical(other.assetId, assetId) || other.assetId == assetId) && (identical(other.assetName, assetName) || other.assetName == assetName) && - (identical(other.disposalReason, disposalReason) || - other.disposalReason == disposalReason) && - (identical(other.disposalDate, disposalDate) || - other.disposalDate == disposalDate) && + (identical(other.assetCode, assetCode) || + other.assetCode == assetCode) && + (identical(other.type, type) || other.type == type) && + (identical(other.title, title) || other.title == title) && + (identical(other.message, message) || other.message == message) && + (identical(other.expiryDate, expiryDate) || + other.expiryDate == expiryDate) && + (identical(other.dueDate, dueDate) || other.dueDate == dueDate) && + (identical(other.daysRemaining, daysRemaining) || + other.daysRemaining == daysRemaining) && (identical(other.status, status) || other.status == status) && - (identical(other.requestedBy, requestedBy) || - other.requestedBy == requestedBy) && - (identical(other.approvedBy, approvedBy) || - other.approvedBy == approvedBy) && - (identical(other.createdAt, createdAt) || - other.createdAt == createdAt) && - (identical(other.updatedAt, updatedAt) || - other.updatedAt == updatedAt)); + (identical(other.plantName, plantName) || + other.plantName == plantName)); } @JsonKey(includeFromJson: false, includeToJson: false) @@ -2013,80 +2481,93 @@ class _$AssetDisposalModelImpl implements _AssetDisposalModel { id, assetId, assetName, - disposalReason, - disposalDate, + assetCode, + type, + title, + message, + expiryDate, + dueDate, + daysRemaining, status, - requestedBy, - approvedBy, - createdAt, - updatedAt, + plantName, ); - /// Create a copy of AssetDisposalModel + /// Create a copy of AssetAlertModel /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @override @pragma('vm:prefer-inline') - _$$AssetDisposalModelImplCopyWith<_$AssetDisposalModelImpl> get copyWith => - __$$AssetDisposalModelImplCopyWithImpl<_$AssetDisposalModelImpl>( + _$$AssetAlertModelImplCopyWith<_$AssetAlertModelImpl> get copyWith => + __$$AssetAlertModelImplCopyWithImpl<_$AssetAlertModelImpl>( this, _$identity, ); @override Map toJson() { - return _$$AssetDisposalModelImplToJson(this); + return _$$AssetAlertModelImplToJson(this); } } -abstract class _AssetDisposalModel implements AssetDisposalModel { - const factory _AssetDisposalModel({ - required final String id, - @JsonKey(name: 'asset_id') required final String assetId, +abstract class _AssetAlertModel implements AssetAlertModel { + const factory _AssetAlertModel({ + @JsonKey(fromJson: _idFromJson) required final String id, + @JsonKey(name: 'asset_id', fromJson: _idFromJson) final String? assetId, @JsonKey(name: 'asset_name') final String? assetName, - @JsonKey(name: 'disposal_reason') required final String disposalReason, - @JsonKey(name: 'disposal_date') final DateTime? disposalDate, - final String status, - @JsonKey(name: 'requested_by') final String? requestedBy, - @JsonKey(name: 'approved_by') final String? approvedBy, - final DateTime? createdAt, - final DateTime? updatedAt, - }) = _$AssetDisposalModelImpl; + @JsonKey(name: 'asset_code') final String? assetCode, + final String? type, + final String? title, + final String? message, + @JsonKey(name: 'expiry_date', fromJson: _dateFromJsonNullable) + final DateTime? expiryDate, + @JsonKey(name: 'due_date', fromJson: _dateFromJsonNullable) + final DateTime? dueDate, + @JsonKey(name: 'days_remaining', fromJson: _intFromJsonNullable) + final int? daysRemaining, + final String? status, + @JsonKey(name: 'plant_name') final String? plantName, + }) = _$AssetAlertModelImpl; - factory _AssetDisposalModel.fromJson(Map json) = - _$AssetDisposalModelImpl.fromJson; + factory _AssetAlertModel.fromJson(Map json) = + _$AssetAlertModelImpl.fromJson; @override + @JsonKey(fromJson: _idFromJson) String get id; @override - @JsonKey(name: 'asset_id') - String get assetId; + @JsonKey(name: 'asset_id', fromJson: _idFromJson) + String? get assetId; @override @JsonKey(name: 'asset_name') String? get assetName; @override - @JsonKey(name: 'disposal_reason') - String get disposalReason; + @JsonKey(name: 'asset_code') + String? get assetCode; @override - @JsonKey(name: 'disposal_date') - DateTime? get disposalDate; + String? get type; @override - String get status; + String? get title; @override - @JsonKey(name: 'requested_by') - String? get requestedBy; + String? get message; @override - @JsonKey(name: 'approved_by') - String? get approvedBy; + @JsonKey(name: 'expiry_date', fromJson: _dateFromJsonNullable) + DateTime? get expiryDate; @override - DateTime? get createdAt; + @JsonKey(name: 'due_date', fromJson: _dateFromJsonNullable) + DateTime? get dueDate; @override - DateTime? get updatedAt; + @JsonKey(name: 'days_remaining', fromJson: _intFromJsonNullable) + int? get daysRemaining; + @override + String? get status; + @override + @JsonKey(name: 'plant_name') + String? get plantName; - /// Create a copy of AssetDisposalModel + /// Create a copy of AssetAlertModel /// with the given fields replaced by the non-null parameter values. @override @JsonKey(includeFromJson: false, includeToJson: false) - _$$AssetDisposalModelImplCopyWith<_$AssetDisposalModelImpl> get copyWith => + _$$AssetAlertModelImplCopyWith<_$AssetAlertModelImpl> get copyWith => throw _privateConstructorUsedError; } diff --git a/lib/shared/models/asset_model.g.dart b/lib/shared/models/asset_model.g.dart index 3cb858b..ac55a5f 100644 --- a/lib/shared/models/asset_model.g.dart +++ b/lib/shared/models/asset_model.g.dart @@ -9,189 +9,200 @@ part of 'asset_model.dart'; _$AssetCategoryModelImpl _$$AssetCategoryModelImplFromJson( Map json, ) => _$AssetCategoryModelImpl( - id: json['id'] as String, + id: _idFromJson(json['id']), + code: json['code'] as String, name: json['name'] as String, - slug: json['slug'] as String, - description: json['description'] as String?, - companyId: json['company_id'] as String?, + codePrefix: json['code_prefix'] as String?, + defaultUsefulLifeYears: _intFromJsonNullable( + json['default_useful_life_years'], + ), + defaultDepreciationMethod: json['default_depreciation_method'] as String?, + isActive: json['is_active'] as bool? ?? true, createdAt: json['createdAt'] == null ? null : DateTime.parse(json['createdAt'] as String), + updatedAt: json['updatedAt'] == null + ? null + : DateTime.parse(json['updatedAt'] as String), ); Map _$$AssetCategoryModelImplToJson( _$AssetCategoryModelImpl instance, ) => { 'id': instance.id, + 'code': instance.code, 'name': instance.name, - 'slug': instance.slug, - 'description': instance.description, - 'company_id': instance.companyId, + 'code_prefix': instance.codePrefix, + 'default_useful_life_years': instance.defaultUsefulLifeYears, + 'default_depreciation_method': instance.defaultDepreciationMethod, + 'is_active': instance.isActive, 'createdAt': instance.createdAt?.toIso8601String(), + 'updatedAt': instance.updatedAt?.toIso8601String(), }; _$AssetModelImpl _$$AssetModelImplFromJson(Map json) => _$AssetModelImpl( - id: json['id'] as String, - name: json['name'] as String, - assetCode: json['asset_code'] as String, - categoryId: json['category_id'] as String, - categoryName: json['category_name'] as String?, - brand: json['brand'] as String?, - model: json['model'] as String?, - serialNumber: json['serial_number'] as String?, - purchaseDate: json['purchase_date'] == null - ? null - : DateTime.parse(json['purchase_date'] as String), - purchaseCost: (json['purchase_cost'] as num?)?.toDouble(), - vendor: json['vendor'] as String?, - warrantyStart: json['warranty_start'] == null - ? null - : DateTime.parse(json['warranty_start'] as String), - warrantyEnd: json['warranty_end'] == null - ? null - : DateTime.parse(json['warranty_end'] as String), - status: json['status'] as String? ?? 'available', - branchId: json['branch_id'] as String?, - branchName: json['branch_name'] as String?, - companyId: json['company_id'] as String?, - qrCodeUrl: json['qr_code_url'] as String?, - createdAt: json['createdAt'] == null - ? null - : DateTime.parse(json['createdAt'] as String), - updatedAt: json['updatedAt'] == null - ? null - : DateTime.parse(json['updatedAt'] as String), + id: _idFromJson(json['id']), + assetName: json['asset_name'] as String, + assetCode: json['asset_code'] as String?, + assetCategoryId: _intFromJsonNullable( + _readAssetCategoryId(json, 'asset_category_id'), + ), + assetCategoryName: + _readAssetCategoryName(json, 'asset_category_name') as String?, + plantId: _intFromJsonNullable(_readPlantId(json, 'plant_id')), + plantName: _readPlantName(json, 'plant_name') as String?, + warrantyExpiryDate: _dateFromJsonNullable(json['warranty_expiry_date']), + purchaseCost: _doubleFromJsonNullable(json['purchase_cost']), + status: json['status'] as String?, + isActive: json['is_active'] as bool? ?? true, + createdAt: _dateFromJsonNullable(json['created_at']), + updatedAt: _dateFromJsonNullable(json['updated_at']), ); Map _$$AssetModelImplToJson(_$AssetModelImpl instance) => { 'id': instance.id, - 'name': instance.name, + 'asset_name': instance.assetName, 'asset_code': instance.assetCode, - 'category_id': instance.categoryId, - 'category_name': instance.categoryName, - 'brand': instance.brand, - 'model': instance.model, - 'serial_number': instance.serialNumber, - 'purchase_date': instance.purchaseDate?.toIso8601String(), + 'asset_category_id': instance.assetCategoryId, + 'asset_category_name': instance.assetCategoryName, + 'plant_id': instance.plantId, + 'plant_name': instance.plantName, + 'warranty_expiry_date': instance.warrantyExpiryDate?.toIso8601String(), 'purchase_cost': instance.purchaseCost, - 'vendor': instance.vendor, - 'warranty_start': instance.warrantyStart?.toIso8601String(), - 'warranty_end': instance.warrantyEnd?.toIso8601String(), 'status': instance.status, - 'branch_id': instance.branchId, - 'branch_name': instance.branchName, - 'company_id': instance.companyId, - 'qr_code_url': instance.qrCodeUrl, - 'createdAt': instance.createdAt?.toIso8601String(), - 'updatedAt': instance.updatedAt?.toIso8601String(), + 'is_active': instance.isActive, + 'created_at': instance.createdAt?.toIso8601String(), + 'updated_at': instance.updatedAt?.toIso8601String(), }; -_$AssetAllocationModelImpl _$$AssetAllocationModelImplFromJson( +_$AmcContractModelImpl _$$AmcContractModelImplFromJson( Map json, -) => _$AssetAllocationModelImpl( - id: json['id'] as String, - assetId: json['asset_id'] as String, - assetName: json['asset_name'] as String?, - employeeId: json['employee_id'] as String, - employeeName: json['employee_name'] as String?, - assignedDate: DateTime.parse(json['assigned_date'] as String), - returnedDate: json['returned_date'] == null - ? null - : DateTime.parse(json['returned_date'] as String), - remarks: json['remarks'] as String?, +) => _$AmcContractModelImpl( + id: _idFromJson(json['id']), + assetId: _idFromJson(json['asset_id']), + vendorId: _intFromJsonNullable(json['vendor_id']), + vendorName: json['vendor_name'] as String?, + contractNo: json['contract_no'] as String?, + contractType: json['contract_type'] as String?, + startDate: _dateFromJson(json['start_date']), + endDate: _dateFromJson(json['end_date']), + annualCost: _doubleFromJsonNullable(json['annual_cost']), status: json['status'] as String? ?? 'active', createdAt: json['createdAt'] == null ? null : DateTime.parse(json['createdAt'] as String), ); -Map _$$AssetAllocationModelImplToJson( - _$AssetAllocationModelImpl instance, +Map _$$AmcContractModelImplToJson( + _$AmcContractModelImpl instance, ) => { 'id': instance.id, 'asset_id': instance.assetId, - 'asset_name': instance.assetName, - 'employee_id': instance.employeeId, - 'employee_name': instance.employeeName, - 'assigned_date': instance.assignedDate.toIso8601String(), - 'returned_date': instance.returnedDate?.toIso8601String(), - 'remarks': instance.remarks, + 'vendor_id': instance.vendorId, + 'vendor_name': instance.vendorName, + 'contract_no': instance.contractNo, + 'contract_type': instance.contractType, + 'start_date': instance.startDate.toIso8601String(), + 'end_date': instance.endDate.toIso8601String(), + 'annual_cost': instance.annualCost, 'status': instance.status, 'createdAt': instance.createdAt?.toIso8601String(), }; -_$AssetMaintenanceModelImpl _$$AssetMaintenanceModelImplFromJson( +_$ServiceVisitModelImpl _$$ServiceVisitModelImplFromJson( Map json, -) => _$AssetMaintenanceModelImpl( - id: json['id'] as String, - assetId: json['asset_id'] as String, - assetName: json['asset_name'] as String?, - description: json['description'] as String, - serviceVendor: json['service_vendor'] as String?, - cost: (json['cost'] as num?)?.toDouble(), - status: json['status'] as String? ?? 'open', - requestedBy: json['requested_by'] as String?, - completedDate: json['completed_date'] == null - ? null - : DateTime.parse(json['completed_date'] as String), +) => _$ServiceVisitModelImpl( + id: _idFromJson(json['id']), + assetId: _idFromJson(json['asset_id']), + visitType: json['visit_type'] as String, + visitDate: _dateFromJson(json['visit_date']), + complaintNo: json['complaint_no'] as String?, + workDone: json['work_done'] as String?, + nextServiceDate: _dateFromJsonNullable(json['next_service_date']), + status: json['status'] as String? ?? 'COMPLETED', createdAt: json['createdAt'] == null ? null : DateTime.parse(json['createdAt'] as String), - updatedAt: json['updatedAt'] == null - ? null - : DateTime.parse(json['updatedAt'] as String), ); -Map _$$AssetMaintenanceModelImplToJson( - _$AssetMaintenanceModelImpl instance, +Map _$$ServiceVisitModelImplToJson( + _$ServiceVisitModelImpl instance, ) => { 'id': instance.id, 'asset_id': instance.assetId, - 'asset_name': instance.assetName, - 'description': instance.description, - 'service_vendor': instance.serviceVendor, - 'cost': instance.cost, + 'visit_type': instance.visitType, + 'visit_date': instance.visitDate.toIso8601String(), + 'complaint_no': instance.complaintNo, + 'work_done': instance.workDone, + 'next_service_date': instance.nextServiceDate?.toIso8601String(), 'status': instance.status, - 'requested_by': instance.requestedBy, - 'completed_date': instance.completedDate?.toIso8601String(), 'createdAt': instance.createdAt?.toIso8601String(), - 'updatedAt': instance.updatedAt?.toIso8601String(), }; -_$AssetDisposalModelImpl _$$AssetDisposalModelImplFromJson( +_$InsurancePolicyModelImpl _$$InsurancePolicyModelImplFromJson( Map json, -) => _$AssetDisposalModelImpl( - id: json['id'] as String, - assetId: json['asset_id'] as String, - assetName: json['asset_name'] as String?, - disposalReason: json['disposal_reason'] as String, - disposalDate: json['disposal_date'] == null - ? null - : DateTime.parse(json['disposal_date'] as String), - status: json['status'] as String? ?? 'pending', - requestedBy: json['requested_by'] as String?, - approvedBy: json['approved_by'] as String?, +) => _$InsurancePolicyModelImpl( + id: _idFromJson(json['id']), + assetId: _idFromJson(json['asset_id']), + policyNo: json['policy_no'] as String, + insurerName: json['insurer_name'] as String, + policyType: json['policy_type'] as String?, + sumInsured: _doubleFromJsonNullable(json['sum_insured']), + policyStartDate: _dateFromJson(json['policy_start_date']), + policyEndDate: _dateFromJson(json['policy_end_date']), + status: json['status'] as String? ?? 'active', createdAt: json['createdAt'] == null ? null : DateTime.parse(json['createdAt'] as String), - updatedAt: json['updatedAt'] == null - ? null - : DateTime.parse(json['updatedAt'] as String), ); -Map _$$AssetDisposalModelImplToJson( - _$AssetDisposalModelImpl instance, +Map _$$InsurancePolicyModelImplToJson( + _$InsurancePolicyModelImpl instance, +) => { + 'id': instance.id, + 'asset_id': instance.assetId, + 'policy_no': instance.policyNo, + 'insurer_name': instance.insurerName, + 'policy_type': instance.policyType, + 'sum_insured': instance.sumInsured, + 'policy_start_date': instance.policyStartDate.toIso8601String(), + 'policy_end_date': instance.policyEndDate.toIso8601String(), + 'status': instance.status, + 'createdAt': instance.createdAt?.toIso8601String(), +}; + +_$AssetAlertModelImpl _$$AssetAlertModelImplFromJson( + Map json, +) => _$AssetAlertModelImpl( + id: _idFromJson(json['id']), + assetId: _idFromJson(json['asset_id']), + assetName: json['asset_name'] as String?, + assetCode: json['asset_code'] as String?, + type: json['type'] as String?, + title: json['title'] as String?, + message: json['message'] as String?, + expiryDate: _dateFromJsonNullable(json['expiry_date']), + dueDate: _dateFromJsonNullable(json['due_date']), + daysRemaining: _intFromJsonNullable(json['days_remaining']), + status: json['status'] as String?, + plantName: json['plant_name'] as String?, +); + +Map _$$AssetAlertModelImplToJson( + _$AssetAlertModelImpl instance, ) => { 'id': instance.id, 'asset_id': instance.assetId, 'asset_name': instance.assetName, - 'disposal_reason': instance.disposalReason, - 'disposal_date': instance.disposalDate?.toIso8601String(), + 'asset_code': instance.assetCode, + 'type': instance.type, + 'title': instance.title, + 'message': instance.message, + 'expiry_date': instance.expiryDate?.toIso8601String(), + 'due_date': instance.dueDate?.toIso8601String(), + 'days_remaining': instance.daysRemaining, 'status': instance.status, - 'requested_by': instance.requestedBy, - 'approved_by': instance.approvedBy, - 'createdAt': instance.createdAt?.toIso8601String(), - 'updatedAt': instance.updatedAt?.toIso8601String(), + 'plant_name': instance.plantName, }; diff --git a/lib/shared/routes/app_router.dart b/lib/shared/routes/app_router.dart index a2ab977..029ece4 100644 --- a/lib/shared/routes/app_router.dart +++ b/lib/shared/routes/app_router.dart @@ -5,15 +5,10 @@ import 'package:go_router/go_router.dart'; import '../../core/config/dev_config.dart'; import '../../core/constants/route_constants.dart'; import '../../modules/dashboard/presentation/screens/dashboard_screen.dart'; -import '../../modules/assets/presentation/screens/asset_allocations_screen.dart'; +import '../../modules/assets/presentation/screens/asset_alerts_screen.dart'; import '../../modules/assets/presentation/screens/asset_categories_screen.dart'; import '../../modules/assets/presentation/screens/asset_detail_screen.dart'; -import '../../modules/assets/presentation/screens/asset_disposal_screen.dart'; -import '../../modules/assets/presentation/screens/asset_form_screen.dart'; import '../../modules/assets/presentation/screens/asset_list_screen.dart'; -import '../../modules/assets/presentation/screens/asset_maintenance_screen.dart'; -import '../../modules/assets/presentation/screens/asset_qr_generate_screen.dart'; -import '../../modules/assets/presentation/screens/asset_qr_scan_screen.dart'; import '../../modules/auth/presentation/screens/change_password_screen.dart'; import '../../modules/auth/presentation/screens/forgot_password_screen.dart'; import '../../modules/auth/presentation/screens/login_screen.dart'; @@ -210,44 +205,19 @@ final routerProvider = Provider((ref) { pageBuilder: (context, state) => shellPage(state, const AssetListScreen()), routes: [ - GoRoute( - path: 'add', - builder: (context, state) => const AssetFormScreen(), - ), GoRoute( path: 'categories', builder: (context, state) => const AssetCategoriesScreen(), ), GoRoute( - path: 'allocations', - builder: (context, state) => const AssetAllocationsScreen(), - ), - GoRoute( - path: 'maintenance', - builder: (context, state) => const AssetMaintenanceScreen(), - ), - GoRoute( - path: 'disposal', - builder: (context, state) => const AssetDisposalScreen(), - ), - GoRoute( - path: 'qr-scan', - builder: (context, state) => const AssetQrScanScreen(), - ), - GoRoute( - path: 'qr-generate', - builder: (context, state) => const AssetQrGenerateScreen(), + path: 'alerts', + builder: (context, state) => const AssetAlertsScreen(), ), GoRoute( path: ':id', builder: (context, state) => AssetDetailScreen(assetId: state.pathParameters['id']!), ), - GoRoute( - path: ':id/edit', - builder: (context, state) => - AssetFormScreen(assetId: state.pathParameters['id']), - ), ], ), GoRoute( diff --git a/lib/shared/routes/menu_config.dart b/lib/shared/routes/menu_config.dart index 314adeb..7fd0bd3 100644 --- a/lib/shared/routes/menu_config.dart +++ b/lib/shared/routes/menu_config.dart @@ -67,33 +67,9 @@ const List appMenuItems = [ module: 'asset_categories', ), MenuItem( - label: 'Allocations', - icon: Icons.assignment_ind_outlined, - route: RouteConstants.assetAllocations, - module: 'asset_allocations', - ), - MenuItem( - label: 'Maintenance', - icon: Icons.build_outlined, - route: RouteConstants.assetMaintenance, - module: 'asset_maintenance', - ), - MenuItem( - label: 'Disposal', - icon: Icons.delete_outline, - route: RouteConstants.assetDisposal, - module: 'asset_disposal', - ), - MenuItem( - label: 'QR Scan', - icon: Icons.qr_code_scanner_outlined, - route: RouteConstants.assetQrScan, - module: 'assets', - ), - MenuItem( - label: 'QR Generate', - icon: Icons.qr_code_2_outlined, - route: RouteConstants.assetQrGenerate, + label: 'Alerts', + icon: Icons.notifications_outlined, + route: RouteConstants.assetAlerts, module: 'assets', ), ], diff --git a/lib/shared/widgets/app_sidebar.dart b/lib/shared/widgets/app_sidebar.dart index 3a4dc28..05d71a0 100644 --- a/lib/shared/widgets/app_sidebar.dart +++ b/lib/shared/widgets/app_sidebar.dart @@ -49,26 +49,46 @@ class AppSidebar extends ConsumerStatefulWidget { class _AppSidebarState extends ConsumerState { final Set _expandedMenus = {}; + final Set _manuallyCollapsedMenus = {}; List get _mainMenuItems => widget.menuItems.where((item) => item.route != RouteConstants.settings).toList(); - bool _isSelected(String route) { - if (route == '/') return widget.currentRoute == route; - return widget.currentRoute.startsWith(route); + bool _routeMatches(String route) { + final current = widget.currentRoute; + if (route == '/') return current == route; + if (current == route) return true; + return current.startsWith('$route/'); } - bool _isGroupActive(menu.MenuItem item) => - item.children.any((child) => _isSelected(child.route)); + bool _isSelected(String route) => _routeMatches(route); - bool _isGroupExpanded(menu.MenuItem item) => - _expandedMenus.contains(item.route) || _isGroupActive(item); + bool _isSelectedAmongSiblings(String route, List siblings) { + if (!_routeMatches(route)) return false; + for (final sibling in siblings) { + if (sibling.route == route) continue; + if (sibling.route.length > route.length && _routeMatches(sibling.route)) { + return false; + } + } + return true; + } + + bool _isGroupActive(menu.MenuItem item) => item.children + .any((child) => _isSelectedAmongSiblings(child.route, item.children)); + + bool _isGroupExpanded(menu.MenuItem item) { + if (_manuallyCollapsedMenus.contains(item.route)) return false; + return _expandedMenus.contains(item.route) || _isGroupActive(item); + } void _toggleGroup(menu.MenuItem item) { setState(() { - if (_expandedMenus.contains(item.route)) { + if (_isGroupExpanded(item)) { _expandedMenus.remove(item.route); + _manuallyCollapsedMenus.add(item.route); } else { + _manuallyCollapsedMenus.remove(item.route); _expandedMenus.add(item.route); } }); @@ -81,6 +101,7 @@ class _AppSidebarState extends ConsumerState { for (final item in _mainMenuItems) { if (item.children.isNotEmpty && _isGroupActive(item)) { _expandedMenus.add(item.route); + _manuallyCollapsedMenus.remove(item.route); } } } @@ -148,7 +169,8 @@ class _AppSidebarState extends ConsumerState { return _CollapsedFlyoutNavItem( item: item, selected: _isGroupActive(item), - isChildSelected: _isSelected, + isChildSelected: (route) => + _isSelectedAmongSiblings(route, item.children), onChildTap: widget.onItemTap, ); } @@ -173,7 +195,10 @@ class _AppSidebarState extends ConsumerState { (child) => _SidebarNavItem( icon: child.icon, label: child.label, - selected: _isSelected(child.route), + selected: _isSelectedAmongSiblings( + child.route, + item.children, + ), collapsed: false, indent: _sidebarChildIndent, onTap: () => widget.onItemTap(child.route),