From f30a853edb54300e02a67c59c1deba3f1270e9c9 Mon Sep 17 00:00:00 2001 From: Aditya Kumdale <95978829+AdityaKumdale@users.noreply.github.com> Date: Thu, 4 Jul 2024 02:18:06 +0530 Subject: [PATCH] Invoice package cleaned (#1688) --- .../mifospay/feature/invoices/InvoiceItem.kt | 6 +- .../feature/invoices/InvoiceScreen.kt | 12 +- ...ure_invoices_ic_check_round_black_24dp.xml | 9 + ...es_ic_remove_circle_outline_black_24dp.xml | 9 + .../invoices/src/main/res/values/colors.xml | 4 + .../invoices/src/main/res/values/strings.xml | 14 +- mifospay/build.gradle.kts | 2 +- mifospay/src/main/AndroidManifest.xml | 2 +- .../mifospay/home/screens/PaymentsScreen.kt | 2 +- .../org/mifospay/invoice/InvoiceContract.kt | 33 -- .../presenter/InvoiceDetailViewModel.kt | 53 --- .../invoice/presenter/InvoicePresenter.kt | 44 --- .../invoice/presenter/InvoicesPresenter.kt | 54 --- .../invoice/presenter/InvoicesViewModel.kt | 60 ---- .../mifospay/invoice/ui/InvoiceActivity.kt | 20 -- .../invoice/ui/InvoiceDetailScreen.kt | 310 ------------------ .../org/mifospay/invoice/ui/InvoiceItem.kt | 121 ------- .../org/mifospay/invoice/ui/InvoiceScreen.kt | 130 -------- .../mifospay/invoice/ui/InvoicesFragment.kt | 179 ---------- .../invoice/ui/adapter/InvoicesAdapter.kt | 93 ------ 20 files changed, 37 insertions(+), 1120 deletions(-) create mode 100644 feature/invoices/src/main/res/drawable/feature_invoices_ic_check_round_black_24dp.xml create mode 100644 feature/invoices/src/main/res/drawable/feature_invoices_ic_remove_circle_outline_black_24dp.xml create mode 100644 feature/invoices/src/main/res/values/colors.xml delete mode 100644 mifospay/src/main/java/org/mifospay/invoice/InvoiceContract.kt delete mode 100644 mifospay/src/main/java/org/mifospay/invoice/presenter/InvoiceDetailViewModel.kt delete mode 100644 mifospay/src/main/java/org/mifospay/invoice/presenter/InvoicePresenter.kt delete mode 100644 mifospay/src/main/java/org/mifospay/invoice/presenter/InvoicesPresenter.kt delete mode 100644 mifospay/src/main/java/org/mifospay/invoice/presenter/InvoicesViewModel.kt delete mode 100644 mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceActivity.kt delete mode 100644 mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceDetailScreen.kt delete mode 100644 mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceItem.kt delete mode 100644 mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceScreen.kt delete mode 100644 mifospay/src/main/java/org/mifospay/invoice/ui/InvoicesFragment.kt delete mode 100644 mifospay/src/main/java/org/mifospay/invoice/ui/adapter/InvoicesAdapter.kt diff --git a/feature/invoices/src/main/kotlin/org/mifospay/feature/invoices/InvoiceItem.kt b/feature/invoices/src/main/kotlin/org/mifospay/feature/invoices/InvoiceItem.kt index 457e0e02f..ab1e4aabe 100644 --- a/feature/invoices/src/main/kotlin/org/mifospay/feature/invoices/InvoiceItem.kt +++ b/feature/invoices/src/main/kotlin/org/mifospay/feature/invoices/InvoiceItem.kt @@ -21,8 +21,8 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import org.mifospay.R import org.mifospay.core.designsystem.theme.grey +import org.mifospay.invoices.R @Composable fun InvoiceItem( @@ -51,8 +51,8 @@ fun InvoiceItem( ) { Icon( painter = painterResource( - id = if (invoiceStatusIcon == 0L) R.drawable.ic_remove_circle_outline_black_24dp - else R.drawable.ic_check_round_black_24dp + id = if (invoiceStatusIcon == 0L) R.drawable.feature_invoices_ic_remove_circle_outline_black_24dp + else R.drawable.feature_invoices_ic_check_round_black_24dp ), contentDescription = "Invoice Status", modifier = Modifier diff --git a/feature/invoices/src/main/kotlin/org/mifospay/feature/invoices/InvoiceScreen.kt b/feature/invoices/src/main/kotlin/org/mifospay/feature/invoices/InvoiceScreen.kt index 50826ac2a..db9b19a4d 100644 --- a/feature/invoices/src/main/kotlin/org/mifospay/feature/invoices/InvoiceScreen.kt +++ b/feature/invoices/src/main/kotlin/org/mifospay/feature/invoices/InvoiceScreen.kt @@ -19,11 +19,11 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.mifospay.core.model.entity.Invoice -import org.mifospay.R import org.mifospay.core.designsystem.component.MifosLoadingWheel import org.mifospay.core.designsystem.icon.MifosIcons.Info import org.mifospay.core.designsystem.theme.MifosTheme import org.mifospay.core.ui.EmptyContentScreen +import org.mifospay.invoices.R @Composable fun InvoiceScreen( @@ -46,8 +46,8 @@ fun InvoiceScreen( is InvoicesUiState.Error -> { EmptyContentScreen( modifier = Modifier, - title = stringResource(id = R.string.error_oops), - subTitle = stringResource(id = R.string.unexpected_error_subtitle), + title = stringResource(id = R.string.feature_invoices_error_oops), + subTitle = stringResource(id = R.string.feature_invoices_unexpected_error_subtitle), iconTint = Color.Black, iconImageVector = Info ) @@ -78,8 +78,8 @@ fun InvoiceScreen( InvoicesUiState.Empty -> { EmptyContentScreen( modifier = Modifier, - title = stringResource(id = R.string.error_oops), - subTitle = stringResource(id = R.string.error_no_invoices_found), + title = stringResource(id = R.string.feature_invoices_error_oops), + subTitle = stringResource(id = R.string.feature_invoices_error_no_invoices_found), iconTint = Color.Black, ) } @@ -87,7 +87,7 @@ fun InvoiceScreen( InvoicesUiState.Loading -> { MifosLoadingWheel( modifier = Modifier.fillMaxWidth(), - contentDesc = stringResource(R.string.loading) + contentDesc = stringResource(R.string.feature_invoices_loading) ) } } diff --git a/feature/invoices/src/main/res/drawable/feature_invoices_ic_check_round_black_24dp.xml b/feature/invoices/src/main/res/drawable/feature_invoices_ic_check_round_black_24dp.xml new file mode 100644 index 000000000..7d196dc5e --- /dev/null +++ b/feature/invoices/src/main/res/drawable/feature_invoices_ic_check_round_black_24dp.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/feature/invoices/src/main/res/drawable/feature_invoices_ic_remove_circle_outline_black_24dp.xml b/feature/invoices/src/main/res/drawable/feature_invoices_ic_remove_circle_outline_black_24dp.xml new file mode 100644 index 000000000..e66f7111d --- /dev/null +++ b/feature/invoices/src/main/res/drawable/feature_invoices_ic_remove_circle_outline_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/feature/invoices/src/main/res/values/colors.xml b/feature/invoices/src/main/res/values/colors.xml new file mode 100644 index 000000000..a9648874c --- /dev/null +++ b/feature/invoices/src/main/res/values/colors.xml @@ -0,0 +1,4 @@ + + + #303F9F + \ No newline at end of file diff --git a/feature/invoices/src/main/res/values/strings.xml b/feature/invoices/src/main/res/values/strings.xml index d52fe8e60..67101d8e6 100644 --- a/feature/invoices/src/main/res/values/strings.xml +++ b/feature/invoices/src/main/res/values/strings.xml @@ -15,15 +15,7 @@ UPI) Unique Payment Link - - - - - - - - - - - + Oops! + An unexpected error occurred. Please try again. + Couldn\'t fetch invoice list. Please, try again. \ No newline at end of file diff --git a/mifospay/build.gradle.kts b/mifospay/build.gradle.kts index 3a5f46df6..ca19d9241 100644 --- a/mifospay/build.gradle.kts +++ b/mifospay/build.gradle.kts @@ -86,9 +86,9 @@ dependencies { implementation(projects.feature.settings) implementation(projects.feature.savedcards) implementation(projects.feature.qr) + implementation(projects.feature.invoices) implementation(projects.feature.merchants) implementation(projects.feature.history) - implementation(projects.feature.kyc) // Compose diff --git a/mifospay/src/main/AndroidManifest.xml b/mifospay/src/main/AndroidManifest.xml index 105adf96b..ea02338e6 100644 --- a/mifospay/src/main/AndroidManifest.xml +++ b/mifospay/src/main/AndroidManifest.xml @@ -104,7 +104,7 @@ diff --git a/mifospay/src/main/java/org/mifospay/home/screens/PaymentsScreen.kt b/mifospay/src/main/java/org/mifospay/home/screens/PaymentsScreen.kt index 321a47c44..c8a56942a 100644 --- a/mifospay/src/main/java/org/mifospay/home/screens/PaymentsScreen.kt +++ b/mifospay/src/main/java/org/mifospay/home/screens/PaymentsScreen.kt @@ -12,8 +12,8 @@ import com.google.accompanist.pager.rememberPagerState import com.mifospay.core.model.domain.Transaction import org.mifospay.core.ui.MifosScrollableTabRow import org.mifospay.core.ui.utility.TabContent +import org.mifospay.feature.invoices.InvoiceScreen import org.mifospay.feature.history.HistoryScreen -import org.mifospay.invoice.ui.InvoiceScreen import org.mifospay.payments.TransferViewModel import org.mifospay.payments.send.SendScreenRoute import org.mifospay.payments.ui.RequestScreen diff --git a/mifospay/src/main/java/org/mifospay/invoice/InvoiceContract.kt b/mifospay/src/main/java/org/mifospay/invoice/InvoiceContract.kt deleted file mode 100644 index fb897049f..000000000 --- a/mifospay/src/main/java/org/mifospay/invoice/InvoiceContract.kt +++ /dev/null @@ -1,33 +0,0 @@ -package org.mifospay.invoice - -import android.net.Uri -import com.mifospay.core.model.entity.Invoice -import org.mifospay.base.BasePresenter -import org.mifospay.base.BaseView - -/** - * Created by ankur on 07/June/2018 - */ -interface InvoiceContract { - interface InvoiceView : BaseView { - fun showInvoiceDetails(invoice: Invoice?, merchantId: String?, paymentLink: String?) - fun showSnackbar(message: String?) - fun showToast(message: String?) - } - - interface InvoicePresenter : BasePresenter { - fun getInvoiceDetails(data: Uri?) - } - - interface InvoicesView : BaseView { - fun showSnackbar(message: String?) - fun showInvoices(invoiceList: List?) - fun showErrorStateView(drawable: Int, title: Int, subtitle: Int) - fun showFetchingProcess() - } - - interface InvoicesPresenter : BasePresenter { - fun fetchInvoices() - fun getUniqueInvoiceLink(id: Long): Uri? - } -} \ No newline at end of file diff --git a/mifospay/src/main/java/org/mifospay/invoice/presenter/InvoiceDetailViewModel.kt b/mifospay/src/main/java/org/mifospay/invoice/presenter/InvoiceDetailViewModel.kt deleted file mode 100644 index 65afc0e42..000000000 --- a/mifospay/src/main/java/org/mifospay/invoice/presenter/InvoiceDetailViewModel.kt +++ /dev/null @@ -1,53 +0,0 @@ -package org.mifospay.invoice.presenter - -import android.net.Uri -import androidx.lifecycle.ViewModel -import com.mifospay.core.model.entity.Invoice -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import org.mifospay.core.data.base.UseCase -import org.mifospay.core.data.base.UseCaseHandler -import org.mifospay.core.data.domain.usecase.invoice.FetchInvoice -import org.mifospay.core.datastore.PreferencesHelper -import javax.inject.Inject - -@HiltViewModel -class InvoiceDetailViewModel @Inject constructor( - private val mUseCaseHandler: UseCaseHandler, - private val mPreferencesHelper: PreferencesHelper, - private val fetchInvoiceUseCase: FetchInvoice -) : ViewModel() { - - private val _invoiceDetailUiState = - MutableStateFlow(InvoiceDetailUiState.Loading) - val invoiceDetailUiState: StateFlow = _invoiceDetailUiState - - fun getInvoiceDetails(data: Uri?) { - mUseCaseHandler.execute(fetchInvoiceUseCase, FetchInvoice.RequestValues(data), - object : UseCase.UseCaseCallback { - override fun onSuccess(response: FetchInvoice.ResponseValue) { - _invoiceDetailUiState.value = InvoiceDetailUiState.Success( - response.invoices[0], - mPreferencesHelper.fullName + " " - + mPreferencesHelper.clientId, data.toString() - ) - } - - override fun onError(message: String) { - _invoiceDetailUiState.value = InvoiceDetailUiState.Error(message) - } - }) - } -} - -sealed interface InvoiceDetailUiState { - data object Loading : InvoiceDetailUiState - data class Success( - val invoice: Invoice?, - val merchantId: String?, - val paymentLink: String? - ) : InvoiceDetailUiState - - data class Error(val message: String) : InvoiceDetailUiState -} \ No newline at end of file diff --git a/mifospay/src/main/java/org/mifospay/invoice/presenter/InvoicePresenter.kt b/mifospay/src/main/java/org/mifospay/invoice/presenter/InvoicePresenter.kt deleted file mode 100644 index 2e8f9417f..000000000 --- a/mifospay/src/main/java/org/mifospay/invoice/presenter/InvoicePresenter.kt +++ /dev/null @@ -1,44 +0,0 @@ -package org.mifospay.invoice.presenter - -import android.net.Uri -import org.mifospay.core.data.base.UseCase.UseCaseCallback -import org.mifospay.core.data.base.UseCaseHandler -import org.mifospay.core.data.domain.usecase.invoice.FetchInvoice -import org.mifospay.base.BaseView -import org.mifospay.core.datastore.PreferencesHelper -import org.mifospay.invoice.InvoiceContract -import org.mifospay.invoice.InvoiceContract.InvoiceView -import javax.inject.Inject - -/** - * Created by ankur on 07/June/2018 - */ -class InvoicePresenter @Inject constructor( - private val mUseCaseHandler: UseCaseHandler, - private val mPreferencesHelper: PreferencesHelper, - private val fetchInvoiceUseCase: FetchInvoice -) : InvoiceContract.InvoicePresenter { - var mInvoiceView: InvoiceView? = null - - override fun attachView(baseView: BaseView<*>?) { - mInvoiceView = baseView as InvoiceView? - mInvoiceView!!.setPresenter(this) - } - - override fun getInvoiceDetails(data: Uri?) { - mUseCaseHandler.execute(fetchInvoiceUseCase, FetchInvoice.RequestValues(data), - object : UseCaseCallback { - override fun onSuccess(response: FetchInvoice.ResponseValue) { - mInvoiceView?.showInvoiceDetails( - response.invoices[0], - mPreferencesHelper.fullName + " " - + mPreferencesHelper.clientId, data.toString() - ) - } - - override fun onError(message: String) { - mInvoiceView!!.showToast(message) - } - }) - } -} \ No newline at end of file diff --git a/mifospay/src/main/java/org/mifospay/invoice/presenter/InvoicesPresenter.kt b/mifospay/src/main/java/org/mifospay/invoice/presenter/InvoicesPresenter.kt deleted file mode 100644 index d6ec23ed9..000000000 --- a/mifospay/src/main/java/org/mifospay/invoice/presenter/InvoicesPresenter.kt +++ /dev/null @@ -1,54 +0,0 @@ -package org.mifospay.invoice.presenter - -import android.net.Uri -import org.mifospay.core.data.base.UseCase.UseCaseCallback -import org.mifospay.core.data.base.UseCaseHandler -import org.mifospay.core.data.domain.usecase.invoice.FetchInvoices -import org.mifospay.R -import org.mifospay.base.BaseView -import org.mifospay.core.datastore.PreferencesHelper -import org.mifospay.invoice.InvoiceContract -import org.mifospay.invoice.InvoiceContract.InvoicesView -import org.mifospay.common.Constants -import javax.inject.Inject - -/** - * Created by ankur on 11/June/2018 - */ -class InvoicesPresenter @Inject constructor( - private val mUseCaseHandler: UseCaseHandler, - private val mPreferencesHelper: PreferencesHelper, - private val fetchInvoicesUseCase: FetchInvoices -) : InvoiceContract.InvoicesPresenter { - - private var mInvoicesView: InvoicesView? = null - override fun attachView(baseView: BaseView<*>?) { - mInvoicesView = baseView as InvoicesView? - mInvoicesView!!.setPresenter(this) - } - - override fun fetchInvoices() { - mInvoicesView!!.showFetchingProcess() - mUseCaseHandler.execute(fetchInvoicesUseCase, - FetchInvoices.RequestValues(mPreferencesHelper.clientId.toString() + ""), - object : UseCaseCallback { - override fun onSuccess(response: FetchInvoices.ResponseValue) { - mInvoicesView!!.showInvoices(response?.invoiceList) - } - - override fun onError(message: String) { - mInvoicesView!!.showErrorStateView( - R.drawable.ic_error_state, - R.string.error_oops, - R.string.error_no_invoices_found - ) - } - }) - } - - override fun getUniqueInvoiceLink(id: Long): Uri? { - return Uri.parse( - Constants.INVOICE_DOMAIN + mPreferencesHelper.clientId + "/" + id - ) - } -} \ No newline at end of file diff --git a/mifospay/src/main/java/org/mifospay/invoice/presenter/InvoicesViewModel.kt b/mifospay/src/main/java/org/mifospay/invoice/presenter/InvoicesViewModel.kt deleted file mode 100644 index 7a9fd2af8..000000000 --- a/mifospay/src/main/java/org/mifospay/invoice/presenter/InvoicesViewModel.kt +++ /dev/null @@ -1,60 +0,0 @@ -package org.mifospay.invoice.presenter - -import android.net.Uri -import androidx.lifecycle.ViewModel -import com.mifospay.core.model.entity.Invoice -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import org.mifospay.core.data.base.UseCase -import org.mifospay.core.data.base.UseCaseHandler -import org.mifospay.core.data.domain.usecase.invoice.FetchInvoices -import org.mifospay.common.Constants.INVOICE_DOMAIN -import org.mifospay.core.datastore.PreferencesHelper -import javax.inject.Inject - -@HiltViewModel -class InvoicesViewModel @Inject constructor( - private val mUseCaseHandler: UseCaseHandler, - private val mPreferencesHelper: PreferencesHelper, - private val fetchInvoicesUseCase: FetchInvoices -) : ViewModel() { - - - private val _invoiceUiState = MutableStateFlow(InvoicesUiState.Loading) - val invoiceUiState: StateFlow = _invoiceUiState - - fun fetchInvoices() { - _invoiceUiState.value = InvoicesUiState.Loading - mUseCaseHandler.execute(fetchInvoicesUseCase, - FetchInvoices.RequestValues(mPreferencesHelper.clientId.toString() + ""), - object : UseCase.UseCaseCallback { - override fun onSuccess(response: FetchInvoices.ResponseValue) { - if (response.invoiceList.isNotEmpty()) - _invoiceUiState.value = InvoicesUiState.InvoiceList(response.invoiceList) - else _invoiceUiState.value = InvoicesUiState.Empty - } - - override fun onError(message: String) { - _invoiceUiState.value = InvoicesUiState.Error(message) - } - }) - } - - fun getUniqueInvoiceLink(id: Long): Uri? { - return Uri.parse( - INVOICE_DOMAIN + mPreferencesHelper.clientId + "/" + id - ) - } - - init { - fetchInvoices() - } -} - -sealed class InvoicesUiState { - data object Loading : InvoicesUiState() - data object Empty : InvoicesUiState() - data class Error(val message: String) : InvoicesUiState() - data class InvoiceList(val list: List) : InvoicesUiState() -} \ No newline at end of file diff --git a/mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceActivity.kt b/mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceActivity.kt deleted file mode 100644 index fe7b724a7..000000000 --- a/mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceActivity.kt +++ /dev/null @@ -1,20 +0,0 @@ -package org.mifospay.invoice.ui - -import android.os.Bundle -import androidx.activity.compose.setContent -import dagger.hilt.android.AndroidEntryPoint -import org.mifospay.base.BaseActivity -import org.mifospay.theme.MifosTheme - -@AndroidEntryPoint -class InvoiceActivity : BaseActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - val data = intent.data - setContent { - MifosTheme { - InvoiceDetailScreen(data = data,onBackPress = { finish() }) - } - } - } -} \ No newline at end of file diff --git a/mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceDetailScreen.kt b/mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceDetailScreen.kt deleted file mode 100644 index e5cc2db38..000000000 --- a/mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceDetailScreen.kt +++ /dev/null @@ -1,310 +0,0 @@ -package org.mifospay.invoice.ui - -import android.content.Intent -import android.net.Uri -import androidx.compose.foundation.background -import androidx.compose.foundation.gestures.detectTapGestures -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.platform.LocalClipboardManager -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.mifospay.core.model.entity.Invoice -import com.mifospay.core.model.utils.DateHelper -import org.mifospay.R -import org.mifospay.common.Constants -import org.mifospay.core.designsystem.component.MfOverlayLoadingWheel -import org.mifospay.core.designsystem.component.MifosScaffold -import org.mifospay.core.designsystem.theme.primaryDarkBlue -import org.mifospay.core.ui.ErrorScreenContent -import org.mifospay.feature.receipt.ReceiptActivity -import org.mifospay.invoice.presenter.InvoiceDetailUiState -import org.mifospay.invoice.presenter.InvoiceDetailViewModel -import org.mifospay.theme.MifosTheme - -@Composable -fun InvoiceDetailScreen( - viewModel: InvoiceDetailViewModel = hiltViewModel(), - data: Uri?, - onBackPress: () -> Unit -) { - val invoiceDetailUiState by viewModel.invoiceDetailUiState.collectAsStateWithLifecycle() - InvoiceDetailScreen(invoiceDetailUiState = invoiceDetailUiState, onBackPress = onBackPress) - LaunchedEffect(key1 = true) { - viewModel.getInvoiceDetails(data) - } -} - -@Composable -fun InvoiceDetailScreen( - invoiceDetailUiState: InvoiceDetailUiState, onBackPress: () -> Unit -) { - MifosScaffold( - topBarTitle = R.string.invoice, - backPress = { onBackPress.invoke() }, - scaffoldContent = { - Column( - modifier = Modifier - .fillMaxSize() - .background(Color.White) - .padding(it) - ) { - when (invoiceDetailUiState) { - is InvoiceDetailUiState.Error -> { - ErrorScreenContent() - } - - InvoiceDetailUiState.Loading -> { - MfOverlayLoadingWheel( - contentDesc = stringResource(R.string.loading) - ) - } - - is InvoiceDetailUiState.Success -> { - InvoiceDetailsContent( - invoiceDetailUiState.invoice, - invoiceDetailUiState.merchantId, - invoiceDetailUiState.paymentLink - ) - } - } - } - }) -} - -@Composable -fun InvoiceDetailsContent(invoice: Invoice?, merchantId: String?, paymentLink: String?) { - val clipboardManager = LocalClipboardManager.current - - Column( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp) - ) { - val context = LocalContext.current - Text( - text = stringResource(R.string.invoice_details), - modifier = Modifier.padding(top = 16.dp) - ) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = stringResource(R.string.merchant_id), - modifier = Modifier.padding(top = 16.dp) - ) - Text( - text = merchantId.toString(), - modifier = Modifier.padding(top = 16.dp) - ) - } - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = stringResource(R.string.consumer_id), - modifier = Modifier.padding(top = 8.dp) - ) - Text( - text = (invoice?.consumerName + " " + invoice?.consumerId), - modifier = Modifier.padding(top = 8.dp) - ) - } - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = stringResource(id = R.string.amount), - modifier = Modifier.padding(top = 8.dp) - ) - Text( - text = Constants.INR + " " + invoice?.amount + "", - modifier = Modifier.padding(top = 8.dp) - ) - } - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = stringResource(id = R.string.items_bought), - modifier = Modifier.padding(top = 8.dp) - ) - Text( - text = invoice?.itemsBought.toString(), - modifier = Modifier.padding(top = 8.dp) - ) - } - - if (invoice?.status == 1L) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = stringResource(id = R.string.status), - modifier = Modifier.padding(top = 8.dp) - ) - - Text( - text = Constants.DONE, - modifier = Modifier.padding(top = 8.dp) - ) - } - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = stringResource(id = R.string.transaction_id), - color = primaryDarkBlue, - modifier = Modifier - .padding(top = 10.dp) - ) - Text( - text = invoice.transactionId ?: "", - color = primaryDarkBlue, - modifier = Modifier - .padding(top = 10.dp) - .then(Modifier.height(0.dp)) - ) - } - Divider() - Text( - text = stringResource(id = R.string.unique_receipt_link), - fontWeight = FontWeight.Normal, - modifier = Modifier.padding(bottom = 10.dp) - ) - Text( - text = invoice.transactionId ?: "", - color = primaryDarkBlue, - modifier = Modifier - .padding(top = 10.dp) - .pointerInput(Unit) { - detectTapGestures( - onPress = { - val intent = Intent(context, ReceiptActivity::class.java) - intent.data = Uri.parse( - Constants.RECEIPT_DOMAIN + invoice.transactionId - ) - context.startActivity(intent) - }, - onLongPress = { - clipboardManager.setText(AnnotatedString(Constants.RECEIPT_DOMAIN + invoice.transactionId)) - }) - } - ) - } - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = stringResource(id = R.string.date), - modifier = Modifier.padding(top = 10.dp) - ) - Text( - text = DateHelper.getDateAsString(invoice!!.date), - modifier = Modifier.padding(top = 10.dp) - ) - } - - Divider() - Text( - text = stringResource(id = R.string.payment_options_will_be_fetched_from_upi), - fontWeight = FontWeight.Normal, - modifier = Modifier.padding(vertical = 10.dp) - ) - Divider() - Text( - text = stringResource(id = R.string.unique_payment_link), - fontWeight = FontWeight.Normal, - modifier = Modifier.padding(bottom = 10.dp) - ) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = paymentLink.toString(), - color = primaryDarkBlue, - modifier = Modifier - .padding(top = 10.dp) - .pointerInput(Unit) { - detectTapGestures( - onLongPress = { - clipboardManager.setText(AnnotatedString(paymentLink.toString())) - }) - } - ) - } - - } -} - -@Composable -fun Divider(modifier: Modifier = Modifier) { - Box( - modifier = modifier - .fillMaxWidth() - .height(1.dp) - .background(Color(0x44000000)) - ) -} - -class InvoiceDetailScreenProvider : PreviewParameterProvider { - override val values: Sequence - get() = sequenceOf( - InvoiceDetailUiState.Loading, - InvoiceDetailUiState.Error("Some Error Occurred"), - InvoiceDetailUiState.Success(Invoice(), "", "") - ) - -} - -@Preview(showBackground = true, showSystemUi = true) -@Composable -fun InvoiceDetailScreenPreview( - @PreviewParameter(InvoiceDetailScreenProvider::class) invoiceDetailUiState: InvoiceDetailUiState -) { - MifosTheme { - InvoiceDetailScreen(invoiceDetailUiState = invoiceDetailUiState) {} - } -} \ No newline at end of file diff --git a/mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceItem.kt b/mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceItem.kt deleted file mode 100644 index 68a997569..000000000 --- a/mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceItem.kt +++ /dev/null @@ -1,121 +0,0 @@ -package org.mifospay.invoice.ui - -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.Icon -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import org.mifospay.R -import org.mifospay.core.designsystem.theme.grey - -@Composable -fun InvoiceItem( - invoiceTitle: String, - invoiceAmount: String, - invoiceStatus: String, - invoiceDate: String, - invoiceId: String, - invoiceStatusIcon: Long, - onClick: (String) -> Unit -) { - Card( - modifier = Modifier - .fillMaxWidth() - .padding(4.dp) - .clickable { onClick(invoiceId) }, - elevation = CardDefaults.cardElevation(4.dp), - colors = CardDefaults.cardColors(Color.White) - ) { - Column { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(10.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - painter = painterResource( - id = if (invoiceStatusIcon == 0L) R.drawable.ic_remove_circle_outline_black_24dp - else R.drawable.ic_check_round_black_24dp - ), - contentDescription = "Invoice Status", - modifier = Modifier - .size(64.dp) - .padding(5.dp), - tint = if (invoiceStatusIcon == 0L) Color.Yellow else Color.Blue - ) - Column( - modifier = Modifier - .fillMaxWidth() - .padding(end = 10.dp) - ) { - Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = invoiceTitle, - color = Color.Black, - modifier = Modifier.weight(1f) - ) - Text( - text = invoiceAmount, - color = Color.Black, - textAlign = TextAlign.End, - modifier = Modifier.weight(1f) - ) - } - Text( - text = invoiceStatus, - color = grey, - modifier = Modifier.padding(top = 1.dp) - ) - Row( - modifier = Modifier.fillMaxWidth() - ) { - Text( - text = invoiceDate, - color = grey, - modifier = Modifier.weight(1f) - ) - Text( - text = invoiceId, - color = grey, - textAlign = TextAlign.End, - modifier = Modifier.weight(1f) - ) - } - Spacer( - modifier = Modifier - .padding(top = 10.dp) - .fillMaxWidth() - .height(1.dp) - .background(Color.Gray) - ) - } - } - } - } -} - -@Preview(showBackground = true) -@Composable -fun PreviewInvoiceItem() { - InvoiceItem("Logo for Richard", "$3000", "Pending", "12/3/4", "Invoice id:12345", 0L,{}) -} diff --git a/mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceScreen.kt b/mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceScreen.kt deleted file mode 100644 index 8f4760628..000000000 --- a/mifospay/src/main/java/org/mifospay/invoice/ui/InvoiceScreen.kt +++ /dev/null @@ -1,130 +0,0 @@ -package org.mifospay.invoice.ui - -import android.content.Intent -import android.net.Uri -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.mifospay.core.model.entity.Invoice -import org.mifospay.R -import org.mifospay.core.designsystem.component.MifosLoadingWheel -import org.mifospay.core.designsystem.icon.MifosIcons.Info -import org.mifospay.core.ui.EmptyContentScreen -import org.mifospay.invoice.presenter.InvoicesUiState -import org.mifospay.invoice.presenter.InvoicesViewModel -import org.mifospay.theme.MifosTheme - -@Composable -fun InvoiceScreen( - viewModel: InvoicesViewModel = hiltViewModel() -) { - val invoiceUiState by viewModel.invoiceUiState.collectAsStateWithLifecycle() - InvoiceScreen( - invoiceUiState = invoiceUiState, - getUniqueInvoiceLink = { viewModel.getUniqueInvoiceLink(it) } - ) -} - -@Composable -fun InvoiceScreen( - invoiceUiState: InvoicesUiState, - getUniqueInvoiceLink: (Long) -> Uri? -) { - val context = LocalContext.current - when (invoiceUiState) { - is InvoicesUiState.Error -> { - EmptyContentScreen( - modifier = Modifier, - title = stringResource(id = R.string.error_oops), - subTitle = stringResource(id = R.string.unexpected_error_subtitle), - iconTint = Color.Black, - iconImageVector = Info - ) - } - - is InvoicesUiState.InvoiceList -> { - Column(modifier = Modifier.fillMaxSize()) { - LazyColumn(modifier = Modifier.fillMaxSize()) { - items(invoiceUiState.list) { - InvoiceItem( - invoiceTitle = it?.title.toString(), - invoiceAmount = it?.amount.toString(), - invoiceStatus = it?.status.toString(), - invoiceDate = it?.date.toString(), - invoiceId = it?.id.toString(), - invoiceStatusIcon = it?.status!!, - onClick = { invoiceId -> - val intent = Intent(context, InvoiceActivity::class.java) - intent.data = getUniqueInvoiceLink(invoiceId.toLong()) - context.startActivity(intent) - } - ) - } - } - } - } - - InvoicesUiState.Empty -> { - EmptyContentScreen( - modifier = Modifier, - title = stringResource(id = R.string.error_oops), - subTitle = stringResource(id = R.string.error_no_invoices_found), - iconTint = Color.Black, - ) - } - - InvoicesUiState.Loading -> { - MifosLoadingWheel( - modifier = Modifier.fillMaxWidth(), - contentDesc = stringResource(R.string.loading) - ) - } - } -} - -class InvoicesUiStateProvider : PreviewParameterProvider { - override val values: Sequence - get() = sequenceOf( - InvoicesUiState.Loading, - InvoicesUiState.Empty, - InvoicesUiState.InvoiceList(sampleInvoiceList), - InvoicesUiState.Error("Some Error Occurred") - ) -} - -@Preview(showBackground = true, showSystemUi = true) -@Composable -private fun InvoiceScreenPreview( - @PreviewParameter(InvoicesUiStateProvider::class) invoiceUiState: InvoicesUiState -) { - MifosTheme { - InvoiceScreen(invoiceUiState = invoiceUiState, getUniqueInvoiceLink = { Uri.EMPTY }) - } -} - -val sampleInvoiceList = List(10) { index -> - Invoice( - consumerId = "123456", - consumerName = "John Doe", - amount = 250.75, - itemsBought = "2x Notebook, 1x Pen", - status = 1L, - transactionId = "txn_78910", - id = index.toLong(), - title = "Stationery Purchase", - date = mutableListOf(2024, 3, 23) - ) -} diff --git a/mifospay/src/main/java/org/mifospay/invoice/ui/InvoicesFragment.kt b/mifospay/src/main/java/org/mifospay/invoice/ui/InvoicesFragment.kt deleted file mode 100644 index 817cf8f58..000000000 --- a/mifospay/src/main/java/org/mifospay/invoice/ui/InvoicesFragment.kt +++ /dev/null @@ -1,179 +0,0 @@ -package org.mifospay.invoice.ui - -import android.content.Intent -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.ImageView -import android.widget.ProgressBar -import android.widget.TextView -import androidx.recyclerview.widget.DividerItemDecoration -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import butterknife.BindView -import butterknife.ButterKnife -import dagger.hilt.android.AndroidEntryPoint -import com.mifospay.core.model.entity.Invoice -import org.mifospay.R -import org.mifospay.base.BaseFragment -import org.mifospay.invoice.InvoiceContract -import org.mifospay.invoice.InvoiceContract.InvoicesView -import org.mifospay.invoice.presenter.InvoicesPresenter -import org.mifospay.invoice.ui.adapter.InvoicesAdapter -import org.mifospay.utils.DebugUtil -import org.mifospay.utils.RecyclerItemClickListener -import org.mifospay.utils.Toaster -import javax.inject.Inject - -@AndroidEntryPoint -class InvoicesFragment : BaseFragment(), InvoicesView { - @JvmField - @Inject - var mPresenter: InvoicesPresenter? = null - var mInvoicesPresenter: InvoiceContract.InvoicesPresenter? = null - - @JvmField - @BindView(R.id.inc_state_view) - var vStateView: View? = null - - @JvmField - @BindView(R.id.iv_empty_no_transaction_history) - var ivTransactionsStateIcon: ImageView? = null - - @JvmField - @BindView(R.id.tv_empty_no_transaction_history_title) - var tvTransactionsStateTitle: TextView? = null - - @JvmField - @BindView(R.id.tv_empty_no_transaction_history_subtitle) - var tvTransactionsStateSubtitle: TextView? = null - - @JvmField - @BindView(R.id.tv_account_number) - var mTvAccountNumber: TextView? = null - - @JvmField - @BindView(R.id.tv_account_balance) - var mTvAccountBalance: TextView? = null - - @JvmField - @BindView(R.id.rv_invoices) - var mRvInvoices: RecyclerView? = null - - @JvmField - @BindView(R.id.pb_invoices) - var pbInvoices: ProgressBar? = null - - @JvmField - @Inject - var mInvoicesAdapter: InvoicesAdapter? = null - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - val root = inflater.inflate(R.layout.fragment_invoices, container, false) - ButterKnife.bind(this, root) - mPresenter!!.attachView(this) - setupRecyclerView() - setUpSwipeRefresh() - showSwipeProgress() - mInvoicesPresenter!!.fetchInvoices() - return root - } - - private fun setupRecyclerView() { - mRvInvoices!!.layoutManager = LinearLayoutManager(activity) - mRvInvoices!!.adapter = mInvoicesAdapter - mRvInvoices!!.addItemDecoration( - DividerItemDecoration( - activity, - DividerItemDecoration.VERTICAL - ) - ) - mRvInvoices!!.addOnItemTouchListener( - RecyclerItemClickListener( - activity, - object : RecyclerItemClickListener.OnItemClickListener { - override fun onItemClick(childView: View?, position: Int) { - val intent = Intent(activity, InvoiceActivity::class.java) - // incomplete - intent.data = mInvoicesPresenter!!.getUniqueInvoiceLink( - mInvoicesAdapter!!.invoiceList!![position].id - ) - startActivity(intent) - } - - override fun onItemLongPress(childView: View?, position: Int) {} - }) - ) - } - - private fun setUpSwipeRefresh() { - swipeRefreshLayout?.setOnRefreshListener { - swipeRefreshLayout?.isRefreshing = false - mInvoicesPresenter!!.fetchInvoices() - } - } - - override fun showInvoices(invoiceList: List?) { - if (invoiceList.isNullOrEmpty()) { - DebugUtil.log("null") - pbInvoices!!.visibility = View.GONE - mRvInvoices!!.visibility = View.GONE - showEmptyStateView() - } else { - DebugUtil.log("yes") - pbInvoices?.visibility = View.GONE - mRvInvoices?.visibility = View.VISIBLE - mInvoicesAdapter?.setData(invoiceList as List) - hideEmptyStateView() - } - mInvoicesAdapter?.setData(invoiceList as List) - hideSwipeProgress() - } - - private fun showEmptyStateView() { - if (activity != null) { - pbInvoices!!.visibility = View.GONE - vStateView!!.visibility = View.VISIBLE - val res = resources - ivTransactionsStateIcon - ?.setImageDrawable(res.getDrawable(R.drawable.ic_invoices)) - tvTransactionsStateTitle?.text = res.getString(R.string.empty_no_invoices_title) - tvTransactionsStateSubtitle?.text = res.getString(R.string.empty_no_invoices_subtitle) - } - } - - override fun showErrorStateView(drawable: Int, title: Int, subtitle: Int) { - mRvInvoices!!.visibility = View.GONE - pbInvoices!!.visibility = View.GONE - hideSwipeProgress() - vStateView!!.visibility = View.VISIBLE - if (activity != null) { - val res = resources - ivTransactionsStateIcon - ?.setImageDrawable(res.getDrawable(drawable)) - tvTransactionsStateTitle?.text = res.getString(title) - tvTransactionsStateSubtitle?.text = res.getString(subtitle) - } - } - - override fun showFetchingProcess() { - vStateView!!.visibility = View.GONE - mRvInvoices!!.visibility = View.GONE - pbInvoices!!.visibility = View.VISIBLE - } - - override fun setPresenter(presenter: InvoiceContract.InvoicesPresenter?) { - mInvoicesPresenter = presenter - } - - private fun hideEmptyStateView() { - vStateView!!.visibility = View.GONE - } - - override fun showSnackbar(message: String?) { - Toaster.show(view, message) - } -} \ No newline at end of file diff --git a/mifospay/src/main/java/org/mifospay/invoice/ui/adapter/InvoicesAdapter.kt b/mifospay/src/main/java/org/mifospay/invoice/ui/adapter/InvoicesAdapter.kt deleted file mode 100644 index 884887d12..000000000 --- a/mifospay/src/main/java/org/mifospay/invoice/ui/adapter/InvoicesAdapter.kt +++ /dev/null @@ -1,93 +0,0 @@ -package org.mifospay.invoice.ui.adapter - -import android.content.Context -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.ImageView -import android.widget.TextView -import androidx.recyclerview.widget.RecyclerView -import butterknife.BindView -import butterknife.ButterKnife -import com.mifospay.core.model.entity.Invoice -import com.mifospay.core.model.utils.DateHelper -import org.mifospay.R -import org.mifospay.common.Constants -import javax.inject.Inject - -/** - * Created by ankur on 11/June/2018 - */ -class InvoicesAdapter @Inject constructor() : RecyclerView.Adapter() { - private var context: Context? = null - var invoiceList: List? = null - private set - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - val v = LayoutInflater.from(parent.context).inflate( - R.layout.invoice_item, parent, false - ) - return ViewHolder(v) - } - - override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val invoice = invoiceList!![position] - holder.mTvInvoiceTitle!!.text = invoice.title - holder.mTvInvoiceId!!.text = "Invoice Id: " + invoice.id + "" - holder.mTvInvoiceStatus!!.text = - if (invoice.status == 0L) Constants.PENDING else Constants.DONE - holder.mInvoiceImage!!.setImageResource( - if (invoice.status == 0L) R.drawable.ic_remove_circle_outline_black_24dp - else R.drawable.ic_check_round_black_24dp - ) - holder.mTvInvoiceDate!!.text = DateHelper.getDateAsString(invoice.date) - holder.mTvInvoiceAmount!!.text = Constants.INR + invoice.amount - } - - override fun getItemCount(): Int { - return if (invoiceList != null) { - invoiceList!!.size - } else { - 0 - } - } - - fun setContext(context: Context?) { - this.context = context - } - - fun setData(invoices: List?) { - invoiceList = invoices - notifyDataSetChanged() - } - - inner class ViewHolder(v: View?) : RecyclerView.ViewHolder(v!!) { - @JvmField - @BindView(R.id.tv_invoice_id) - var mTvInvoiceId: TextView? = null - - @JvmField - @BindView(R.id.invoice_status_image) - var mInvoiceImage: ImageView? = null - - @JvmField - @BindView(R.id.tv_invoice_date) - var mTvInvoiceDate: TextView? = null - - @JvmField - @BindView(R.id.tv_invoice_status) - var mTvInvoiceStatus: TextView? = null - - @JvmField - @BindView(R.id.tv_invoice_amount) - var mTvInvoiceAmount: TextView? = null - - @JvmField - @BindView(R.id.tv_invoice_title) - var mTvInvoiceTitle: TextView? = null - - init { - ButterKnife.bind(this, v!!) - } - } -} \ No newline at end of file