# Login

- File ID: file:csf9l7:login-razor
- Path: NexusReader.UI.Shared/Pages/Account/Login.razor
- Role: ui-page
- Layer: frontend

## Purpose

Razor UI page for user login: renders email/password and Google auth UI, validates input, calls identity service to authenticate, and triggers a hidden form JS submission for cookie-based sign-in.

## Key Details

Uses an EditForm with DataAnnotations validation; on successful credentials-based login it invokes a JS helper to POST a hidden form for cookie-based sign-in; supports Google external login via forced navigation; maps query-supplied error codes to localized user messages.

## Symbols

- Login: Razor UI page for user login: renders email/password and Google auth UI, validates input, calls identity service to authenticate, and triggers a hidden form JS submission for cookie-based sign-in.
- OnInitialized(): Initializes component state by mapping an incoming query error code to a user-friendly error message.
- HandleLogin(): Handles form submission: calls IdentityService.LoginAsync, sets submission state, handles success by invoking a JS helper to submit a hidden form (cookie sign-in), and surfaces errors.
- HandleGoogleLogin(): Initiates external Google/OAuth login by navigating to the identity external-login route with forceLoad.
- TogglePassword(): Toggles password visibility state used by the input field.
- LoginModel: Holds credentials and remember-me flag submitted by the login form.

## Dependencies

- No resolved dependencies.

## Calls

- No resolved calls.

## Unresolved References

- dependency-target: NexusReader.UI.Shared/Services/IIdentityService (injected)
- dependency-target: Microsoft.AspNetCore.Components.NavigationManager (injected)
- dependency-target: Microsoft.JSInterop.IJSRuntime (injected)
- dependency-target: NexusReader.UI.Shared.Components.Atoms.NexusIcon (used in markup)
- call-target: unknown
- interaction-target: _errorMessage = result.Errors.FirstOrDefault()?.Message ?? "Nieprawidłowy e-mail lub hasło.";
- interaction-target: Calls injected IIdentityService.LoginAsync to authenticate user; external project service (result examined afterwards).
- interaction-target: Calls JS.InvokeVoidAsync('nexusAuth.submitLoginForm', 'nexusLoginForm', email, password, remember) to perform cookie-based sign-in (framework JS runtime call).

## Coverage

- Symbols: 6
- Executable symbols: 4
- Executable symbols with control flow: 4
- Grounded edges: 6
- Unresolved references: 8
- Control-flow fragments: 4
- Unresolved jumps: 1
- Unsupported constructs: 0
- Control-flow coverage: 100%
- Required diagrams: 2
- Generated diagrams: 4

## Control Flow Fragments

- OnInitialized: 11 nodes, 12 edges, 0 jumps, 0 unsupported constructs
- HandleLogin: 27 nodes, 29 edges, 1 jumps, 0 unsupported constructs
- HandleGoogleLogin: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs
- TogglePassword: 3 nodes, 2 edges, 0 jumps, 0 unsupported constructs

## Diagrams

### Login Neighborhood

```mermaid
flowchart LR
    class_1qurvhs_login("Login")
    file_csf9l7_login_razor("Login")
    method_1v0viho_oninitialized[["OnInitialized()"]]
    method_5hqhux_togglepassword[["TogglePassword()"]]
    method_ulfoov_handlegooglelogin[["HandleGoogleLogin()"]]
    method_uwsk5z_handlelogin[["HandleLogin()"]]
    type_gqgg0k_loginmodel[/"LoginModel"/]
```

### Login Execution Overview

```mermaid
flowchart TD
    class_1qurvhs_login("Login")
    method_1v0viho_oninitialized[["OnInitialized()"]]
    method_5hqhux_togglepassword[["TogglePassword()"]]
    method_ulfoov_handlegooglelogin[["HandleGoogleLogin()"]]
    method_uwsk5z_handlelogin[["HandleLogin()"]]
    unresolved_unresolved_112phtm_interaction_target{"Unresolved: Calls JS.InvokeVoidAsync('nexusAuth.submitLoginForm', 'nexusLoginForm', email, password, remember) to perform cookie-based sign-in (framework JS runtime call)."}
    unresolved_unresolved_181g12z_interaction_target{"Unresolved: Calls injected IIdentityService.LoginAsync to authenticate user; external project service (result examined afterwards)."}
    unresolved_unresolved_1b7ud7n_call_target{"Unresolved: LoginAsync"}
    unresolved_unresolved_nialgy_interaction_target{"Unresolved: _errorMessage = result.Errors.FirstOrDefault()?.Message ?? \\"Nieprawidłowy e-mail lub hasło.\\";"}
    class_1qurvhs_login -->|contains| method_1v0viho_oninitialized
    class_1qurvhs_login -->|contains| method_5hqhux_togglepassword
    class_1qurvhs_login -->|contains| method_ulfoov_handlegooglelogin
    class_1qurvhs_login -->|contains| method_uwsk5z_handlelogin
    class_1qurvhs_login -->|unresolved interaction| unresolved_unresolved_112phtm_interaction_target
    class_1qurvhs_login -->|unresolved interaction| unresolved_unresolved_181g12z_interaction_target
    class_1qurvhs_login -->|unresolved interaction| unresolved_unresolved_nialgy_interaction_target
    method_uwsk5z_handlelogin -->|unresolved call| unresolved_unresolved_1b7ud7n_call_target
```

### OnInitialized() Control Flow

```mermaid
flowchart TD
    method_1v0viho_oninitialized__action_112_guard_clause_112__condition{"if (!string.IsNullOrEmpty(ErrorCode))"}
    method_1v0viho_oninitialized__action_112_guard_clause_112__false("no-op")
    method_1v0viho_oninitialized__action_112_guard_clause_112__merge("merge")
    method_1v0viho_oninitialized__action_112_guard_clause_112__true("map error to message")
    method_1v0viho_oninitialized__action_112_oninitialized_branch_112_0__condition{"!string.IsNullOrEmpty(ErrorCode)"}
    method_1v0viho_oninitialized__action_112_oninitialized_branch_112_0__false("false")
    method_1v0viho_oninitialized__action_112_oninitialized_branch_112_0__merge("merge")
    method_1v0viho_oninitialized__action_112_oninitialized_branch_112_0__true("true")
    method_1v0viho_oninitialized__action_114_branch_switch_114__linear("Map ErrorCode to localized message")
    method_1v0viho_oninitialized__entry(["OnInitialized entry"])
    method_1v0viho_oninitialized__implicit_return(["return"])
    method_1v0viho_oninitialized__action_112_guard_clause_112__condition -->|no-op| method_1v0viho_oninitialized__action_112_guard_clause_112__false
    method_1v0viho_oninitialized__action_112_guard_clause_112__condition -->|map error to message| method_1v0viho_oninitialized__action_112_guard_clause_112__true
    method_1v0viho_oninitialized__action_112_guard_clause_112__false -->|next| method_1v0viho_oninitialized__action_112_guard_clause_112__merge
    method_1v0viho_oninitialized__action_112_guard_clause_112__merge -->|next| method_1v0viho_oninitialized__action_114_branch_switch_114__linear
    method_1v0viho_oninitialized__action_112_guard_clause_112__true -->|next| method_1v0viho_oninitialized__action_112_guard_clause_112__merge
    method_1v0viho_oninitialized__action_112_oninitialized_branch_112_0__condition -->|false| method_1v0viho_oninitialized__action_112_oninitialized_branch_112_0__false
    method_1v0viho_oninitialized__action_112_oninitialized_branch_112_0__condition -->|true| method_1v0viho_oninitialized__action_112_oninitialized_branch_112_0__true
    method_1v0viho_oninitialized__action_112_oninitialized_branch_112_0__false -->|next| method_1v0viho_oninitialized__action_112_oninitialized_branch_112_0__merge
    method_1v0viho_oninitialized__action_112_oninitialized_branch_112_0__merge -->|next| method_1v0viho_oninitialized__action_112_guard_clause_112__condition
    method_1v0viho_oninitialized__action_112_oninitialized_branch_112_0__true -->|next| method_1v0viho_oninitialized__action_112_oninitialized_branch_112_0__merge
    method_1v0viho_oninitialized__action_114_branch_switch_114__linear -->|return| method_1v0viho_oninitialized__implicit_return
    method_1v0viho_oninitialized__entry -->|next| method_1v0viho_oninitialized__action_112_oninitialized_branch_112_0__condition
```

### HandleLogin() Control Flow

_Warnings: diagram method_uwsk5z_handlelogin__fragment_diagram exceeds preferred complexity thresholds (27 nodes, 29 edges)._

```mermaid
---
config:
  flowchart:
    defaultRenderer: "elk"
---
flowchart TD
    method_uwsk5z_handlelogin__call_133_LoginAsync[["LoginAsync"]]
    method_uwsk5z_handlelogin__action_128_state_mutation_128__linear("Set submitting state")
    method_uwsk5z_handlelogin__action_131_handlelogin_try_131_0__try("Begins protected execution")
    method_uwsk5z_handlelogin__action_131_try_catch_finally_131__linear("Wrap remote login call")
    method_uwsk5z_handlelogin__action_133_handlelogin_await_133_1__await[["Waits for async work"]]
    method_uwsk5z_handlelogin__action_134_branch_134__condition{"if (result.IsSuccess) ... else ..."}
    method_uwsk5z_handlelogin__action_134_branch_134__false("failure -> set _errorMessage from result.Errors")
    method_uwsk5z_handlelogin__action_134_branch_134__merge("merge")
    method_uwsk5z_handlelogin__action_134_branch_134__true("success -> invoke JS to submit hidden form")
    method_uwsk5z_handlelogin__action_134_handlelogin_branch_134_2__condition{"result.IsSuccess"}
    method_uwsk5z_handlelogin__action_134_handlelogin_branch_134_2__false("false")
    method_uwsk5z_handlelogin__action_134_handlelogin_branch_134_2__merge("merge")
    method_uwsk5z_handlelogin__action_134_handlelogin_branch_134_2__true("true")
    method_uwsk5z_handlelogin__action_137_handlelogin_await_137_3__await[["Waits for async work"]]
    method_uwsk5z_handlelogin__action_139_handlelogin_fallback_139_4__condition{"Falls back to alternate path"}
    method_uwsk5z_handlelogin__action_139_handlelogin_fallback_139_4__false("otherwise")
    method_uwsk5z_handlelogin__action_139_handlelogin_fallback_139_4__merge("merge")
    method_uwsk5z_handlelogin__action_139_handlelogin_fallback_139_4__true("fallback")
    method_uwsk5z_handlelogin__action_144_error_handling_144__linear("Catch exceptions from login process")
    method_uwsk5z_handlelogin__action_144_handlelogin_catch_144_6__catch("catch Exception ex")
    method_uwsk5z_handlelogin__action_148_handlelogin_finally_148_7__finally("Runs cleanup or finalization")
    method_uwsk5z_handlelogin__action_150_state_mutation_150__linear("Clear submitting state")
    method_uwsk5z_handlelogin__entry(["HandleLogin entry"])
    method_uwsk5z_handlelogin__action_133_external_call_133__linear("Call identity service")
    method_uwsk5z_handlelogin__action_137_external_call_137__linear("Invoke JS helper for hidden form submission")
    method_uwsk5z_handlelogin__action_141_handlelogin_repository_read_141_5__linear[("Reads repository or persistence state")]
    method_uwsk5z_handlelogin__implicit_return(["return"])
    method_uwsk5z_handlelogin__action_128_state_mutation_128__linear -->|next| method_uwsk5z_handlelogin__action_131_try_catch_finally_131__linear
    method_uwsk5z_handlelogin__action_131_handlelogin_try_131_0__try -->|next| method_uwsk5z_handlelogin__action_133_handlelogin_await_133_1__await
    method_uwsk5z_handlelogin__action_131_try_catch_finally_131__linear -->|next| method_uwsk5z_handlelogin__action_131_handlelogin_try_131_0__try
    method_uwsk5z_handlelogin__action_133_external_call_133__linear -->|calls| method_uwsk5z_handlelogin__call_133_LoginAsync
    method_uwsk5z_handlelogin__action_133_handlelogin_await_133_1__await -->|next| method_uwsk5z_handlelogin__action_133_external_call_133__linear
    method_uwsk5z_handlelogin__action_134_branch_134__condition -->|failure -> set _errorMessage from result.Errors| method_uwsk5z_handlelogin__action_134_branch_134__false
    method_uwsk5z_handlelogin__action_134_branch_134__condition -->|success -> invoke JS to submit hidden form| method_uwsk5z_handlelogin__action_134_branch_134__true
    method_uwsk5z_handlelogin__action_134_branch_134__false -->|next| method_uwsk5z_handlelogin__action_134_branch_134__merge
    method_uwsk5z_handlelogin__action_134_branch_134__merge -->|next| method_uwsk5z_handlelogin__action_134_handlelogin_branch_134_2__condition
    method_uwsk5z_handlelogin__action_134_branch_134__true -->|next| method_uwsk5z_handlelogin__action_134_branch_134__merge
    method_uwsk5z_handlelogin__action_134_handlelogin_branch_134_2__condition -->|false| method_uwsk5z_handlelogin__action_134_handlelogin_branch_134_2__false
    method_uwsk5z_handlelogin__action_134_handlelogin_branch_134_2__condition -->|true| method_uwsk5z_handlelogin__action_134_handlelogin_branch_134_2__true
    method_uwsk5z_handlelogin__action_134_handlelogin_branch_134_2__false -->|next| method_uwsk5z_handlelogin__action_134_handlelogin_branch_134_2__merge
    method_uwsk5z_handlelogin__action_134_handlelogin_branch_134_2__merge -->|next| method_uwsk5z_handlelogin__action_137_handlelogin_await_137_3__await
    method_uwsk5z_handlelogin__action_134_handlelogin_branch_134_2__true -->|next| method_uwsk5z_handlelogin__action_134_handlelogin_branch_134_2__merge
    method_uwsk5z_handlelogin__action_137_external_call_137__linear -->|fallback| method_uwsk5z_handlelogin__action_139_handlelogin_fallback_139_4__condition
    method_uwsk5z_handlelogin__action_137_handlelogin_await_137_3__await -->|next| method_uwsk5z_handlelogin__action_137_external_call_137__linear
    method_uwsk5z_handlelogin__action_139_handlelogin_fallback_139_4__condition -->|otherwise| method_uwsk5z_handlelogin__action_139_handlelogin_fallback_139_4__false
    method_uwsk5z_handlelogin__action_139_handlelogin_fallback_139_4__condition -->|fallback| method_uwsk5z_handlelogin__action_139_handlelogin_fallback_139_4__true
    method_uwsk5z_handlelogin__action_139_handlelogin_fallback_139_4__false -->|next| method_uwsk5z_handlelogin__action_139_handlelogin_fallback_139_4__merge
    method_uwsk5z_handlelogin__action_139_handlelogin_fallback_139_4__merge -->|next| method_uwsk5z_handlelogin__action_141_handlelogin_repository_read_141_5__linear
    method_uwsk5z_handlelogin__action_139_handlelogin_fallback_139_4__true -->|next| method_uwsk5z_handlelogin__action_139_handlelogin_fallback_139_4__merge
    method_uwsk5z_handlelogin__action_141_handlelogin_repository_read_141_5__linear -->|exception| method_uwsk5z_handlelogin__action_144_handlelogin_catch_144_6__catch
    method_uwsk5z_handlelogin__action_144_error_handling_144__linear -->|next| method_uwsk5z_handlelogin__action_148_handlelogin_finally_148_7__finally
    method_uwsk5z_handlelogin__action_144_handlelogin_catch_144_6__catch -->|next| method_uwsk5z_handlelogin__action_144_error_handling_144__linear
    method_uwsk5z_handlelogin__action_148_handlelogin_finally_148_7__finally -->|next| method_uwsk5z_handlelogin__action_150_state_mutation_150__linear
    method_uwsk5z_handlelogin__action_150_state_mutation_150__linear -->|return| method_uwsk5z_handlelogin__implicit_return
    method_uwsk5z_handlelogin__call_133_LoginAsync -->|next| method_uwsk5z_handlelogin__action_134_branch_134__condition
    method_uwsk5z_handlelogin__entry -->|next| method_uwsk5z_handlelogin__action_128_state_mutation_128__linear
```

## Diagram Validation

- Status: warn
- Warning: Control-flow extraction left 1 unresolved jumps.
- Warning: control-flow: diagram method_uwsk5z_handlelogin__fragment_diagram exceeds preferred complexity thresholds (27 nodes, 29 edges).
