Ir al contenido
DocuGraph

DocuGraph

Frontend Spec: User Authentication Form Composable (LoginForm)

Estado de fase (MASTER-00): POST_MVP — documento de catálogo de producto sujeto a validación; no es alcance aprobado de Gate 0 / PoC / MVP. Gobernanza: MASTER-00.

Frontend Spec: User Authentication Form Composable (LoginForm)

Sección titulada «Frontend Spec: User Authentication Form Composable (LoginForm)»

This specification details the Compose Multiplatform UI component (LoginForm) in :docugraph-app. It renders the interactive login form, captures user email/password credentials, performs client-side field validation, dispatches authentication requests to BE-01 loginUser, handles authentication states, and securely persists JWT tokens into platform keychain/encrypted storage.

package io.docugraph.app.ui.auth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@Composable
fun LoginForm(
viewModel: AuthViewModel,
onLoginSuccess: () -> Unit,
modifier: Modifier = Modifier
)
package io.docugraph.app.ui.auth
data class LoginUiState(
val email: String = "",
val password: String = "",
val isPasswordVisible: Boolean = false,
val isLoading: Boolean = false,
val errorMessage: String? = null,
val emailError: String? = null,
val passwordError: String? = null
) {
val isFormValid: Boolean
get() = email.isNotBlank() && password.length >= 8 && emailError == null && passwordError == null
}
Surface (FillMaxSize, MaterialTheme.colorScheme.background)
└── Column (Alignment.CenterHorizontally, Padding 24.dp)
├── Text ("Welcome to DocuGraph", style = HeadlineMedium)
├── Spacer (Height 8.dp)
├── Text ("Sign in to access your documentation DAG", style = BodyMedium)
├── Spacer (Height 32.dp)
├── OutlinedTextField (Email)
│ ├── LeadingIcon: Icon(Icons.Default.Email)
│ └── IsError: emailError != null
├── Spacer (Height 16.dp)
├── OutlinedTextField (Password)
│ ├── LeadingIcon: Icon(Icons.Default.Lock)
│ ├── TrailingIcon: IconButton (PasswordVisibilityToggle)
│ └── VisualTransformation: PasswordVisualTransformation / None
├── Spacer (Height 24.dp)
├── AnimatedVisibility (errorMessage != null)
│ └── ErrorBanner (Text = errorMessage, Color = Error)
├── Spacer (Height 16.dp)
└── Button (Submit)
├── Enabled = isFormValid && !isLoading
└── Content: if (isLoading) CircularProgressIndicator else Text("Sign In")
User Input LoginForm Composable AuthViewModel Backend (BE-01)
| | | |
|-- types email ---------->|-- onEmailChanged ------>| |
| | |-- validate email regex |
|-- types password ------->|-- onPasswordChanged --->| |
| | |-- validate length >= 8 |
|-- clicks "Sign In" ----->|-- onLoginClicked ----->| |
| | |-- POST /auth/login --->|
| | |<- 200 AuthTokenResp ---|
| | |-- save JWT to storage |
|<-- triggers callback ----|<- onLoginSuccess() ----| |

6. Secure Token Persistence & Platform Target Notes

Sección titulada «6. Secure Token Persistence & Platform Target Notes»
  • Android: Stores JWT in EncryptedSharedPreferences via AndroidX Security.
  • Desktop (JVM): Stores JWT in OS Keyring via java-keyring library.
  • iOS: Stores JWT in Keychain Services via Kotlin/Native interop.
  • Screenshot / Component Test: Render LoginForm in @Preview state with error banner and loading indicator.
  • UiTest: Type invalid email, assert error message shown. Type valid credentials, tap button, verify onLoginSuccess called.