import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:frontend/Screens/plans/dynamic_itinerary_stepper.dart'; import 'package:go_router/go_router.dart'; import 'package:responsive_builder/responsive_builder.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:http/http.dart' as http; import '../../config/apiUrl.dart'; import '../../data/models/plan.dart'; import '../../routes/custom_appBar.dart'; import '../../routes/custom_drawer.dart'; import '../../widgets/custom_radio_button.dart'; import '../../widgets/custom_text_field.dart'; import '../dialog/user_selection_dialog.dart'; class CreatePlan extends StatefulWidget { const CreatePlan({super.key}); @override _CreatePlansState createState() => _CreatePlansState(); } class _CreatePlansState extends State { @override Widget build(BuildContext context) { return ResponsiveBuilder(builder: (context, sizingInfo) { bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop; final args = GoRouterState.of(context).extra as Map? ?? {}; // final planData = args?['planData']; final bool isViewMode = args?['isViewMode'] ?? false; final Map planData = args['planData'] as Map? ?? {}; // print("isViewMode: $isViewMode"); // final bool isViewMode = true; // final planData = GoRouterState.of(context).extra as Map? ?? {}; print("RECived palndata"); // print("RECived palndata - ${planData}"); return Scaffold( backgroundColor: Colors.white, body: Column( children: [ Container( color: Color(0xFFF4F4FB), padding: EdgeInsets.symmetric(vertical: 10, horizontal: 16), child: Row(children: [ Row( children: [ Padding( padding: const EdgeInsets.all(8.0), child: Icon( Icons.create_new_folder_outlined, color: Color(0xFF84869A), size: 23, ), ), Text( isViewMode ? "View Plan" : (planData.isNotEmpty ? "Update Plan" : "New Plan"), style: TextStyle(fontSize: 18), ), ], ), Spacer(), Container( color: Color(0xFFE9EBF6), child: IconButton( icon: Icon(Icons.close), onPressed: () { context.go('/listPlan'); }, ), ) ]), ), Expanded( child: Container( color: Colors.white, child: SingleChildScrollView( child: Padding( padding: EdgeInsets.all(26.0), child: CreateNewPlan(isDesktop: isDesktop, selectedPlanData: planData, isViewMode : isViewMode), ), ), ), ) ], ), ); }); } } class CreateNewPlan extends StatefulWidget { final bool isDesktop; final bool isViewMode; final Map selectedPlanData; const CreateNewPlan({super.key, required this.isDesktop, required this.selectedPlanData, required this.isViewMode}); @override _CreateNewPlansState createState() => _CreateNewPlansState(); } class _CreateNewPlansState extends State { final TextEditingController _tripTitleController = TextEditingController(); final TextEditingController _descriptionController = TextEditingController(); final FocusNode _tripTitleFocusNode = FocusNode(); final FocusNode _descriptionFocusNode = FocusNode(); // Declare FocusNode bool _isTripTitleFocused = false; bool _isdescriptionFocused = false; late String _selectedOption = "Option 1"; // late String? _selectedIsBillable = "Billable"; String? selectedPlanId; String? userDetails; String? userName; String? selfId; String? otherUserName; String? selectedplanUserId; bool? selectedIstravelUser; Map? apiData; // Store API response here List? apiCountryData; List? apiCostData; // Store API response here bool isLoading = true; // Track loading state String? planUsrId; String? planTravlrId; String? _selectedTripType; String? selectedCostCenterId; String? _selectedIsBillable ; String? selectedFuncDept; String? selectedPurpose; Map validationErrors = {}; List> miscellaneousList = []; // List> miscellaneousList = [{"special_request": 1, "comments": "posta", "indx": 1}]; List> visaList = []; List> insuranceList = []; List> accommodationList = []; List> trainList = []; List> busList = []; List> taxiList = []; List> forexList = []; List> flightList = []; //Getter Method Map get planData => { "user_id": planUsrId, "traveller_id": planTravlrId, "trip_title": _tripTitleController.text, "trip_type": _selectedTripType, "cost_center_id": selectedCostCenterId, "is_billable": _selectedIsBillable, "purpose_of_travel": selectedPurpose, "description": _descriptionController.text, "functional_department": selectedFuncDept, "so_number": "12345", "status": "0", "created_by": selfId, "updated_by": selfId, "is_active": "1", "flight":flightList, "accomodation": accommodationList, "bus": busList, "taxi": taxiList, "train": trainList, "visa": visaList, "forex": forexList, "insurance": insuranceList, "miscellaneous": miscellaneousList, }; // // Function to update miscellaneous list // void updateMiscellaneousData(List> newMiscellaneousList) { // setState(() { // miscellaneousList = newMiscellaneousList; // Update miscellaneous data // }); // print("Updated Miscellaneous Data in CreateNewPlan: $miscellaneousList"); // } void handleItineraryUpdate(String type, List> newList) { setState(() { switch (type) { case "Miscellaneous": miscellaneousList = newList; break; case "Visa": visaList = newList; break; case "Insurance": insuranceList = newList; break; case "Train": trainList = newList; break; case "Bus": busList = newList; break; case "Taxi": taxiList = newList; break; case "Forex": forexList = newList; break; case "Flight": flightList = newList; break; case "Accomodation": accommodationList = newList; break; default: print("Unknown itinerary type: $type"); } }); print("Updated $type List: $newList"); } @override void initState(){ super.initState(); fetchUserDetails(); fetchPlans(); fetchCostCenter(); fetchCountryList(); // _tripTitleController.addListener(() { // print("Current Value: ${_tripTitleController.text}"); // }); _tripTitleFocusNode.addListener(() { setState(() { _isTripTitleFocused = _tripTitleFocusNode.hasFocus; }); }); _descriptionFocusNode.addListener(() { setState(() { _isdescriptionFocused = _descriptionFocusNode.hasFocus; }); }); handleUpdateData(); } @override void dispose() { _tripTitleFocusNode.dispose(); _descriptionFocusNode.dispose(); super.dispose(); } void handleUpdateData() { if (widget.selectedPlanData != null) { setState(() { planUsrId = widget.selectedPlanData['user_id'] ?? ''; _tripTitleController.text = widget.selectedPlanData['trip_title'] ?? ''; _descriptionController.text = widget.selectedPlanData['description'] ?? ''; _selectedTripType = widget.selectedPlanData['trip_type']; _selectedIsBillable = widget.selectedPlanData['is_billable'] == "1" ? "1" : "2"; // selectedCostCenterId = widget.selectedPlanData['cost_center_id']?.toString() ; // selectedPurpose = widget.selectedPlanData['purpose_of_travel']?.toString(); // selectedFuncDept =widget.selectedPlanData['functional_department']?.toString(); if (widget.selectedPlanData!["cost_center_id"] != null) { selectedCostCenterId = widget.selectedPlanData!["cost_center_id"].toString(); } // if (widget.selectedPlanData!["purpose_of_travel"] != null) { selectedPurpose = widget.selectedPlanData!["purpose_of_travel"].toString(); } if (widget.selectedPlanData!["functional_department"] != null) { // selectedFuncDept = widget.selectedPlanData!["functional_department"].toString(); selectedFuncDept = widget.selectedPlanData!["functional_department"]; } // Assign lists from selectedPlanData, ensuring they are properly formatted flightList = List>.from(widget.selectedPlanData['flight'] ?? []); accommodationList = List>.from(widget.selectedPlanData['accomodation'] ?? []); busList = List>.from(widget.selectedPlanData['bus'] ?? []); taxiList = List>.from(widget.selectedPlanData['taxi'] ?? []); trainList = List>.from(widget.selectedPlanData['train'] ?? []); visaList = List>.from(widget.selectedPlanData['visa'] ?? []); forexList = List>.from(widget.selectedPlanData['forex'] ?? []); insuranceList = List>.from(widget.selectedPlanData['insurance'] ?? []); miscellaneousList = List>.from(widget.selectedPlanData['miscellaneous'] ?? []); }); if (widget.selectedPlanData.containsKey('plan_id') && widget.selectedPlanData['plan_id'] != null) { print("Plan ID exists: ${widget.selectedPlanData['plan_id']}"); selectedPlanId = widget.selectedPlanData['plan_id']?.toString(); } else { print("Plan ID is missing or null"); } print("updatedPlanDAta - $planData"); } } void getSelectedPlanFor(){ if (!mounted) return; setState(() { if(selectedplanUserId != null){ if(selectedIstravelUser!){ planUsrId = ""; planTravlrId = selectedplanUserId; }else { planUsrId = selectedplanUserId; planTravlrId = ""; } } else { planUsrId = selfId; planTravlrId = ""; } }); print("USER ID - $planUsrId , TRAVELLER ID - $planTravlrId"); } void fetchUserDetails() async { final details = await getUserDetails(); print("details- $details"); if (details != null) { setState(() { userDetails = details.toString(); // Store the full Map userName = details['name']; // Extract the name selfId = details['user_id']; }); } print("userDetails - $selfId"); getSelectedPlanFor(); } Future getToken() async { final prefs = await SharedPreferences.getInstance(); return prefs.getString('auth_token'); } Future getUserId() async { final prefs = await SharedPreferences.getInstance(); return prefs.getString('userId'); } Future ?> getUserDetails() async{ final prefs = await SharedPreferences.getInstance(); final userData = prefs.getString('user_data'); if(userData!= null){ final decodedData = jsonDecode(userData); return { 'user_id': decodedData['user_id'].toString(), 'name': "${decodedData['first_name']} ${decodedData['last_name']}", }; } return null; } Future fetchPlans() async { final String apiUrldata = '$apiUrl/api/getDropdownMaster'; final token = await getToken(); if (token == null) { throw Exception('Token not found. Please log in.'); } final response = await http.get( Uri.parse(apiUrldata), headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', }, ); if (response.statusCode == 200) { try { final data = json.decode(response.body); print(data); if (!data.containsKey('data') || data['data'] is! Map) { throw Exception("Invalid response format: 'data' field is missing or not a Map"); } Map plansJson = data['data']; // 'data' is a Map, not a List setState(() { apiData = plansJson; // Store API response in state isLoading = false; }); } catch (e) { throw Exception('Error parsing response: $e'); } } else { throw Exception('Failed to load plans'); } } Future fetchCostCenter() async { final String apiUrldata = '$apiUrl/api/getCostCenterMaster'; final token = await getToken(); final userId = await getUserId(); // print("SUSRTRT- $userId"); // if (token == null) { throw Exception('Token not found. Please log in.'); } final response = await http.get( Uri.parse(apiUrldata), headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', }, ); if (response.statusCode == 200) { try { final data = json.decode(response.body); print(data); if (!data.containsKey('data') || data['data'] is!List) { throw Exception("Invalid response format: 'data' field is missing or not a List"); } List plansJson = data['data']; // 'data' is a Map, not a List setState(() { apiCostData = plansJson; // Store API response in state // if(apiCostData!.isNotEmpty){ // selectedCostCenterId =apiCostData?.first['department_id']; // } if (apiCostData != null && apiCostData!.isNotEmpty) { selectedCostCenterId ??= apiCostData!.first['department_id']?.toString(); } }); print('plansJSON'); } catch (e) { throw Exception('Error parsing response: $e'); } } else { throw Exception('Failed to load plans'); } } Future fetchCountryList() async { final String apiUrldata = '$apiUrl/api/getcountryMaster'; final token = await getToken(); final userId = await getUserId(); // print("SUSRTRT- $userId"); // if (token == null) { throw Exception('Token not found. Please log in.'); } final response = await http.get( Uri.parse(apiUrldata), headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', }, ); if (response.statusCode == 200) { try { final data = json.decode(response.body); print("Country - $data"); if (!data.containsKey('data') || data['data'] is!List) { throw Exception("Invalid response format: 'data' field is missing or not a List"); } List plansJson = data['data']; // 'data' is a Map, not a List if (data['data'] is List) { List plansJson = data['data']; print("plansJson.length - ${plansJson.length}"); } else { print("The 'data' key does not contain a list."); } setState(() { apiCountryData = plansJson; // Store API response in state }); print('plansJSONContry - $plansJson'); } catch (e) { throw Exception('Error parsing response: $e'); } } else { throw Exception('Failed to load plans'); } } // Handle Submit bool validateForm(){ validationErrors.clear(); // Clear previous errors // Ensure either "user_id" or "traveller_id" is provided if ((planUsrId == null || planUsrId!.isEmpty) && (planTravlrId == null || planTravlrId!.isEmpty)) { validationErrors["user_id"] = "Either User ID or Traveller ID is required"; validationErrors["traveller_id"] = "Either User ID or Traveller ID is required"; } final requiredFields = { "trip_type": _selectedTripType, "cost_center_id": selectedCostCenterId, "functional_department": selectedFuncDept, "purpose_of_travel": selectedPurpose, }; for (var entry in requiredFields.entries) { if (entry.value == null || entry.value!.isEmpty) { validationErrors[entry.key] = "${entry.key.replaceAll('_', ' ').toUpperCase()} is required"; } } return validationErrors.isEmpty; // Returns true if no errors } void handleSubmit() { setState(() { if(validateForm()){ print("Form submitted successfully: $planData"); postPlanData(planData); context.go('/listPlan'); } }); } Future postPlanData(Map planData) async { final String apiUrldata = '$apiUrl/api/plans/createOrEditPlan'; final token = await getToken(); // Fetch token if (token == null) { throw Exception('Token not found. Please log in.'); } if (selectedPlanId != null && selectedPlanId!.isNotEmpty) { planData['plan_id'] = selectedPlanId; // Add plan_id for update } try { final response = await http.post( Uri.parse(apiUrldata), headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', }, body: jsonEncode(planData), // Convert map to JSON ); if (response.statusCode == 200) { print("Plan submitted successfully!"); print("Response: ${response.body}"); } else { print("Failed to submit plan. Status: ${response.statusCode}"); print("Error: ${response.body}"); } } catch (e) { print(" Error submitting plan: $e"); } } Widget build(BuildContext context) { return ResponsiveBuilder(builder: (context, sizingInfo) { bool isMobile = sizingInfo.isMobile; bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Text( // "Plan This Trip For : ${userName} ", // Your label // style: TextStyle( // fontSize: 12, // fontWeight: FontWeight.w600, // color: Color(0xFF575A74)), // ), Text.rich( TextSpan( text: "Plan This Trip For: ", // Static text style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF575A74), // Default color ), children: [ TextSpan( text: otherUserName ?? userName ?? " ", // Dynamic username style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Colors.blueAccent, // Change this to any color ), ), ], ), ), SizedBox(height: 7), isMobile ? SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: _buildPlanTrip(isMobile), ), ) : Row( children: _buildPlanTrip(isMobile), ), ], ), ), ], ), Padding( padding: const EdgeInsets.all(8.0), child: Divider( color: Color(0xFFE6E7F5), // Change color thickness: 0.5, ), ), Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Trip Title", // Your label style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF575A74)), ), SizedBox(height: 5), CustomTextFieldWrapper( isFocused: _isTripTitleFocused, isDesktop: widget.isDesktop, child: SizedBox( height: 40, child: TextField( focusNode: _tripTitleFocusNode, controller: _tripTitleController, style: TextStyle(fontSize: 12), enabled: !widget.isViewMode, decoration: InputDecoration( labelText: "Trip Title", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 16), ), ), ), ), ], ), ], ), SizedBox( height: 10, ), Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Trip Type *", // Your label style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF575A74)), ), SizedBox(height: 5), isMobile ? SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: _buildTripType(isMobile), ), ) : Row( children: _buildTripType(isMobile), ), if (validationErrors["trip_type"] != null) Padding( padding: EdgeInsets.only(top: 4), child: Text( validationErrors["trip_type"]!, style: TextStyle(color: Colors.red, fontSize: 10), ), ), ], ), ), ], ), SizedBox( height: 15, ), isDesktop ? Row( crossAxisAlignment: CrossAxisAlignment.start, children: _buildCostIsBillable()) : Column( crossAxisAlignment: CrossAxisAlignment.start, children: _buildCostIsBillable()), SizedBox( height: 8, ), isDesktop ? Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildNonDescriptionColumn(), SizedBox(width: 25), _buildDescriptionColumn(isDesktop), ], ) : Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildNonDescriptionColumn(), SizedBox(height: 15), _buildDescriptionColumn(isDesktop), ], ), Padding( padding: const EdgeInsets.all(8.0), child: Divider( color: Color(0xFFE6E7F5), // Change color thickness: 0.5, ), ), Row( children: [ Expanded(child: DynamicItinerary(apiData: apiData, apiCountryData: apiCountryData, onItineraryUpdate: handleItineraryUpdate,loginUser: selfId,selectedPlanData: planData, isViewMode:widget.isViewMode , )), // Wrap with Expanded if needed ], ), SizedBox(height: 15), isDesktop ? Row( mainAxisAlignment: MainAxisAlignment.end, children: _buildSubmit(isDesktop),) :Row( mainAxisAlignment: MainAxisAlignment.center, children: _buildSubmit(isDesktop),) ], ); }); } /// Extracted helper function List _buildCostIsBillable() { List purposeList = apiData?['plan_is_billable'] ?? []; return [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Cost Center *", // Your label style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF575A74)), ), SizedBox(height: 5), CustomTextFieldWrapper( isFocused: false, // Dropdown doesn't use focus isDesktop: widget.isDesktop, child: SizedBox( height: 45, // Set appropriate height child: DropdownButtonFormField( value: selectedCostCenterId, style: TextStyle(fontSize: 12), decoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric(horizontal: 10), // Proper padding ), onChanged: widget.isViewMode ? null : (newValue) { setState(() { selectedCostCenterId = newValue; }); }, items:apiCostData?.map>((item){ return DropdownMenuItem( value: item['department_id'], // ID as value child: Text(item['name'] ?? "Unknown"), ); }).toList(), ), ), ), ], ), SizedBox(width: 25,height: 5,), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Is Billable ", // Your label style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF575A74)), ), SizedBox(height: 5), Row( children: purposeList.map((item) { return Row( children: [ Radio( // value: item['dropdown_key'], // Use dropdown_value as value value: item['dropdown_key'].toString(),// Convert to String groupValue: _selectedIsBillable, activeColor: Colors.blueAccent, onChanged: widget.isViewMode ? null :(value) { setState(() { _selectedIsBillable = value; }); print("SELECBILL - $_selectedIsBillable"); }, ), Text(item['dropdown_value'] ?? ''), // Display dropdown_value SizedBox(width: 20), // Spacing ], ); }).toList(), ), ]) // Column( // crossAxisAlignment: CrossAxisAlignment.start, // children: [ // Text( // "Is Billable ", // Your label // style: TextStyle( // fontSize: 12, // fontWeight: FontWeight.w600, // color: Color(0xFF575A74)), // ), // SizedBox(height: 5), // Row( // children: [ // Row( // children: [ // Radio( // value: "Billable", // groupValue: _selectedIsBillable, // activeColor: Colors.blueAccent, // onChanged: (value) { // setState(() { // _selectedIsBillable = value; // }); // }, // ), // Text("Billable"), // ], // ), // SizedBox(width: 20), // Spacing // Row( // children: [ // Radio( // value: "Non Billable", // groupValue: _selectedIsBillable, // activeColor: Colors.blueAccent, // onChanged: (value) { // setState(() { // _selectedIsBillable = value; // }); // }, // ), // Text("Non Billable"), // ], // ), // ], // ), // ], // ) ]; } List _buildPlanTrip(bool isDesktop) { List> options = [ {"title": "Self", "value": "Option 1"}, {"title": "Other Employee", "value": "Option 2"}, {"title": "Others", "value": "Option 3"}, ]; return options.map((option) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 5), child: CustomTextFieldWrapper( color: Color(0xFFF4F4FB), width: option["value"] == "Option 2" ? 175 : 120, // Adjust width conditionally isFocused: _selectedOption == option["value"], isDesktop: isDesktop, child: RadioListTile( activeColor: Colors.blueAccent, contentPadding: EdgeInsets.zero, dense: true, title: Text(option["title"]!), value: option["value"]!, groupValue: _selectedOption, onChanged: widget.isViewMode ? null : (value) { setState(() { _selectedOption = value!; if(value == 'Option 2' || value == 'Option 3' ){ _showInputDialog(option["title"]!); } }); }, ), ), ); }).toList(); } List _buildTripType(bool isMobile) { return [ CustomTextFieldWrapper( color: Color(0xFFF4F4FB), padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2), width: 120, isFocused: _selectedTripType == "1", isDesktop: widget.isDesktop, child: SizedBox( height: 35, child: Material( color: Colors.transparent, child: RadioListTile( activeColor: Colors.blueAccent, contentPadding: EdgeInsets.zero, visualDensity: VisualDensity.compact, dense: true, title: Text("Domestic"), value: "1", groupValue: _selectedTripType, onChanged: widget.isViewMode ? null : (value) { setState(() { _selectedTripType = value!; }); }, ), ), ), ), SizedBox(width: 20), CustomTextFieldWrapper( color: Color(0xFFF4F4FB), width: 150, padding: EdgeInsets.symmetric(horizontal: 5, vertical: 2), isFocused: _selectedTripType == "2", isDesktop: widget.isDesktop, child: RadioListTile( activeColor: Colors.blueAccent, contentPadding: EdgeInsets.zero, dense: true, title: Text("International"), value: "2", groupValue: _selectedTripType, onChanged: widget.isViewMode ? null :(value) { setState(() { _selectedTripType = value!; }); }, ), ), ]; } Widget _buildNonDescriptionColumn (){ // if (apiData == null) { // return Center(child: CircularProgressIndicator()); // Show loading indicator // } // 'plan_purpose_of_travel' Starts ------------------------------------------------------ List purposeList = apiData?['plan_purpose_of_travel'] ?? []; List> dropdownItems = purposeList .map((item)=>DropdownMenuItem( // value: item['dropdown_key'], value: item['dropdown_key']?.toString(), // value: item['dropdown_key'].toString(), child: Text(item['dropdown_value']), )).toList(); if (dropdownItems.isEmpty) { dropdownItems.add( DropdownMenuItem( // value: null, value: "1", child: Text("No options available", style: TextStyle(color: Colors.grey)), ), ); } // Ensure Selected Value Exists in the Dropdown List List dropdownKeys = dropdownItems.map((e) => e.value ?? "").toList(); selectedPurpose ??= dropdownItems.isNotEmpty ? dropdownItems.first.value.toString() : "No options"; print("Dropdown Purpose List: ${dropdownItems.map((e) => e.value).toList()}"); print("Selected Purpose: $selectedPurpose"); // 'plan_functional_department' Starts --------------------------------------------- List funcDeptList = apiData?['plan_functional_department'] ?? []; List> dropdownFuncDeptItems = funcDeptList .map((item)=>DropdownMenuItem( // value: item['dropdown_key'], value: item['dropdown_key']?.toString(), child: Text(item['dropdown_value']), )).toList(); if (dropdownFuncDeptItems.isEmpty) { dropdownFuncDeptItems.add( DropdownMenuItem( // value: null, value: "1", child: Text("No options available", style: TextStyle(color: Colors.grey)), ), ); } // selectedFuncDept ??= dropdownFuncDeptItems.isNotEmpty ? dropdownFuncDeptItems.first.value.toString() : null; selectedFuncDept ??= dropdownFuncDeptItems.isNotEmpty ? dropdownFuncDeptItems.first.value.toString() : "No options"; print("Dropdown Functional Department List: ${dropdownFuncDeptItems.map((e) => e.value).toList()}"); print("Selected Functional Department: $selectedFuncDept"); return Column( children: [ Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Purpose of Travel *", // Your label style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF575A74)), ), SizedBox(height: 5), CustomTextFieldWrapper( isFocused: false, // Dropdown doesn't use focus isDesktop: widget.isDesktop, child: SizedBox( height: 45, // Set appropriate height child: apiData == null ? Center(child: CircularProgressIndicator()) // Show loading inside dropdown : DropdownButtonFormField( value: selectedPurpose, style: TextStyle(fontSize: 12), decoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 10), // Proper padding ), onChanged: widget.isViewMode ? null : purposeList.isNotEmpty ? (newValue) { setState(() { selectedPurpose = newValue; }); print("selectedPurpose - $selectedPurpose"); } : null, items: dropdownItems, ), ), ), ], ), ], ), SizedBox( height: 8, ), Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Functional Department", // Your label style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF575A74)), ), SizedBox(height: 5), CustomTextFieldWrapper( isFocused: false, // Dropdown doesn't use focus isDesktop: widget.isDesktop, child: SizedBox( height: 45, // Set appropriate height child: apiData == null ? Center(child: CircularProgressIndicator()) // Show loading inside dropdown :DropdownButtonFormField( value: selectedFuncDept, style: TextStyle(fontSize: 12), decoration: InputDecoration( border: InputBorder.none, contentPadding: EdgeInsets.symmetric( horizontal: 10), // Proper padding ), onChanged: widget.isViewMode ? null : funcDeptList.isNotEmpty ? (newValue) { setState(() { selectedFuncDept = newValue; }); } : null, items: dropdownFuncDeptItems, ), ), ), ], ), ], ), SizedBox( height: 15, ), ] ); } Widget _buildDescriptionColumn(isDesktop){ return Column( children: [ Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Description", // Your label style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF575A74)), ), SizedBox(height: 5), CustomTextFieldWrapper( isFocused: _isdescriptionFocused, width: isDesktop? MediaQuery.of(context).size.width * 0.5 : MediaQuery.of(context).size.width * 0.85 , isDesktop: widget.isDesktop, child: TextField( focusNode: _descriptionFocusNode, controller: _descriptionController, maxLines: 6, keyboardType: TextInputType.multiline, style: TextStyle(fontSize: 12), enabled: !widget.isViewMode, decoration: InputDecoration( labelText: "Description", labelStyle: TextStyle(fontSize: 12, color: Colors.grey), floatingLabelBehavior: FloatingLabelBehavior.never, border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 4), ), ), ), ], ), ], ), ], ); } List _buildSubmit(isDesktop){ return[ ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.white, foregroundColor: Colors.blueAccent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), side: BorderSide(color: Colors.blueAccent, width: 2), ), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), onPressed: (){ context.go('/listPlan'); }, child: Text("Cancel") ), SizedBox(width: 20,), MouseRegion( cursor: widget.isViewMode ? SystemMouseCursors.forbidden : SystemMouseCursors.click, child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: widget.isViewMode ? Colors.blueAccent : Colors.blueAccent, // Keep original color foregroundColor: widget.isViewMode ? Colors.white : Colors.white, // Keep original color disabledBackgroundColor: Colors.blueAccent, // Ensure color remains when disabled disabledForegroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), side: BorderSide(color: Colors.blueAccent, width: 2), ), padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12), ), onPressed: widget.isViewMode ? null : handleSubmit, // Disable when in view mode child: Text("Submit"), ), ) ]; } void _showInputDialog(String title){ showDialog( context: context, builder: (BuildContext context){ return UserSelectionDialog( title:title, onSubmit: (input,userId,isTraveller){ setState(() { otherUserName = input; selectedplanUserId = userId; selectedIstravelUser = isTraveller; }); print("USer entered : $otherUserName $userId $isTraveller"); getSelectedPlanFor(); } ); } ); } }