init #48
@@ -2,6 +2,7 @@ package cc.n0th1ng.tripmoney.data.dao
|
|||||||
|
|
||||||
import androidx.paging.PagingSource
|
import androidx.paging.PagingSource
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import androidx.room.Upsert
|
import androidx.room.Upsert
|
||||||
@@ -19,4 +20,6 @@ interface TripDao {
|
|||||||
)
|
)
|
||||||
fun tripsPaged(): PagingSource<Int, Trip>
|
fun tripsPaged(): PagingSource<Int, Trip>
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun delete(trip: Trip)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,4 +22,9 @@ class TripRepository @Inject constructor(private val tripDao: TripDao) {
|
|||||||
pagingSourceFactory = { tripDao.tripsPaged() }
|
pagingSourceFactory = { tripDao.tripsPaged() }
|
||||||
).flow
|
).flow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
suspend fun delete(trip: Trip) {
|
||||||
|
tripDao.delete(trip)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -38,6 +38,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.core.graphics.toColorInt
|
import androidx.core.graphics.toColorInt
|
||||||
|
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||||
import cc.n0th1ng.tripmoney.R
|
import cc.n0th1ng.tripmoney.R
|
||||||
import cc.n0th1ng.tripmoney.data.entity.Category
|
import cc.n0th1ng.tripmoney.data.entity.Category
|
||||||
import cc.n0th1ng.tripmoney.data.entity.Expense
|
import cc.n0th1ng.tripmoney.data.entity.Expense
|
||||||
@@ -46,9 +47,11 @@ import cc.n0th1ng.tripmoney.screens.listexpense.CategorySelectionDialog
|
|||||||
import cc.n0th1ng.tripmoney.screens.listexpense.CurrencySelectionDialog
|
import cc.n0th1ng.tripmoney.screens.listexpense.CurrencySelectionDialog
|
||||||
import cc.n0th1ng.tripmoney.screens.listexpense.DateTimePicker
|
import cc.n0th1ng.tripmoney.screens.listexpense.DateTimePicker
|
||||||
import cc.n0th1ng.tripmoney.theme.TripMoneyTheme
|
import cc.n0th1ng.tripmoney.theme.TripMoneyTheme
|
||||||
|
import cc.n0th1ng.tripmoney.utils.Currencies
|
||||||
import cc.n0th1ng.tripmoney.viewmodel.ExpenseAndCategoryViewModel
|
import cc.n0th1ng.tripmoney.viewmodel.ExpenseAndCategoryViewModel
|
||||||
import cc.n0th1ng.tripmoney.viewmodel.SettingsViewModel
|
import cc.n0th1ng.tripmoney.viewmodel.SettingsViewModel
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@@ -57,11 +60,10 @@ import java.time.LocalDateTime
|
|||||||
fun AddExpenseBottomSheet(
|
fun AddExpenseBottomSheet(
|
||||||
onSave: (Expense) -> Unit,
|
onSave: (Expense) -> Unit,
|
||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
settingsViewModel: SettingsViewModel,
|
|
||||||
categories: List<Category>,
|
categories: List<Category>,
|
||||||
expenseAndCategoryViewModel: ExpenseAndCategoryViewModel,
|
|
||||||
expenseDtoToEdit: ExpenseDto?
|
expenseDtoToEdit: ExpenseDto?
|
||||||
) {
|
) {
|
||||||
|
val settingsViewModel: SettingsViewModel = hiltViewModel()
|
||||||
val currentTripId by settingsViewModel.currentTrip.collectAsState()
|
val currentTripId by settingsViewModel.currentTrip.collectAsState()
|
||||||
var amount by remember {
|
var amount by remember {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
@@ -70,11 +72,18 @@ fun AddExpenseBottomSheet(
|
|||||||
}
|
}
|
||||||
var showCurrencyDialog by remember { mutableStateOf(false) }
|
var showCurrencyDialog by remember { mutableStateOf(false) }
|
||||||
var showCategoryDialog by remember { mutableStateOf(false) }
|
var showCategoryDialog by remember { mutableStateOf(false) }
|
||||||
var currency by remember { mutableStateOf(expenseDtoToEdit?.expense?.currency ?: "PLN") }
|
var showDateTimePicker by remember { mutableStateOf(false) }
|
||||||
|
var currency by remember {
|
||||||
|
mutableStateOf(
|
||||||
|
expenseDtoToEdit?.expense?.currency ?: Currencies.PLN.name
|
||||||
|
)
|
||||||
|
}
|
||||||
var category by remember { mutableStateOf(expenseDtoToEdit?.category ?: categories[0]) }
|
var category by remember { mutableStateOf(expenseDtoToEdit?.category ?: categories[0]) }
|
||||||
var datetime by remember {
|
var datetime by remember {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
LocalDateTime.parse(expenseDtoToEdit?.expense?.datetime ?: LocalDateTime.now().toString())
|
LocalDateTime.parse(
|
||||||
|
expenseDtoToEdit?.expense?.datetime ?: LocalDateTime.now().toString()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
var note by remember { mutableStateOf(expenseDtoToEdit?.expense?.note ?: "") }
|
var note by remember { mutableStateOf(expenseDtoToEdit?.expense?.note ?: "") }
|
||||||
@@ -103,10 +112,12 @@ fun AddExpenseBottomSheet(
|
|||||||
CurrencyButton(onClick = { showCurrencyDialog = true }, text = currency)
|
CurrencyButton(onClick = { showCurrencyDialog = true }, text = currency)
|
||||||
}
|
}
|
||||||
Spacer(Modifier.height(14.dp))
|
Spacer(Modifier.height(14.dp))
|
||||||
DateTimePicker(
|
OutlinedButton(onClick = { showDateTimePicker = true }) {
|
||||||
dateTime = datetime,
|
Text(
|
||||||
onChange = { datetime = it }
|
text = datetime.format(DateTimeFormatter.ofPattern("dd.MM HH:mm")),
|
||||||
)
|
fontSize = 17.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
Spacer(Modifier.height(14.dp))
|
Spacer(Modifier.height(14.dp))
|
||||||
CategoryButton(onClick = { showCategoryDialog = true }, category = category)
|
CategoryButton(onClick = { showCategoryDialog = true }, category = category)
|
||||||
Spacer(Modifier.height(14.dp))
|
Spacer(Modifier.height(14.dp))
|
||||||
@@ -155,7 +166,12 @@ fun AddExpenseBottomSheet(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showDateTimePicker) {
|
||||||
|
DateTimePicker(datetime, onChange = { newDateTime ->
|
||||||
|
datetime = newDateTime
|
||||||
|
showDateTimePicker = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (showCurrencyDialog) {
|
if (showCurrencyDialog) {
|
||||||
CurrencySelectionDialog(
|
CurrencySelectionDialog(
|
||||||
@@ -164,8 +180,7 @@ fun AddExpenseBottomSheet(
|
|||||||
showCurrencyDialog = false
|
showCurrencyDialog = false
|
||||||
currency = selectedCurrency
|
currency = selectedCurrency
|
||||||
},
|
},
|
||||||
selected = currency,
|
selected = currency
|
||||||
listOfCurrencies = listOf("PLN", "EUR", "USD")
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,8 +192,7 @@ fun AddExpenseBottomSheet(
|
|||||||
category = selectedCategory
|
category = selectedCategory
|
||||||
},
|
},
|
||||||
selected = category,
|
selected = category,
|
||||||
categories = categories,
|
categories = categories
|
||||||
settingsAndCategoryViewModel = expenseAndCategoryViewModel
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import androidx.compose.ui.res.painterResource
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.graphics.toColorInt
|
import androidx.core.graphics.toColorInt
|
||||||
|
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||||
import cc.n0th1ng.tripmoney.R.*
|
import cc.n0th1ng.tripmoney.R.*
|
||||||
import cc.n0th1ng.tripmoney.data.entity.Category
|
import cc.n0th1ng.tripmoney.data.entity.Category
|
||||||
import cc.n0th1ng.tripmoney.screens.AddCategoryDialog
|
import cc.n0th1ng.tripmoney.screens.AddCategoryDialog
|
||||||
@@ -36,9 +37,9 @@ fun CategorySelectionDialog(
|
|||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
onCategorySelected: (Category) -> Unit,
|
onCategorySelected: (Category) -> Unit,
|
||||||
selected: Category,
|
selected: Category,
|
||||||
categories: List<Category>,
|
categories: List<Category>
|
||||||
settingsAndCategoryViewModel: ExpenseAndCategoryViewModel
|
|
||||||
) {
|
) {
|
||||||
|
val expenseAndCategoryViewModel: ExpenseAndCategoryViewModel = hiltViewModel()
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
var showAddCategoryDialog by remember { mutableStateOf(false) }
|
var showAddCategoryDialog by remember { mutableStateOf(false) }
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
@@ -99,7 +100,7 @@ fun CategorySelectionDialog(
|
|||||||
AddCategoryDialog(onDismiss = {
|
AddCategoryDialog(onDismiss = {
|
||||||
showAddCategoryDialog = false
|
showAddCategoryDialog = false
|
||||||
}, onSave = { category ->
|
}, onSave = { category ->
|
||||||
settingsAndCategoryViewModel.save(category)
|
expenseAndCategoryViewModel.save(category)
|
||||||
showAddCategoryDialog = false
|
showAddCategoryDialog = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,20 +14,20 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import cc.n0th1ng.tripmoney.R
|
import cc.n0th1ng.tripmoney.R
|
||||||
|
import cc.n0th1ng.tripmoney.utils.Currencies
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CurrencySelectionDialog(
|
fun CurrencySelectionDialog(
|
||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
onCurrencySelected: (String) -> Unit,
|
onCurrencySelected: (String) -> Unit,
|
||||||
selected: String,
|
selected: String
|
||||||
listOfCurrencies: List<String>
|
|
||||||
) {
|
) {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
title = { Text(stringResource(R.string.pick_currency)) },
|
title = { Text(stringResource(R.string.pick_currency)) },
|
||||||
text = {
|
text = {
|
||||||
Column {
|
Column {
|
||||||
listOfCurrencies.forEach { currency ->
|
Currencies.names().forEach { currency ->
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|||||||
@@ -5,11 +5,13 @@ import androidx.annotation.RequiresApi
|
|||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.DatePicker
|
import androidx.compose.material3.DatePicker
|
||||||
import androidx.compose.material3.DatePickerDialog
|
import androidx.compose.material3.DatePickerDialog
|
||||||
|
import androidx.compose.material3.DatePickerState
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TimePicker
|
import androidx.compose.material3.TimePicker
|
||||||
|
import androidx.compose.material3.TimePickerState
|
||||||
import androidx.compose.material3.rememberDatePickerState
|
import androidx.compose.material3.rememberDatePickerState
|
||||||
import androidx.compose.material3.rememberTimePickerState
|
import androidx.compose.material3.rememberTimePickerState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -20,11 +22,73 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import cc.n0th1ng.tripmoney.R.*
|
import cc.n0th1ng.tripmoney.R.*
|
||||||
|
import java.sql.Time
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
import java.time.ZoneId
|
import java.time.ZoneId
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
import java.util.Calendar
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun DatePicker(
|
||||||
|
dateTime: LocalDate = LocalDate.now(),
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
onConfirm: (LocalDate) -> Unit
|
||||||
|
) {
|
||||||
|
val datePickerState =
|
||||||
|
rememberDatePickerState(initialSelectedDateMillis = dateTime.toEpochMilli())
|
||||||
|
|
||||||
|
DatePickerDialog(
|
||||||
|
onDismissRequest = onDismiss,
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = {
|
||||||
|
val selectedMillis = datePickerState.selectedDateMillis
|
||||||
|
if (selectedMillis != null) {
|
||||||
|
val selectedDate = Instant.ofEpochMilli(selectedMillis)
|
||||||
|
.atZone(ZoneId.systemDefault())
|
||||||
|
.toLocalDate()
|
||||||
|
onConfirm(selectedDate)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("OK")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = onDismiss) { Text(stringResource(string.cancel)) }
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
DatePicker(state = datePickerState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun TimePicker(onDismiss: () -> Unit, onConfirm: (TimePickerState) -> Unit) {
|
||||||
|
val currentTime = Calendar.getInstance()
|
||||||
|
val timePickerState = rememberTimePickerState(
|
||||||
|
initialHour = currentTime.get(Calendar.HOUR_OF_DAY),
|
||||||
|
initialMinute = currentTime.get(Calendar.MINUTE),
|
||||||
|
is24Hour = true
|
||||||
|
)
|
||||||
|
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = onDismiss,
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = { onConfirm(timePickerState) }) {
|
||||||
|
Text("OK")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = onDismiss) { Text(stringResource(string.cancel)) }
|
||||||
|
},
|
||||||
|
text = { TimePicker(state = timePickerState) }
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
@@ -33,76 +97,34 @@ fun DateTimePicker(
|
|||||||
dateTime: LocalDateTime = LocalDateTime.now(),
|
dateTime: LocalDateTime = LocalDateTime.now(),
|
||||||
onChange: (LocalDateTime) -> Unit
|
onChange: (LocalDateTime) -> Unit
|
||||||
) {
|
) {
|
||||||
val datePickerState =
|
|
||||||
rememberDatePickerState(initialSelectedDateMillis = dateTime.toEpochMilli())
|
|
||||||
val timePickerState = rememberTimePickerState(
|
|
||||||
initialHour = dateTime.hour,
|
|
||||||
initialMinute = dateTime.minute
|
|
||||||
)
|
|
||||||
|
|
||||||
var showDatePicker by remember { mutableStateOf(false) }
|
var showDatePicker by remember { mutableStateOf(true) }
|
||||||
var showTimePicker by remember { mutableStateOf(false) }
|
var showTimePicker by remember { mutableStateOf(false) }
|
||||||
|
var date by remember { mutableStateOf(dateTime.toLocalDate()) }
|
||||||
|
|
||||||
val formatter = DateTimeFormatter.ofPattern("dd.MM HH:mm")
|
|
||||||
OutlinedButton(onClick = { showDatePicker = true }) {
|
|
||||||
Text(text = dateTime.format(formatter), fontSize = 17.sp)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (showDatePicker) {
|
if (showDatePicker) {
|
||||||
DatePickerDialog(
|
DatePicker(onDismiss = { showDatePicker = false }, onConfirm = { newDate ->
|
||||||
onDismissRequest = { showDatePicker = false },
|
date = newDate
|
||||||
confirmButton = {
|
})
|
||||||
TextButton(onClick = {
|
|
||||||
showDatePicker = false
|
|
||||||
val selectedMillis = datePickerState.selectedDateMillis
|
|
||||||
if (selectedMillis != null) {
|
|
||||||
val selectedDate = Instant.ofEpochMilli(selectedMillis)
|
|
||||||
.atZone(ZoneId.systemDefault())
|
|
||||||
.toLocalDate()
|
|
||||||
// open time picker next
|
|
||||||
showTimePicker = true
|
|
||||||
onChange(
|
|
||||||
LocalDateTime.of(
|
|
||||||
selectedDate,
|
|
||||||
dateTime.toLocalTime()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Text("OK")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dismissButton = {
|
|
||||||
TextButton(onClick = {
|
|
||||||
showDatePicker = false
|
|
||||||
}) { Text(stringResource(string.cancel)) }
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
DatePicker(state = datePickerState)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showTimePicker) {
|
if (showTimePicker) {
|
||||||
AlertDialog(
|
TimePicker(onDismiss = {
|
||||||
onDismissRequest = { showTimePicker = false },
|
showTimePicker = false
|
||||||
confirmButton = {
|
showDatePicker = true
|
||||||
TextButton(onClick = {
|
}, onConfirm = { timePickerState ->
|
||||||
showTimePicker = false
|
showTimePicker = false
|
||||||
val newTime = LocalTime.of(timePickerState.hour, timePickerState.minute)
|
showDatePicker = true
|
||||||
onChange(LocalDateTime.of(dateTime.toLocalDate(), newTime))
|
val newTime = LocalTime.of(timePickerState.hour, timePickerState.minute)
|
||||||
}) {
|
onChange(LocalDateTime.of(date, newTime))
|
||||||
Text("OK")
|
})
|
||||||
}
|
|
||||||
},
|
|
||||||
dismissButton = {
|
|
||||||
TextButton(onClick = { showTimePicker = false }) { Text(stringResource(string.cancel)) }
|
|
||||||
},
|
|
||||||
text = { TimePicker(state = timePickerState) }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
fun LocalDateTime.toEpochMilli(): Long =
|
fun LocalDateTime.toEpochMilli(): Long =
|
||||||
this.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
|
this.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
fun LocalDate.toEpochMilli(): Long =
|
||||||
|
this.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
|
||||||
@@ -2,7 +2,6 @@ package cc.n0th1ng.tripmoney.screens.listexpense
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.activity.viewModels
|
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@@ -53,7 +52,7 @@ import androidx.compose.ui.unit.sp
|
|||||||
import androidx.core.graphics.toColorInt
|
import androidx.core.graphics.toColorInt
|
||||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import cc.n0th1ng.tripmoney.R.*
|
import cc.n0th1ng.tripmoney.R.string
|
||||||
import cc.n0th1ng.tripmoney.data.entity.Expense
|
import cc.n0th1ng.tripmoney.data.entity.Expense
|
||||||
import cc.n0th1ng.tripmoney.data.entity.ExpenseDto
|
import cc.n0th1ng.tripmoney.data.entity.ExpenseDto
|
||||||
import cc.n0th1ng.tripmoney.screens.addexpense.AddExpenseBottomSheet
|
import cc.n0th1ng.tripmoney.screens.addexpense.AddExpenseBottomSheet
|
||||||
@@ -61,7 +60,6 @@ import cc.n0th1ng.tripmoney.viewmodel.ExpenseAndCategoryViewModel
|
|||||||
import cc.n0th1ng.tripmoney.viewmodel.SettingsViewModel
|
import cc.n0th1ng.tripmoney.viewmodel.SettingsViewModel
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
import kotlin.getValue
|
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@@ -145,9 +143,7 @@ fun ListExpenseScreen() {
|
|||||||
expenseDtoToEdit = null
|
expenseDtoToEdit = null
|
||||||
showBottomSheet = false
|
showBottomSheet = false
|
||||||
},
|
},
|
||||||
settingsViewModel = settingsViewModel,
|
|
||||||
categories = categories,
|
categories = categories,
|
||||||
expenseAndCategoryViewModel = expenseAndCategoryViewModel,
|
|
||||||
expenseDtoToEdit = expenseDtoToEdit
|
expenseDtoToEdit = expenseDtoToEdit
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -287,8 +283,8 @@ fun ExpenseCard(expenseDto: ExpenseDto, onClick: (ExpenseDto) -> Unit) {
|
|||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.padding(vertical = 8.dp)
|
.padding(vertical = 8.dp)
|
||||||
) {
|
) {
|
||||||
Column(
|
Column()
|
||||||
) {
|
{
|
||||||
Text(
|
Text(
|
||||||
text = expenseDto.category.name,
|
text = expenseDto.category.name,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
package cc.n0th1ng.tripmoney.screens.trippicker
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Check
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
|
import androidx.compose.material3.OutlinedButton
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextButton
|
||||||
|
import androidx.compose.material3.rememberModalBottomSheetState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import cc.n0th1ng.tripmoney.R
|
||||||
|
import cc.n0th1ng.tripmoney.R.string
|
||||||
|
import cc.n0th1ng.tripmoney.data.entity.Trip
|
||||||
|
import cc.n0th1ng.tripmoney.screens.addexpense.CurrencyButton
|
||||||
|
import cc.n0th1ng.tripmoney.screens.addexpense.isDoubleTwoDigitsAboveZero
|
||||||
|
import cc.n0th1ng.tripmoney.screens.listexpense.CurrencySelectionDialog
|
||||||
|
import cc.n0th1ng.tripmoney.screens.listexpense.DatePicker
|
||||||
|
import cc.n0th1ng.tripmoney.screens.listexpense.DateTimePicker
|
||||||
|
import cc.n0th1ng.tripmoney.utils.Currencies
|
||||||
|
import java.time.Instant
|
||||||
|
import java.time.LocalDate
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.ZoneId
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun AddTripBottomSheet(onDismiss: () -> Unit, onSave: (Trip) -> Unit, tripToEdit: Trip?) {
|
||||||
|
|
||||||
|
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||||
|
var name by remember { mutableStateOf(tripToEdit?.name ?: "") }
|
||||||
|
var startDate by remember {
|
||||||
|
mutableStateOf(
|
||||||
|
LocalDate.parse(tripToEdit?.startDate ?: LocalDate.now().toString())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
var showCurrencyDialog by remember { mutableStateOf(false) }
|
||||||
|
var showDatePicker by remember { mutableStateOf(false) }
|
||||||
|
var currency by remember { mutableStateOf(tripToEdit?.currency ?: Currencies.default().name) }
|
||||||
|
var enableSave by remember { mutableStateOf(tripToEdit != null) }
|
||||||
|
|
||||||
|
ModalBottomSheet(
|
||||||
|
onDismissRequest = onDismiss,
|
||||||
|
sheetState = sheetState,
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp),
|
||||||
|
horizontalAlignment = Alignment.Start
|
||||||
|
) {
|
||||||
|
NameInput(name = name, onTextChange = { newText ->
|
||||||
|
name = newText
|
||||||
|
enableSave = !name.isEmpty()
|
||||||
|
})
|
||||||
|
CurrencyButton(onClick = {showCurrencyDialog = true}, currency)
|
||||||
|
OutlinedButton(onClick = { showDatePicker = true }) {
|
||||||
|
Text(
|
||||||
|
text = startDate.format(DateTimeFormatter.ofPattern("dd.MM.yyyy")),
|
||||||
|
fontSize = 17.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
OutlinedButton(
|
||||||
|
enabled = enableSave,
|
||||||
|
onClick = {
|
||||||
|
onSave(Trip(name = name, startDate = startDate.toString(), currency = currency))
|
||||||
|
}) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.Check,
|
||||||
|
contentDescription = stringResource(R.string.save)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showCurrencyDialog) {
|
||||||
|
CurrencySelectionDialog(
|
||||||
|
onDismiss = { showCurrencyDialog = false },
|
||||||
|
onCurrencySelected = { selectedCurrency ->
|
||||||
|
showCurrencyDialog = false
|
||||||
|
currency = selectedCurrency
|
||||||
|
},
|
||||||
|
selected = currency
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showDatePicker) {
|
||||||
|
DatePicker(startDate, onDismiss = {showDatePicker = false}, onConfirm = { newDate ->
|
||||||
|
startDate = newDate
|
||||||
|
showDatePicker = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun NameInput(name: String, onTextChange: (String) -> Unit) {
|
||||||
|
var text by remember { mutableStateOf(name) }
|
||||||
|
OutlinedTextField(
|
||||||
|
label = { Text(stringResource(R.string.name)) }, value = name, onValueChange = { newText ->
|
||||||
|
text = newText
|
||||||
|
onTextChange(text)
|
||||||
|
}, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
package cc.n0th1ng.tripmoney.screens.trippicker
|
package cc.n0th1ng.tripmoney.screens.trippicker
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
@@ -7,74 +11,158 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.paging.compose.LazyPagingItems
|
import androidx.compose.material.icons.filled.Add
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.paging.compose.itemKey
|
|
||||||
import cc.n0th1ng.tripmoney.data.entity.Trip
|
|
||||||
import cc.n0th1ng.tripmoney.viewmodel.TripViewModel
|
|
||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
|
||||||
import androidx.compose.material3.ElevatedCard
|
import androidx.compose.material3.ElevatedCard
|
||||||
|
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||||
|
import androidx.compose.material3.FabPosition
|
||||||
|
import androidx.compose.material3.FloatingActionButton
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.SwipeToDismissBox
|
||||||
|
import androidx.compose.material3.SwipeToDismissBoxValue
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.rememberSwipeToDismissBoxState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
import androidx.compose.ui.draw.alpha
|
||||||
import androidx.compose.ui.layout.ModifierLocalBeyondBoundsLayout
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import androidx.paging.compose.LazyPagingItems
|
||||||
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
|
import androidx.paging.compose.itemKey
|
||||||
|
import cc.n0th1ng.tripmoney.R.string
|
||||||
|
import cc.n0th1ng.tripmoney.data.entity.Trip
|
||||||
import cc.n0th1ng.tripmoney.navigation.Screens
|
import cc.n0th1ng.tripmoney.navigation.Screens
|
||||||
|
import cc.n0th1ng.tripmoney.screens.addexpense.AddExpenseBottomSheet
|
||||||
|
import cc.n0th1ng.tripmoney.screens.listexpense.DeleteConfirmationDialog
|
||||||
import cc.n0th1ng.tripmoney.viewmodel.SettingsViewModel
|
import cc.n0th1ng.tripmoney.viewmodel.SettingsViewModel
|
||||||
|
import cc.n0th1ng.tripmoney.viewmodel.TripViewModel
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
@Composable
|
@Composable
|
||||||
|
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
||||||
fun TripPickerScreen(
|
fun TripPickerScreen(
|
||||||
navController: NavController
|
navController: NavController
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val settingsViewModel: SettingsViewModel = hiltViewModel()
|
val settingsViewModel: SettingsViewModel = hiltViewModel()
|
||||||
val tripViewModel: TripViewModel = hiltViewModel()
|
val tripViewModel: TripViewModel = hiltViewModel()
|
||||||
|
var showBottomSheet by remember { mutableStateOf(false) }
|
||||||
val trips: LazyPagingItems<Trip> = tripViewModel.getTrips().collectAsLazyPagingItems()
|
val trips: LazyPagingItems<Trip> = tripViewModel.getTrips().collectAsLazyPagingItems()
|
||||||
val currentTripId by settingsViewModel.currentTrip.collectAsState()
|
val currentTripId by settingsViewModel.currentTrip.collectAsState()
|
||||||
|
Scaffold(floatingActionButtonPosition = FabPosition.EndOverlay, floatingActionButton = {
|
||||||
LazyColumn(
|
FloatingActionButton(
|
||||||
modifier = Modifier
|
onClick = { showBottomSheet = true }) {
|
||||||
.padding(horizontal = 15.dp)
|
Icon(Icons.Filled.Add, stringResource(string.add_trip))
|
||||||
.fillMaxSize(),
|
}
|
||||||
verticalArrangement = Arrangement.Center
|
}) { paddingValues ->
|
||||||
) {
|
LazyColumn(
|
||||||
|
modifier = Modifier
|
||||||
items(trips.itemCount, trips.itemKey { it.id }) { i ->
|
.padding(horizontal = 15.dp)
|
||||||
Spacer(Modifier.height(10.dp))
|
.fillMaxSize(),
|
||||||
val trip = trips[i]
|
verticalArrangement = Arrangement.Center
|
||||||
if (trip != null) {
|
) {
|
||||||
TripCard(trip, currentTripId == trip.id, onClick = {
|
items(trips.itemCount, trips.itemKey { it.id }) { i ->
|
||||||
settingsViewModel.setCurrentTrip(trip.id)
|
Spacer(Modifier.height(10.dp))
|
||||||
navController.navigate(Screens.LIST_EXPENSE)
|
val trip = trips[i]
|
||||||
})
|
if (trip != null) {
|
||||||
|
SwipeToDeleteTripCard(trip, onDelete = {
|
||||||
|
tripViewModel.delete(trip)
|
||||||
|
}, onClick = {
|
||||||
|
settingsViewModel.setCurrentTrip(trip.id)
|
||||||
|
navController.navigate(Screens.LIST_EXPENSE)
|
||||||
|
}, isSelected = currentTripId == trip.id)
|
||||||
|
}
|
||||||
|
Spacer(Modifier.height(10.dp))
|
||||||
}
|
}
|
||||||
Spacer(Modifier.height(10.dp))
|
}
|
||||||
|
|
||||||
|
if (showBottomSheet) {
|
||||||
|
AddTripBottomSheet(
|
||||||
|
onDismiss = {
|
||||||
|
showBottomSheet = false
|
||||||
|
},
|
||||||
|
onSave = { trip ->
|
||||||
|
tripViewModel.save(trip)
|
||||||
|
showBottomSheet = false
|
||||||
|
},
|
||||||
|
null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
@Composable
|
@Composable
|
||||||
fun TripCard(trip: Trip, isSelected: Boolean, onClick: () -> Unit) {
|
fun SwipeToDeleteTripCard(
|
||||||
|
trip: Trip, onDelete: (Trip) -> Unit, onClick: (Trip) -> Unit, isSelected: Boolean
|
||||||
|
) {
|
||||||
|
var dismissed by remember { mutableStateOf(false) }
|
||||||
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
if (!dismissed) {
|
||||||
|
val dismissState = rememberSwipeToDismissBoxState(
|
||||||
|
confirmValueChange = { dismissValue ->
|
||||||
|
if (dismissValue == SwipeToDismissBoxValue.EndToStart) {
|
||||||
|
showDialog = true
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (showDialog) {
|
||||||
|
DeleteConfirmationDialog(onConfirm = {
|
||||||
|
showDialog = false
|
||||||
|
dismissed = true
|
||||||
|
onDelete(trip)
|
||||||
|
}, onCancel = { showDialog = false })
|
||||||
|
}
|
||||||
|
|
||||||
|
SwipeToDismissBox(
|
||||||
|
modifier = Modifier.alpha(if (isSelected) 1.0f else 0.7f),
|
||||||
|
state = dismissState,
|
||||||
|
enableDismissFromStartToEnd = false,
|
||||||
|
backgroundContent = {
|
||||||
|
Box(
|
||||||
|
Modifier
|
||||||
|
.clip(CardDefaults.elevatedShape)
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(MaterialTheme.colorScheme.onError)
|
||||||
|
.padding(horizontal = 20.dp),
|
||||||
|
contentAlignment = Alignment.CenterEnd
|
||||||
|
) {
|
||||||
|
Icon(Icons.Default.Delete, contentDescription = stringResource(string.delete))
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
TripCard(trip, isSelected, onClick = onClick)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TripCard(trip: Trip, isSelected: Boolean, onClick: (Trip) -> Unit) {
|
||||||
ElevatedCard(
|
ElevatedCard(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(100.dp)
|
.height(100.dp)
|
||||||
.clickable(true, onClick = onClick)
|
.clickable(true, onClick = { onClick(trip) }),
|
||||||
.alpha(if (isSelected) 1.0f else 0.7f),
|
|
||||||
elevation = CardDefaults.cardElevation(defaultElevation = if (isSelected) 7.dp else 0.dp)
|
elevation = CardDefaults.cardElevation(defaultElevation = if (isSelected) 7.dp else 0.dp)
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
@@ -83,8 +171,7 @@ fun TripCard(trip: Trip, isSelected: Boolean, onClick: () -> Unit) {
|
|||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier.padding(16.dp)
|
||||||
.padding(16.dp)
|
|
||||||
) {
|
) {
|
||||||
Text(fontSize = 25.sp, fontWeight = FontWeight.SemiBold, text = trip.name)
|
Text(fontSize = 25.sp, fontWeight = FontWeight.SemiBold, text = trip.name)
|
||||||
Text(trip.startDate)
|
Text(trip.startDate)
|
||||||
@@ -96,6 +183,5 @@ fun TripCard(trip: Trip, isSelected: Boolean, onClick: () -> Unit) {
|
|||||||
fontWeight = FontWeight.SemiBold
|
fontWeight = FontWeight.SemiBold
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
16
app/src/main/java/cc/n0th1ng/tripmoney/utils/Currencies.kt
Normal file
16
app/src/main/java/cc/n0th1ng/tripmoney/utils/Currencies.kt
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package cc.n0th1ng.tripmoney.utils
|
||||||
|
|
||||||
|
enum class Currencies {
|
||||||
|
PLN,
|
||||||
|
EUR,
|
||||||
|
USD;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun default(): Currencies {
|
||||||
|
return PLN
|
||||||
|
}
|
||||||
|
fun names(): List<String> {
|
||||||
|
return Currencies.entries.map { it.name }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,10 +5,12 @@ import androidx.lifecycle.ViewModelProvider
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import androidx.paging.PagingData
|
import androidx.paging.PagingData
|
||||||
import androidx.paging.cachedIn
|
import androidx.paging.cachedIn
|
||||||
|
import cc.n0th1ng.tripmoney.data.entity.Expense
|
||||||
import cc.n0th1ng.tripmoney.data.entity.Trip
|
import cc.n0th1ng.tripmoney.data.entity.Trip
|
||||||
import cc.n0th1ng.tripmoney.data.repository.TripRepository
|
import cc.n0th1ng.tripmoney.data.repository.TripRepository
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
@@ -16,4 +18,16 @@ class TripViewModel @Inject constructor(private val repository: TripRepository)
|
|||||||
|
|
||||||
fun getTrips(): Flow<PagingData<Trip>> = repository.getTrips().cachedIn(viewModelScope)
|
fun getTrips(): Flow<PagingData<Trip>> = repository.getTrips().cachedIn(viewModelScope)
|
||||||
|
|
||||||
|
fun delete(trip: Trip) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
repository.delete(trip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun save(trip: Trip) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
repository.save(trip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -16,4 +16,6 @@
|
|||||||
<string name="system_settings">Zgodnie z systemem</string>
|
<string name="system_settings">Zgodnie z systemem</string>
|
||||||
<string name="theme">Motyw</string>
|
<string name="theme">Motyw</string>
|
||||||
<string name="dark_theme">Ciemny motyw</string>
|
<string name="dark_theme">Ciemny motyw</string>
|
||||||
|
<string name="add_trip">Dodaj Wycieczkę</string>
|
||||||
|
<string name="name">Nazwa</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -16,5 +16,6 @@
|
|||||||
<string name="light_theme">Light theme</string>
|
<string name="light_theme">Light theme</string>
|
||||||
<string name="pick_theme">Pick a theme</string>
|
<string name="pick_theme">Pick a theme</string>
|
||||||
<string name="system_settings">System settings</string>
|
<string name="system_settings">System settings</string>
|
||||||
<!-- <string name="theme">Theme</string>-->
|
<string name="add_trip">Add Trip</string>
|
||||||
|
<string name="name">Name</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user