rluv_client/lib/features/account/signup.dart

259 lines
8.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:helpers/helpers/misc_build/build_media.dart';
import 'package:helpers/helpers/print.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<FormState> formKey;
final Widget exitNav;
@override
ConsumerState<Signup> createState() => _SignupState();
}
class _SignupState extends ConsumerState<Signup> {
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 = BuildMedia(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);
printAmber(data);
// final user = User.fromJson(data?['user']);
// ref.read(tokenProvider.notifier).state =
} catch (err) {
printRed(err);
}
}
}