This commit is contained in:
nuryuda 2025-11-07 17:02:27 +07:00
parent 099c35f19a
commit b88d767571
2 changed files with 698 additions and 145 deletions

View File

@ -8,3 +8,56 @@ https://docs.google.com/document/d/1iGiC0Bg3Bdcd2Maq45TYkCDUkZ5Ql51E/edit?rtpof=
Starter dimodifikasi dan terinspirasi dari:
https://developer.android.com/codelabs/basic-android-compose-calculate-tip#0
# 🧮 BMI Calculator (Metrik & Imperial)
Sebuah aplikasi modern dan interaktif untuk menghitung **Body Mass Index (BMI)** menggunakan dua sistem satuan:
🌍 **Metrik (kg, m)** dan 🇺🇸 **Imperial (lbs, inch)**.
Aplikasi ini membantu kamu mengetahui apakah berat badanmu tergolong **kurus**, **ideal**, **berlebih**, atau **obesitas** berdasarkan standar kesehatan internasional (WHO).
---
## ✨ Fitur Utama
✅ Hitung BMI dengan **dua pilihan sistem satuan**:
- **Metrik** → kilogram (kg) & meter (m)
- **Imperial** → pound (lbs) & inch (in)
✅ Menampilkan hasil **BMI secara otomatis**
✅ Menentukan **kategori berat badan** sesuai standar WHO
✅ Antarmuka **sederhana, responsif, dan mudah digunakan**
✅ Dapat dijalankan di **desktop maupun mobile**
✅ Dikembangkan dengan bantuan **AI cerdas (ChatGPT & Claude)**
---
## 🧠 Kategori BMI
| Kategori | Rentang Nilai BMI |
|------------------------------|------------------|
| Kurang / Underweight | < 18.5 |
| Normal / Ideal | 18.5 24.9 |
| Kelebihan berat badan / Overweight | 25.0 29.9 |
| Obesitas / Obese | ≥ 30.0 |
---
## 🚀 Cara Menggunakan
1. Pilih sistem satuan: **Metrik** atau **Imperial**
2. Masukkan berat badan dan tinggi badan sesuai sistem satuan
3. Klik tombol **Hitung / Calculate**
4. Lihat hasil **BMI** dan kategori kesehatannya
---
## 💻 Contoh Penggunaan
### 🌍 **Metrik**
Aplikasi Ini Di Bantu Oleh
-ChatGpt
-Claude Ai
Satrio Putra Wardani 202310715307

View File

@ -1,18 +1,3 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.tiptime
import android.os.Bundle
@ -20,42 +5,42 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
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.foundation.layout.safeDrawingPadding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.animation.*
import androidx.compose.animation.core.*
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
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.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.tiptime.ui.theme.TipTimeTheme
import java.text.NumberFormat
import kotlin.math.pow
import java.text.DecimalFormat
// Warna tema klasik
private val ClassicGold = Color(0xFFD4AF37)
private val ClassicCream = Color(0xFFFFF8DC)
private val ClassicBrown = Color(0xFF8B4513)
private val ClassicDarkBrown = Color(0xFF654321)
private val ClassicBeige = Color(0xFFF5F5DC)
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@ -63,10 +48,14 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
TipTimeTheme {
Surface(
modifier = Modifier.fillMaxSize(),
) {
TipTimeLayout()
Surface(modifier = Modifier.fillMaxSize()) {
var showWelcome by remember { mutableStateOf(true) }
if (showWelcome) {
WelcomeScreen(onContinue = { showWelcome = false })
} else {
BmiCalculatorLayout(onBackPressed = { showWelcome = true })
}
}
}
}
@ -74,141 +63,652 @@ class MainActivity : ComponentActivity() {
}
@Composable
fun TipTimeLayout() {
var amountInput by remember { mutableStateOf("") }
var tipInput by remember { mutableStateOf("") }
var roundUp by remember { mutableStateOf(false) }
fun WelcomeScreen(onContinue: () -> Unit) {
var visible by remember { mutableStateOf(false) }
val BmiHeight = amountInput.toDoubleOrNull() ?: 0.0
val BmiWeight = tipInput.toDoubleOrNull() ?: 0.0
val bmi = calculateBMI(BmiHeight, BmiWeight, roundUp)
val category = calculateBMICategory(BmiHeight, BmiWeight, roundUp)
LaunchedEffect(Unit) {
visible = true
}
Box(
modifier = Modifier
.fillMaxSize()
.background(
Brush.verticalGradient(
colors = listOf(
ClassicDarkBrown,
ClassicBrown,
ClassicBeige
)
)
)
) {
Column(
modifier = Modifier
.fillMaxSize()
.statusBarsPadding()
.padding(32.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceBetween
) {
// Spacer untuk centering
Spacer(modifier = Modifier.height(60.dp))
// Content utama
AnimatedVisibility(
visible = visible,
enter = fadeIn(animationSpec = tween(1000)) +
scaleIn(initialScale = 0.8f, animationSpec = tween(1000))
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
// Icon/Logo
Card(
modifier = Modifier
.size(140.dp)
.shadow(16.dp, RoundedCornerShape(70.dp)),
shape = RoundedCornerShape(70.dp),
colors = CardDefaults.cardColors(
containerColor = ClassicGold
),
border = BorderStroke(4.dp, ClassicCream)
) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.fillMaxSize()
) {
Text(
text = "💪",
fontSize = 72.sp
)
}
}
Spacer(modifier = Modifier.height(40.dp))
// Ornamen atas
Text(
text = "✦ ═══════════════ ✦",
color = ClassicGold,
fontSize = 18.sp,
modifier = Modifier.padding(bottom = 20.dp)
)
// Judul utama
Text(
text = "KALKULATOR",
fontSize = 32.sp,
fontWeight = FontWeight.Bold,
color = ClassicGold,
letterSpacing = 5.sp
)
Text(
text = "BMI Satrio Putra Wardani",
fontSize = 20.sp,
fontWeight = FontWeight.Bold,
color = ClassicCream,
letterSpacing = 3.sp,
modifier = Modifier.padding(vertical = 12.dp)
)
// Ornamen bawah
Text(
text = "✦ ═══════════════ ✦",
color = ClassicGold,
fontSize = 18.sp,
modifier = Modifier.padding(bottom = 32.dp)
)
// Deskripsi
Card(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp),
shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors(
containerColor = ClassicCream.copy(alpha = 0.15f)
),
border = BorderStroke(1.5.dp, ClassicGold.copy(alpha = 0.4f))
) {
Column(
modifier = Modifier.padding(28.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Hitung Indeks Massa Tubuh Anda",
fontSize = 19.sp,
fontWeight = FontWeight.SemiBold,
color = ClassicCream,
textAlign = TextAlign.Center,
modifier = Modifier.padding(bottom = 16.dp)
)
Text(
text = "Ketahui status kesehatan Anda dengan perhitungan BMI yang akurat dan mudah",
fontSize = 15.sp,
color = ClassicCream.copy(alpha = 0.85f),
textAlign = TextAlign.Center,
lineHeight = 22.sp
)
}
}
}
}
// Tombol dan footer
AnimatedVisibility(
visible = visible,
enter = fadeIn(animationSpec = tween(1000, delayMillis = 500)) +
slideInVertically(
initialOffsetY = { 50 },
animationSpec = tween(1000, delayMillis = 500)
)
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(bottom = 8.dp)
) {
Button(
onClick = onContinue,
modifier = Modifier
.fillMaxWidth()
.height(60.dp)
.shadow(12.dp, RoundedCornerShape(30.dp)),
shape = RoundedCornerShape(30.dp),
colors = ButtonDefaults.buttonColors(
containerColor = ClassicGold,
contentColor = ClassicDarkBrown
),
border = BorderStroke(2.5.dp, ClassicCream)
) {
Text(
text = "MULAI PERHITUNGAN",
fontSize = 19.sp,
fontWeight = FontWeight.Bold,
letterSpacing = 1.5.sp
)
}
Spacer(modifier = Modifier.height(28.dp))
// Divider dekoratif
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(horizontal = 32.dp)
) {
Box(
modifier = Modifier
.weight(1f)
.height(1.dp)
.background(ClassicCream.copy(alpha = 0.3f))
)
Text(
text = "",
color = ClassicGold.copy(alpha = 0.6f),
fontSize = 16.sp
)
Box(
modifier = Modifier
.weight(1f)
.height(1.dp)
.background(ClassicCream.copy(alpha = 0.3f))
)
}
Spacer(modifier = Modifier.height(20.dp))
Text(
text = "Universitas Bhayangkara Jakarta Raya",
fontSize = 13.sp,
color = ClassicDarkBrown.copy(alpha = 0.5f),
letterSpacing = 1.sp
)
Text(
text = "SATRIO PUTRA WARDANI",
fontSize = 15.sp,
fontWeight = FontWeight.Bold,
color = ClassicGold.copy(alpha = 0.8f),
letterSpacing = 2.sp,
modifier = Modifier.padding(top = 4.dp)
)
}
}
}
}
}
@Composable
fun BmiCalculatorLayout(onBackPressed: () -> Unit) {
var heightInput by remember { mutableStateOf("") }
var weightInput by remember { mutableStateOf("") }
var useImperial by remember { mutableStateOf(false) }
val height = heightInput.toDoubleOrNull() ?: 0.0
val weight = weightInput.toDoubleOrNull() ?: 0.0
val bmi = calculateBMI(height, weight, useImperial)
val category = getBMICategory(bmi)
Box(
modifier = Modifier
.fillMaxSize()
.background(
Brush.verticalGradient(
colors = listOf(
ClassicCream,
ClassicBeige
)
)
)
) {
Column(
modifier = Modifier
.statusBarsPadding()
.padding(horizontal = 40.dp)
.verticalScroll(rememberScrollState())
.safeDrawingPadding(),
.padding(20.dp)
.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally
) {
// Tombol Back
Row(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 8.dp),
verticalAlignment = Alignment.CenterVertically
) {
IconButton(
onClick = onBackPressed,
modifier = Modifier
.shadow(4.dp, RoundedCornerShape(12.dp))
.background(ClassicGold, RoundedCornerShape(12.dp))
.size(48.dp)
) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "Kembali",
tint = ClassicDarkBrown
)
}
Spacer(modifier = Modifier.width(12.dp))
Text(
text = "Kembali ke Beranda",
fontSize = 16.sp,
fontWeight = FontWeight.Medium,
color = ClassicDarkBrown
)
}
// Header dengan ornamen klasik
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp)
.shadow(8.dp, RoundedCornerShape(16.dp)),
shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors(
containerColor = ClassicDarkBrown
),
border = BorderStroke(2.dp, ClassicGold)
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
modifier = Modifier.padding(24.dp)
) {
Text(
text = stringResource(R.string.calculate_tip),
modifier = Modifier
.padding(bottom = 16.dp, top = 40.dp)
.align(alignment = Alignment.Start)
text = "═══════════════",
color = ClassicGold,
fontSize = 20.sp
)
EditNumberField(
label = R.string.height,
Text(
text = "KALKULATOR BMI",
fontSize = 32.sp,
fontWeight = FontWeight.Bold,
color = ClassicGold,
letterSpacing = 2.sp,
modifier = Modifier.padding(vertical = 8.dp)
)
Text(
text = "═══════════════",
color = ClassicGold,
fontSize = 20.sp
)
Text(
text = "Body Mass Index Calculator",
fontSize = 14.sp,
color = ClassicCream,
fontWeight = FontWeight.Light,
modifier = Modifier.padding(top = 8.dp)
)
}
}
// Form Input Card
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp)
.shadow(6.dp, RoundedCornerShape(12.dp)),
shape = RoundedCornerShape(12.dp),
colors = CardDefaults.cardColors(
containerColor = Color.White
),
border = BorderStroke(1.dp, ClassicGold)
) {
Column(
modifier = Modifier.padding(20.dp)
) {
Text(
text = "Data Pengukuran",
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
color = ClassicDarkBrown,
modifier = Modifier.padding(bottom = 16.dp)
)
ClassicTextField(
label = if (useImperial) "Tinggi (inch)" else "Tinggi (cm)",
leadingIcon = R.drawable.number,
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Next
),
value = amountInput,
onValueChanged = { amountInput = it },
modifier = Modifier.padding(bottom = 32.dp).fillMaxWidth(),
value = heightInput,
onValueChanged = { heightInput = it },
modifier = Modifier
.padding(bottom = 16.dp)
.fillMaxWidth()
)
EditNumberField(
label = R.string.weight,
ClassicTextField(
label = if (useImperial) "Berat (lbs)" else "Berat (kg)",
leadingIcon = R.drawable.number,
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Number,
imeAction = ImeAction.Done
),
value = tipInput,
onValueChanged = { tipInput = it },
modifier = Modifier.padding(bottom = 32.dp).fillMaxWidth(),
)
RoundTheTipRow(
roundUp = roundUp,
onRoundUpChanged = { roundUp = it },
modifier = Modifier.padding(bottom = 32.dp)
)
Text(
text = stringResource(R.string.bmi_calculation, bmi),
style = MaterialTheme.typography.displaySmall
)
Text(
text = stringResource(R.string.bmi_category, category),
style = MaterialTheme.typography.displaySmall
value = weightInput,
onValueChanged = { weightInput = it },
modifier = Modifier
.padding(bottom = 16.dp)
.fillMaxWidth()
)
Spacer(modifier = Modifier.height(150.dp))
HorizontalDivider(
color = ClassicGold,
thickness = 1.dp,
modifier = Modifier.padding(vertical = 8.dp)
)
ClassicUnitSwitch(
useImperial = useImperial,
onUnitChange = { useImperial = it }
)
}
}
// Result Card
if (height > 0 && weight > 0) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp)
.shadow(8.dp, RoundedCornerShape(12.dp)),
shape = RoundedCornerShape(12.dp),
colors = CardDefaults.cardColors(
containerColor = ClassicDarkBrown
),
border = BorderStroke(2.dp, ClassicGold)
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.padding(28.dp)
) {
Text(
text = "— Hasil Perhitungan —",
fontSize = 16.sp,
color = ClassicGold,
fontWeight = FontWeight.Medium,
modifier = Modifier.padding(bottom = 16.dp)
)
Text(
text = "INDEKS MASSA TUBUH",
fontSize = 14.sp,
color = ClassicCream,
letterSpacing = 1.sp,
modifier = Modifier.padding(bottom = 8.dp)
)
Text(
text = DecimalFormat("#.##").format(bmi),
fontSize = 56.sp,
fontWeight = FontWeight.Bold,
color = ClassicGold,
modifier = Modifier.padding(vertical = 8.dp)
)
Box(
modifier = Modifier
.background(
color = getCategoryColor(category),
shape = RoundedCornerShape(24.dp)
)
.padding(horizontal = 24.dp, vertical = 12.dp)
) {
Text(
text = category.uppercase(),
fontSize = 20.sp,
color = Color.White,
fontWeight = FontWeight.Bold,
letterSpacing = 1.sp
)
}
Text(
text = getCategoryDescription(category),
fontSize = 13.sp,
color = ClassicCream,
textAlign = TextAlign.Center,
modifier = Modifier.padding(top = 16.dp)
)
}
}
// Info Card
BMICategoryInfo()
}
Spacer(modifier = Modifier.height(40.dp))
}
}
}
@Composable
fun EditNumberField(
@StringRes label: Int,
fun ClassicTextField(
label: String,
@DrawableRes leadingIcon: Int,
keyboardOptions: KeyboardOptions,
value: String,
onValueChanged: (String) -> Unit,
modifier: Modifier = Modifier
) {
TextField(
OutlinedTextField(
value = value,
singleLine = true,
leadingIcon = { Icon(painter = painterResource(id = leadingIcon), null) },
modifier = modifier,
onValueChange = onValueChanged,
label = { Text(stringResource(label)) },
keyboardOptions = keyboardOptions
label = {
Text(
label,
color = ClassicBrown,
fontWeight = FontWeight.Medium
)
},
singleLine = true,
leadingIcon = {
Icon(
painter = painterResource(id = leadingIcon),
contentDescription = null,
tint = ClassicGold
)
},
keyboardOptions = keyboardOptions,
modifier = modifier,
colors = OutlinedTextFieldDefaults.colors(
focusedBorderColor = ClassicGold,
unfocusedBorderColor = ClassicBrown.copy(alpha = 0.5f),
focusedTextColor = ClassicDarkBrown,
unfocusedTextColor = ClassicDarkBrown
),
shape = RoundedCornerShape(8.dp)
)
}
@Composable
fun RoundTheTipRow(
roundUp: Boolean,
onRoundUpChanged: (Boolean) -> Unit,
modifier: Modifier = Modifier
fun ClassicUnitSwitch(
useImperial: Boolean,
onUnitChange: (Boolean) -> Unit
) {
Row(
modifier = modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(text = stringResource(R.string.use_usc))
Text(
"Satuan Imperial (US)",
color = ClassicDarkBrown,
fontWeight = FontWeight.Medium
)
Switch(
modifier = Modifier
.fillMaxWidth()
.wrapContentWidth(Alignment.End),
checked = roundUp,
onCheckedChange = onRoundUpChanged
checked = useImperial,
onCheckedChange = onUnitChange,
colors = SwitchDefaults.colors(
checkedThumbColor = ClassicGold,
checkedTrackColor = ClassicGold.copy(alpha = 0.5f),
uncheckedThumbColor = ClassicBrown,
uncheckedTrackColor = ClassicBrown.copy(alpha = 0.3f)
)
)
}
}
/**
* Calculates the BMI
*
* Catatan: tambahkan unit test untuk kalkulasi BMI ini
*/
private fun calculateBMI(BmiHeight: Double, BmiWeight: Double = 15.0, roundUp: Boolean): String {
var bmi = BmiWeight / 100 * BmiHeight
if (roundUp) {
bmi = kotlin.math.ceil(bmi)
}
return NumberFormat.getNumberInstance().format(bmi)
}
/**
* Calculates the BMI Category
*
* Catatan: tambahkan unit test untuk kalkulasi BMI ini
*/
@Composable
fun BMICategoryInfo() {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp)
.shadow(4.dp, RoundedCornerShape(12.dp)),
shape = RoundedCornerShape(12.dp),
colors = CardDefaults.cardColors(
containerColor = Color.White
),
border = BorderStroke(1.dp, ClassicGold.copy(alpha = 0.3f))
) {
Column(
modifier = Modifier.padding(20.dp)
) {
Text(
text = "Kategori BMI",
fontSize = 16.sp,
fontWeight = FontWeight.Bold,
color = ClassicDarkBrown,
modifier = Modifier.padding(bottom = 12.dp)
)
private fun calculateBMICategory(BmiHeight: Double, BmiWeight: Double = 15.0, roundUp: Boolean): String {
var bmi = BmiWeight / 100 * BmiHeight
if (roundUp) {
bmi = kotlin.math.ceil(bmi)
CategoryRow("Kurus", "< 18.5", Color(0xFF4A90E2))
CategoryRow("Normal", "18.5 - 24.9", Color(0xFF50C878))
CategoryRow("Gemuk", "25.0 - 29.9", Color(0xFFFF9500))
CategoryRow("Obesitas", "≥ 30.0", Color(0xFFE74C3C))
}
return NumberFormat.getNumberInstance().format(bmi)
}
}
@Composable
fun CategoryRow(category: String, range: String, color: Color) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 6.dp),
verticalAlignment = Alignment.CenterVertically
) {
Box(
modifier = Modifier
.size(12.dp)
.background(color, RoundedCornerShape(2.dp))
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = category,
fontSize = 14.sp,
fontWeight = FontWeight.Medium,
color = ClassicDarkBrown,
modifier = Modifier.weight(1f)
)
Text(
text = range,
fontSize = 14.sp,
color = ClassicBrown,
fontWeight = FontWeight.Normal
)
}
}
fun getCategoryColor(category: String): Color {
return when (category) {
"Kurus" -> Color(0xFF4A90E2)
"Normal" -> Color(0xFF50C878)
"Gemuk" -> Color(0xFFFF9500)
"Obesitas" -> Color(0xFFE74C3C)
else -> ClassicBrown
}
}
fun getCategoryDescription(category: String): String {
return when (category) {
"Kurus" -> "Berat badan Anda kurang dari ideal"
"Normal" -> "Berat badan Anda ideal dan sehat"
"Gemuk" -> "Berat badan Anda melebihi ideal"
"Obesitas" -> "Konsultasikan dengan dokter Anda"
else -> ""
}
}
fun calculateBMI(height: Double, weight: Double, useImperial: Boolean): Double {
if (height <= 0 || weight <= 0) return 0.0
return if (useImperial) {
703 * weight / height.pow(2)
} else {
weight / (height / 100).pow(2)
}
}
fun getBMICategory(bmi: Double): String {
return when {
bmi == 0.0 -> "-"
bmi < 18.5 -> "Kurus"
bmi < 25 -> "Normal"
bmi < 30 -> "Gemuk"
else -> "Obesitas"
}
}
@Preview(showBackground = true)
@Composable
fun TipTimeLayoutPreview() {
fun WelcomeScreenPreview() {
TipTimeTheme {
TipTimeLayout()
WelcomeScreen(onContinue = {})
}
}
@Preview(showBackground = true)
@Composable
fun BmiCalculatorPreview() {
TipTimeTheme {
BmiCalculatorLayout(onBackPressed = {})
}
}