Skip to content

Commit

Permalink
Feat: Migrated Saved Card Module to KMP (#1800)
Browse files Browse the repository at this point in the history
  • Loading branch information
niyajali authored Oct 27, 2024
1 parent 3135f66 commit ff171dd
Show file tree
Hide file tree
Showing 73 changed files with 4,222 additions and 1,124 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ that can be used as a dependency in any other wallet based project. It is develo
| :feature:qr | Not started ||||||
| :feature:receipt | Not started ||||||
| :feature:request-money | Not started ||||||
| :feature:saved-cards | Not started | | | | | |
| :feature:saved-cards | Done | | | | | |
| :feature:search | Not started ||||||
| :feature:send-money | Not started ||||||
| :feature:standing-instruction | Not started ||||||
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ package org.mifospay.core.data.repository

import kotlinx.coroutines.flow.Flow
import org.mifospay.core.common.DataState
import org.mifospay.core.network.model.GenericResponse
import org.mifospay.core.network.model.entity.savedcards.Card
import org.mifospay.core.model.savedcards.CardPayload
import org.mifospay.core.model.savedcards.SavedCard

interface SavedCardRepository {
suspend fun getSavedCards(clientId: Int): Flow<DataState<List<Card>>>
fun getSavedCards(clientId: Long): Flow<DataState<List<SavedCard>>>

suspend fun addSavedCard(clientId: Int, card: Card): Flow<DataState<GenericResponse>>
fun getSavedCard(clientId: Long, cardId: Long): Flow<DataState<SavedCard>>

suspend fun deleteCard(clientId: Int, cardId: Int): Flow<DataState<GenericResponse>>
suspend fun addSavedCard(clientId: Long, card: CardPayload): DataState<String>

suspend fun updateCard(clientId: Int, cardId: Int, card: Card): Flow<DataState<GenericResponse>>
suspend fun deleteCard(clientId: Long, cardId: Long): DataState<String>

suspend fun updateCard(clientId: Long, cardId: Long, card: CardPayload): DataState<String>
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,76 @@ package org.mifospay.core.data.repositoryImp

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.withContext
import org.mifospay.core.common.DataState
import org.mifospay.core.common.asDataStateFlow
import org.mifospay.core.data.repository.SavedCardRepository
import org.mifospay.core.model.savedcards.CardPayload
import org.mifospay.core.model.savedcards.SavedCard
import org.mifospay.core.network.FineractApiManager
import org.mifospay.core.network.model.GenericResponse
import org.mifospay.core.network.model.entity.savedcards.Card

class SavedCardRepositoryImpl(
private val apiManager: FineractApiManager,
private val ioDispatcher: CoroutineDispatcher,
) : SavedCardRepository {
override suspend fun getSavedCards(clientId: Int): Flow<DataState<List<Card>>> {
return apiManager.savedCardApi.getSavedCards(clientId).asDataStateFlow().flowOn(ioDispatcher)
override fun getSavedCards(clientId: Long): Flow<DataState<List<SavedCard>>> {
return apiManager.savedCardApi
.getSavedCards(clientId)
.catch { DataState.Error(it, null) }
.onStart { DataState.Loading }
.asDataStateFlow().flowOn(ioDispatcher)
}

override suspend fun addSavedCard(clientId: Int, card: Card): Flow<DataState<GenericResponse>> {
return apiManager.savedCardApi.addSavedCard(clientId, card).asDataStateFlow().flowOn(ioDispatcher)
override fun getSavedCard(clientId: Long, cardId: Long): Flow<DataState<SavedCard>> {
return apiManager.savedCardApi
.getSavedCard(clientId, cardId)
.catch { DataState.Error(it, null) }
.onStart { DataState.Loading }
.map { it.first() }
.asDataStateFlow().flowOn(ioDispatcher)
}

override suspend fun deleteCard(clientId: Int, cardId: Int): Flow<DataState<GenericResponse>> {
return apiManager.savedCardApi.deleteCard(clientId, cardId).asDataStateFlow().flowOn(ioDispatcher)
override suspend fun addSavedCard(clientId: Long, card: CardPayload): DataState<String> {
return try {
withContext(ioDispatcher) {
apiManager.savedCardApi.addSavedCard(clientId, card)
}

DataState.Success("Card added successfully")
} catch (e: Exception) {
DataState.Error(e, null)
}
}

override suspend fun deleteCard(clientId: Long, cardId: Long): DataState<String> {
return try {
withContext(ioDispatcher) {
apiManager.savedCardApi.deleteCard(clientId, cardId)
}

DataState.Success("Card deleted successfully")
} catch (e: Exception) {
DataState.Error(e, null)
}
}

override suspend fun updateCard(
clientId: Int,
cardId: Int,
card: Card,
): Flow<DataState<GenericResponse>> {
return apiManager.savedCardApi
.updateCard(clientId, cardId, card)
.asDataStateFlow().flowOn(ioDispatcher)
clientId: Long,
cardId: Long,
card: CardPayload,
): DataState<String> {
return try {
withContext(ioDispatcher) {
apiManager.savedCardApi.updateCard(clientId, cardId, card)
}

DataState.Success("Card updated successfully")
} catch (e: Exception) {
DataState.Error(e, null)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
Expand Down Expand Up @@ -86,7 +88,10 @@ fun MifosScaffold(
)
}
},
modifier = modifier,
modifier = modifier
.fillMaxSize()
.navigationBarsPadding()
.imePadding(),
)
}

Expand All @@ -106,7 +111,10 @@ fun MifosScaffold(
content: @Composable (PaddingValues) -> Unit,
) {
Scaffold(
modifier = modifier,
modifier = modifier
.fillMaxSize()
.navigationBarsPadding()
.imePadding(),
topBar = topBar,
bottomBar = bottomBar,
snackbarHost = { SnackbarHost(snackbarHostState) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ fun MifosOutlinedTextField(
showClearIcon: Boolean = true,
readOnly: Boolean = false,
clearIcon: ImageVector = MifosIcons.Close,
onClickClearIcon: () -> Unit = {},
onClickClearIcon: () -> Unit = { onValueChange("") },
onKeyboardActions: (() -> Unit)? = null,
leadingIcon: @Composable (() -> Unit)? = null,
trailingIcon: @Composable (() -> Unit)? = null,
Expand Down Expand Up @@ -111,7 +111,7 @@ fun MifosTextField(
showClearIcon: Boolean = true,
readOnly: Boolean = false,
clearIcon: ImageVector = MifosIcons.Close,
onClickClearIcon: () -> Unit = {},
onClickClearIcon: () -> Unit = { onValueChange("") },
textStyle: TextStyle = LocalTextStyle.current,
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardActions: KeyboardActions = KeyboardActions.Default,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@
*/
package org.mifospay.core.designsystem.utils

import androidx.compose.foundation.Indication
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.scale
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.input.key.Key
Expand All @@ -22,6 +27,8 @@ import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.input.key.type
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.LayoutDirection

@Stable
Expand Down Expand Up @@ -52,3 +59,27 @@ fun Modifier.tabNavigation(): Modifier {
}
}
}

fun Modifier.onClick(
indication: Indication? = null,
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
onClick: () -> Unit,
) = this.composed(
inspectorInfo = debugInspectorInfo {
name = "onClickModifier"
value = enabled
},
) {
val interactionSource = remember { MutableInteractionSource() }
clickable(
indication = indication,
interactionSource = interactionSource,
enabled = enabled,
onClickLabel = onClickLabel,
role = role,
) {
onClick.invoke()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package org.mifospay.core.model.notification

import kotlinx.serialization.Serializable
import org.mifospay.core.common.DateHelper.toFormattedDateTime
import org.mifospay.core.common.IgnoredOnParcel
import org.mifospay.core.common.Parcelable
import org.mifospay.core.common.Parcelize

Expand All @@ -27,5 +28,6 @@ data class Notification(
val isSystemGenerated: Boolean,
val createdAt: String,
) : Parcelable {
@IgnoredOnParcel
val formattedDate = createdAt.toFormattedDateTime()
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
*
* See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md
*/
package org.mifospay.core.network.model.entity.savedcards
package org.mifospay.core.model.savedcards

import kotlinx.serialization.Serializable

@Serializable
data class Card(
val cardNumber: String = "",
val cvv: String = "",
val expiryDate: String = "",
val firstName: String = "",
val lastName: String = "",
val id: Int = 0,
data class CardPayload(
val firstName: String,
val lastName: String,
val cardNumber: String,
val cvv: String,
val expiryDate: String,
val backgroundColor: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2024 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md
*/
package org.mifospay.core.model.savedcards

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.mifospay.core.common.IgnoredOnParcel
import org.mifospay.core.common.Parcelable
import org.mifospay.core.common.Parcelize

@Serializable
@Parcelize
data class SavedCard(
val id: Long = 0,
@SerialName("client_id")
val clientId: Long,
val firstName: String,
val lastName: String,
val cardNumber: String,
val cvv: String,
val expiryDate: String,
val backgroundColor: String,
@SerialName("created_at")
val createdAt: List<Long>,
@SerialName("updated_at")
val updatedAt: List<Long>,
) : Parcelable {
@IgnoredOnParcel
val fullName = "$firstName $lastName"

@IgnoredOnParcel
val formattedExpiryDate: String
get() = "${expiryDate.substring(0, 2)}/${expiryDate.substring(2, 4)}"

@IgnoredOnParcel
val maskedCvv: String
get() = "*".repeat(cvv.length)
}
1 change: 1 addition & 0 deletions core/network/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ kotlin {
implementation(libs.ktor.client.okhttp)
implementation(libs.koin.android)
}

nativeMain.dependencies {
implementation(libs.ktor.client.darwin)
}
Expand Down
Loading

0 comments on commit ff171dd

Please sign in to comment.