medora-provider/lib/screens/patientScreens/registrationScreens/patient_adress_screen.dart
2024-10-31 21:25:50 +05:30

382 lines
12 KiB
Dart

import 'package:flutter/material.dart';
import 'package:country_state_city_picker/country_state_city_picker.dart';
import 'package:telemednet/controller/patient_controller.dart';
class PatientAddressScreen extends StatefulWidget {
final PatientController? controller;
const PatientAddressScreen({super.key, required this.controller});
@override
State<PatientAddressScreen> createState() => _PatientAddressScreenState();
}
class _PatientAddressScreenState extends State<PatientAddressScreen> {
late PatientController _controller;
late TextEditingController _houseNoController;
late TextEditingController _lineController;
late TextEditingController _townController;
late TextEditingController _pincodeController;
late TextEditingController _otherLabelController;
final String country = 'India';
String? state;
String? city;
String? addressType;
final Map<String, String> _errors = {};
bool _hasErrors = false;
@override
void initState() {
super.initState();
_controller = widget.controller ?? PatientController();
_loadSavedData();
}
void _loadSavedData() {
final address = _controller.model.address;
_houseNoController = TextEditingController(text: address.houseNo ?? '');
_lineController = TextEditingController(text: address.line ?? '');
_townController = TextEditingController(text: address.town ?? '');
_pincodeController = TextEditingController(text: address.pincode ?? '');
_otherLabelController =
TextEditingController(text: address.otherLabel ?? '');
state = address.state;
city = address.city;
addressType = address.addressType;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Address'),
actions: [
TextButton(
onPressed: _saveAndExit,
child: const Text('Done', style: TextStyle(color: Colors.blue)),
),
],
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildSectionContainer(
'Address Information',
Column(
children: [
_buildTextField(
'House No.',
_houseNoController,
(value) => widget.controller!.updateHouseNo(value),
icon: Icons.home_outlined,
errorKey: 'houseNo',
),
_buildTextField(
'Address Line',
_lineController,
(value) => widget.controller!.updateLine(value),
icon: Icons.location_on_outlined,
errorKey: 'line',
),
_buildTextField(
'Town (Optional)',
_townController,
(value) => widget.controller!.updateTown(value),
icon: Icons.location_city_outlined,
),
_buildTextField(
'Pincode',
_pincodeController,
(value) => widget.controller!.updatePincode(value),
icon: Icons.pin_drop_outlined,
errorKey: 'pincode',
),
],
),
),
const SizedBox(height: 20),
_buildSectionContainer(
'Location',
Column(
children: [
_buildCountrySelection(),
const SizedBox(height: 10),
SelectState(
onCountryChanged: (value) {
setState(() {});
widget.controller!.updateCountry('India');
},
onStateChanged: (value) {
setState(() {
state = value;
});
widget.controller!.updateState(value);
},
onCityChanged: (value) {
setState(() {
city = value;
});
widget.controller!.updateCity(value);
},
),
const SizedBox(height: 20),
if (state != null)
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Text('State: $state',
style: const TextStyle(
fontSize: 14, color: Colors.black87)),
),
if (city != null)
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Text('City: $city',
style: const TextStyle(
fontSize: 14, color: Colors.black87)),
),
],
),
),
const SizedBox(height: 20),
_buildSectionContainer(
'Address Type',
Column(
children: [
_buildAddressTypeChips(),
if (addressType == 'Other')
_buildTextField(
'Other Label',
_otherLabelController,
(value) => widget.controller!.updateOtherLabel(value),
icon: Icons.label_outline,
),
],
),
),
],
),
),
);
}
bool _validateFields() {
setState(() {
_errors.clear();
_hasErrors = false;
if (_houseNoController.text.trim().isEmpty) {
_errors['houseNo'] = 'House No. is required';
_hasErrors = true;
}
if (_lineController.text.trim().isEmpty) {
_errors['line'] = 'Address Line is required';
_hasErrors = true;
}
final pincode = _pincodeController.text.trim();
if (pincode.isEmpty) {
_errors['pincode'] = 'Pincode is required';
_hasErrors = true;
} else if (!RegExp(r'^\d{6}$').hasMatch(pincode)) {
_errors['pincode'] = 'Enter a valid 6-digit pincode';
_hasErrors = true;
}
if (state == null || state!.isEmpty) {
_errors['state'] = 'State is required';
_hasErrors = true;
}
if (city == null || city!.isEmpty) {
_errors['city'] = 'City is required';
_hasErrors = true;
}
if (addressType == null || addressType!.isEmpty) {
_errors['addressType'] = 'Please select an address type';
_hasErrors = true;
}
if (addressType == 'Other' && _otherLabelController.text.trim().isEmpty) {
_errors['otherLabel'] = 'Please specify other label';
_hasErrors = true;
}
});
return !_hasErrors;
}
Widget _buildSectionContainer(String title, Widget content) {
return Container(
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.blueGrey.withOpacity(0.5),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
content,
],
),
);
}
Widget _buildTextField(
String label,
TextEditingController controller,
Function(String) onChanged, {
required IconData icon,
String? errorKey,
}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
controller: controller,
decoration: InputDecoration(
labelText: label,
prefixIcon: Icon(icon,
color: _errors.containsKey(errorKey)
? Colors.red
: Colors.blueAccent),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(
color: _errors.containsKey(errorKey) ? Colors.red : Colors.grey,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(
color: _errors.containsKey(errorKey) ? Colors.red : Colors.grey,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(
color: _errors.containsKey(errorKey)
? Colors.red
: Colors.blueAccent,
),
),
errorText: _errors[errorKey],
),
onChanged: onChanged,
),
const SizedBox(height: 20),
],
);
}
Widget _buildCountrySelection() {
return Container(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: const Row(
children: [
Text(
'Country:',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
SizedBox(width: 8),
Text('India', style: TextStyle(fontSize: 16)),
],
),
);
}
Widget _buildAddressTypeChips() {
return Wrap(
spacing: 8.0,
children: ['Home', 'Office', 'Other'].map((String type) {
return ChoiceChip(
label: Text(type),
selected: addressType == type,
onSelected: (bool selected) {
setState(() {
addressType = selected ? type : addressType;
});
widget.controller!.updateAddressType(addressType!);
},
);
}).toList(),
);
}
void _saveAndExit() {
if (_validateFields()) {
widget.controller!.updateHouseNo(_houseNoController.text);
widget.controller!.updateLine(_lineController.text);
widget.controller!.updateTown(_townController.text);
widget.controller!.updatePincode(_pincodeController.text);
widget.controller!.updateCountry(country);
widget.controller!.updateState(state ?? '');
widget.controller!.updateCity(city ?? '');
widget.controller!.updateAddressType(addressType ?? '');
widget.controller!.updateOtherLabel(_otherLabelController.text);
widget.controller!.updatePatientData();
Navigator.pop(context, true);
} else {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Row(
children: [
Icon(Icons.error_outline, color: Colors.red),
SizedBox(width: 8),
Text('Validation Errors'),
],
),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: _errors.entries
.map((error) => Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Text(
'${error.value}',
style: const TextStyle(color: Colors.red),
),
))
.toList(),
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('OK'),
),
],
),
);
}
}
@override
void dispose() {
_houseNoController.dispose();
_lineController.dispose();
_townController.dispose();
_pincodeController.dispose();
_otherLabelController.dispose();
super.dispose();
}
}