Comentar codigo aplicacion
This commit is contained in:
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user