고객사 목록 쿼리스트링 연동 및 공통 JSON 파서 도입
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import 'package:superport_v2/core/common/utils/json_utils.dart';
|
||||
|
||||
import '../../domain/entities/postal_code.dart';
|
||||
|
||||
/// 우편번호 검색 API 응답을 표현하는 DTO.
|
||||
class PostalCodeDto {
|
||||
PostalCodeDto({
|
||||
required this.zipcode,
|
||||
this.sido,
|
||||
this.sigungu,
|
||||
this.roadName,
|
||||
this.buildingMainNo,
|
||||
this.buildingSubNo,
|
||||
});
|
||||
|
||||
final String zipcode;
|
||||
final String? sido;
|
||||
final String? sigungu;
|
||||
final String? roadName;
|
||||
final int? buildingMainNo;
|
||||
final int? buildingSubNo;
|
||||
|
||||
factory PostalCodeDto.fromJson(Map<String, dynamic> json) {
|
||||
return PostalCodeDto(
|
||||
zipcode: json['zipcode'] as String,
|
||||
sido: json['sido'] as String?,
|
||||
sigungu: json['sigungu'] as String?,
|
||||
roadName: json['road_name'] as String?,
|
||||
buildingMainNo: _parseInt(json['building_main_no']),
|
||||
buildingSubNo: _parseInt(json['building_sub_no']),
|
||||
);
|
||||
}
|
||||
|
||||
PostalCode toEntity() {
|
||||
return PostalCode(
|
||||
zipcode: zipcode,
|
||||
sido: sido,
|
||||
sigungu: sigungu,
|
||||
roadName: roadName,
|
||||
buildingMainNo: buildingMainNo,
|
||||
buildingSubNo: buildingSubNo,
|
||||
);
|
||||
}
|
||||
|
||||
static List<PostalCode> fromResponse(dynamic data) {
|
||||
final items = JsonUtils.extractList(data, keys: const ['items', 'data']);
|
||||
if (items.isEmpty) {
|
||||
return const [];
|
||||
}
|
||||
return items
|
||||
.map(PostalCodeDto.fromJson)
|
||||
.map((dto) => dto.toEntity())
|
||||
.toList(growable: false);
|
||||
}
|
||||
}
|
||||
|
||||
int? _parseInt(Object? value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
if (value is int) {
|
||||
return value;
|
||||
}
|
||||
if (value is String) {
|
||||
return int.tryParse(value);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
import 'package:superport_v2/core/network/api_client.dart';
|
||||
|
||||
import '../../domain/entities/postal_code.dart';
|
||||
import '../../domain/repositories/postal_search_repository.dart';
|
||||
import '../dtos/postal_code_dto.dart';
|
||||
|
||||
/// 우편번호 검색 API를 호출하는 원격 저장소 구현체.
|
||||
class PostalSearchRepositoryRemote implements PostalSearchRepository {
|
||||
PostalSearchRepositoryRemote({required ApiClient apiClient})
|
||||
: _api = apiClient;
|
||||
|
||||
final ApiClient _api;
|
||||
|
||||
static const _path = '/zipcodes';
|
||||
|
||||
@override
|
||||
Future<List<PostalCode>> search({
|
||||
required String keyword,
|
||||
int limit = 20,
|
||||
}) async {
|
||||
final trimmed = keyword.trim();
|
||||
if (trimmed.isEmpty) {
|
||||
return const [];
|
||||
}
|
||||
|
||||
final response = await _api.get<dynamic>(
|
||||
_path,
|
||||
query: {
|
||||
'zipcode': trimmed,
|
||||
'road_name': trimmed,
|
||||
'q': trimmed,
|
||||
'page_size': limit,
|
||||
},
|
||||
options: Options(responseType: ResponseType.json),
|
||||
);
|
||||
|
||||
return PostalCodeDto.fromResponse(response.data);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user