import 'package:flutter/material.dart'; import 'package:telemednet/controller/patient_controller.dart'; import 'package:telemednet/data/models/patient.dart'; class FamilyMembersEditScreen extends StatefulWidget { final FamilyMember? familyMember; final PatientController controller; const FamilyMembersEditScreen( {super.key, this.familyMember, required this.controller}); @override State createState() => _FamilyMembersEditScreenState(); } class _FamilyMembersEditScreenState extends State { late TextEditingController nameController; late TextEditingController relationController; late TextEditingController genderController; late TextEditingController dobController; Map errors = {}; @override void initState() { super.initState(); nameController = TextEditingController(text: widget.familyMember?.name ?? ''); relationController = TextEditingController(text: widget.familyMember?.relation ?? ''); genderController = TextEditingController(text: widget.familyMember?.gender ?? ''); dobController = TextEditingController( text: widget.familyMember?.dateOfBirth?.toString().split(' ')[0] ?? ''); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Edit Family Member'), actions: _buildAppBarActions(), ), body: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildTextField(nameController, 'Name', Icons.person, 'name'), _buildDropdownField( 'Relation', relationController.text, (String? newValue) { setState(() { relationController.text = newValue ?? ''; }); }, Icons.family_restroom, ), _buildDropdownField( 'Gender', genderController.text, (String? newValue) { setState(() { genderController.text = newValue ?? ''; }); }, Icons.transgender, ), _buildDateField(context), ], ), ), ); } Widget _buildDropdownField( String label, String value, Function(String?) onChanged, IconData icon) { return Padding( padding: const EdgeInsets.only(bottom: 16), child: DropdownButtonFormField( decoration: InputDecoration( labelText: label, prefixIcon: Icon(icon, color: Colors.blue), border: const OutlineInputBorder(), ), value: value.isEmpty ? null : value, onChanged: onChanged, items: label == 'Relation' ? ['Father', 'Mother', 'Son', 'Daughter', 'Other'] .map>((String value) { return DropdownMenuItem( value: value, child: Text(value), ); }).toList() : ['Male', 'Female', 'Other'] .map>((String value) { return DropdownMenuItem( value: value, child: Text(value), ); }).toList(), ), ); } Widget _buildDateField(BuildContext context) { return Padding( padding: const EdgeInsets.only(bottom: 16), child: TextField( controller: dobController, decoration: const InputDecoration( labelText: 'Date of Birth', border: OutlineInputBorder(), prefixIcon: Icon(Icons.calendar_today, color: Colors.blue), ), readOnly: true, onTap: () async { DateTime? pickedDate = await showDatePicker( context: context, initialDate: DateTime.now().subtract(const Duration(days: 365)), firstDate: DateTime(1900), lastDate: DateTime.now().subtract(const Duration(days: 365)), ); if (pickedDate != null) { setState(() { dobController.text = pickedDate.toString().split(' ')[0]; }); } }, ), ); } bool _validateFields() { errors.clear(); if (nameController.text.trim().isEmpty) { errors['name'] = 'Name is required'; } else if (nameController.text.trim().length < 2) { errors['name'] = 'Name must be at least 2 characters'; } if (relationController.text.isEmpty) { errors['relation'] = 'Please select a relation'; } if (genderController.text.isEmpty) { errors['gender'] = 'Please select a gender'; } if (dobController.text.isEmpty) { errors['dob'] = 'Date of Birth is required'; } else { final dob = DateTime.tryParse(dobController.text); if (dob == null) { errors['dob'] = 'Invalid date format'; } else if (dob.isAfter(DateTime.now())) { errors['dob'] = 'Date of Birth cannot be in the future'; } } setState(() {}); return errors.isEmpty; } void _showValidationErrors() { 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'), ), ], ), ); } Widget _buildTextField( TextEditingController controller, String label, IconData icon, String errorKey, ) { return Padding( padding: const EdgeInsets.only(bottom: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ TextField( controller: controller, decoration: InputDecoration( labelText: label, prefixIcon: Icon( icon, color: errors.containsKey(errorKey) ? Colors.red : Colors.blue, ), border: OutlineInputBorder( borderSide: BorderSide( color: errors.containsKey(errorKey) ? Colors.red : Colors.grey, ), ), enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: errors.containsKey(errorKey) ? Colors.red : Colors.grey, ), ), focusedBorder: OutlineInputBorder( borderSide: BorderSide( color: errors.containsKey(errorKey) ? Colors.red : Colors.blue, ), ), ), ), if (errors.containsKey(errorKey)) Padding( padding: const EdgeInsets.only(top: 4, left: 12), child: Text( errors[errorKey]!, style: const TextStyle(color: Colors.red, fontSize: 12), ), ), ], ), ); } List _buildAppBarActions() { return [ TextButton( onPressed: () { if (_validateFields()) { FamilyMember newMember = FamilyMember( name: nameController.text, relation: relationController.text, gender: genderController.text, dateOfBirth: DateTime.tryParse(dobController.text), ); Navigator.pop(context, newMember); } else { _showValidationErrors(); } }, child: const Text('Done', style: TextStyle(color: Colors.blue)), ), ]; } @override void dispose() { nameController.dispose(); relationController.dispose(); genderController.dispose(); dobController.dispose(); super.dispose(); } }