Files
sendico/frontend/pweb/lib/pages/login/form.dart
Stephan D c6a56071b5
Some checks failed
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/billing_fees Pipeline was successful
ci/woodpecker/push/chain_gateway Pipeline was successful
ci/woodpecker/push/fx_ingestor Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
ci/woodpecker/push/fx_oracle Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/ledger Pipeline was successful
ci/woodpecker/push/notification Pipeline was successful
ci/woodpecker/push/payments_orchestrator Pipeline was successful
ci/woodpecker/push/bump_version Pipeline failed
+signup +login
2025-11-17 20:16:45 +01:00

110 lines
3.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:pshared/provider/account.dart';
import 'package:pshared/provider/locale.dart';
import 'package:pweb/app/router/pages.dart';
import 'package:pweb/pages/login/buttons.dart';
import 'package:pweb/pages/login/header.dart';
import 'package:pweb/widgets/constrained_form.dart';
import 'package:pweb/widgets/password/hint/short.dart';
import 'package:pweb/widgets/password/password.dart';
import 'package:pweb/widgets/username.dart';
import 'package:pweb/widgets/vspacer.dart';
import 'package:pweb/widgets/error/snackbar.dart';
import 'package:pweb/generated/i18n/app_localizations.dart';
class LoginForm extends StatefulWidget {
const LoginForm({super.key});
@override
State<LoginForm> createState() => _LoginFormState();
}
class _LoginFormState extends State<LoginForm> {
final TextEditingController _usernameController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final _formKey = GlobalKey<FormState>();
// ValueNotifiers for validation state
final ValueNotifier<bool> _isUsernameAcceptable = ValueNotifier<bool>(false);
final ValueNotifier<bool> _isPasswordAcceptable = ValueNotifier<bool>(false);
Future<String?> _login(BuildContext context, VoidCallback onLogin, void Function(Object e) onError) async {
final provider = Provider.of<AccountProvider>(context, listen: false);
try {
//final account =
await provider.login(
email: _usernameController.text,
password: _passwordController.text,
locale: context.read<LocaleProvider>().locale.languageCode,
);
onLogin();
return 'ok';
} catch (e) {
onError(provider.error ?? e);
}
return null;
}
@override
void dispose() {
_usernameController.dispose();
_passwordController.dispose();
_isUsernameAcceptable.dispose();
_isPasswordAcceptable.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) => Align(
alignment: Alignment.center,
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 400, maxHeight: 300),
child: Card(
child: ConstrainedForm(
formKey: _formKey,
children: [
const LoginHeader(),
const VSpacer(multiplier: 1.5),
UsernameField(
controller: _usernameController,
onValid: (isValid) => _isUsernameAcceptable.value = isValid,
),
VSpacer(),
defaulRulesPasswordField(
context,
controller: _passwordController,
validationRuleBuilder: (rules, value) => shortValidation(context, rules, value),
onValid: (isValid) => _isPasswordAcceptable.value = isValid,
),
VSpacer(multiplier: 2.0),
ValueListenableBuilder<bool>(
valueListenable: _isUsernameAcceptable,
builder: (context, isUsernameValid, child) => ValueListenableBuilder<bool>(
valueListenable: _isPasswordAcceptable,
builder: (context, isPasswordValid, child) => ButtonsRow(
onSignUp: () => navigate(context, Pages.signup),
login: () => _login(
context,
() => navigateAndReplace(context, Pages.sfactor),
(e) => postNotifyUserOfErrorX(
context: context,
errorSituation: AppLocalizations.of(context)!.errorLogin,
exception: e,
),
),
isEnabled: isUsernameValid && isPasswordValid,
),
),
),
],
),
)));
}