Añadir pantalla login y conexion a mariadb

This commit is contained in:
2026-07-13 13:02:27 +02:00
parent 6a02e05de5
commit f680750119
10 changed files with 214 additions and 18 deletions
+1
View File
@@ -42,6 +42,7 @@ dependencies {
implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.mariadb.java.client)
testImplementation(libs.junit)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
+2
View File
@@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
@@ -4,6 +4,16 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.example.saludapp.ui.LoginScreen
import com.example.saludapp.ui.StartScreen
import com.example.saludapp.ui.theme.SaludappTheme
@@ -13,8 +23,24 @@ class MainActivity : ComponentActivity() {
enableEdgeToEdge()
setContent {
SaludappTheme {
StartScreen {
// Acción al presionar el botón
var currentScreen by remember { mutableStateOf("start") }
when (currentScreen) {
"start" -> StartScreen {
currentScreen = "login"
}
"login" -> LoginScreen {
// Aquí iría la lógica tras login exitoso
currentScreen = "home"
}
"home" -> {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text("Bienvenido a Saludapp")
}
}
}
}
}
@@ -0,0 +1,43 @@
package com.example.saludapp.data
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.sql.Connection
import java.sql.DriverManager
import java.sql.SQLException
object DatabaseHelper {
private const val URL = "jdbc:mariadb://mariadb.peta9.com:3306/saludapp_db"
private const val USER = "saludapp_dba"
private const val PASSWORD = "TU_CONTRASEÑA_AQUÍ" // TODO: Reemplazar con la contraseña real
suspend fun validateLogin(user: String, pass: String): Boolean = withContext(Dispatchers.IO) {
var connection: Connection? = null
try {
// Cargar el driver explícitamente si es necesario
Class.forName("org.mariadb.jdbc.Driver")
connection = DriverManager.getConnection(URL, USER, PASSWORD)
val query = "SELECT COUNT(*) FROM usuarios WHERE (username = ? OR email = ?) AND password = ?"
connection.prepareStatement(query).use { statement ->
statement.setString(1, user)
statement.setString(2, user)
statement.setString(3, pass)
val resultSet = statement.executeQuery()
if (resultSet.next()) {
return@withContext resultSet.getInt(1) > 0
}
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
try {
connection?.close()
} catch (e: SQLException) {
e.printStackTrace()
}
}
return@withContext false
}
}
@@ -0,0 +1,102 @@
package com.example.saludapp.ui
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp
import com.example.saludapp.data.DatabaseHelper
import kotlinx.coroutines.launch
@Composable
fun LoginScreen(onLoginSuccess: () -> Unit) {
var email by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var isLoading by remember { mutableStateOf(false) }
var errorMessage by remember { mutableStateOf<String?>(null) }
val scope = rememberCoroutineScope()
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "Iniciar Sesión",
style = MaterialTheme.typography.headlineMedium,
color = MaterialTheme.colorScheme.primary
)
Spacer(modifier = Modifier.height(32.dp))
OutlinedTextField(
value = email,
onValueChange = { email = it },
label = { Text("Usuario o Email") },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
enabled = !isLoading
)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = { Text("Contraseña") },
visualTransformation = PasswordVisualTransformation(),
modifier = Modifier.fillMaxWidth(),
singleLine = true,
enabled = !isLoading
)
if (errorMessage != null) {
Text(
text = errorMessage!!,
color = MaterialTheme.colorScheme.error,
modifier = Modifier.padding(top = 16.dp)
)
}
Spacer(modifier = Modifier.height(32.dp))
Button(
onClick = {
scope.launch {
isLoading = true
errorMessage = null
val success = DatabaseHelper.validateLogin(email, password)
isLoading = false
if (success) {
onLoginSuccess()
} else {
errorMessage = "Usuario o contraseña incorrectos"
}
}
},
modifier = Modifier
.fillMaxWidth()
.height(56.dp),
enabled = !isLoading && email.isNotEmpty() && password.isNotEmpty()
) {
if (isLoading) {
CircularProgressIndicator(
modifier = Modifier.size(24.dp),
color = MaterialTheme.colorScheme.onPrimary,
strokeWidth = 2.dp
)
} else {
Text("Entrar")
}
}
}
}
}