Añadir pantalla login y conexion a mariadb
This commit is contained in:
Generated
+11
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="deploymentTargetSelector">
|
||||||
|
<selectionStates>
|
||||||
|
<SelectionState runConfigName="app">
|
||||||
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
|
<DialogSelection />
|
||||||
|
</SelectionState>
|
||||||
|
</selectionStates>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
Generated
+1
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||||
<component name="GradleSettings">
|
<component name="GradleSettings">
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|||||||
@@ -1,38 +1,46 @@
|
|||||||
# Saludapp
|
# Saludapp
|
||||||
|
|
||||||
Saludapp es una aplicación Android moderna enfocada en la salud y el bienestar, desarrollada utilizando las últimas tecnologías y prácticas recomendadas de Android.
|
Saludapp es una aplicación Android moderna enfocada en la salud y el bienestar, diseñada para ser multiusuario y conectada a una base de datos externa.
|
||||||
|
|
||||||
## 🚀 Características
|
## 🚀 Características
|
||||||
- Interfaz de usuario moderna con **Jetpack Compose**.
|
- **Sistema Multiusuario:** Autenticación de usuarios mediante Login.
|
||||||
- Pantalla de inicio atractiva con mensaje de bienvenida.
|
- **Conexión a Base de Datos:** Integración directa con **MariaDB** autohospedado.
|
||||||
- Diseño basado en **Material 3** con soporte para temas dinámicos.
|
- **Interfaz Moderna:** Desarrollada íntegramente con **Jetpack Compose**.
|
||||||
- Arquitectura limpia y escalable.
|
- **Diseño Material 3:** Uso de componentes y temas dinámicos de última generación.
|
||||||
|
- **Navegación Fluida:** Flujo desde pantalla de inicio hasta el panel principal.
|
||||||
|
|
||||||
## 🛠️ Tecnologías utilizadas
|
## 🛠️ Tecnologías utilizadas
|
||||||
- **Lenguaje:** [Kotlin](https://kotlinlang.org/)
|
- **Lenguaje:** [Kotlin](https://kotlinlang.org/)
|
||||||
- **UI Framework:** [Jetpack Compose](https://developer.android.com/jetpack/compose)
|
- **UI Framework:** [Jetpack Compose](https://developer.android.com/jetpack/compose)
|
||||||
|
- **Base de Datos:** [MariaDB](https://mariadb.org/) (via MariaDB Java Client)
|
||||||
|
- **Asincronía:** Corrutinas de Kotlin para operaciones de red no bloqueantes.
|
||||||
- **Diseño:** [Material Design 3](https://m3.material.io/)
|
- **Diseño:** [Material Design 3](https://m3.material.io/)
|
||||||
- **Gestión de dependencias:** Gradle (Kotlin DSL)
|
|
||||||
|
|
||||||
## 📋 Requisitos previos
|
## 📋 Requisitos previos
|
||||||
- Android Studio Ladybug o superior.
|
- Android Studio Ladybug o superior.
|
||||||
- JDK 17 o superior.
|
- JDK 17 o superior.
|
||||||
- SDK de Android (Nivel de API 24 o superior recomendado).
|
- SDK de Android 37 (API level 37).
|
||||||
|
|
||||||
## 🔧 Configuración e Instalación
|
## 🔧 Configuración e Instalación
|
||||||
1. Clona este repositorio:
|
1. **Clonar el repositorio:**
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/tu-usuario/Saludapp.git
|
git clone https://github.com/tu-usuario/Saludapp.git
|
||||||
```
|
```
|
||||||
2. Abre el proyecto en **Android Studio**.
|
2. **Configurar Credenciales:**
|
||||||
3. Sincroniza el proyecto con los archivos de Gradle.
|
- Abre el archivo `app/src/main/java/com/example/saludapp/data/DatabaseHelper.kt`.
|
||||||
4. Ejecuta la aplicación en un emulador o dispositivo físico.
|
- Sustituye `TU_CONTRASEÑA_AQUÍ` por la contraseña real de tu base de datos MariaDB.
|
||||||
|
3. **Sincronizar Gradle:** Abre el proyecto en Android Studio y espera a que termine la sincronización de dependencias.
|
||||||
|
4. **Ejecutar:** Compila y ejecuta en un dispositivo o emulador con acceso a Internet.
|
||||||
|
|
||||||
## 📂 Estructura del Proyecto
|
## 📂 Estructura del Proyecto
|
||||||
- `app/`: Contiene el código fuente principal de la aplicación.
|
- `app/`: Módulo principal de la aplicación.
|
||||||
- `src/main/java/com/example/saludapp/MainActivity.kt`: Punto de entrada de la aplicación.
|
- `src/main/java/com/example/saludapp/`:
|
||||||
- `src/main/java/com/example/saludapp/ui/StartScreen.kt`: Composable de la pantalla de inicio.
|
- `MainActivity.kt`: Gestiona el flujo de navegación principal.
|
||||||
- `src/main/java/com/example/saludapp/ui/theme/`: Configuración del tema, colores y tipografía de Material 3.
|
- `data/DatabaseHelper.kt`: Lógica de conexión y consultas a MariaDB.
|
||||||
|
- `ui/`: Contiene los componentes de la interfaz de usuario.
|
||||||
|
- `StartScreen.kt`: Pantalla de bienvenida.
|
||||||
|
- `LoginScreen.kt`: Interfaz de inicio de sesión con validación real.
|
||||||
|
- `theme/`: Definición de estilos y colores de Material 3.
|
||||||
|
|
||||||
---
|
---
|
||||||
Desarrollado con ❤️ para mejorar la salud de los usuarios.
|
Desarrollado con ❤️ para mejorar la salud de los usuarios.
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ dependencies {
|
|||||||
implementation(libs.androidx.compose.ui.tooling.preview)
|
implementation(libs.androidx.compose.ui.tooling.preview)
|
||||||
implementation(libs.androidx.core.ktx)
|
implementation(libs.androidx.core.ktx)
|
||||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||||
|
implementation(libs.mariadb.java.client)
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(platform(libs.androidx.compose.bom))
|
androidTestImplementation(platform(libs.androidx.compose.bom))
|
||||||
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
|
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
|
|||||||
@@ -4,6 +4,16 @@ import android.os.Bundle
|
|||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
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.StartScreen
|
||||||
import com.example.saludapp.ui.theme.SaludappTheme
|
import com.example.saludapp.ui.theme.SaludappTheme
|
||||||
|
|
||||||
@@ -13,8 +23,24 @@ class MainActivity : ComponentActivity() {
|
|||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
setContent {
|
setContent {
|
||||||
SaludappTheme {
|
SaludappTheme {
|
||||||
StartScreen {
|
var currentScreen by remember { mutableStateOf("start") }
|
||||||
// Acción al presionar el botón
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,8 +8,10 @@ lifecycleRuntimeKtx = "2.11.0"
|
|||||||
activityCompose = "1.13.0"
|
activityCompose = "1.13.0"
|
||||||
kotlin = "2.2.10"
|
kotlin = "2.2.10"
|
||||||
composeBom = "2026.02.01"
|
composeBom = "2026.02.01"
|
||||||
|
mariadb = "3.5.1"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
|
mariadb-java-client = { group = "org.mariadb.jdbc", name = "mariadb-java-client", version.ref = "mariadb" }
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||||
|
|||||||
Reference in New Issue
Block a user