commit f4cbea5b6c7ffec7cd1d69adee6a3173953d29bd Author: nabilasuwandira <202310715066@mhs.ubharajaya.ac.id> Date: Fri Nov 7 13:31:21 2025 +0700 ppp diff --git a/app/src/main/java/com/example/kalkulatorbmi/MainScreen.kt b/app/src/main/java/com/example/kalkulatorbmi/MainScreen.kt new file mode 100644 index 0000000..cdbb7d2 --- /dev/null +++ b/app/src/main/java/com/example/kalkulatorbmi/MainScreen.kt @@ -0,0 +1,209 @@ +package com.example.kalkulatorbmi + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.tween +import androidx.compose.animation.fadeIn +import androidx.compose.animation.slideInVertically +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.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalFocusManager +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.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController +import kotlin.math.pow + +// Enum untuk merepresentasikan sistem unit yang dipilih +enum class UnitSystem { + Metric, USC +} + +@Composable +fun MainScreen(navController: NavController) { + // --- STATE UNTUK SEMUA FITUR --- + var unitSystem by remember { mutableStateOf(UnitSystem.Metric) } + var umur by remember { mutableStateOf("") } + var jenisKelamin by remember { mutableStateOf(null) } + + // State untuk Metric + var tinggiCm by remember { mutableStateOf("") } + var beratKg by remember { mutableStateOf("") } + + // State untuk USC + var tinggiFt by remember { mutableStateOf("") } + var tinggiIn by remember { mutableStateOf("") } + var beratLbs by remember { mutableStateOf("") } + + var bmiResult by remember { mutableStateOf(null) } + var bmiCategory by remember { mutableStateOf("") } + + // Variabel Warna dari Tema + val surfaceVariantColor = MaterialTheme.colorScheme.surfaceVariant + val errorColor = MaterialTheme.colorScheme.error + val errorContainerColor = MaterialTheme.colorScheme.errorContainer + val primaryColor = MaterialTheme.colorScheme.primary + val backgroundColor = MaterialTheme.colorScheme.background + val onBackgroundColor = MaterialTheme.colorScheme.onBackground + val secondaryColor = MaterialTheme.colorScheme.secondary + + var bmiColor by remember { mutableStateOf(surfaceVariantColor) } + val focusManager = LocalFocusManager.current + + fun calculateBmi() { + focusManager.clearFocus() + var bmi: Float? = null + + if (unitSystem == UnitSystem.Metric) { + val tinggiCmFloat = tinggiCm.toFloatOrNull() + val beratKgFloat = beratKg.toFloatOrNull() + if (tinggiCmFloat != null && beratKgFloat != null && tinggiCmFloat > 0) { + val tinggiM = tinggiCmFloat / 100 + bmi = beratKgFloat / tinggiM.pow(2) + } + } else { // USC + val tinggiFtFloat = tinggiFt.toFloatOrNull() ?: 0f + val tinggiInFloat = tinggiIn.toFloatOrNull() ?: 0f + val beratLbsFloat = beratLbs.toFloatOrNull() + if (beratLbsFloat != null && (tinggiFtFloat > 0 || tinggiInFloat > 0)) { + val totalTinggiInches = (tinggiFtFloat * 12) + tinggiInFloat + bmi = (beratLbsFloat / totalTinggiInches.pow(2)) * 703 + } + } + + if (bmi != null && umur.isNotBlank() && jenisKelamin != null) { + bmiResult = bmi + bmiCategory = when { + bmi < 18.5 -> { + bmiColor = errorColor; "Berat badan kurang" + } + bmi < 25 -> { + bmiColor = Color(0xFF4CAF50); "Berat badan normal" + } + bmi < 30 -> { + bmiColor = Color(0xFFFFC107); "Kelebihan berat badan" + } + else -> { + bmiColor = errorContainerColor; "Obesitas" + } + } + } + } + + fun reset() { + umur = ""; jenisKelamin = null; tinggiCm = ""; beratKg = "" + tinggiFt = ""; tinggiIn = ""; beratLbs = "" + bmiResult = null; bmiCategory = ""; bmiColor = surfaceVariantColor + } + + val gradientBrush = Brush.verticalGradient( + colors = listOf(primaryColor.copy(alpha = 0.2f), backgroundColor) + ) + + Box(modifier = Modifier.fillMaxSize().background(gradientBrush)) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + .verticalScroll(rememberScrollState()), // Membuat Column bisa di-scroll + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + "Kalkulator BMI", + style = MaterialTheme.typography.headlineLarge, + color = onBackgroundColor + ) + + // --- UI UNTUK PILIHAN UNIT SYSTEM --- + Row( + modifier = Modifier.fillMaxWidth().padding(vertical = 16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + Text("Metric (kg, cm)", color = if (unitSystem == UnitSystem.Metric) primaryColor else onBackgroundColor) + Spacer(Modifier.width(8.dp)) + Switch( + checked = unitSystem == UnitSystem.USC, + onCheckedChange = { + unitSystem = if (it) UnitSystem.USC else UnitSystem.Metric + } + ) + Spacer(Modifier.width(8.dp)) + Text("USC (lbs, ft, in)", color = if (unitSystem == UnitSystem.USC) primaryColor else onBackgroundColor) + } + + Card( + shape = RoundedCornerShape(16.dp), + elevation = CardDefaults.cardElevation(8.dp), + modifier = Modifier.fillMaxWidth() + ) { + Column(modifier = Modifier.padding(16.dp)) { + // --- Pilihan Jenis Kelamin (Tetap Sama) --- + Text("Jenis Kelamin", style = MaterialTheme.typography.bodyLarge, modifier = Modifier.padding(bottom = 8.dp)) + // (Kode Row untuk jenis kelamin tidak berubah, jadi disingkat untuk kejelasan) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + val isLakiSelected = jenisKelamin == "Laki-laki" + Button(onClick={jenisKelamin="Laki-laki"},modifier=Modifier.weight(1f),colors=ButtonDefaults.buttonColors(containerColor=if(isLakiSelected)primaryColor else MaterialTheme.colorScheme.surface,contentColor=if(isLakiSelected)MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface),border=BorderStroke(1.dp,if(isLakiSelected)primaryColor else MaterialTheme.colorScheme.outline)){Icon(Icons.Default.Male,"Laki-laki",modifier=Modifier.size(18.dp));Spacer(Modifier.width(8.dp));Text("Laki-laki")} + val isPerempuanSelected = jenisKelamin == "Perempuan" + Button(onClick={jenisKelamin="Perempuan"},modifier=Modifier.weight(1f),colors=ButtonDefaults.buttonColors(containerColor=if(isPerempuanSelected)primaryColor else MaterialTheme.colorScheme.surface,contentColor=if(isPerempuanSelected)MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface),border=BorderStroke(1.dp,if(isPerempuanSelected)primaryColor else MaterialTheme.colorScheme.outline)){Icon(Icons.Default.Female,"Perempuan",modifier=Modifier.size(18.dp));Spacer(Modifier.width(8.dp));Text("Perempuan")} + } + + Spacer(modifier = Modifier.height(16.dp)) + OutlinedTextField(value=umur,onValueChange={umur=it},label={Text("Umur")},leadingIcon={Icon(Icons.Default.CalendarToday,"Umur")},keyboardOptions=KeyboardOptions(keyboardType=KeyboardType.Number,imeAction=ImeAction.Next),singleLine=true,modifier=Modifier.fillMaxWidth()) + Spacer(modifier = Modifier.height(16.dp)) + + // --- INPUT FIELD DINAMIS BERDASARKAN UNIT SYSTEM --- + if (unitSystem == UnitSystem.Metric) { + // Input untuk METRIC + OutlinedTextField(value=tinggiCm,onValueChange={tinggiCm=it},label={Text("Tinggi Badan (cm)")},leadingIcon={Icon(Icons.Default.Height,"Tinggi Badan")},keyboardOptions=KeyboardOptions(keyboardType=KeyboardType.Number,imeAction=ImeAction.Next),singleLine=true,modifier=Modifier.fillMaxWidth()) + Spacer(modifier = Modifier.height(16.dp)) + OutlinedTextField(value=beratKg,onValueChange={beratKg=it},label={Text("Berat Badan (kg)")},leadingIcon={Icon(Icons.Default.MonitorWeight,"Berat Badan")},keyboardOptions=KeyboardOptions(keyboardType=KeyboardType.Number,imeAction=ImeAction.Done),keyboardActions=KeyboardActions(onDone={calculateBmi()}),singleLine=true,modifier=Modifier.fillMaxWidth()) + } else { + // Input untuk USC + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(16.dp)) { + OutlinedTextField(value=tinggiFt,onValueChange={tinggiFt=it},label={Text("Tinggi (ft)")},modifier=Modifier.weight(1f),keyboardOptions=KeyboardOptions(keyboardType=KeyboardType.Number,imeAction=ImeAction.Next),singleLine=true) + OutlinedTextField(value=tinggiIn,onValueChange={tinggiIn=it},label={Text("Tinggi (in)")},modifier=Modifier.weight(1f),keyboardOptions=KeyboardOptions(keyboardType=KeyboardType.Number,imeAction=ImeAction.Next),singleLine=true) + } + Spacer(modifier = Modifier.height(16.dp)) + OutlinedTextField(value=beratLbs,onValueChange={beratLbs=it},label={Text("Berat Badan (lbs)")},leadingIcon={Icon(Icons.Default.MonitorWeight,"Berat Badan")},keyboardOptions=KeyboardOptions(keyboardType=KeyboardType.Number,imeAction=ImeAction.Done),keyboardActions=KeyboardActions(onDone={calculateBmi()}),singleLine=true,modifier=Modifier.fillMaxWidth()) + } + } + } + + Spacer(modifier = Modifier.height(24.dp)) + Row(Modifier.fillMaxWidth(),horizontalArrangement=Arrangement.SpaceAround){Button(onClick={calculateBmi()},modifier=Modifier.weight(1f).height(50.dp)){Text("Hitung",fontSize=16.sp)};Spacer(Modifier.width(16.dp));Button(onClick={reset()},colors=ButtonDefaults.buttonColors(containerColor=secondaryColor),modifier=Modifier.weight(1f).height(50.dp)){Text("Ulang",fontSize=16.sp)}} + Spacer(modifier = Modifier.height(32.dp)) + + // Kartu Hasil (Tidak perlu diubah) + AnimatedVisibility(visible=bmiResult!=null,enter=fadeIn(animationSpec=tween(500))+slideInVertically(initialOffsetY={it/2},animationSpec=tween(500))){Card(shape=RoundedCornerShape(16.dp),colors=CardDefaults.cardColors(containerColor=bmiColor),modifier=Modifier.fillMaxWidth()){Column(modifier=Modifier.padding(24.dp),horizontalAlignment=Alignment.CenterHorizontally,verticalArrangement=Arrangement.Center){Text("Hasil untuk $jenisKelamin, Usia $umur Tahun",color=Color.White,style=MaterialTheme.typography.titleMedium);Spacer(Modifier.height(8.dp));Text(if(bmiResult!=null)"%.2f".format(bmiResult)else { + "" + },color=Color.White,fontSize=48.sp,fontWeight=FontWeight.Bold);Spacer(Modifier.height(8.dp));Text(bmiCategory,color=Color.White,fontSize=20.sp,textAlign=TextAlign.Center,style=MaterialTheme.typography.bodyLarge)}}} + + Spacer(modifier = Modifier.weight(1f, fill = false).padding(32.dp)) // Spacer fleksibel + + // Tombol Keluar (Tidak perlu diubah) + OutlinedButton(onClick={navController.navigate("login"){popUpTo(0)}},modifier=Modifier.fillMaxWidth(),border=BorderStroke(1.dp,primaryColor)){Icon(Icons.Default.ArrowBack,"Keluar",tint=primaryColor);Spacer(Modifier.width(8.dp));Text("Keluar",color=primaryColor)} + } + } +}