mirror of
https://github.com/oliexdev/openScale.git
synced 2025-08-16 13:44:26 +02:00
Add scale and measure unit to user settings
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"formatVersion": 1,
|
"formatVersion": 1,
|
||||||
"database": {
|
"database": {
|
||||||
"version": 1,
|
"version": 7,
|
||||||
"identityHash": "e9e1b3a9fbc321cf52bf869c01f5be21",
|
"identityHash": "d539026586245a45a135ae5bf3aaf73c",
|
||||||
"entities": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"tableName": "User",
|
"tableName": "User",
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `birthDate` INTEGER NOT NULL, `gender` TEXT NOT NULL, `heightCm` REAL, `activityLevel` TEXT NOT NULL)",
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `birthDate` INTEGER NOT NULL, `gender` TEXT NOT NULL, `heightCm` REAL NOT NULL, `activityLevel` TEXT NOT NULL, `scaleUnit` TEXT NOT NULL, `measureUnit` TEXT NOT NULL)",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldPath": "id",
|
"fieldPath": "id",
|
||||||
@@ -35,13 +35,26 @@
|
|||||||
{
|
{
|
||||||
"fieldPath": "heightCm",
|
"fieldPath": "heightCm",
|
||||||
"columnName": "heightCm",
|
"columnName": "heightCm",
|
||||||
"affinity": "REAL"
|
"affinity": "REAL",
|
||||||
|
"notNull": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldPath": "activityLevel",
|
"fieldPath": "activityLevel",
|
||||||
"columnName": "activityLevel",
|
"columnName": "activityLevel",
|
||||||
"affinity": "TEXT",
|
"affinity": "TEXT",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "scaleUnit",
|
||||||
|
"columnName": "scaleUnit",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "measureUnit",
|
||||||
|
"columnName": "measureUnit",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"primaryKey": {
|
"primaryKey": {
|
||||||
@@ -279,7 +292,7 @@
|
|||||||
],
|
],
|
||||||
"setupQueries": [
|
"setupQueries": [
|
||||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'e9e1b3a9fbc321cf52bf869c01f5be21')"
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd539026586245a45a135ae5bf3aaf73c')"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -26,6 +26,8 @@ data class User(
|
|||||||
val name: String,
|
val name: String,
|
||||||
val birthDate: Long,
|
val birthDate: Long,
|
||||||
val gender: GenderType,
|
val gender: GenderType,
|
||||||
val heightCm: Float? = null,
|
val heightCm: Float,
|
||||||
val activityLevel: ActivityLevel
|
val activityLevel: ActivityLevel,
|
||||||
|
var scaleUnit: WeightUnit,
|
||||||
|
var measureUnit: MeasureUnit
|
||||||
)
|
)
|
@@ -39,7 +39,7 @@ import com.health.openscale.core.utils.LogManager
|
|||||||
MeasurementValue::class,
|
MeasurementValue::class,
|
||||||
MeasurementType::class
|
MeasurementType::class
|
||||||
],
|
],
|
||||||
version = 1,
|
version = 7,
|
||||||
exportSchema = true
|
exportSchema = true
|
||||||
)
|
)
|
||||||
@TypeConverters(DatabaseConverters::class)
|
@TypeConverters(DatabaseConverters::class)
|
||||||
|
@@ -22,6 +22,7 @@ import androidx.compose.foundation.clickable
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.add
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@@ -59,10 +60,13 @@ import androidx.navigation.NavController
|
|||||||
import com.health.openscale.R
|
import com.health.openscale.R
|
||||||
import com.health.openscale.core.data.ActivityLevel
|
import com.health.openscale.core.data.ActivityLevel
|
||||||
import com.health.openscale.core.data.GenderType
|
import com.health.openscale.core.data.GenderType
|
||||||
|
import com.health.openscale.core.data.MeasureUnit
|
||||||
import com.health.openscale.core.data.User
|
import com.health.openscale.core.data.User
|
||||||
|
import com.health.openscale.core.data.WeightUnit
|
||||||
import com.health.openscale.ui.screen.SharedViewModel
|
import com.health.openscale.ui.screen.SharedViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Calendar
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
@@ -94,17 +98,29 @@ fun UserDetailScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var name by remember { mutableStateOf(user?.name.orEmpty()) }
|
var name by remember { mutableStateOf(user?.name.orEmpty()) }
|
||||||
var birthDate by remember { mutableStateOf(user?.birthDate ?: System.currentTimeMillis()) }
|
var birthDate by remember {
|
||||||
|
val initialBirthDate = user?.birthDate
|
||||||
|
if (initialBirthDate != null) {
|
||||||
|
mutableStateOf(initialBirthDate)
|
||||||
|
} else {
|
||||||
|
val calendar = Calendar.getInstance()
|
||||||
|
calendar.add(Calendar.YEAR, -18)
|
||||||
|
mutableStateOf(calendar.timeInMillis)
|
||||||
|
}
|
||||||
|
}
|
||||||
var gender by remember { mutableStateOf(user?.gender ?: GenderType.MALE) }
|
var gender by remember { mutableStateOf(user?.gender ?: GenderType.MALE) }
|
||||||
var height by remember { mutableStateOf(user?.heightCm?.toString().orEmpty()) }
|
var height by remember { mutableStateOf(user?.heightCm?.toString().orEmpty()) }
|
||||||
var activityLevel by remember { mutableStateOf(user?.activityLevel ?: ActivityLevel.SEDENTARY) }
|
var activityLevel by remember { mutableStateOf(user?.activityLevel ?: ActivityLevel.SEDENTARY) }
|
||||||
|
var scaleUnit by remember { mutableStateOf(user?.scaleUnit ?: WeightUnit.KG) }
|
||||||
|
var measureUnit by remember { mutableStateOf(user?.measureUnit ?: MeasureUnit.CM) }
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
// Date formatter for displaying the birth date. Consider device locale.
|
|
||||||
val dateFormatter = remember { SimpleDateFormat("dd.MM.yyyy", Locale.getDefault()) }
|
val dateFormatter = remember { SimpleDateFormat("dd.MM.yyyy", Locale.getDefault()) }
|
||||||
val datePickerState = rememberDatePickerState(initialSelectedDateMillis = birthDate)
|
val datePickerState = rememberDatePickerState(initialSelectedDateMillis = birthDate)
|
||||||
var showDatePicker by remember { mutableStateOf(false) }
|
var showDatePicker by remember { mutableStateOf(false) }
|
||||||
var activityLevelExpanded by remember { mutableStateOf(false) }
|
var activityLevelExpanded by remember { mutableStateOf(false) }
|
||||||
|
var scaleUnitExpanded by remember { mutableStateOf(false) }
|
||||||
|
var measureUnitExpanded by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
if (showDatePicker) {
|
if (showDatePicker) {
|
||||||
DatePickerDialog(
|
DatePickerDialog(
|
||||||
@@ -149,7 +165,9 @@ fun UserDetailScreen(
|
|||||||
birthDate = birthDate,
|
birthDate = birthDate,
|
||||||
gender = gender,
|
gender = gender,
|
||||||
heightCm = validHeight,
|
heightCm = validHeight,
|
||||||
activityLevel = activityLevel
|
activityLevel = activityLevel,
|
||||||
|
scaleUnit = scaleUnit,
|
||||||
|
measureUnit = measureUnit
|
||||||
)
|
)
|
||||||
settingsViewModel.viewModelScope.launch {
|
settingsViewModel.viewModelScope.launch {
|
||||||
if (isEdit) {
|
if (isEdit) {
|
||||||
@@ -216,7 +234,6 @@ fun UserDetailScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(stringResource(id = R.string.user_detail_label_activity_level)) // "Activity Level"
|
|
||||||
ExposedDropdownMenuBox(
|
ExposedDropdownMenuBox(
|
||||||
expanded = activityLevelExpanded,
|
expanded = activityLevelExpanded,
|
||||||
onExpandedChange = { activityLevelExpanded = !activityLevelExpanded },
|
onExpandedChange = { activityLevelExpanded = !activityLevelExpanded },
|
||||||
@@ -226,7 +243,7 @@ fun UserDetailScreen(
|
|||||||
value = activityLevel.name.lowercase().replaceFirstChar { it.uppercaseChar().toString() },
|
value = activityLevel.name.lowercase().replaceFirstChar { it.uppercaseChar().toString() },
|
||||||
onValueChange = {}, // Input is read-only, selection via dropdown
|
onValueChange = {}, // Input is read-only, selection via dropdown
|
||||||
readOnly = true,
|
readOnly = true,
|
||||||
label = { Text(stringResource(id = R.string.user_detail_label_select_level)) }, // "Select Level"
|
label = { Text(stringResource(id = R.string.user_detail_label_activity_level)) },
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
ExposedDropdownMenuDefaults.TrailingIcon(expanded = activityLevelExpanded)
|
ExposedDropdownMenuDefaults.TrailingIcon(expanded = activityLevelExpanded)
|
||||||
},
|
},
|
||||||
@@ -252,6 +269,74 @@ fun UserDetailScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExposedDropdownMenuBox(
|
||||||
|
expanded = scaleUnitExpanded,
|
||||||
|
onExpandedChange = { scaleUnitExpanded = !scaleUnitExpanded },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = scaleUnit.toString(),
|
||||||
|
onValueChange = {},
|
||||||
|
readOnly = true,
|
||||||
|
label = { Text(stringResource(id = R.string.user_detail_label_scale_unit)) },
|
||||||
|
trailingIcon = {
|
||||||
|
ExposedDropdownMenuDefaults.TrailingIcon(expanded = scaleUnitExpanded)
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.menuAnchor(type = MenuAnchorType.PrimaryNotEditable)
|
||||||
|
.fillMaxWidth()
|
||||||
|
)
|
||||||
|
ExposedDropdownMenu(
|
||||||
|
expanded = scaleUnitExpanded,
|
||||||
|
onDismissRequest = { scaleUnitExpanded = false }
|
||||||
|
) {
|
||||||
|
WeightUnit.entries.forEach { selectionOption ->
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(selectionOption.toString()) },
|
||||||
|
onClick = {
|
||||||
|
scaleUnit = selectionOption
|
||||||
|
scaleUnitExpanded = false
|
||||||
|
},
|
||||||
|
contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExposedDropdownMenuBox(
|
||||||
|
expanded = measureUnitExpanded,
|
||||||
|
onExpandedChange = { measureUnitExpanded = !measureUnitExpanded },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = measureUnit.toString(),
|
||||||
|
onValueChange = {},
|
||||||
|
readOnly = true,
|
||||||
|
label = { Text(stringResource(id = R.string.user_detail_label_measure_unit)) },
|
||||||
|
trailingIcon = {
|
||||||
|
ExposedDropdownMenuDefaults.TrailingIcon(expanded = measureUnitExpanded)
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.menuAnchor(type = MenuAnchorType.PrimaryNotEditable)
|
||||||
|
.fillMaxWidth()
|
||||||
|
)
|
||||||
|
ExposedDropdownMenu(
|
||||||
|
expanded = measureUnitExpanded,
|
||||||
|
onDismissRequest = { measureUnitExpanded = false }
|
||||||
|
) {
|
||||||
|
MeasureUnit.entries.forEach { selectionOption ->
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(selectionOption.toString()) },
|
||||||
|
onClick = {
|
||||||
|
measureUnit = selectionOption
|
||||||
|
measureUnitExpanded = false
|
||||||
|
},
|
||||||
|
contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Text(stringResource(id = R.string.user_detail_label_birth_date)) // "Birth Date"
|
Text(stringResource(id = R.string.user_detail_label_birth_date)) // "Birth Date"
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = dateFormatter.format(Date(birthDate)),
|
value = dateFormatter.format(Date(birthDate)),
|
||||||
|
@@ -51,9 +51,10 @@
|
|||||||
<string name="user_detail_label_height_cm">Größe (cm)</string>
|
<string name="user_detail_label_height_cm">Größe (cm)</string>
|
||||||
<string name="user_detail_label_gender">Geschlecht</string>
|
<string name="user_detail_label_gender">Geschlecht</string>
|
||||||
<string name="user_detail_label_activity_level">Aktivitätslevel</string>
|
<string name="user_detail_label_activity_level">Aktivitätslevel</string>
|
||||||
<string name="user_detail_label_select_level">Level auswählen</string>
|
|
||||||
<string name="user_detail_label_birth_date">Geburtsdatum</string>
|
<string name="user_detail_label_birth_date">Geburtsdatum</string>
|
||||||
<string name="user_detail_error_invalid_data">Bitte geben Sie gültige Daten ein</string>
|
<string name="user_detail_error_invalid_data">Bitte geben Sie gültige Daten ein</string>
|
||||||
|
<string name="user_detail_label_scale_unit">Gewichtseinheit</string>
|
||||||
|
<string name="user_detail_label_measure_unit">Größeneinheit</string>
|
||||||
<string name="height_value_cm">%.1f cm</string>
|
<string name="height_value_cm">%.1f cm</string>
|
||||||
<string name="user_settings_item_details_conditional">Alter: %1$d, Größe: %2$s</string>
|
<string name="user_settings_item_details_conditional">Alter: %1$d, Größe: %2$s</string>
|
||||||
<string name="user_settings_content_description_edit">Benutzer bearbeiten</string>
|
<string name="user_settings_content_description_edit">Benutzer bearbeiten</string>
|
||||||
|
@@ -52,9 +52,10 @@
|
|||||||
<string name="user_detail_label_height_cm">Height (cm)</string>
|
<string name="user_detail_label_height_cm">Height (cm)</string>
|
||||||
<string name="user_detail_label_gender">Gender</string>
|
<string name="user_detail_label_gender">Gender</string>
|
||||||
<string name="user_detail_label_activity_level">Activity Level</string>
|
<string name="user_detail_label_activity_level">Activity Level</string>
|
||||||
<string name="user_detail_label_select_level">Select Level</string>
|
|
||||||
<string name="user_detail_label_birth_date">Birth Date</string>
|
<string name="user_detail_label_birth_date">Birth Date</string>
|
||||||
<string name="user_detail_error_invalid_data">Please enter valid data</string>
|
<string name="user_detail_error_invalid_data">Please enter valid data</string>
|
||||||
|
<string name="user_detail_label_scale_unit">Scale Unit</string>
|
||||||
|
<string name="user_detail_label_measure_unit">Measure Unit</string>
|
||||||
<string name="height_value_cm">%.1f cm</string>
|
<string name="height_value_cm">%.1f cm</string>
|
||||||
<string name="user_settings_item_details_conditional">Age: %1$d, Height: %2$s</string>
|
<string name="user_settings_item_details_conditional">Age: %1$d, Height: %2$s</string>
|
||||||
<string name="user_settings_content_description_edit">Edit user</string>
|
<string name="user_settings_content_description_edit">Edit user</string>
|
||||||
|
Reference in New Issue
Block a user