login works

This commit is contained in:
2025-07-24 16:25:58 +05:00
parent 039fcd690f
commit cf4e2307b5
12 changed files with 623 additions and 30 deletions

View File

@@ -2,20 +2,58 @@ package sh.sar.gridflow
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import sh.sar.gridflow.databinding.ActivityLoginBinding
import sh.sar.gridflow.network.ApiResult
import sh.sar.gridflow.network.FenakaApiService
import sh.sar.gridflow.utils.SecureStorage
class LoginActivity : AppCompatActivity() {
private lateinit var binding: ActivityLoginBinding
private lateinit var secureStorage: SecureStorage
private lateinit var apiService: FenakaApiService
companion object {
private const val TAG = "LoginActivity"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "LoginActivity onCreate")
binding = ActivityLoginBinding.inflate(layoutInflater)
setContentView(binding.root)
try {
secureStorage = SecureStorage(this)
apiService = FenakaApiService()
// Check if already logged in
if (secureStorage.isLoggedIn()) {
Log.d(TAG, "User already logged in, navigating to main")
navigateToMain()
return
}
// Pre-fill saved credentials
secureStorage.getMobile()?.let { mobile ->
Log.d(TAG, "Pre-filling mobile number: $mobile")
binding.etMobileNumber.setText(mobile)
}
} catch (e: Exception) {
Log.e(TAG, "Failed to initialize SecureStorage, continuing without it", e)
apiService = FenakaApiService()
Toast.makeText(this, "Warning: Secure storage not available", Toast.LENGTH_SHORT).show()
}
setupClickListeners()
}
@@ -41,17 +79,91 @@ class LoginActivity : AppCompatActivity() {
val mobileNumber = binding.etMobileNumber.text.toString().trim()
val password = binding.etPassword.text.toString().trim()
Log.d(TAG, "handleSignIn called with mobile: $mobileNumber")
if (validateInput(mobileNumber, password)) {
// TODO: Implement actual authentication logic
// For now, just navigate to main activity
Toast.makeText(this, "Signing in...", Toast.LENGTH_SHORT).show()
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
Log.d(TAG, "Input validation passed, calling performLogin")
performLogin(mobileNumber, password)
} else {
Log.d(TAG, "Input validation failed")
}
}
private fun performLogin(mobile: String, password: String) {
Log.d(TAG, "performLogin called with mobile: $mobile")
setLoading(true)
lifecycleScope.launch {
Log.d(TAG, "Starting coroutine for API call")
try {
when (val result = apiService.login(mobile, password)) {
is ApiResult.Success -> {
Log.d(TAG, "Login successful: ${result.data}")
// Save credentials and user info (if SecureStorage is available)
if (this@LoginActivity::secureStorage.isInitialized) {
try {
secureStorage.saveCredentials(mobile, password)
secureStorage.saveUserInfo(
result.data.name,
result.data.email,
result.data.id
)
// Extract and save cookie
result.cookie?.let { cookie ->
val sessionId = extractSessionId(cookie)
Log.d(TAG, "Extracted session ID: $sessionId")
secureStorage.saveCookie(sessionId)
}
} catch (e: Exception) {
Log.e(TAG, "Failed to save credentials securely", e)
}
}
setLoading(false)
navigateToMain()
}
is ApiResult.Error -> {
Log.d(TAG, "Login failed: ${result.message} (code: ${result.code})")
setLoading(false)
Toast.makeText(this@LoginActivity, result.message, Toast.LENGTH_LONG).show()
}
}
} catch (e: Exception) {
Log.e(TAG, "Exception in performLogin coroutine", e)
setLoading(false)
Toast.makeText(this@LoginActivity, "Login failed: ${e.message}", Toast.LENGTH_LONG).show()
}
}
}
private fun extractSessionId(setCookieHeader: String): String {
// Extract the session ID from Set-Cookie header
// Format: connect.sid=s%3A-vUZGRtHZZygj5Xm1Xg9nKdcZqanQCWm.JVdk7%2Bv63292vx5TWsOiws4QiGwKCYKjh%2FUhLWGEYVs; HttpOnly; Path=/; Expires=...
return setCookieHeader.substringBefore(";").substringAfter("connect.sid=")
}
private fun setLoading(isLoading: Boolean) {
binding.btnSignIn.isEnabled = !isLoading
binding.btnSignIn.text = if (isLoading) "Signing in..." else "Sign In"
// Disable other buttons during loading
binding.btnRegister.isEnabled = !isLoading
binding.btnForgotPassword.isEnabled = !isLoading
binding.btnPayWithoutAccount.isEnabled = !isLoading
// Show/hide progress indicator
binding.etMobileNumber.isEnabled = !isLoading
binding.etPassword.isEnabled = !isLoading
}
private fun navigateToMain() {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
}
private fun handleRegister() {
Toast.makeText(this, "Register functionality coming soon", Toast.LENGTH_SHORT).show()
// TODO: Navigate to registration screen
@@ -78,6 +190,12 @@ class LoginActivity : AppCompatActivity() {
return false
}
// Client-side password validation - must be at least 8 characters
if (password.length < 8) {
binding.etPassword.error = "Password must be at least 8 characters"
return false
}
// Basic Maldives mobile number validation (7xxxxxx format)
if (!mobileNumber.matches(Regex("^[79]\\d{6}$"))) {
binding.etMobileNumber.error = "Enter a valid Maldives mobile number"