Last active
July 29, 2023 14:34
-
-
Save Aldikitta/b86cc0079b2a985e4ff92475df10e00a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Dto Class | |
sealed interface MockDraftDetailResponseDto { | |
data class MockDraftDetail( | |
@SerializedName("code") | |
val code: Int, | |
@SerializedName("data") | |
val data: Data, | |
@SerializedName("errors") | |
val errors: Errors? = null, | |
@SerializedName("message") | |
val message: String, | |
@SerializedName("request_id") | |
val requestId: String, | |
@SerializedName("timestamp") | |
val timestamp: String | |
) | |
data class Data( | |
@SerializedName("assets") | |
val assets: List<Asset>, | |
@SerializedName("branch_id") | |
val branchId: String, | |
@SerializedName("created_at") | |
val createdAt: String, | |
@SerializedName("cro_id") | |
val croId: String, | |
@SerializedName("cro_name") | |
val croName: String, | |
@SerializedName("customer_id") | |
val customerId: String, | |
@SerializedName("customer_limit_category") | |
val customerLimitCategory: String, | |
@SerializedName("customer_mobile_phone") | |
val customerMobilePhone: String, | |
@SerializedName("customer_name") | |
val customerName: String, | |
@SerializedName("group_category_code") | |
val groupCategoryCode: String, | |
@SerializedName("group_category_id") | |
val groupCategoryId: Int, | |
@SerializedName("group_category_name") | |
val groupCategoryName: String, | |
@SerializedName("is_editable") | |
val isEditable: Boolean, | |
@SerializedName("is_near_customer") | |
val isNearCustomer: Boolean, | |
@SerializedName("is_new_wg") | |
val isNewWg: Boolean, | |
@SerializedName("latitude") | |
val latitude: String, | |
@SerializedName("longitude") | |
val longitude: String, | |
@SerializedName("prospect_id") | |
val prospectId: String, | |
@SerializedName("source_application") | |
val sourceApplication: String, | |
@SerializedName("supplier_address") | |
val supplierAddress: String, | |
@SerializedName("supplier_id") | |
val supplierId: String, | |
@SerializedName("supplier_key") | |
val supplierKey: String, | |
@SerializedName("supplier_name") | |
val supplierName: String, | |
@SerializedName("total_otr") | |
val totalOtr: Int, | |
@SerializedName("updated_at") | |
val updatedAt: String, | |
@SerializedName("user_id") | |
val userId: String | |
) | |
class Errors | |
data class Asset( | |
@SerializedName("category_id") | |
val categoryId: String, | |
@SerializedName("category_name") | |
val categoryName: String, | |
@SerializedName("code") | |
val code: String, | |
@SerializedName("description") | |
val description: String, | |
@SerializedName("otr") | |
val otr: Int, | |
@SerializedName("qty") | |
val qty: Int | |
) | |
} | |
// Model Class | |
sealed interface MockDraftDetailResponse { | |
data class MockDraftDetail( | |
val code: Int, | |
val data: Data, | |
val errors: Errors? = null, | |
val message: String, | |
val requestId: String, | |
val timestamp: String | |
) | |
data class Data( | |
val assets: List<Asset>, | |
val branchId: String, | |
val createdAt: String, | |
val croId: String, | |
val croName: String, | |
val customerId: String, | |
val customerLimitCategory: String, | |
val customerMobilePhone: String, | |
val customerName: String, | |
val groupCategoryCode: String, | |
val groupCategoryId: Int, | |
val groupCategoryName: String, | |
val isEditable: Boolean, | |
val isNearCustomer: Boolean, | |
val isNewWg: Boolean, | |
val latitude: String, | |
val longitude: String, | |
val prospectId: String, | |
val sourceApplication: String, | |
val supplierAddress: String, | |
val supplierId: String, | |
val supplierKey: String, | |
val supplierName: String, | |
val totalOtr: Int, | |
val updatedAt: String, | |
val userId: String | |
) | |
class Errors | |
data class Asset( | |
val categoryId: String, | |
val categoryName: String, | |
val code: String, | |
val description: String, | |
val otr: Int, | |
val qty: Int | |
) | |
} | |
// Model Mapper | |
fun MockDraftDetailResponseDto.MockDraftDetail.toMockDraftDetailResponseModel(): MockDraftDetailResponse.MockDraftDetail { | |
return MockDraftDetailResponse.MockDraftDetail( | |
code = this.code, | |
data = this.data.toMockDraftDetailDataModel(), | |
message = this.message, | |
requestId = this.requestId, | |
timestamp = this.timestamp, | |
) | |
} | |
fun MockDraftDetailResponseDto.Data.toMockDraftDetailDataModel(): MockDraftDetailResponse.Data { | |
return MockDraftDetailResponse.Data( | |
assets = this.assets.map { | |
it.toMockDraftDetailAssetModel() | |
}, | |
branchId = this.branchId, | |
createdAt = this.createdAt, | |
croId = this.croId, | |
croName = this.croName, | |
customerId = this.customerId, | |
customerLimitCategory = this.customerLimitCategory, | |
customerMobilePhone = this.customerMobilePhone, | |
customerName = this.customerName, | |
groupCategoryCode = this.groupCategoryCode, | |
groupCategoryId = this.groupCategoryId, | |
groupCategoryName = this.groupCategoryName, | |
isEditable = this.isEditable, | |
isNearCustomer = this.isNearCustomer, | |
isNewWg = this.isNewWg, | |
latitude = this.latitude, | |
longitude = this.longitude, | |
prospectId = this.prospectId, | |
sourceApplication = this.sourceApplication, | |
supplierAddress = this.supplierAddress, | |
supplierId = this.supplierId, | |
supplierKey = this.supplierKey, | |
supplierName = this.supplierName, | |
totalOtr = this.totalOtr, | |
updatedAt = this.updatedAt, | |
userId = this.userId | |
) | |
} | |
fun MockDraftDetailResponseDto.Asset.toMockDraftDetailAssetModel(): MockDraftDetailResponse.Asset { | |
return MockDraftDetailResponse.Asset( | |
categoryId = this.categoryId, | |
categoryName = this.categoryName, | |
code = this.code, | |
description = this.description, | |
otr = this.otr, | |
qty = this.qty | |
) | |
} | |
// API Service | |
@GET("submissions/wg/draft-orders/NWG-1") | |
suspend fun getDraftDetailMock(): MockDraftDetailResponseDto.MockDraftDetail | |
// Data Source | |
fun getDetailDraftMock(): Flow<MockDraftDetailResponseDto.MockDraftDetail> = flow { | |
delay(5_000) | |
while (true) { | |
val draftDetail = mockServices.getDraftDetailMock() | |
emit(draftDetail) | |
delay(5 * 60 * 1000) | |
} | |
} | |
// Rpository | |
override fun getDetailDraftMock(): Flow<SallyResponseResource<MockDraftDetailResponse.MockDraftDetail>> { | |
return remoteDataSource.getDetailDraftMock().map { | |
it.toMockDraftDetailResponseModel() | |
}.asSallyResponseResourceFlow() | |
} | |
// Usecase | |
override fun getDraftDetailMock(): Flow<SallyResponseResource<MockDraftDetailResponse.MockDraftDetail>> { | |
return iWGRepository.getDetailDraftMock() | |
} | |
// PAGING | |
// api service | |
@GET("submissions/wg/draft-orders") | |
suspend fun getDraftListMock( | |
@QueryMap body: MutableMap<String, Any>, | |
): MockDraftListResponseDto.MockDraftList | |
// data source | |
suspend fun getListDraftMock(body: MockDraftListRequestDto.MockDraftList): MockDraftListResponseDto.MockDraftList { | |
return mockServices.getDraftListMock(body = convertDataClassToMap(body)) | |
} | |
// Paging source | |
class DraftListPagingSource( | |
private val wgRemoteDataSource: WGRemoteDataSource, | |
private val mockDraftListRequestDto: MockDraftListRequestDto.MockDraftList | |
) : PagingSource<Int, MockDraftListResponseDto.Data>() { | |
override val keyReuseSupported: Boolean = true | |
override fun getRefreshKey(state: PagingState<Int, MockDraftListResponseDto.Data>): Int? { | |
return state.anchorPosition?.let { anchorPosition -> | |
state.closestPageToPosition(anchorPosition)?.prevKey?.plus(1) | |
?: state.closestPageToPosition(anchorPosition)?.nextKey?.minus(1) | |
} | |
} | |
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MockDraftListResponseDto.Data> { | |
return try { | |
val nextPage = params.key ?: 1 | |
val bodyWithPage = mockDraftListRequestDto.copy(page = nextPage, pageSize = 20) | |
val getListResponse = wgRemoteDataSource.getListDraftMock( | |
body = bodyWithPage | |
) | |
val currentPage = getListResponse.paginator.currentPage | |
val totalPages = getListResponse.paginator.totalPages | |
val prevKey = getListResponse.paginator.backPage | |
val nextKey = getListResponse.paginator.nextPage | |
LoadResult.Page( | |
data = getListResponse.data, | |
prevKey = prevKey, | |
nextKey = nextKey | |
// prevKey = if (nextPage == 1) null else nextPage - 1, | |
// nextKey = if (currentPage + 1 > totalPages) null else currentPage + 1 | |
) | |
// ALTERNATIVE 1 | |
val nextPage = params.key ?: 1 | |
val bodyWithPage = draftListRequestRequestDto.copy(page = nextPage, pageSize = 20) | |
val getListResponse = wgRemoteDataSource.getListDraft( | |
token = token, | |
body = bodyWithPage | |
) | |
LoadResult.Page( | |
data = getListResponse.data, | |
prevKey = if (nextPage == 1) null else nextPage - 1, | |
nextKey = if (getListResponse.data.isEmpty()) null else nextPage + 1 | |
) | |
// ALTERNATIVE 2 | |
val nextPage = params.key ?: 1 | |
val bodyWithPage = pengajuanListRequestDto.copy(page = nextPage, limit = 20) | |
val getListResponse = wgRemoteDataSource.getListPengajuan( | |
token = token, | |
body = bodyWithPage | |
) | |
LoadResult.Page( | |
data = getListResponse.data, | |
prevKey = if (nextPage == 1) null else nextPage - 1, | |
nextKey = if (getListResponse.data.isEmpty()) null else nextPage + 1 | |
) | |
} catch (e: IOException) { | |
LoadResult.Error(e) | |
} catch (e: Exception) { | |
LoadResult.Error(e) | |
} catch (e: HttpException) { | |
LoadResult.Error(e) | |
} | |
} | |
} | |
// repository | |
override fun getListDaftMock(body: MockDraftListRequest.MockDraftList): Flow<PagingData<MockDraftListResponse.Data>> { | |
val requestModel = body.toMockDraftListRequestDtoModel() | |
return Pager( | |
config = PagingConfig( | |
pageSize = 20, | |
prefetchDistance = 10 | |
), | |
pagingSourceFactory = { | |
DraftListPagingSource( | |
wgRemoteDataSource = remoteDataSource, | |
mockDraftListRequestDto = requestModel | |
) | |
} | |
).flow.map { pagingData -> | |
pagingData.map { data -> | |
data.toMockDraftListResponseDataModel() | |
} | |
} | |
} | |
// use case | |
override fun getListDaftMock(body: MockDraftListRequest.MockDraftList): Flow<PagingData<MockDraftListResponse.Data>> { | |
return iWGRepository.getListDaftMock(body = body) | |
} | |
// viewmodel | |
sealed interface DraftListUiEvent { | |
data class DateFilterOnClick(val startDate: String, val endDate: String) : DraftListUiEvent | |
data class CategoryLimitOnClick(val category: String) : DraftListUiEvent | |
data class SearchOnClick(val search: String) : DraftListUiEvent | |
data class StatusOnChange(val status: String) : DraftListUiEvent | |
} | |
data class DraftListUiState( | |
val draftList: Flow<PagingData<MockDraftListResponse.Data>>, | |
) { | |
companion object { | |
val default: DraftListUiState = DraftListUiState( | |
draftList = emptyFlow(), | |
) | |
} | |
} | |
data class FilterDraftListUiState( | |
val search: String, | |
val startDate: String, | |
val endDate: String, | |
val customerLimitCategory: String, | |
val status: String | |
) { | |
companion object { | |
val default: FilterDraftListUiState = FilterDraftListUiState( | |
search = "", | |
startDate = "", | |
endDate = "", | |
customerLimitCategory = "", | |
status = "" | |
) | |
} | |
} | |
@OptIn(ExperimentalCoroutinesApi::class) | |
val getDraftList: StateFlow<DraftListUiState> = | |
filterDraftListState.flatMapLatest { filterDraftListState -> | |
flow { | |
val draftList = useCase.getListDaftMock( | |
body = MockDraftListRequest.MockDraftList( | |
search = filterDraftListState.search, | |
startDate = filterDraftListState.startDate, | |
endDate = filterDraftListState.endDate, | |
customerLimitCategory = filterDraftListState.customerLimitCategory | |
) | |
).cachedIn(viewModelScope) | |
emit(DraftListUiState(draftList = draftList)) | |
} | |
}.stateIn( | |
viewModelScope, | |
SharingStarted.WhileSubscribed(5_000), | |
DraftListUiState.default | |
) | |
fun setFilterDraftListState( | |
search: String? = null, | |
startDate: String? = null, | |
endDate: String? = null, | |
customerLimitCategory: String? = null | |
) { | |
val currentFilter = filterDraftListState.value | |
val updatedFilter = currentFilter.copy( | |
search = search ?: currentFilter.search, | |
startDate = startDate ?: currentFilter.startDate, | |
endDate = endDate ?: currentFilter.endDate, | |
customerLimitCategory = customerLimitCategory ?: currentFilter.customerLimitCategory | |
) | |
filterDraftListState.value = updatedFilter | |
} | |
fun onEvent(draftListUiEvent: DraftListUiEvent) { | |
when (draftListUiEvent) { | |
is DraftListUiEvent.DateFilterOnClick -> { | |
setFilterDraftListState( | |
startDate = draftListUiEvent.startDate, | |
endDate = draftListUiEvent.endDate | |
) | |
} | |
is DraftListUiEvent.CategoryLimitOnClick -> { | |
setFilterDraftListState( | |
customerLimitCategory = draftListUiEvent.category | |
) | |
} | |
is DraftListUiEvent.SearchOnClick -> { | |
setFilterDraftListState( | |
search = draftListUiEvent.search | |
) | |
} | |
is DraftListUiEvent.StatusOnChange -> { | |
setFilterDraftListState( | |
status = draftListUiEvent.status | |
) | |
} | |
} | |
} | |
fun resetFilterDraftListState() { | |
filterDraftListState.value = FilterDraftListUiState.default | |
} | |
// SUSPEND FUNCTION | |
// MAPPER CLASS | |
// REQUEST | |
fun CreateProspectAgentRequestModel.CreateProspectAgentRequest.toCreateProspectAgentRequestDto(): CreateProspectAgentRequestDto.CreateProspectAgentRequest { | |
return CreateProspectAgentRequestDto.CreateProspectAgentRequest( | |
agentName = this.agentName, | |
agentProfession = this.agentProfession, | |
agentProfessionCode = this.agentProfessionCode, | |
branchCode = this.branchCode, | |
fotoAgentUrl = this.fotoAgentUrl, | |
latitude = this.latitude, | |
longitude = this.longitude, | |
moId = this.moId, | |
moName = this.moName, | |
mobilePhone = this.mobilePhone, | |
) | |
} | |
// RESPONSE | |
fun CreateProspectAgentResponseDto.CreateProspectAgentResponse.toCreateProspectAgentResponseModel(): CreateProspectAgentResponseModel.CreateProspectAgentResponse { | |
return CreateProspectAgentResponseModel.CreateProspectAgentResponse( | |
status = this.status, | |
message = this.message, | |
validation = this.validation | |
) | |
} | |
// API SERVICE | |
@POST("agent-prospect") | |
suspend fun createAgentProspect( | |
@Header("Authorization") token: String, | |
@Body body: CreateProspectAgentRequestDto.CreateProspectAgentRequest, | |
): CreateProspectAgentResponseDto.CreateProspectAgentResponse | |
// DATA SOURCE | |
suspend fun createAgentProspect( | |
token: String, | |
body: CreateProspectAgentRequestDto.CreateProspectAgentRequest | |
): CreateProspectAgentResponseDto.CreateProspectAgentResponse { | |
return agentActivityService.createAgentProspect( | |
token = token, | |
body = body | |
) | |
} | |
// REPOSITORY | |
override suspend fun createAgentProspect(body: CreateProspectAgentRequestModel.CreateProspectAgentRequest): KreditPlusResponse<CreateProspectAgentResponseModel.CreateProspectAgentResponse> { | |
return asSuspendKreditPlusResponse { | |
val requestDto = body.toCreateProspectAgentRequestDto() | |
val responseDto = agentVisitDataSource.createAgentProspect( | |
token = "Bearer ${getAccountInfo().token}", | |
body = requestDto | |
) | |
responseDto.toCreateProspectAgentResponseModel() | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment