326 lines
10 KiB
Dart
326 lines
10 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:marco/helpers/widgets/my_form_validator.dart';
|
|
import 'package:marco/helpers/services/auth_service.dart';
|
|
import 'package:marco/helpers/widgets/my_snackbar.dart';
|
|
|
|
class OrganizationFormBottomSheet {
|
|
static void show(BuildContext context) {
|
|
showModalBottomSheet(
|
|
context: context,
|
|
isScrollControlled: true,
|
|
backgroundColor: Colors.transparent,
|
|
builder: (_) => DraggableScrollableSheet(
|
|
expand: false,
|
|
initialChildSize: 0.85,
|
|
minChildSize: 0.5,
|
|
maxChildSize: 0.95,
|
|
builder: (context, scrollController) {
|
|
return _OrganizationForm(scrollController: scrollController);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _OrganizationForm extends StatefulWidget {
|
|
final ScrollController scrollController;
|
|
const _OrganizationForm({required this.scrollController});
|
|
|
|
@override
|
|
State<_OrganizationForm> createState() => _OrganizationFormState();
|
|
}
|
|
|
|
class _OrganizationFormState extends State<_OrganizationForm> {
|
|
final MyFormValidator validator = MyFormValidator();
|
|
|
|
List<Map<String, dynamic>> _industries = [];
|
|
String? _selectedIndustryId;
|
|
|
|
final List<String> _sizes = [
|
|
'1-10',
|
|
'11-50',
|
|
'51-200',
|
|
'201-1000',
|
|
'1000+',
|
|
];
|
|
|
|
final Map<String, String> _sizeApiMap = {
|
|
'1-10': 'less than 10',
|
|
'11-50': '11 to 50',
|
|
'51-200': '51 to 200',
|
|
'201-1000': 'more than 200',
|
|
'1000+': 'more than 1000',
|
|
};
|
|
|
|
String? _selectedSize;
|
|
bool _agreed = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
_loadIndustries();
|
|
|
|
validator.addField<String>('organizationName',
|
|
required: true, controller: TextEditingController());
|
|
validator.addField<String>('email',
|
|
required: true, controller: TextEditingController());
|
|
validator.addField<String>('contactPerson',
|
|
required: true, controller: TextEditingController());
|
|
validator.addField<String>('contactNumber',
|
|
required: true, controller: TextEditingController());
|
|
validator.addField<String>('about', controller: TextEditingController());
|
|
validator.addField<String>('address',
|
|
required: true, controller: TextEditingController());
|
|
}
|
|
|
|
Future<void> _loadIndustries() async {
|
|
final industries = await AuthService.getIndustries();
|
|
if (industries != null) {
|
|
setState(() {
|
|
_industries = industries;
|
|
});
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container(
|
|
decoration: const BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
|
),
|
|
padding: const EdgeInsets.all(20),
|
|
child: SingleChildScrollView(
|
|
controller: widget.scrollController,
|
|
child: Form(
|
|
key: validator.formKey,
|
|
child: Column(
|
|
children: [
|
|
Container(
|
|
width: 40,
|
|
height: 5,
|
|
margin: const EdgeInsets.only(bottom: 20),
|
|
decoration: BoxDecoration(
|
|
color: Colors.grey[300],
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
),
|
|
Text(
|
|
'Adventure starts here 🚀',
|
|
style: Theme.of(context).textTheme.titleLarge,
|
|
),
|
|
const SizedBox(height: 4),
|
|
const Text("Make your app management easy and fun!"),
|
|
const SizedBox(height: 20),
|
|
_buildTextField('organizationName', 'Organization Name'),
|
|
_buildTextField('email', 'Email',
|
|
keyboardType: TextInputType.emailAddress),
|
|
_buildTextField('contactPerson', 'Contact Person'),
|
|
_buildTextField('contactNumber', 'Contact Number',
|
|
keyboardType: TextInputType.phone),
|
|
_buildTextField('about', 'About Organization'),
|
|
_buildTextField('address', 'Current Address'),
|
|
const SizedBox(height: 10),
|
|
_buildPopupMenuField(
|
|
'Organization Size',
|
|
_sizes,
|
|
_selectedSize,
|
|
(val) => setState(() => _selectedSize = val),
|
|
'Please select organization size',
|
|
),
|
|
_buildPopupMenuField(
|
|
'Industry',
|
|
_industries.map((e) => e['name'] as String).toList(),
|
|
_selectedIndustryId != null
|
|
? _industries.firstWhere(
|
|
(e) => e['id'] == _selectedIndustryId)['name']
|
|
: null,
|
|
(val) {
|
|
setState(() {
|
|
final selectedIndustry = _industries.firstWhere(
|
|
(element) => element['name'] == val,
|
|
orElse: () => {});
|
|
_selectedIndustryId = selectedIndustry['id'];
|
|
});
|
|
},
|
|
'Please select industry',
|
|
),
|
|
const SizedBox(height: 10),
|
|
Row(
|
|
children: [
|
|
Checkbox(
|
|
value: _agreed,
|
|
onChanged: (val) => setState(() => _agreed = val ?? false),
|
|
fillColor: MaterialStateProperty.all(Colors.white),
|
|
checkColor: Colors.white,
|
|
side: MaterialStateBorderSide.resolveWith(
|
|
(states) =>
|
|
BorderSide(color: Colors.blueAccent, width: 2),
|
|
),
|
|
),
|
|
const Expanded(
|
|
child: Text('I agree to privacy policy & terms')),
|
|
],
|
|
),
|
|
const SizedBox(height: 10),
|
|
ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.blueAccent,
|
|
),
|
|
onPressed: _submitForm,
|
|
child: const Text("Submit"),
|
|
),
|
|
TextButton(
|
|
onPressed: () => Navigator.pop(context),
|
|
child: const Text("Back to login"),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildPopupMenuField(
|
|
String label,
|
|
List<String> items,
|
|
String? selectedValue,
|
|
ValueChanged<String?> onSelected,
|
|
String errorText,
|
|
) {
|
|
final bool hasError = selectedValue == null;
|
|
final GlobalKey _key = GlobalKey();
|
|
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 6),
|
|
child: FormField<String>(
|
|
validator: (value) => hasError ? errorText : null,
|
|
builder: (fieldState) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(label,
|
|
style: TextStyle(fontSize: 12, color: Colors.grey[700])),
|
|
const SizedBox(height: 6),
|
|
GestureDetector(
|
|
key: _key,
|
|
onTap: () async {
|
|
final RenderBox renderBox =
|
|
_key.currentContext!.findRenderObject() as RenderBox;
|
|
final Offset offset = renderBox.localToGlobal(Offset.zero);
|
|
final Size size = renderBox.size;
|
|
|
|
final selected = await showMenu<String>(
|
|
context: fieldState.context,
|
|
position: RelativeRect.fromLTRB(
|
|
offset.dx,
|
|
offset.dy + size.height,
|
|
offset.dx + size.width,
|
|
offset.dy,
|
|
),
|
|
items: items
|
|
.map((item) => PopupMenuItem<String>(
|
|
value: item,
|
|
child: Text(item),
|
|
))
|
|
.toList(),
|
|
);
|
|
if (selected != null) {
|
|
onSelected(selected);
|
|
fieldState.didChange(selected);
|
|
}
|
|
},
|
|
child: InputDecorator(
|
|
decoration: InputDecoration(
|
|
border: const OutlineInputBorder(),
|
|
errorText: fieldState.errorText,
|
|
contentPadding: const EdgeInsets.symmetric(
|
|
horizontal: 12, vertical: 14),
|
|
),
|
|
child: Text(
|
|
selectedValue ?? 'Select $label',
|
|
style: TextStyle(
|
|
color: selectedValue == null ? Colors.grey : Colors.black,
|
|
fontSize: 16,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildTextField(String fieldName, String label,
|
|
{TextInputType keyboardType = TextInputType.text}) {
|
|
final controller = validator.getController(fieldName);
|
|
final validatorFunc = validator.getValidation<String>(fieldName);
|
|
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 6),
|
|
child: TextFormField(
|
|
controller: controller,
|
|
keyboardType: keyboardType,
|
|
decoration: InputDecoration(
|
|
labelText: label,
|
|
border: const OutlineInputBorder(),
|
|
),
|
|
validator: validatorFunc,
|
|
),
|
|
);
|
|
}
|
|
|
|
void _submitForm() async {
|
|
bool isValid = validator.validateForm();
|
|
|
|
if (_selectedSize == null || _selectedIndustryId == null) {
|
|
isValid = false;
|
|
setState(() {});
|
|
}
|
|
|
|
if (!_agreed) {
|
|
isValid = false;
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(
|
|
content: Text('Please agree to the privacy policy & terms')),
|
|
);
|
|
}
|
|
|
|
if (isValid) {
|
|
final formData = validator.getData();
|
|
|
|
final Map<String, dynamic> requestBody = {
|
|
'organizatioinName': formData['organizationName'],
|
|
'email': formData['email'],
|
|
'about': formData['about'],
|
|
'contactNumber': formData['contactNumber'],
|
|
'contactPerson': formData['contactPerson'],
|
|
'industryId': _selectedIndustryId ?? '',
|
|
'oragnizationSize': _sizeApiMap[_selectedSize] ?? '',
|
|
'terms': _agreed,
|
|
'address': formData['address'],
|
|
};
|
|
|
|
final error = await AuthService.requestDemo(requestBody);
|
|
|
|
if (error == null) {
|
|
showAppSnackbar(
|
|
title: "Success",
|
|
message: "Demo request submitted successfully!.",
|
|
type: SnackbarType.success,
|
|
);
|
|
Navigator.pop(context);
|
|
} else {
|
|
showAppSnackbar(
|
|
title: "Success",
|
|
message: (error['error'] ?? 'Unknown error'),
|
|
type: SnackbarType.success,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|