/// Generic API Response wrapper /// /// Wraps all API responses in a consistent format with success status, /// data payload, optional message, and optional pagination metadata. class ApiResponse { final bool success; final T data; final String? message; final PaginationMeta? meta; const ApiResponse({ required this.success, required this.data, this.message, this.meta, }); /// Create from JSON with a data parser function factory ApiResponse.fromJson( Map json, T Function(dynamic) dataParser, ) { return ApiResponse( success: json['success'] as bool? ?? false, data: dataParser(json['data']), message: json['message'] as String?, meta: json['meta'] != null ? PaginationMeta.fromJson(json['meta'] as Map) : null, ); } /// Convert to JSON Map toJson(dynamic Function(T) dataSerializer) { return { 'success': success, 'data': dataSerializer(data), if (message != null) 'message': message, if (meta != null) 'meta': meta!.toJson(), }; } } /// Pagination metadata class PaginationMeta { final int page; final int limit; final int total; final int totalPages; final bool hasPreviousPage; final bool hasNextPage; const PaginationMeta({ required this.page, required this.limit, required this.total, required this.totalPages, required this.hasPreviousPage, required this.hasNextPage, }); /// Create from JSON factory PaginationMeta.fromJson(Map json) { return PaginationMeta( page: json['page'] as int, limit: json['limit'] as int, total: json['total'] as int, totalPages: json['totalPages'] as int, hasPreviousPage: json['hasPreviousPage'] as bool, hasNextPage: json['hasNextPage'] as bool, ); } /// Convert to JSON Map toJson() { return { 'page': page, 'limit': limit, 'total': total, 'totalPages': totalPages, 'hasPreviousPage': hasPreviousPage, 'hasNextPage': hasNextPage, }; } /// Create a copy with updated fields PaginationMeta copyWith({ int? page, int? limit, int? total, int? totalPages, bool? hasPreviousPage, bool? hasNextPage, }) { return PaginationMeta( page: page ?? this.page, limit: limit ?? this.limit, total: total ?? this.total, totalPages: totalPages ?? this.totalPages, hasPreviousPage: hasPreviousPage ?? this.hasPreviousPage, hasNextPage: hasNextPage ?? this.hasNextPage, ); } }