import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; import 'package:responsive_builder/responsive_builder.dart'; import '../../utils/auth_utils.dart'; import '../../widgets/custom_text_field.dart'; import '../../widgets/custom_text_itnerary_sub.dart'; class MiscellaneousScreen extends StatefulWidget { final Map? apiData; final Function(String, bool) onClose; final Function(Map) onSaveMiscellaneous; final Map? selectedItem; final int? selectedIndex; final String? loginUser; MiscellaneousScreen({ required this.onClose, required this.apiData, required this.onSaveMiscellaneous, this.selectedItem, this.selectedIndex, required this.loginUser, }); @override _MiscellaneousScreenState createState() => _MiscellaneousScreenState(); } class _MiscellaneousScreenState extends State { final GlobalKey _formKey = GlobalKey(); Map selectedValues = {}; final FocusNode _tripTypeFocusNode = FocusNode(); final FocusNode _hotelNameFocusNode = FocusNode(); final FocusNode _commentsFocusNode = FocusNode(); late Map _controllers; late TextEditingController _tripTypeController = TextEditingController(); late TextEditingController _commentsController = TextEditingController(); bool _hotelNameFocused = false; bool _commentsFocus = false; String? selectedSpecialType; Color layoutColor = Colors.grey; Map errorMessages = {}; Map get miscellaneousData { Map data = { "special_request": selectedSpecialType, "comments": _commentsController.text, "created_by": widget.loginUser, "updated_by": widget.loginUser, }; if (widget.selectedItem != null) { if (widget.selectedItem?["indx"] != null && widget.selectedItem?["indx"] != 0) { data["indx"] = widget.selectedItem!["indx"]; } else if (widget.selectedItem?["miscellaneous_id"] != null && widget.selectedItem?["miscellaneous_id"] != 0) { data["miscellaneous_id"] = widget.selectedItem!["miscellaneous_id"]; } } return data; } @override void initState() { super.initState(); if (widget.selectedItem == null) { _commentsController.clear(); } WidgetsBinding.instance.addPostFrameCallback((_) { loadInitialData(); }); _hotelNameFocusNode.addListener(() { setState(() { _hotelNameFocused = _hotelNameFocusNode.hasFocus; }); }); _commentsFocusNode.addListener(() { setState(() { _commentsFocus = _commentsFocusNode.hasFocus; }); }); _commentsController = TextEditingController( text: widget.selectedItem?["comments"] ?? "", ); // Set the selected value if available if (widget.selectedItem != null && widget.selectedItem!["special_request"] != null) { selectedSpecialType = widget.selectedItem!["special_request"].toString(); } } @override void dispose() { _tripTypeFocusNode.dispose(); _hotelNameFocusNode.dispose(); _tripTypeController.dispose(); _commentsController.dispose(); super.dispose(); } void loadInitialData() async { String? layoutString = await getLayoutColor(); // setState(() { // layoutColor = // layoutString != null // ? Color(int.parse(layoutString)) // : Colors.redAccent; // }); setState(() { layoutColor = layoutString != null ? Color(int.parse(layoutString)) : Colors.redAccent; }); } bool isValidData(Map data) { errorMessages.clear(); // Reset errors // Required fields that must not be empty List requiredFields = ["special_request", "comments"]; // Check validation for each field for (String field in requiredFields) { if (data[field] == null || data[field].toString().trim().isEmpty) { errorMessages[field] = "Required"; } } return errorMessages.isEmpty; // Valid if there are no errors } void handleSave() { print("Handle Save miscellaneousData $miscellaneousData"); Map data = miscellaneousData; if (!isValidData(data)) { print("Validation Failed: Required fields are missing."); setState(() {}); return; // Stop execution if validation fails } else { widget.onSaveMiscellaneous(miscellaneousData); // Send object to parent } widget.onClose("Miscellaneous", false); // Close screen after saving // widget.onClose(false); // Close screen after saving // Clear only if this is a new entry // if (widget.selectedItem == null) { // _commentsController.clear(); // } } @override Widget build(BuildContext context) { return ResponsiveBuilder( builder: (context, sizingInfo) { bool isMobile = sizingInfo.isMobile; bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop; return Container( child: Form( key: _formKey, child: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ Padding( padding: const EdgeInsets.only(top: 30.0), child: Center( child: Column(children: _buildAccomadtionForm(isDesktop)), ), ), ], ), ), ), ); }, ); } List _buildAccomadtionForm(bool isDesktop) { List buildResponsiveRow(List children) { return [ isDesktop ? Row(children: children) : Column(children: children), SizedBox(height: 10), ]; } return [ ...buildResponsiveRow(_buildFirstRow(isDesktop)), ...buildResponsiveRow(_buildThirdRow(isDesktop)), // Actions row remains a Row ]; } List _buildFirstRow(isDesktop) { return [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Special Type *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, color: Color(0xFF575A74), ), ), SizedBox(height: 5), isDesktop ? Row(children: _buildTripType(isDesktop)) : Column(children: _buildTripType(isDesktop)), ], ), ]; } List _buildTripType(bool isDesktop) { List purposeList = widget.apiData?['miscellaneous_special_request'] ?? []; // selectedInsuranceType = purposeList.isNotEmpty ? purposeList.first['dropdown_value'] : null; List> dropdownItems = purposeList .map( (item) => DropdownMenuItem( value: item['dropdown_key'], child: Text(item['dropdown_value']), ), ) .toList(); if (dropdownItems.isEmpty) { dropdownItems.add( DropdownMenuItem( value: null, child: Text( "No options available", style: TextStyle(color: Colors.grey), ), ), ); } // Default selected value selectedSpecialType ??= dropdownItems.isNotEmpty ? dropdownItems.first.value : "No options"; return [ // CustomTextFieldWrapper( // isFocused: _isHotelNameFocused, // isDesktop: isDesktop, // width: // isDesktop // ? MediaQuery.of(context).size.width * 0.34 // : MediaQuery.of(context).size.width * 0.66, // child: SizedBox( // height: 40, // child: DropdownButtonFormField( // focusNode: _tripTypeFocusNode, // Assign the correct focus node // value: selectedSpecialType, // style: TextStyle(fontSize: 12), // decoration: InputDecoration( // border: InputBorder.none, // contentPadding: EdgeInsets.symmetric( // horizontal: 10, // ), // Proper padding // ), // onChanged: // purposeList.isNotEmpty // ? (newValue) { // setState(() { // selectedSpecialType = newValue; // }); // // print(selectedSpecialType); // } // : null, // items: dropdownItems, // ), // ), // ), CustomTextFieldItnerarySubWrapper( isFocused: _hotelNameFocused, isDesktop: isDesktop, padding: const EdgeInsets.symmetric(horizontal: 0), width: isDesktop ? MediaQuery.of(context).size.width * 0.34 : null, //MediaQuery.of(context).size.width * 0.66, child: SizedBox( height: 40, width: double.infinity, child: Focus( focusNode: _hotelNameFocusNode, onFocusChange: (hasFocus) { setState(() { _hotelNameFocused = hasFocus; }); }, child: GestureDetector( // onTap: () { // Request focus when user taps _hotelNameFocusNode?.requestFocus(); }, child: DropdownSearch>( // focusNode: _taxiReqFocusNode, items: purposeList.cast>(), selectedItem: purposeList.firstWhere( (item) => item['dropdown_key'] == selectedSpecialType, orElse: () => {}, ), itemAsString: (item) => item['dropdown_value'] ?? '', popupProps: PopupProps.menu( showSearchBox: false, fit: FlexFit.loose, menuProps: const MenuProps(backgroundColor: Colors.white), itemBuilder: (context, item, isSelected) { return Padding( padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 5, ), child: Text( item['dropdown_value'] ?? '', style: GoogleFonts.poppins( fontSize: 12, color: Colors.black, ), ), ); }, ), dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( // border: InputBorder.none, border: OutlineInputBorder( borderRadius: BorderRadius.circular(4), borderSide: BorderSide( color: (_hotelNameFocused ?? false) ? layoutColor! : Colors.white, width: 0.5, ), ), enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: (_hotelNameFocused ?? false) ? layoutColor : Colors.white, // : const Color(0xFFD6D5E6), width: 0.5, // const Color(0xFFD6D5E6), ), ), focusedBorder: OutlineInputBorder( borderSide: BorderSide(color: layoutColor, width: 0.5), ), contentPadding: EdgeInsets.symmetric( horizontal: 10, vertical: 10, ), ), ), dropdownBuilder: (context, selectedItem) { if (selectedItem == null || selectedItem.isEmpty) { return Text( "Select ", style: GoogleFonts.poppins( color: Colors.grey, fontSize: 13, ), ); } return Text( selectedItem['dropdown_value'] ?? '', style: GoogleFonts.poppins( fontSize: 12, color: Colors.black, ), ); }, onChanged: purposeList.isNotEmpty ? (newValue) { setState(() { selectedSpecialType = newValue as String?; }); print("Updating form data: -> ${newValue ?? ""}"); } : null, ), ), ), ), ), if (errorMessages["special_request"] != null) ...[ SizedBox(height: 5), // Space before error message Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)), ], ]; } List _buildThirdRow(bool isDesktop) { return [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Comments *", style: GoogleFonts.poppins( fontSize: 12, fontWeight: FontWeight.w500, color: Color(0xFF575A74), ), ), SizedBox(height: 5), // CustomTextFieldWrapper CustomTextFieldItnerarySubWrapper( isFocused: _commentsFocus, // Dropdown doesn't use focus isDesktop: isDesktop, width: isDesktop ? MediaQuery.of(context).size.width * 0.34 : null, //MediaQuery.of(context).size.width * 0.66, child: SizedBox( height: 40, child: TextField( inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9 _-]')), ], focusNode: _commentsFocusNode, controller: _commentsController, style: TextStyle(fontSize: 12), decoration: InputDecoration( labelText: "Comments", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 16), ), ), ), ), if (errorMessages["comments"] != null) ...[ SizedBox(height: 5), // Space before error message Text("Required", style: TextStyle(color: Colors.red, fontSize: 12)), ], ], ), if (isDesktop) Spacer(), SizedBox(height: 5), Row( mainAxisAlignment: MainAxisAlignment.end, children: _handleAction(isDesktop), ), ]; } List _handleAction(bool isDesktop) { return [ // Close Button ElevatedButton( onPressed: () { _commentsController.clear(); widget.onClose("Miscellaneous", false); // widget.onClose(false); // Close the dialog or screen }, style: ElevatedButton.styleFrom( backgroundColor: Colors.grey[400], // Light grey color shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), child: Text( "Close", style: GoogleFonts.poppins(color: Colors.white, fontSize: 12), ), ), SizedBox(width: 10), // Space between buttons // Save Changes Button ElevatedButton( onPressed: () { handleSave(); }, style: ElevatedButton.styleFrom( backgroundColor: Color(0xFF114D8B), // Primary color for save shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), child: Text( "Save Changes", style: GoogleFonts.poppins(color: Colors.white, fontSize: 12), ), ), ]; } }