import 'dart:developer'; import 'package:data_channel/data_channel.dart'; import 'package:dio/dio.dart'; import 'package:injectable/injectable.dart'; import '../../../common/api/api_client.dart'; import '../../../common/api/api_failure.dart'; import '../../../common/api/interceptors/sensitive_aware_log_interceptor.dart'; import '../../../common/function/app_function.dart'; import '../../../common/url/api_path.dart'; import '../../../domain/wallet/wallet.dart'; import '../wallet_dtos.dart'; import '../wallet_response.dart'; /// Katalog, tukar, dan riwayat voucher (ยง9). @injectable class VoucherRemoteDataProvider { final ApiClient _apiClient; final String _logName = 'VoucherRemoteDataProvider'; VoucherRemoteDataProvider(this._apiClient); Future>> fetchVouchers() => _request( 'fetchVouchers', () => _apiClient.get(ApiPath.vouchers, headers: getAuthorizationHeader()), (response) => ((response.data as Map)['data'] as List? ?? []) .map((e) => VoucherDto.fromJson(Map.from(e as Map))) .toList(), ); Future> redeem({ required String voucherId, required String pin, required String idempotencyKey, }) => _request( 'redeem', () => _apiClient.post( ApiPath.voucherRedeem(voucherId), headers: {...getAuthorizationHeader(), 'Idempotency-Key': idempotencyKey}, data: {'pin': pin}, extra: {kSensitiveRequest: true}, ), (response) => VoucherRedemptionDto.fromJson(walletDataOf(response)), ); Future> fetchRedemptions({ required int page, required int limit, }) => _request( 'fetchRedemptions', () => _apiClient.get( ApiPath.voucherRedemptions, headers: getAuthorizationHeader(), params: {'page': page, 'limit': limit}, ), _parseRedemptionPage, ); /// `data` bisa berupa list langsung dengan `pagination` di envelope, atau /// objek `{ data, pagination }`. VoucherRedemptionPageDto _parseRedemptionPage(Response response) { final body = response.data as Map; final payload = body['data']; final rawItems = payload is Map ? payload['data'] : payload; final rawPagination = payload is Map ? payload['pagination'] : body['pagination']; return VoucherRedemptionPageDto( items: (rawItems as List? ?? []) .map( (e) => VoucherRedemptionDto.fromJson( Map.from(e as Map), ), ) .toList(), pagination: rawPagination is Map ? WalletPaginationDto.fromJson( Map.from(rawPagination), ) : const WalletPaginationDto(), ); } Future> _request( String name, Future Function() call, T Function(Response response) parse, ) async { try { final response = await call(); final failure = parseWalletFailure(response); if (failure != null) return DC.error(failure); return DC.data(parse(response)); } on ApiFailure catch (e, s) { log(name, name: _logName, error: e, stackTrace: s); return DC.error(WalletFailure.serverError(e)); } } }