import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../global/api.dart'; import '../../global/styles.dart'; import '../../global/utils.dart'; import '../../global/widgets/ui_button.dart'; class Signup extends ConsumerStatefulWidget { const Signup({super.key, required this.formKey, required this.exitNav}); final GlobalKey formKey; final Widget exitNav; @override ConsumerState createState() => _SignupState(); } class _SignupState extends ConsumerState { bool hasFamilyCode = false; final nameCotroller = TextEditingController(); final usernameController = TextEditingController(); final emailController = TextEditingController(); final passwordController = TextEditingController(); final familyCodeController = TextEditingController(); final focusNodes = [ FocusNode(), FocusNode(), FocusNode(), FocusNode(), FocusNode(), ]; @override Widget build(BuildContext context) { final screen = MediaQuery.of(context).size; return Form( key: widget.formKey, child: Stack( children: [ Column( children: [ const Spacer(), const Text( 'Signup', style: TextStyle(fontSize: 24), ), const Spacer(), generateTextField( controller: nameCotroller, size: screen, text: 'Name:', validatorFunc: (s) { if (s == null || s.isEmpty) { return 'You matter! Enter a name :)'; } return null; }, index: 0), generateTextField( controller: usernameController, size: screen, text: 'Username: ', validatorFunc: (s) { if (s == null || s.isEmpty) { return 'Invalid Username'; } if (s.length < 3) { return 'Username Not 3 Letters Long'; } if (s.length > 20) { return 'Username Too Long'; } if (!isUsernameValid(s)) { return 'Letters, Numbers, and ., -, _ Allowed'; } return null; }, index: 1), generateTextField( controller: emailController, size: screen, validatorFunc: (s) { if (s != null && s.isNotEmpty && !isEmailValid(s)) { return 'Email entered is invalid'; } return null; }, text: 'Email:', subtext: '(optional)', index: 2), generateTextField( controller: passwordController, size: screen, validatorFunc: (s) { if (s != null && s.length < 6) { return 'Please do a better password (you have to)'; } return null; }, text: 'Password:', index: 3, isPassword: true), const SizedBox(height: 30), AnimatedSwitcher( duration: const Duration(milliseconds: 300), child: hasFamilyCode ? Column( children: [ generateTextField( controller: familyCodeController, size: screen, validatorFunc: (s) { if (hasFamilyCode) { if (s == null || s.length != 5) { return 'Invalid Code'; } } return null; }, text: 'Family Code:', index: 4, ), UiButton( width: screen.width * 0.4, icon: const Icon(Icons.cancel, color: Styles.washedStone, size: 20), onPressed: () { setState( () => hasFamilyCode = false, ); }, text: 'Cancel', ), ], ) : Padding( padding: const EdgeInsets.all(8.0), child: UiButton( width: screen.width * 0.5 > 400 ? 400 : screen.width * 0.5, text: 'JOIN FAMILY', // color: Styles.flounderBlue, onPressed: () { setState( () => hasFamilyCode = true, ); }, ), )), const Spacer(), UiButton( showLoading: true, onPressed: () => signup(), text: 'Submit', color: Styles.seaweedGreen, ), const Spacer(), ], ), widget.exitNav, ], ), ); } Widget generateTextField({ required String text, String? subtext, String? label, required int index, required TextEditingController controller, isPassword = false, required Size size, required String? Function(String?) validatorFunc, }) { return Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Text( text, style: TextStyle(fontSize: size.width < 350 ? 16 : 20), ), if (subtext != null) Text(subtext, style: const TextStyle(fontSize: 12)), ], ), ), const Spacer(), Container( decoration: Styles.boxLavenderBubble, width: size.width * 0.5 > 300 ? 300 : size.width * 0.5, child: TextFormField( validator: validatorFunc, controller: controller, decoration: Styles.inputLavenderBubble(labelText: label), obscureText: isPassword, focusNode: focusNodes[index], style: const TextStyle(fontSize: 16), onFieldSubmitted: (_) { if (index != focusNodes.length - 1) { focusNodes[index + 1].requestFocus(); } }, ), ), SizedBox( width: size.width * 0.05, ), ], ), ); } Future signup() async { try { if (widget.formKey.currentState != null && !widget.formKey.currentState!.validate()) { return; } final data = await ref.read(apiProvider.notifier).post(path: 'auth/signup', data: { 'name': nameCotroller.text, 'username': usernameController.text.isEmpty ? null : usernameController.text, 'email': emailController.text.isEmpty ? null : emailController.text, 'password': passwordController.text, 'family_code': familyCodeController.text.isEmpty ? null : familyCodeController.text.toUpperCase(), 'budget_name': 'Budget' }); final success = data?['success'] ?? false; showSnack( ref: ref, text: data?['message'] ?? success ? 'Login successful' : 'Login unsuccessful', type: !success ? SnackType.error : SnackType.success); print(data); // final user = User.fromJson(data?['user']); // ref.read(tokenProvider.notifier).state = } catch (err) { print(err); } } }