251 lines
8.3 KiB
Dart
251 lines
8.3 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: (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? 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: Text(
|
|
text,
|
|
style: TextStyle(fontSize: size.width < 350 ? 16 : 20),
|
|
),
|
|
),
|
|
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);
|
|
}
|
|
}
|
|
}
|