Skip to content
This repository has been archived by the owner on Nov 5, 2024. It is now read-only.

Commit

Permalink
Connect the manual CSV import screen
Browse files Browse the repository at this point in the history
  • Loading branch information
ILIYANGERMANOV committed Apr 15, 2023
1 parent c79c0bb commit f789d33
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 10 deletions.
2 changes: 2 additions & 0 deletions app/src/main/java/com/ivy/wallet/ui/RootActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import com.ivy.wallet.ui.balance.BalanceScreen
import com.ivy.wallet.ui.budget.BudgetScreen
import com.ivy.wallet.ui.category.CategoriesScreen
import com.ivy.wallet.ui.charts.ChartsScreen
import com.ivy.wallet.ui.csv.CSVScreen
import com.ivy.wallet.ui.csvimport.ImportCSVScreen
import com.ivy.wallet.ui.donate.DonateScreen
import com.ivy.wallet.ui.edit.EditTransactionScreen
Expand Down Expand Up @@ -218,6 +219,7 @@ class RootActivity : AppCompatActivity() {
is ImagesScreen -> ImagesScreen(screen = screen)
is ExperimentalScreen -> ExperimentalScreen(screen = screen)
is DonateScreen -> DonateScreen(screen = screen)
is CSVScreen -> CSVScreen()
null -> {
}
}
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/ivy/wallet/ui/Screens.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ object Onboarding : Screen

object ServerStop : Screen

object CSVScreen : Screen

data class EditTransaction(
val initialTransactionId: UUID?,
val type: TransactionType,
Expand Down
6 changes: 4 additions & 2 deletions app/src/main/java/com/ivy/wallet/ui/csv/CSVScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ private fun UI(
spacer8()
csvTable(state.csv)
}

if (state.columns != null && state.important != null) {
important(state.columns, importantFields = state.important, onEvent = onEvent)
}
}
}

Expand Down Expand Up @@ -96,7 +98,7 @@ fun Spacer8(horizontal: Boolean = false) {
private fun LazyListScope.csvTable(
csv: List<CSVRow>
) {
itemsIndexed(items = csv) { index, row ->
itemsIndexed(items = csv.take(10)) { index, row ->
CSVRow(row = row, header = index == 0, even = index % 2 == 0)
}
}
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/ivy/wallet/ui/csv/CSVState.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.ivy.wallet.ui.csv

data class CSVState(
val columns: CSVRow,
val columns: CSVRow?,
val csv: List<CSVRow>?,
val important: ImportantFields?,
val transfer: TransferFields?,
val optional: OptionalFields?,

val successPercent: Double,
val successPercent: Double?,
val failedRows: List<CSVRow>?,
)

Expand Down
77 changes: 72 additions & 5 deletions app/src/main/java/com/ivy/wallet/ui/csv/CSVViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,27 +1,94 @@
package com.ivy.wallet.ui.csv

import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.ivy.wallet.domain.deprecated.logic.csv.CSVNormalizer
import com.ivy.wallet.domain.deprecated.logic.csv.IvyFileReader
import com.opencsv.CSVReaderBuilder
import com.opencsv.validators.LineValidator
import com.opencsv.validators.RowValidator
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.StringReader
import javax.inject.Inject

@HiltViewModel
class CSVViewModel @Inject constructor(

private val fileReader: IvyFileReader,
) : ViewModel() {

private var columns by mutableStateOf<CSVRow?>(null)
private var csv by mutableStateOf<List<CSVRow>?>(null)
private var important by mutableStateOf<ImportantFields?>(null)
private var transfer by mutableStateOf<TransferFields?>(null)
private var optional by mutableStateOf<OptionalFields?>(null)
private var successPercent by mutableStateOf<Double?>(null)
private var failedRows by mutableStateOf<List<CSVRow>?>(null)

@Composable
fun uiState(): CSVState = TODO()
fun uiState(): CSVState = CSVState(
columns = columns,
csv = csv,
important = important,
transfer = transfer,
optional = optional,
successPercent = successPercent,
failedRows = failedRows,
)


private suspend fun handleEvent(event: CSVEvent) {
when (event) {
is CSVEvent.FilePicked -> handleFilePicked(event)
is CSVEvent.AmountMultiplier -> TODO()
is CSVEvent.DataMetaChange -> TODO()
is CSVEvent.MapAccount -> TODO()
is CSVEvent.MapAccountCurrency -> TODO()
is CSVEvent.MapAmount -> TODO()
is CSVEvent.MapDate -> TODO()
is CSVEvent.MapType -> TODO()
is CSVEvent.TypeMetaChange -> TODO()
}
}

private suspend fun handleFilePicked(event: CSVEvent.FilePicked) = withContext(Dispatchers.IO) {
val fileContent = fileReader.read(event.uri, Charsets.UTF_8) ?: return@withContext
csv = parseCSV(fileContent).takeIf { it.isNotEmpty() }
}

private suspend fun parseCSV(csv: String): List<CSVRow> {
val csvReader = CSVReaderBuilder(StringReader(csv))
.withSkipLines(1)
.withLineValidator(object : LineValidator {
override fun isValid(line: String?): Boolean {
return true
}

override fun validate(line: String?) {
//do nothing
}

})
.withRowValidator(object : RowValidator {
override fun isValid(row: Array<out String>?): Boolean {
return true
}

override fun validate(row: Array<out String>?) {
//do nothing
}
})
.build()

return csvReader.readAll()
.map { CSVRow(it.toList()) }
}


Expand Down
19 changes: 19 additions & 0 deletions app/src/main/java/com/ivy/wallet/ui/csvimport/flow/ImportFrom.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
Expand All @@ -24,7 +25,9 @@ import com.ivy.design.l0_system.style
import com.ivy.frp.view.navigation.navigation
import com.ivy.wallet.R
import com.ivy.wallet.domain.deprecated.logic.csv.model.ImportType
import com.ivy.wallet.ui.CSVScreen
import com.ivy.wallet.ui.IvyWalletPreview
import com.ivy.wallet.ui.ivyWalletCtx
import com.ivy.wallet.ui.onboarding.components.OnboardingToolbar
import com.ivy.wallet.ui.theme.components.GradientCutBottom
import com.ivy.wallet.ui.theme.components.IvyIcon
Expand Down Expand Up @@ -55,6 +58,22 @@ fun BoxWithConstraintsScope.ImportFrom(
//onboarding toolbar include paddingBottom 16.dp
}

item {
Spacer(Modifier.height(8.dp))
val nav = navigation()
Button(
modifier = Modifier
.fillMaxWidth()
.height(64.dp)
.padding(horizontal = 16.dp),
onClick = {
nav.navigateTo(CSVScreen)
}
) {
Text(text = "Manual CSV import")
}
}

item {
Spacer(Modifier.height(8.dp))

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.ivy.wallet.ui.csvimport.flow

import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
Expand All @@ -14,6 +15,7 @@ import com.ivy.design.l0_system.style
import com.ivy.frp.view.navigation.navigation
import com.ivy.wallet.R
import com.ivy.wallet.domain.deprecated.logic.csv.model.ImportResult
import com.ivy.wallet.ui.CSVScreen
import com.ivy.wallet.ui.IvyWalletPreview
import com.ivy.wallet.ui.theme.*
import com.ivy.wallet.ui.theme.components.BackButton
Expand Down Expand Up @@ -139,7 +141,10 @@ fun ImportResultUI(

Text(
modifier = Modifier.padding(horizontal = 32.dp),
text = stringResource(R.string.rows_from_csv_not_recognized, result.rowsFound - result.transactionsImported),
text = stringResource(
R.string.rows_from_csv_not_recognized,
result.rowsFound - result.transactionsImported
),
style = UI.typo.nB2.style(
fontWeight = FontWeight.Bold,
color = Gray
Expand All @@ -148,6 +153,27 @@ fun ImportResultUI(

//TODO: Implement "See failed imports"

Spacer(modifier = Modifier.height(16.dp))
Text(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
text = "If this didn't work, Try manual CSV import.",
color = UI.colors.pureInverse,
)
Spacer(modifier = Modifier.height(8.dp))
Button(
modifier = Modifier
.fillMaxWidth()
.height(52.dp)
.padding(horizontal = 16.dp),
onClick = {
nav.navigateTo(CSVScreen)
}
) {
Text(text = "Manual CSV import")
}

Spacer(Modifier.weight(1f))

OnboardingButton(
Expand Down

0 comments on commit f789d33

Please sign in to comment.