Comentar codigo aplicacion

This commit is contained in:
2026-07-13 13:48:45 +02:00
parent 25d6ef6cdb
commit f6db58f299
3 changed files with 50 additions and 0 deletions
@@ -14,15 +14,23 @@ import com.example.saludapp.ui.RegisterScreen
import com.example.saludapp.ui.StartScreen import com.example.saludapp.ui.StartScreen
import com.example.saludapp.ui.theme.SaludappTheme import com.example.saludapp.ui.theme.SaludappTheme
/**
* Actividad principal de la aplicación.
* Gestiona el flujo de navegación entre pantallas y el estado de la sesión.
*/
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
// Habilitar diseño de borde a borde (edge-to-edge)
enableEdgeToEdge() enableEdgeToEdge()
setContent { setContent {
SaludappTheme { SaludappTheme {
// Estado para controlar en qué pantalla se encuentra el usuario
var currentScreen by remember { mutableStateOf("start") } var currentScreen by remember { mutableStateOf("start") }
// Almacena el nombre del usuario logueado para mostrarlo en el Dashboard
var loggedInUserName by remember { mutableStateOf("") } var loggedInUserName by remember { mutableStateOf("") }
// Enrutador simple basado en el estado 'currentScreen'
when (currentScreen) { when (currentScreen) {
"start" -> StartScreen { "start" -> StartScreen {
currentScreen = "login" currentScreen = "login"
@@ -7,11 +7,20 @@ import java.sql.Connection
import java.sql.DriverManager import java.sql.DriverManager
import java.sql.SQLException import java.sql.SQLException
/**
* Objeto encargado de gestionar todas las operaciones con la base de datos MariaDB.
* Implementa seguridad mediante hashing de contraseñas y operaciones asíncronas.
*/
object DatabaseHelper { object DatabaseHelper {
// Configuración de la conexión al servidor externo
private const val URL = "jdbc:mariadb://mariadb.peta9.com:3306/saludapp_db" private const val URL = "jdbc:mariadb://mariadb.peta9.com:3306/saludapp_db"
private const val USER = "saludapp_dba" private const val USER = "saludapp_dba"
private const val PASSWORD = "Pedro@110387" private const val PASSWORD = "Pedro@110387"
/**
* Encripta la contraseña utilizando el algoritmo SHA-256 para mayor seguridad.
* Retorna la representación hexadecimal del hash.
*/
private fun hashPassword(password: String): String { private fun hashPassword(password: String): String {
val bytes = password.toByteArray() val bytes = password.toByteArray()
val md = MessageDigest.getInstance("SHA-256") val md = MessageDigest.getInstance("SHA-256")
@@ -19,13 +28,21 @@ object DatabaseHelper {
return digest.fold("") { str, it -> str + "%02x".format(it) } return digest.fold("") { str, it -> str + "%02x".format(it) }
} }
/**
* Valida las credenciales de un usuario.
* @param user Nombre de usuario o correo electrónico.
* @param pass Contraseña en texto plano (será hasheada antes de comparar).
* @return El nombre completo del usuario si tiene éxito, null de lo contrario.
*/
suspend fun validateLogin(user: String, pass: String): String? = withContext(Dispatchers.IO) { suspend fun validateLogin(user: String, pass: String): String? = withContext(Dispatchers.IO) {
var connection: Connection? = null var connection: Connection? = null
try { try {
// Cargar el driver de MariaDB y establecer conexión
Class.forName("org.mariadb.jdbc.Driver") Class.forName("org.mariadb.jdbc.Driver")
connection = DriverManager.getConnection(URL, USER, PASSWORD) connection = DriverManager.getConnection(URL, USER, PASSWORD)
val hashedPass = hashPassword(pass) val hashedPass = hashPassword(pass)
// Consulta preparada para evitar ataques de inyección SQL
val query = "SELECT nombre_completo FROM usuarios WHERE (username = ? OR email = ?) AND password = ?" val query = "SELECT nombre_completo FROM usuarios WHERE (username = ? OR email = ?) AND password = ?"
connection.prepareStatement(query).use { statement -> connection.prepareStatement(query).use { statement ->
statement.setString(1, user) statement.setString(1, user)
@@ -34,12 +51,14 @@ object DatabaseHelper {
val resultSet = statement.executeQuery() val resultSet = statement.executeQuery()
if (resultSet.next()) { if (resultSet.next()) {
// Retorna el nombre real del usuario guardado en la DB
return@withContext resultSet.getString("nombre_completo") ?: user return@withContext resultSet.getString("nombre_completo") ?: user
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} finally { } finally {
// Asegurar que la conexión se cierra siempre
try { try {
connection?.close() connection?.close()
} catch (e: SQLException) { } catch (e: SQLException) {
@@ -49,6 +68,14 @@ object DatabaseHelper {
return@withContext null return@withContext null
} }
/**
* Registra un nuevo usuario en la base de datos.
* @param user Nombre de usuario único.
* @param email Correo electrónico único.
* @param pass Contraseña en texto plano (se guardará como hash SHA-256).
* @param fullName Nombre completo del usuario.
* @return true si el registro fue exitoso, false en caso contrario.
*/
suspend fun registerUser(user: String, email: String, pass: String, fullName: String): Boolean = withContext(Dispatchers.IO) { suspend fun registerUser(user: String, email: String, pass: String, fullName: String): Boolean = withContext(Dispatchers.IO) {
var connection: Connection? = null var connection: Connection? = null
try { try {
@@ -16,6 +16,11 @@ 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
/**
* Pantalla principal (Dashboard) que se muestra tras un inicio de sesión exitoso.
* @param userName Nombre del usuario para el mensaje de bienvenida.
* @param onLogout Acción a ejecutar cuando el usuario decide cerrar sesión.
*/
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun HomeScreen(userName: String, onLogout: () -> Unit) { fun HomeScreen(userName: String, onLogout: () -> Unit) {
@@ -24,6 +29,7 @@ fun HomeScreen(userName: String, onLogout: () -> Unit) {
TopAppBar( TopAppBar(
title = { Text("Saludapp", fontWeight = FontWeight.Bold) }, title = { Text("Saludapp", fontWeight = FontWeight.Bold) },
actions = { actions = {
// Botón para cerrar la sesión actual
IconButton(onClick = onLogout) { IconButton(onClick = onLogout) {
Icon(Icons.AutoMirrored.Filled.ExitToApp, contentDescription = "Cerrar sesión") Icon(Icons.AutoMirrored.Filled.ExitToApp, contentDescription = "Cerrar sesión")
} }
@@ -41,6 +47,7 @@ fun HomeScreen(userName: String, onLogout: () -> Unit) {
.padding(padding) .padding(padding)
.padding(16.dp) .padding(16.dp)
) { ) {
// Mensaje de bienvenida personalizado
Text( Text(
text = "Hola, $userName 👋", text = "Hola, $userName 👋",
style = MaterialTheme.typography.headlineMedium, style = MaterialTheme.typography.headlineMedium,
@@ -54,6 +61,7 @@ fun HomeScreen(userName: String, onLogout: () -> Unit) {
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))
// Cuadrícula de tarjetas con estadísticas de salud
LazyVerticalGrid( LazyVerticalGrid(
columns = GridCells.Fixed(2), columns = GridCells.Fixed(2),
horizontalArrangement = Arrangement.spacedBy(16.dp), horizontalArrangement = Arrangement.spacedBy(16.dp),
@@ -83,6 +91,13 @@ fun HomeScreen(userName: String, onLogout: () -> Unit) {
} }
} }
/**
* Componente reutilizable para mostrar una tarjeta de estadística.
* @param title Título del dato (ej. "Agua").
* @param value Valor actual (ej. "1.5L").
* @param icon Icono representativo.
* @param color Color temático para la tarjeta y el icono.
*/
@Composable @Composable
fun StatCard(title: String, value: String, icon: ImageVector, color: androidx.compose.ui.graphics.Color) { fun StatCard(title: String, value: String, icon: ImageVector, color: androidx.compose.ui.graphics.Color) {
Card( Card(