mirror of
https://github.com/danilkinkin/buckwheat.git
synced 2025-12-31 04:13:02 +00:00
feat: draft finish budget early logic
This commit is contained in:
parent
505e78f653
commit
87f2d93acf
8 changed files with 364 additions and 56 deletions
|
|
@ -62,6 +62,9 @@ fun Analytics(
|
|||
val spends by spendsViewModel.spends.observeAsState(emptyList())
|
||||
val wholeBudget = spendsViewModel.budget.value!!
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
val finishPeriodActualDate by spendsViewModel.finishPeriodActualDate.observeAsState(null)
|
||||
|
||||
// Need to hide calendar after migration to transactions,
|
||||
// because after migration can't restore some transactions like INCOME & SET_DAILY_BUDGET
|
||||
val afterMigrationToTransactions =
|
||||
|
|
@ -98,6 +101,7 @@ fun Analytics(
|
|||
currency = spendsViewModel.currency.value!!,
|
||||
startDate = spendsViewModel.startPeriodDate.value!!,
|
||||
finishDate = spendsViewModel.finishPeriodDate.value!!,
|
||||
actualFinishDate = finishPeriodActualDate,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
if (spends.isNotEmpty()) {
|
||||
|
|
|
|||
|
|
@ -8,9 +8,12 @@ import androidx.compose.material3.*
|
|||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Path
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.graphics.StrokeCap
|
||||
import androidx.compose.ui.graphics.drawscope.Fill
|
||||
import androidx.compose.ui.layout.*
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
|
|
@ -21,6 +24,7 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.*
|
||||
import androidx.compose.ui.zIndex
|
||||
import com.danilkinkin.buckwheat.R
|
||||
import com.danilkinkin.buckwheat.data.ExtendCurrency
|
||||
import com.danilkinkin.buckwheat.ui.BuckwheatTheme
|
||||
|
|
@ -36,12 +40,13 @@ fun WholeBudgetCard(
|
|||
currency: ExtendCurrency,
|
||||
startDate: Date,
|
||||
finishDate: Date?,
|
||||
actualFinishDate: Date? = null,
|
||||
colors: CardColors = CardDefaults.cardColors(),
|
||||
bigVariant: Boolean = true,
|
||||
contentPadding: PaddingValues = PaddingValues(vertical = 16.dp, horizontal = 24.dp),
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
|
||||
StatCard(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
contentPadding = contentPadding,
|
||||
|
|
@ -83,49 +88,89 @@ fun WholeBudgetCard(
|
|||
.padding(horizontal = if (bigVariant) 16.dp else 8.dp)
|
||||
.fillMaxHeight()
|
||||
)
|
||||
if (finishDate !== null && bigVariant) {
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
if (actualFinishDate !== null && bigVariant) {
|
||||
CountDaysChip(
|
||||
Modifier
|
||||
.align(Alignment.Center)
|
||||
.requiredHeight(24.dp),
|
||||
shape = CircleShape,
|
||||
color = LocalContentColor.current,
|
||||
contentColor = MaterialTheme.colorScheme.surface,
|
||||
.offset(6.dp, (-12).dp)
|
||||
.rotate(6f)
|
||||
.zIndex(1f),
|
||||
fromDate = startDate,
|
||||
toDate = actualFinishDate
|
||||
)
|
||||
Cross(
|
||||
modifier = Modifier.align(Alignment.Center)
|
||||
) {
|
||||
val days = countDays(finishDate, startDate)
|
||||
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(12.dp, 0.dp),
|
||||
text = String.format(
|
||||
pluralStringResource(R.plurals.days_count, count = days),
|
||||
days,
|
||||
),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
}
|
||||
CountDaysChip(
|
||||
Modifier,
|
||||
fromDate = startDate,
|
||||
toDate = finishDate!!
|
||||
)
|
||||
}
|
||||
} else if (finishDate !== null && bigVariant) {
|
||||
CountDaysChip(
|
||||
Modifier.align(Alignment.Center),
|
||||
fromDate = startDate,
|
||||
toDate = finishDate
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Column(horizontalAlignment = Alignment.End) {
|
||||
Text(
|
||||
text = if (finishDate !== null) {
|
||||
prettyDate(
|
||||
finishDate,
|
||||
pattern = "dd MMM",
|
||||
simplifyIfToday = false,
|
||||
Box {
|
||||
if (actualFinishDate !== null) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.offset((-4).dp, (-20).dp)
|
||||
.rotate(6f),
|
||||
text = prettyDate(
|
||||
actualFinishDate,
|
||||
pattern = "dd MMM",
|
||||
simplifyIfToday = false,
|
||||
),
|
||||
softWrap = false,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
fontSize = if (bigVariant) MaterialTheme.typography.bodySmall.fontSize else MaterialTheme.typography.labelSmall.fontSize,
|
||||
)
|
||||
|
||||
Cross {
|
||||
Box(Modifier.wrapContentSize()) {
|
||||
Text(
|
||||
text = if (finishDate !== null) {
|
||||
prettyDate(
|
||||
finishDate,
|
||||
pattern = "dd MMM",
|
||||
simplifyIfToday = false,
|
||||
)
|
||||
} else {
|
||||
"-"
|
||||
},
|
||||
softWrap = false,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
fontSize = if (bigVariant) MaterialTheme.typography.bodySmall.fontSize else MaterialTheme.typography.labelSmall.fontSize,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
"-"
|
||||
},
|
||||
softWrap = false,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
fontSize = if (bigVariant) MaterialTheme.typography.bodySmall.fontSize else MaterialTheme.typography.labelSmall.fontSize,
|
||||
)
|
||||
Text(
|
||||
text = if (finishDate !== null) {
|
||||
prettyDate(
|
||||
finishDate,
|
||||
pattern = "dd MMM",
|
||||
simplifyIfToday = false,
|
||||
)
|
||||
} else {
|
||||
"-"
|
||||
},
|
||||
softWrap = false,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
fontSize = if (bigVariant) MaterialTheme.typography.bodySmall.fontSize else MaterialTheme.typography.labelSmall.fontSize,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
@ -133,6 +178,60 @@ fun WholeBudgetCard(
|
|||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CountDaysChip(modifier: Modifier = Modifier, fromDate: Date, toDate: Date) {
|
||||
Surface(
|
||||
modifier = modifier
|
||||
.requiredHeight(24.dp),
|
||||
shape = CircleShape,
|
||||
color = LocalContentColor.current,
|
||||
contentColor = MaterialTheme.colorScheme.surface,
|
||||
) {
|
||||
val days = countDays(toDate, fromDate)
|
||||
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(12.dp, 0.dp),
|
||||
text = String.format(
|
||||
pluralStringResource(
|
||||
R.plurals.days_count,
|
||||
count = days
|
||||
),
|
||||
days,
|
||||
),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Cross(
|
||||
modifier: Modifier = Modifier,
|
||||
tint: Color = MaterialTheme.colorScheme.error,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Box(modifier = modifier) {
|
||||
content()
|
||||
Canvas(modifier = Modifier.matchParentSize()) {
|
||||
val width = this.size.width
|
||||
val height = this.size.height
|
||||
val offset = Offset(6f, 6f)
|
||||
val thickness = 6f
|
||||
|
||||
drawLine(
|
||||
color = tint,
|
||||
start = Offset(offset.x, height - offset.y),
|
||||
end = Offset(width - offset.x, offset.y),
|
||||
strokeWidth = thickness,
|
||||
cap = StrokeCap.Round
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Arrow(
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -231,7 +330,18 @@ private fun PreviewChart() {
|
|||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview() {
|
||||
private fun PreviewCross() {
|
||||
BuckwheatTheme {
|
||||
Cross {
|
||||
Text(text = "Hello")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Preview(name = "Night mode", uiMode = UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun PreviewEarlyFinish() {
|
||||
BuckwheatTheme {
|
||||
WholeBudgetCard(
|
||||
modifier = Modifier.height(IntrinsicSize.Min),
|
||||
|
|
@ -239,13 +349,15 @@ private fun Preview() {
|
|||
currency = ExtendCurrency.none(),
|
||||
startDate = LocalDate.now().minusDays(28).toDate(),
|
||||
finishDate = Date(),
|
||||
actualFinishDate = LocalDate.now().minusDays(2).toDate(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Preview(name = "Night mode", uiMode = UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun PreviewNightMode() {
|
||||
private fun Preview() {
|
||||
BuckwheatTheme {
|
||||
WholeBudgetCard(
|
||||
modifier = Modifier.height(IntrinsicSize.Min),
|
||||
|
|
|
|||
|
|
@ -34,10 +34,12 @@ class SpendsViewModel @Inject constructor(
|
|||
var spentFromDailyBudget = spendsRepository.getSpentFromDailyBudget().asLiveData()
|
||||
var startPeriodDate = spendsRepository.getStartPeriodDate().asLiveData()
|
||||
var finishPeriodDate = spendsRepository.getFinishPeriodDate().asLiveData()
|
||||
var finishPeriodActualDate = spendsRepository.getFinishPeriodActualDate().asLiveData()
|
||||
var lastChangeDailyBudgetDate = spendsRepository.getLastChangeDailyBudgetDate().asLiveData()
|
||||
|
||||
var currency = spendsRepository.getCurrency().asLiveData()
|
||||
var restedBudgetDistributionMethod = spendsRepository.getRestedBudgetDistributionMethod().asLiveData()
|
||||
var restedBudgetDistributionMethod =
|
||||
spendsRepository.getRestedBudgetDistributionMethod().asLiveData()
|
||||
var hideOverspendingWarn = spendsRepository.getHideOverspendingWarn().asLiveData()
|
||||
|
||||
var requireDistributionRestedBudget = MutableLiveData(false)
|
||||
|
|
@ -61,6 +63,15 @@ class SpendsViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun finishBudget() {
|
||||
viewModelScope.launch {
|
||||
spendsRepository.finishBudget(Date())
|
||||
|
||||
requireSetBudget.value = false
|
||||
periodFinished.value = true
|
||||
}
|
||||
}
|
||||
|
||||
fun setDailyBudget(newDailyBudget: BigDecimal) {
|
||||
viewModelScope.launch {
|
||||
spendsRepository.setDailyBudget(newDailyBudget)
|
||||
|
|
@ -130,24 +141,42 @@ class SpendsViewModel @Inject constructor(
|
|||
viewModelScope.launch {
|
||||
val lastChangeDailyBudgetDate = spendsRepository.getLastChangeDailyBudgetDate().first()
|
||||
val finishPeriodDate = spendsRepository.getFinishPeriodDate().first()
|
||||
val finishPeriodActualDate = spendsRepository.getFinishPeriodActualDate().first()
|
||||
val dailyBudget = spendsRepository.getDailyBudget().first()
|
||||
val spentFromDailyBudget = spendsRepository.getSpentFromDailyBudget().first()
|
||||
val restedBudgetDistributionMethod = spendsRepository.getRestedBudgetDistributionMethod().first()
|
||||
val restedBudgetDistributionMethod =
|
||||
spendsRepository.getRestedBudgetDistributionMethod().first()
|
||||
|
||||
val finishDayNotReached = if (finishPeriodActualDate === null) {
|
||||
finishPeriodDate !== null
|
||||
&& countDaysToToday(finishPeriodDate) > 0
|
||||
} else {
|
||||
countDaysToToday(finishPeriodActualDate) > 0
|
||||
}
|
||||
|
||||
val finishTimeReached = if (finishPeriodActualDate === null) {
|
||||
finishPeriodDate !== null
|
||||
&& finishPeriodDate.time <= Date().time
|
||||
} else {
|
||||
finishPeriodActualDate.time <= Date().time
|
||||
}
|
||||
|
||||
when {
|
||||
lastChangeDailyBudgetDate !== null
|
||||
&& finishPeriodDate !== null
|
||||
&& !isToday(lastChangeDailyBudgetDate)
|
||||
&& countDaysToToday(finishPeriodDate) > 0 -> {
|
||||
&& finishDayNotReached -> {
|
||||
if (dailyBudget - spentFromDailyBudget > BigDecimal.ZERO) {
|
||||
when (restedBudgetDistributionMethod) {
|
||||
RestedBudgetDistributionMethod.ASK -> {
|
||||
requireDistributionRestedBudget.value = true
|
||||
}
|
||||
|
||||
RestedBudgetDistributionMethod.REST -> {
|
||||
val whatBudgetForDay = spendsRepository.whatBudgetForDay(applyTodaySpends = true)
|
||||
val whatBudgetForDay =
|
||||
spendsRepository.whatBudgetForDay(applyTodaySpends = true)
|
||||
setDailyBudget(whatBudgetForDay)
|
||||
}
|
||||
|
||||
RestedBudgetDistributionMethod.ADD_TODAY -> {
|
||||
val notSpent = spendsRepository.howMuchNotSpent(
|
||||
excludeSkippedPart = true,
|
||||
|
|
@ -157,7 +186,8 @@ class SpendsViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
val whatBudgetForDay = spendsRepository.whatBudgetForDay(applyTodaySpends = true)
|
||||
val whatBudgetForDay =
|
||||
spendsRepository.whatBudgetForDay(applyTodaySpends = true)
|
||||
setDailyBudget(whatBudgetForDay)
|
||||
}
|
||||
}
|
||||
|
|
@ -166,7 +196,7 @@ class SpendsViewModel @Inject constructor(
|
|||
requireSetBudget.value = true
|
||||
}
|
||||
|
||||
finishPeriodDate !== null && finishPeriodDate.time <= Date().time -> {
|
||||
finishTimeReached -> {
|
||||
periodFinished.value = true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ val spentFromDailyBudgetStoreKey = stringPreferencesKey("spentFromDailyBudget")
|
|||
val lastChangeDailyBudgetDateStoreKey = longPreferencesKey("lastChangeDailyBudgetDate")
|
||||
val startPeriodDateStoreKey = longPreferencesKey("startPeriodDate")
|
||||
val finishPeriodDateStoreKey = longPreferencesKey("finishPeriodDate")
|
||||
val finishPeriodActualDateStoreKey = longPreferencesKey("finishPeriodActualDate")
|
||||
|
||||
class SpendsRepository @Inject constructor(
|
||||
@ApplicationContext val context: Context,
|
||||
|
|
@ -84,6 +85,10 @@ class SpendsRepository @Inject constructor(
|
|||
it[finishPeriodDateStoreKey]?.let { value -> Date(value) }
|
||||
}
|
||||
|
||||
fun getFinishPeriodActualDate() = context.budgetDataStore.data.map {
|
||||
it[finishPeriodActualDateStoreKey]?.let { value -> Date(value) }
|
||||
}
|
||||
|
||||
fun getLastChangeDailyBudgetDate() = context.budgetDataStore.data.map {
|
||||
it[lastChangeDailyBudgetDateStoreKey]?.let { value -> Date(value) }
|
||||
}
|
||||
|
|
@ -157,6 +162,22 @@ class SpendsRepository @Inject constructor(
|
|||
hideOverspendingWarn(false)
|
||||
}
|
||||
|
||||
suspend fun finishBudget(finishDate: Date) {
|
||||
context.budgetDataStore.edit {
|
||||
it[finishPeriodActualDateStoreKey] = finishDate.time
|
||||
|
||||
Log.d(
|
||||
"SpendsRepository",
|
||||
"Finish budget ["
|
||||
+ "budget: ${it[budgetStoreKey]} "
|
||||
+ "start date: ${Date(it[startPeriodDateStoreKey]!!)} "
|
||||
+ "actual finish date: ${Date(it[finishPeriodActualDateStoreKey]!!)}"
|
||||
+ "finish date: ${Date(it[finishPeriodDateStoreKey]!!)}"
|
||||
+ "]"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun setDailyBudget(newDailyBudget: BigDecimal) {
|
||||
context.budgetDataStore.edit {
|
||||
val spent: BigDecimal = it[spentStoreKey]?.toBigDecimal()!!
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ fun CustomCurrencyEditor(
|
|||
}
|
||||
|
||||
@Preview(name = "Default")
|
||||
@Preview(name = "Night mode", uiMode = UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun PreviewDefault() {
|
||||
BuckwheatTheme {
|
||||
|
|
@ -184,15 +185,3 @@ private fun PreviewDefault() {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(name = "Night mode", uiMode = UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun PreviewNightMode() {
|
||||
BuckwheatTheme {
|
||||
CustomCurrencyEditorContent(
|
||||
defaultCurrency = "",
|
||||
onChange = { },
|
||||
onClose = { }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
package com.danilkinkin.buckwheat.wallet
|
||||
|
||||
import OverrideLocalize
|
||||
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.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import com.danilkinkin.buckwheat.R
|
||||
import com.danilkinkin.buckwheat.base.RenderAdaptivePane
|
||||
import com.danilkinkin.buckwheat.ui.BuckwheatTheme
|
||||
|
||||
|
||||
@Composable
|
||||
fun ConfirmFinishEarly(
|
||||
onConfirm: () -> Unit,
|
||||
onClose: () -> Unit,
|
||||
) {
|
||||
Card(
|
||||
shape = MaterialTheme.shapes.extraLarge,
|
||||
modifier = Modifier
|
||||
.widthIn(max = 440.dp)
|
||||
.padding(36.dp)
|
||||
) {
|
||||
Column {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxWidth().padding(top = 24.dp, bottom = 16.dp),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_priority_high),
|
||||
tint = LocalContentColor.current.copy(alpha = 0.7f),
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = stringResource(R.string.confirm_finish_budget_title),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 24.dp)
|
||||
.padding(bottom = 24.dp)
|
||||
.fillMaxWidth(),
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.confirm_finish_budget_description),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
modifier = Modifier.padding(horizontal = 24.dp),
|
||||
)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.End,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 12.dp, horizontal = 16.dp),
|
||||
) {
|
||||
Button(
|
||||
onClick = { onClose() },
|
||||
colors = ButtonDefaults.textButtonColors(),
|
||||
contentPadding = ButtonDefaults.TextButtonContentPadding,
|
||||
) {
|
||||
Text(text = stringResource(R.string.cancel))
|
||||
}
|
||||
Button(
|
||||
onClick = {
|
||||
onConfirm()
|
||||
onClose()
|
||||
},
|
||||
colors = ButtonDefaults.textButtonColors(),
|
||||
contentPadding = ButtonDefaults.TextButtonContentPadding,
|
||||
) {
|
||||
Text(text = stringResource(R.string.confirm_finish_budget))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ConfirmFinishEarlyDialog(
|
||||
onConfirm: () -> Unit,
|
||||
onClose: () -> Unit,
|
||||
) {
|
||||
Dialog(
|
||||
onDismissRequest = { onClose() },
|
||||
properties = DialogProperties(usePlatformDefaultWidth = false)
|
||||
) {
|
||||
OverrideLocalize {
|
||||
RenderAdaptivePane {
|
||||
ConfirmFinishEarly(
|
||||
onConfirm = onConfirm,
|
||||
onClose = onClose
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun PreviewDefault() {
|
||||
BuckwheatTheme {
|
||||
ConfirmFinishEarly({}, {})
|
||||
}
|
||||
}
|
||||
|
|
@ -65,6 +65,7 @@ fun Wallet(
|
|||
(budgetCache - spent - spentFromDailyBudget)
|
||||
|
||||
val openConfirmChangeBudgetDialog = remember { mutableStateOf(false) }
|
||||
val openConfirmFinishBudgetDialog = remember { mutableStateOf(false) }
|
||||
|
||||
if (spends === null) return
|
||||
|
||||
|
|
@ -265,6 +266,18 @@ fun Wallet(
|
|||
text = stringResource(R.string.export_to_csv),
|
||||
onClick = { exportCSVLaunch() }
|
||||
)
|
||||
|
||||
CompositionLocalProvider(
|
||||
LocalContentColor provides MaterialTheme.colorScheme.error
|
||||
) {
|
||||
ButtonRow(
|
||||
icon = painterResource(R.drawable.ic_close),
|
||||
text = stringResource(R.string.finish_early),
|
||||
onClick = {
|
||||
openConfirmFinishBudgetDialog.value = true
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(
|
||||
|
|
@ -344,6 +357,18 @@ fun Wallet(
|
|||
onClose = { openConfirmChangeBudgetDialog.value = false },
|
||||
)
|
||||
}
|
||||
|
||||
if (openConfirmFinishBudgetDialog.value) {
|
||||
ConfirmFinishEarlyDialog(
|
||||
onConfirm = {
|
||||
spendsViewModel.finishBudget()
|
||||
|
||||
onClose()
|
||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
},
|
||||
onClose = { openConfirmFinishBudgetDialog.value = false },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
|
|
|
|||
|
|
@ -149,4 +149,8 @@
|
|||
<string name="history_title">History</string>
|
||||
<string name="view_analytics">View analytics</string>
|
||||
<string name="analytics_title">Analytics</string>
|
||||
<string name="finish_early">Finish early</string>
|
||||
<string name="confirm_finish_budget_title">Finish budget</string>
|
||||
<string name="confirm_finish_budget_description">Your current budget finished</string>
|
||||
<string name="confirm_finish_budget">Finish budget</string>
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue