import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:go_router/go_router.dart'; import 'package:manager_app/Components/common_loader.dart'; import 'package:manager_app/Components/message_notification.dart'; import 'package:manager_app/Components/rounded_button.dart'; import 'package:manager_app/Components/rounded_password_field.dart'; import 'package:manager_app/client.dart'; import 'package:manager_app/constants.dart'; import 'package:manager_app/l10n/app_localizations.dart'; /// Used by the 3 flows sharing the same generic token mechanism: onboarding /// welcome step (not currently linked, password is set directly at sign-up), /// user invitation, and forgot-password. The token is read from the URL query /// param, e.g. manager-app.myinfomate.be/set-password?token=xxx class SetPasswordScreen extends StatefulWidget { final String? token; SetPasswordScreen({Key? key, this.token}) : super(key: key); @override _SetPasswordScreenState createState() => _SetPasswordScreenState(); } class _SetPasswordScreenState extends State { final String host = "http://localhost:5000"; String newPassword = ""; bool isLoading = false; bool isDone = false; Future submit() async { final l = AppLocalizations.of(context)!; if (widget.token == null || widget.token!.isEmpty) { showNotification(kError, kWhite, l.setPasswordMissingToken, context, null); return; } if (newPassword.length < 8) { showNotification(Colors.orange, kWhite, l.setPasswordTooShort, context, null); return; } setState(() => isLoading = true); try { final clientAPI = Client(host); await clientAPI.authenticationApi!.authenticationSetPassword( token: widget.token!, newPassword: newPassword, ); setState(() { isDone = true; isLoading = false; }); } catch (e) { setState(() => isLoading = false); showNotification(kError, kWhite, l.setPasswordError, context, null); } } @override Widget build(BuildContext context) { final l = AppLocalizations.of(context)!; return Scaffold( body: LayoutBuilder( builder: (context, constraints) { final isMobile = constraints.maxWidth < 550; final cardWidth = isMobile ? constraints.maxWidth - 32.0 : 440.0; return Container( width: double.infinity, height: double.infinity, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ kPrimaryColor.withValues(alpha: 0.12), kBackgroundColor, kBackgroundColor, ], ), ), child: Center( child: SingleChildScrollView( padding: EdgeInsets.all(isMobile ? 16.0 : 24.0), child: Container( width: cardWidth, decoration: BoxDecoration( color: kWhite, borderRadius: BorderRadius.circular(16.0), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.08), spreadRadius: 0, blurRadius: 32, offset: Offset(0, 8), ), ], ), child: Padding( padding: EdgeInsets.symmetric(horizontal: isMobile ? 24.0 : 40.0, vertical: 40.0), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( constraints: BoxConstraints(maxHeight: 64, minHeight: 40), child: SvgPicture.asset('assets/images/MyInfoMate_logo_only.svg'), ), SizedBox(height: 24), if (!isDone) ...[ Text( l.setPasswordTitle, style: TextStyle(color: kPrimaryColor, fontSize: 22, fontWeight: FontWeight.w600), textAlign: TextAlign.center, ), SizedBox(height: 8), Text( l.setPasswordDesc, style: TextStyle(fontSize: 14, color: Colors.grey[700]), textAlign: TextAlign.center, ), SizedBox(height: 24), RoundedPasswordField( initialValue: newPassword, onChanged: (value) => newPassword = value, ), SizedBox(height: 24), !isLoading ? SizedBox( width: double.infinity, child: RoundedButton( text: l.setPasswordSubmit, fontSize: 16, vertical: 15, horizontal: 30, press: submit, ), ) : CommonLoader(iconSize: 40), ] else ...[ Icon(Icons.check_circle_outline, color: kSuccess, size: 48), SizedBox(height: 16), Text( l.setPasswordSuccess, style: TextStyle(fontSize: 15), textAlign: TextAlign.center, ), SizedBox(height: 24), SizedBox( width: double.infinity, child: RoundedButton( text: l.connect, fontSize: 16, vertical: 15, horizontal: 30, press: () => context.go('/login'), ), ), ], ], ), ), ), ), ), ); }, ), ); } }