ts-tat/lib/Screens/organization/orgSetup.dart
2025-06-23 19:18:50 +05:30

1056 lines
36 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:frontend/Screens/organization/mailSettings.dart';
import 'package:frontend/Screens/organization/themeColor.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';
import 'package:image_picker/image_picker.dart';
import 'package:responsive_builder/responsive_builder.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../config/apiUrl.dart';
import '../../routes/custom_appBar.dart';
import '../../routes/custom_drawer.dart';
import '../../services/apiService.dart';
import '../../utils/auth_utils.dart';
import '../../widgets/custom_breadcrumb_navigation.dart';
class OrgSetUp extends StatefulWidget {
@override
_OrgSetUpState createState() => _OrgSetUpState();
}
class _OrgSetUpState extends State<OrgSetUp> {
final ApiService apiService = ApiService();
String? userId;
String? orgId;
String? token;
bool isViewMode = false;
bool showMail = false;
Map<String, String> errorMessages = {};
final Map<String, TextEditingController> controllers = {};
List<dynamic>? apiAllServices;
Map<String, dynamic>? selectedOrg;
Color? layoutColor;
Color? bodyColor;
bool isSelected = false;
Uint8List? _webImage;
Uint8List? _imageBytes;
final TextEditingController _orgNameController = TextEditingController();
// List<String> selectedServiceIds = [];
List<Map<String, dynamic>> selectedServiceIds = [];
@override
void initState() {
super.initState();
_checkAuthAndLoadData();
// WidgetsBinding.instance.addPostFrameCallback((_) {
// loadAllServices();
// getOrganizationData();
// initializeData();
// loadInitialData();
// });
}
void _checkAuthAndLoadData() async {
final String? token = await getToken(); // Your async function to get token
if (token == null || token.isEmpty) {
// Token doesn't exist → redirect to login
context.go(
"/",
); // or use: router.go("/") if you're using `GoRouter` directly
return;
}
loadAllServices();
getOrganizationData();
initializeData();
loadInitialData();
}
void loadInitialData() async {
String? layoutString = await getLayoutColor();
String? bodyStringColor = await getBodyColor();
setState(() {
layoutColor =
layoutString != null
? Color(int.parse(layoutString))
: Colors.redAccent;
bodyColor =
bodyStringColor != null
? Color(int.parse(bodyStringColor))
: Colors.white;
});
}
Map<String, dynamic> mailConfig = {};
Map<String, dynamic> get orgData {
final data = {
"org_id": 1,
"name": _orgNameController.text,
"logo": null,
"sender_email": mailConfig['sender_email'],
"mail_user_name": mailConfig['mail_user_name'],
"mail_password": mailConfig['mail_password'],
"mail_host": mailConfig['mail_host'],
"mail_port": mailConfig['mail_port'],
"layout_color":
"0x${layoutColor?.toARGB32().toRadixString(16).padLeft(8, '0').toUpperCase()}",
"color":
"0x${bodyColor?.toARGB32().toRadixString(16).padLeft(8, '0').toUpperCase()}",
"services_ids": jsonEncode(selectedServiceIds),
"created_by": null,
"updated_by": null,
"is_active": 1,
// "org_id": orgId,
// "created_by": userId,
// "updated_by": userId,
};
// Only add group_id if it's an edit operation
// if (widget.group != null && widget.group!.containsKey('group_id')) {
// data["group_id"] = selectedGroupId;
// }
return data;
}
Future<void> loadAllServices() async {
try {
final result = await apiService.fetchAllServices();
setState(() {
apiAllServices = result;
});
print("Fetched services: $apiAllServices");
} catch (e) {
print('Error fetching role list: $e');
}
}
Future<void> initializeData() async {
token = await getToken();
userId = await getUserId();
if (token == null || userId == null) {
print("Token or USerId missing");
print("Retrieved Token: $token");
print("Retrieved UserId: $userId");
return;
} else {
setState(() {});
}
}
Future<void> getOrganizationData() async {
try {
print("getUpdatedServices");
final prefs = await SharedPreferences.getInstance();
final String? orgDataString = prefs.getString('org_data');
if (orgDataString != null) {
final Map<String, dynamic> orgData = jsonDecode(orgDataString);
print("UUPdatedServices - $orgData");
setState(() {
selectedOrg = orgData;
String? rawLogoPath = selectedOrg?['logo'];
if (rawLogoPath != null && rawLogoPath.contains('/assets')) {
const baseUrl = "https://apitest.tripapprovaltool.com";
final assetPath = rawLogoPath.split('/assets').last;
selectedOrg!['logo'] = "$baseUrl/assets$assetPath";
}
_orgNameController.text = selectedOrg?['name'];
layoutColor =
selectedOrg?['layout_color'] != null
? Color(
int.parse(
selectedOrg!['layout_color'].toString().replaceFirst(
'0x',
'',
),
radix: 16,
),
)
: Colors.white;
bodyColor =
selectedOrg?['color'] != null
? Color(
int.parse(
selectedOrg!['color'].toString().replaceFirst('0x', ''),
radix: 16,
),
)
: Colors.blue;
// Set mail config fields
mailConfig['sender_email'] = selectedOrg?['sender_email'];
mailConfig['mail_user_name'] = selectedOrg?['mail_user_name'];
mailConfig['mail_password'] = selectedOrg?['mail_password'];
mailConfig['mail_host'] = selectedOrg?['mail_host'];
mailConfig['mail_port'] = selectedOrg?['mail_port'];
// Set selected service IDs
// final services = selectedOrg?['services_ids'] as List<dynamic>? ?? [];
// selectedServiceIds =
// services.map((item) => item['service_id'].toString()).toList();
//
final servicesRaw = selectedOrg?['services_ids'];
List<dynamic> services;
if (servicesRaw is String) {
try {
services = jsonDecode(servicesRaw);
} catch (e) {
print('❌ Failed to decode services_ids: $e');
services = [];
}
} else if (servicesRaw is List) {
services = servicesRaw;
} else {
services = [];
}
selectedServiceIds =
services.map<Map<String, dynamic>>((item) {
// force cast or copy to a regular map
final map = Map<String, dynamic>.from(item);
return {"service_id": map['service_id'].toString()};
}).toList();
});
orgId = await getOrgId();
print("selectedOrg - $selectedOrg");
print("mailConfig - $mailConfig");
}
// final result = await apiService.fetchOrganization();
} catch (e) {
print('Error fetching updatedServices list: $e');
}
}
bool isValidData(Map<String, dynamic> data) {
errorMessages.clear(); // Reset errors
// Required fields that must not be empty
List<String> requiredFields = ["name", "description"];
// 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 _clearError(String field) {
if (mounted && errorMessages.containsKey(field)) {
setState(() {
errorMessages.remove(field);
});
}
}
Future<void> createOrgData(Map<String, dynamic> userData) async {
final bool isUpdating = selectedOrg != null && selectedOrg!.isNotEmpty;
final uri = Uri.parse(
isUpdating
? '$apiUrl/api/organizations/update/${selectedOrg?["org_id"]}'
: '$apiUrl/api/organizations/create',
);
if (token == null) {
throw Exception('Token not found. Please log in.');
}
// Use MultipartRequest (POST only)
final request = http.MultipartRequest('POST', uri);
request.headers['Authorization'] = 'Bearer $token';
// If updating, spoof the method Laravel-style
if (isUpdating) {
request.fields['_method'] = 'PUT';
request.fields['org_id'] = selectedOrg!["org_id"].toString();
print("UpdatingLarvel...");
}
// Add all non-null and non-empty user data fields
userData.forEach((key, value) {
if (value != null && value.toString().trim().isNotEmpty) {
request.fields[key] = value.toString();
}
});
if (_imageBytes != null) {
final multipartFile = http.MultipartFile.fromBytes(
'logo', // 👈 this should match the key expected by your backend
_imageBytes!,
filename: 'logo.png',
contentType: MediaType('image', 'png'),
);
request.files.add(multipartFile);
print("📎 Logo image attached.");
} else {
print("⚠️ No logo selected.");
}
print("🚀 Sending request with fields: ${request.fields}");
try {
final streamedResponse = await request.send();
final response = await http.Response.fromStream(streamedResponse);
print("Response status: ${response.statusCode}");
print("Response body: ${response.body}");
if (response.statusCode == 200 || response.statusCode == 201) {
print("✅ User submitted successfully!");
print("📨 Response Organizt Update: ${response.body}");
final data = json.decode(response.body);
if (!data.containsKey('data') || data['data'] is! Map) {
throw Exception(
"Invalid response format: 'data' field is missing or not a Map",
);
}
// Make sure each item is a Map<String, dynamic>
final Map<String, dynamic> orgList = Map<String, dynamic>.from(
data['data'],
);
print(orgList);
await updateOrgDataWithNewValues(orgList);
print("📨 Response Organizt Update:");
// return orgList;
context.go('/OrganizationSettings');
// context.go('/listPlan');
} else {
print("❌ Submission failed. Status: ${response.statusCode}");
print("📨 Body: ${response.body}");
}
} catch (e) {
print("🔥 Error submitting user: $e");
}
}
Future<void> updateOrgDataWithNewValues(Map<String, dynamic> newData) async {
final prefs = await SharedPreferences.getInstance();
final String? orgDataString = prefs.getString('org_data');
Map<String, dynamic> orgData = {};
if (orgDataString != null) {
try {
orgData = jsonDecode(orgDataString);
layoutColor =
orgData['layout_color'] != null
? Color(
int.parse(
orgData['layout_color'].toString().replaceFirst('0x', ''),
radix: 16,
),
)
: Colors.white;
} catch (e) {
print('❌ Failed to decode org_data: $e');
}
}
// Merge in the new data
orgData.addAll(newData);
// Save back
await prefs.setString('org_data', jsonEncode(orgData));
await prefs.setString('layout_color', orgData['layout_color']);
print("✅ Updated org_data saved.");
}
void handleSubmit() {
print("HandleSubmiy - $orgData");
createOrgData(orgData);
setState(() {
if (!isValidData(orgData)) {
print("USERDETAILS : $orgData");
print("Validation Failed: Required fields are missing.");
return; // Stop execution if validation fails
} else {
print("USERDETAILS : $orgData");
createOrgData(orgData);
}
});
}
@override
Widget build(BuildContext context) {
return ResponsiveBuilder(
builder: (context, sizingInfo) {
bool isDesktop =
sizingInfo.deviceScreenType == DeviceScreenType.desktop;
return Scaffold(
// backgroundColor: Colors.white,
backgroundColor: Color(0xFFf5f5f5),
appBar: CustomAppBar(isDesktop: isDesktop),
drawer: CustomDrawer(isDesktop: false),
body: Padding(
padding:
isDesktop
? EdgeInsets.symmetric(
horizontal:
MediaQuery.of(context).size.width *
0.1, // 30% of screen width as horizontal padding
vertical:
MediaQuery.of(context).size.height *
0, // 5% of screen height as vertical padding
)
: EdgeInsets.all(0),
child: Row(
children: [
// if (isDesktop) CustomDrawer(isDesktop: true),
Expanded(child: buildOrganizationLayout(isDesktop)),
],
),
),
);
},
);
}
Widget buildOrganizationLayout(isDesktop) {
return Container(
margin: isDesktop ? const EdgeInsets.only(top: 10.0, bottom: 10.0) : null,
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: isDesktop ? Colors.white : Color(0xFFFCFCFC),
),
// decoration: BoxDecoration(
// // color: Colors.amber,
// color: bodyColor,
// border: Border.all(
// color: Colors.white,
// // color: Color(0xFFF7F7FB),
// width: 3.5)),
child: Column(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Container(
// color: Colors.redAccent,
// color: bodyColor,
child: buildOrgLayout(isDesktop),
),
),
Container(
padding: const EdgeInsets.all(5),
color: Colors.white,
child:
isDesktop
? Row(
mainAxisAlignment: MainAxisAlignment.end,
// children: [Text("Button")],
children: _buildSubmit(
isDesktop,
isViewMode,
layoutColor,
),
)
: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: _buildSubmit(
isDesktop,
isViewMode,
layoutColor,
),
),
),
],
),
);
}
Widget buildOrgLayout(bool isDesktop) {
final screenWidth = MediaQuery.of(context).size.width;
final screenHeight = MediaQuery.of(context).size.height;
final double responsiveLogoWidth =
screenWidth * 0.15; // 15% of screen width
final double responsiveLogoHeight =
screenHeight * 0.07; // 7% of screen height
final double largeResponsiveLogoWidth =
screenWidth * 0.6; // 60% of screen width
final double largeResponsiveLogoHeight = screenHeight * 0.15;
Future<void> _pickImage() async {
final picker = ImagePicker();
final XFile? pickedFile = await picker.pickImage(
source: ImageSource.gallery,
);
if (pickedFile != null && kIsWeb) {
try {
final bytes = await pickedFile.readAsBytes();
print('✅ Image loaded, size: ${bytes.length} bytes');
setState(() {
_imageBytes = bytes;
});
} catch (e) {
print('❌ Error reading image bytes: $e');
}
} else {
print('⚠️ Image picking canceled or not on web.');
}
}
return Container(
// margin: isDesktop
// ? EdgeInsets.all(10.0)
// : EdgeInsets.only(left: 20.0, bottom: 20.0, top: 10.0, right: 20.0),
height:
isDesktop
? MediaQuery.of(context).size.height * 0.98
: MediaQuery.of(context).size.height,
// decoration: BoxDecoration(
// border: isDesktop
// ? Border.all(
// width: 2,
// color: Colors.white,
// // color: Color(0xFFF7F7FB),
// )
// : null,
// color: Colors.white,
// // color: Color(0xFFF7F7FB),
//
// // color: Colors.amber,
// ),
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Container(
padding: const EdgeInsets.only(
left: 20,
right: 20,
bottom: 20,
top: 5,
),
// height: MediaQuery.of(context).size.height * 0.8,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
child: BreadcrumbNavigation(
isDesktop: isDesktop,
breadcrumbItems: [
BreadcrumbItem(
title: 'Organization Settings',
tooltip: 'Go To Organization Settings',
onTap: (context) {
context.go("/OrganizationSettings");
},
),
BreadcrumbItem(
title:
selectedOrg != null &&
selectedOrg!.isNotEmpty
? "Update Organization"
: "Create Organization",
),
],
),
),
// Text(
// selectedOrg != null && selectedOrg!.isNotEmpty
// ? "Update Organization"
// : "Create Organization",
// style: GoogleFonts.poppins(
// fontSize: 15,
// fontWeight: FontWeight.w500,
// ),
// ),
],
),
),
Container(
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment:
CrossAxisAlignment
.center, // now -> .center , old -> .start
children: [
Padding(
padding: const EdgeInsets.only(top: 1.0),
child: Text(
"Name:",
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Color(0xFF212121),
),
),
),
SizedBox(width: 8),
Expanded(
child: TextFormField(
controller: _orgNameController,
style: GoogleFonts.poppins(
fontSize: 16,
color: Color(0xFF114D8B),
),
decoration: InputDecoration(
hintText: "Enter Organization Name",
hintStyle: GoogleFonts.poppins(
fontSize: 14,
color: Colors.grey,
),
floatingLabelBehavior:
FloatingLabelBehavior.never,
border: InputBorder.none,
isDense: true,
// contentPadding:
// EdgeInsets.symmetric(vertical: 14),
),
// textAlignVertical: TextAlignVertical.center,
),
),
Spacer(),
GestureDetector(
onTap: _pickImage,
child:
_imageBytes != null
? ClipOval(
child: Image.memory(
_imageBytes!,
// width: 50,
// height: 50,
width:
responsiveLogoWidth, // Use responsive width
height: responsiveLogoHeight,
fit: BoxFit.contain,
),
)
: selectedOrg?['logo'] != null
? ClipRect(
child: Image.network(
selectedOrg!['logo'],
width:
responsiveLogoWidth, // Use responsive width
height: responsiveLogoHeight,
// width: 250,
// height: 55,
fit: BoxFit.contain,
errorBuilder: (
context,
error,
stackTrace,
) {
return const CircleAvatar(
radius: 20,
backgroundColor: Colors.redAccent,
child: Icon(Icons.error, size: 10),
);
},
),
)
: const CircleAvatar(
radius: 20,
backgroundColor: Colors.amber,
child: Icon(Icons.add_a_photo, size: 10),
),
),
],
),
),
SizedBox(height: 10),
Text(
"Services",
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Color(0xFF212121),
),
),
SizedBox(height: 10),
Container(
decoration: BoxDecoration(
border: Border.all(color: Color(0xFFF4F4FB)),
borderRadius: BorderRadius.circular(1),
// color: bodyColor,
// color: Color(0xFFF5F5F5),
color: Colors.white,
),
padding: EdgeInsets.only(
left: 5,
right: 5,
top: 15,
bottom: 5,
),
child:
isDesktop
? Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// mainAxisSize: MainAxisSize.min,
children: _buildOptions(),
)
: Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(children: _buildOptions()),
),
),
),
SizedBox(height: 15),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Choose Theme",
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Color(0xFF212121),
),
),
Container(
decoration: BoxDecoration(
// border: Border.all(color: Color(0xFFF4F4FB)),
borderRadius: BorderRadius.circular(1),
// color: Color(0xFFF4F4FB),
),
padding: EdgeInsets.only(
left: 5,
right: 5,
top: 15,
bottom: 5,
),
child:
layoutColor != null && bodyColor != null
? ColorThemePickerWidget(
initialLayoutColor: layoutColor,
initialBodyColor: bodyColor,
onLayoutColorSelected: (
Color selectedLayoutColor,
) {
setState(() {
layoutColor = selectedLayoutColor;
});
},
onBodyColorSelected: (
Color selectedBodyColor,
) {
setState(() {
bodyColor = selectedBodyColor;
});
},
)
: CircularProgressIndicator(),
),
],
),
SizedBox(height: 15),
Container(
color: Colors.white,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Mail Settings",
style: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Color(0xFF212121),
),
),
// GestureDetector(
// onTap: () {
// setState(() {
// showMail = !showMail;
// });
// },
// child: Icon(
// Icons.keyboard_arrow_down_outlined,
// color: Color(0xFF114D8B),
// size: 30,
// ),
// ),
],
),
// if (showMail)
SizedBox(height: 10),
Container(
// width: double.infinity,
decoration: BoxDecoration(
border: Border.all(
color: Color(0xFFF5F5F5),
// color: bodyColor ?? Colors.grey,
width: 1.5,
),
// color: bodyColor,
color: Colors.white70,
// color: Color(0xFFF5F5F5),
),
child: Row(
mainAxisAlignment:
isDesktop
? MainAxisAlignment.start
: MainAxisAlignment.center,
children: [
mailConfig['sender_email'] != null
? MailSetting(
isDesktop: isDesktop,
initialMailData: mailConfig,
onMailDataChanged: (updatedData) {
// You can setState here or do something else with updatedData
print("Updated Mail Data: $updatedData");
mailConfig = updatedData;
},
)
: CircularProgressIndicator(),
],
),
),
],
),
),
// isDesktop
// ? Row(
// mainAxisAlignment: MainAxisAlignment.end,
// children: _buildSubmit(isDesktop),
// )
// : Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: _buildSubmit(isDesktop),
// )
],
),
),
],
),
),
);
}
List<Widget> _buildOptions() {
if (apiAllServices == null) return [];
return apiAllServices!.map((service) {
return Padding(
padding: const EdgeInsets.only(right: 20.0),
child: _buildOption(service),
);
}).toList();
}
Widget _buildOption(Map<String, dynamic> service) {
String name = service['name'];
String iconUrl = service['icon']; // Can be empty string
// Optional: define local icon fallback if iconUrl is empty
IconData fallbackIcon = _getLocalIconForService(name);
// final idMap = {"service_id": service['service_id'].toString()};
// final isSelected = selectedServiceIds.contains(idMap);
String serviceId = service['service_id'].toString();
// bool isSelected = selectedServiceIds.contains(serviceId);
bool isSelected = selectedServiceIds.any(
(item) => item["service_id"] == serviceId,
);
return GestureDetector(
onTap: () {
setState(() {
String serviceId = service['service_id'].toString();
// Check if already selected
int existingIndex = selectedServiceIds.indexWhere(
(item) => item["service_id"] == serviceId,
);
if (existingIndex != -1) {
selectedServiceIds.removeAt(existingIndex);
} else {
selectedServiceIds.add({"service_id": serviceId});
}
});
},
child: Row(
children: [
iconUrl.isNotEmpty
? Image.network(
iconUrl,
width: 18,
height: 18,
errorBuilder: (context, error, stackTrace) {
return Icon(
fallbackIcon,
size: 18,
color:
isSelected == name
? Color(0xFF114D8B)
: Color(0xFF475569),
);
},
)
: Icon(
fallbackIcon,
size: 18,
color:
isSelected == name ? Color(0xFF114D8B) : Color(0xFF475569),
),
SizedBox(width: 2),
Text(
name,
style: GoogleFonts.poppins(
fontSize: 12,
color: isSelected == name ? Color(0xFF114D8B) : Color(0xFF475569),
fontWeight:
isSelected == name ? FontWeight.bold : FontWeight.w500,
),
// fontWeight: selectedListOption == title ? FontWeight.bold : FontWeight.normal,)),
),
SizedBox(width: 2),
// if (selectedListOption == title && widget.isViewMode == false)
Container(
height: 15,
width: 15,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: isSelected ? Colors.green : Colors.grey,
width: 1,
),
),
child: Icon(
Icons.check_circle,
size: 10,
color: isSelected ? Colors.green : Colors.grey,
// color: Colors.grey,
),
),
],
),
);
}
IconData _getLocalIconForService(String name) {
switch (name.toLowerCase()) {
case 'flight':
return Icons.flight_takeoff_outlined;
case 'train':
return Icons.train_outlined;
case 'bus':
return Icons.directions_bus_rounded;
case 'taxi':
return Icons.local_taxi_outlined;
case 'accomodation':
return Icons.local_hotel_outlined;
case 'forex':
return Icons.attach_money_outlined;
case 'insurance':
return Icons.list_alt_outlined;
case 'visa':
return Icons.badge_outlined;
case 'miscellaneous':
return Icons.card_giftcard_outlined;
default:
return Icons.circle_notifications;
}
}
List<Widget> _buildSubmit(isDesktop, bool isViewMode, Color? layoutColor) {
return [
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
foregroundColor: layoutColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
side: BorderSide(color: layoutColor ?? Colors.grey, width: 2),
),
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
),
onPressed: () {
context.go('/listPlan');
},
child: Text("Cancel", style: GoogleFonts.poppins(fontSize: 12)),
),
SizedBox(width: 20),
MouseRegion(
// cursor: widget.isViewMode
// ? SystemMouseCursors.forbidden
// : SystemMouseCursors.click,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: layoutColor, // Keep original color
foregroundColor: Colors.white, // Keep original color
disabledBackgroundColor:
layoutColor, // Ensure color remains when disabled
disabledForegroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
side: BorderSide(color: layoutColor ?? Colors.grey, width: 2),
),
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
),
onPressed: handleSubmit, // Disable when in view mode
child: Text("Submit", style: GoogleFonts.poppins(fontSize: 12)),
),
),
];
}
}