nhance_partner/lib/presentation/screens/Masters/Brokers/broker.dart

416 lines
12 KiB
Dart

import 'dart:convert';
// import 'dart:io' as html;
import 'dart:typed_data'; // Import for Uint8List
import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:nhance_partner/core/routing/routes.dart';
import 'package:nhance_partner/data/utils/toastNotification.dart';
import 'package:nhance_partner/presentation/themes/indicators/text_field_theme.dart';
import 'package:nhance_partner/presentation/themes/indicators/text_field_theme_inline_editor.dart';
import '../../../../core/config/env.dart';
import '../../../../core/services/api_service.dart';
import '../../../../data/services/auth_service.dart';
import '../../../../data/utils/validators.dart';
import '../../../layouts/main_layout.dart';
import '../../../layouts/responsive_layout.dart';
import '../../../providers/manager_provider.dart';
import 'package:universal_html/html.dart' as html;
import '../../../themes/indicators/input_field_decoration.dart';
class Broker extends ConsumerStatefulWidget {
final String? id;
final Map<String, dynamic>? data;
final VoidCallback onSubmit;
const Broker({super.key, this.id, this.data, required this.onSubmit});
@override
ConsumerState<Broker> createState() => BrokerState();
}
class BrokerState extends ConsumerState<Broker> {
final _formKey = GlobalKey<FormState>();
late ApiService apiService;
final GlobalKey<DropdownSearchState<Map<String, dynamic>>> dropDownKey =
GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
final GlobalKey<DropdownSearchState<Map<String, dynamic>>>
dropDownKeyHandler = GlobalKey<DropdownSearchState<Map<String, dynamic>>>();
List<String> tabHeader = ['name', 'email', 'mobile', 'code'];
late String isActive = "1";
html.File? passportFile;
String? selectedFileNames;
String? passportFileUrlFromApi;
dynamic selectedId;
String? _token;
bool isLoading = false;
bool showHandler = false;
String? selectedRole;
List<Map<String, dynamic>> filteredRolesData = [];
List<Map<String, dynamic>> getRolesData = [];
List<dynamic>? selectedHandlerIds = [];
String? selectedHandler;
List<Map<String, dynamic>> filteredHandlersData = [];
List<Map<String, dynamic>> getHandlersData = [];
Map<String, TextEditingController> controllers = {};
dynamic userId;
dynamic managerId;
Map<String, dynamic> dataDetails() {
final data = {
"name": controllers["name"]?.text,
"short_name": controllers["code"]?.text,
"is_active": isActive,
};
return data;
}
@override
void initState() {
super.initState();
apiService = ApiService();
for (String field in tabHeader) {
controllers[field] = TextEditingController();
}
_initializeToken();
updateData();
Future.microtask(() {
managerId = ref.watch(managerIdProvider);
userId = ref.watch(userIdProvider);
if (managerId != null) {
print('hansles');
// getHandlers(managerId);
}
});
}
Future<void> _initializeToken() async {
_token = await AuthService.getToken();
print("APISERTOKEN - $_token");
}
void updateData() async {
if (widget.data == null) return;
final data = widget.data!;
dynamic id = data['id'];
setState(() {
selectedId = id;
controllers['name']?.text = data['name'] ?? '';
controllers['code']?.text = data['short_name'] ?? '';
controllers["is_active"]?.text = data['is_active']?.toString() ?? '';
});
}
// void updateData() async {
// if (widget.data != null) {
// dynamic id = widget.data?['id'];
// final data = widget.data;
//
// if (data == null) return;
// setState(() {
// selectedId = id;
// controllers['name']?.text = data['name'] ?? '';
// controllers['code']?.text = data['short_name'] ?? '';
// controllers["is_active"]?.text = data['is_active'].toString();
// });
// }
// }
Future<void> handleSave() async {
final nameEmpty = controllers['name'] == null ||
controllers['name']!.text.trim().isEmpty;
final codeEmpty = controllers['code'] == null ||
controllers['code']!.text.trim().isEmpty;
// 🔥 Both empty
if (nameEmpty && codeEmpty) {
ToastHelper.showWarningToast(
context,
"Broker and Broker Code is required",
);
return;
}
// Broker Name only
if (nameEmpty) {
ToastHelper.showWarningToast(
context,
"Broker is required",
);
return;
}
// Broker Code only
if (codeEmpty) {
ToastHelper.showWarningToast(
context,
"Broker Code is required",
);
return;
}
if (!_formKey.currentState!.validate()) return;
setState(() {
if (_formKey.currentState!.validate()) {
dataDetails();
final dataSet = dataDetails();
print("dataSetAgent - $dataSet");
print("TYPE of is_active → ${dataSet['is_active'].runtimeType}");
print("TYPE of value → ${dataSet['value'].runtimeType}");
createUserData(dataSet);
} else {
// isDisable = false;
}
});
}
// Future<void> handleSave() async {
// // if (controllers['name'] != null && controllers['name'] != '') {
// // return;
// // }
// if (!_formKey.currentState!.validate()) return;
// setState(() {
// if (_formKey.currentState!.validate()) {
// dataDetails();
// final dataSet = dataDetails();
// print("dataSetAgent - $dataSet");
//
// print("TYPE of is_active → ${dataSet['is_active'].runtimeType}");
// print("TYPE of name → ${dataSet['name'].runtimeType}");
// createUserData(dataSet);
// } else {
// // isDisable = false;
// }
// });
// }
void refresh() {
print('REfresj');
widget.onSubmit();
setState(() {
// clear all text controllers
for (var controller in controllers.values) {
controller.clear();
} // 👈 clear selected agent
controllers['name']?.clear();
});
}
Future<void> createUserData(data) async {
final bool isUpdating = selectedId != null;
final dynamic id = isUpdating ? int.tryParse(selectedId.toString()) : 0;
final String apiUrldata;
print("TYPE of id → $id - ${id.runtimeType}");
print("TYPE of id → $userId - ${userId.runtimeType}");
apiUrldata = isUpdating
? '${Env.apiUrl}/master/updateBroker/$selectedId'
: '${Env.apiUrl}/master/createBroker';
// final token = await getToken(); // Fetch token
if (_token == null) {
throw Exception('Token not found. Please log in.');
}
if (isUpdating) {
data['updated_by'] = userId.toString();
} else {
data['created_by'] = userId.toString();
}
print("data------- $data}");
try {
final response = await http.post(
Uri.parse(apiUrldata),
headers: {
'Authorization': 'Bearer $_token',
'Content-Type': 'application/json',
'app-signature': Env.App_Signature,
},
body: jsonEncode(data), // Convert map to JSON
);
if (response.statusCode == 200) {
final responseBody = jsonDecode(response.body);
final message = responseBody['message'];
print("Broker submitted successfully!");
print("Response: ${response.body}");
if (responseBody['status'] == 200) {
refresh();
isUpdating
? ToastHelper.showSuccessToast(context, message)
: ToastHelper.showSuccessToast(context, message);
} else {
print("Failed to submit plan. Status: ${response.statusCode}");
print("Error: ${response.body}");
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Broker Creation Failed"),
content: Text(message),
actions: [
TextButton(
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
} else if (response.statusCode == 403) {
await apiService.clearLocalStorageAndRedirect();
}
} catch (e) {
print(" Error submitting Staff: $e");
}
}
@override
void dispose() {
for (var controller in controllers.values) {
controller.dispose();
}
super.dispose();
}
@override
Widget build(BuildContext context) {
return SelectionArea(
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
buildFormFields(),
SizedBox(width: 5),
InkWell(
onTap: () {
handleSave();
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 6),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: Color(0xFF2E7D6E),
),
child: Text(
'Save',
style: GoogleFonts.inter(color: Colors.white, fontSize: 10),
),
),
),
SizedBox(width: 5),
InkWell(
onTap: () {
refresh();
},
child: Container(
padding: EdgeInsets.all(6.0),
decoration: BoxDecoration(
color: const Color(0xFF2E7D6E),
borderRadius: BorderRadius.circular(5.0),
),
child: Icon(Icons.refresh, size: 13, color: Colors.white),
),
),
],
),
) );
}
Widget buildFormFields() {
return Form(
key: _formKey,
child: Row(
children: [buildName(), SizedBox(width: 10), buildShortName()],
),
);
}
Widget buildName() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Broker *", style: _textStyle),
SizedBox(width: 10),
SizedBox(
child: ThemedFormInlineField(
controller: controllers['name']!,
validator: (value) => Validators.requiredField(value, "name"),
txtwidth: MediaQuery.of(context).size.width * 0.15,
borderColor: Color(0xFFE2E8F0),
highlightColor: Color(0xFF50A398),
// txtheight: 30,
isdense: true,
errFieldHgt: 0,
),
),
],
);
}
Widget buildShortName() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Broker Code *", style: _textStyle),
SizedBox(width: 10),
SizedBox(
child: ThemedFormInlineField(
controller: controllers['code']!,
validator: (value) => Validators.requiredField(value, "code"),
inputFormatters: [
// This line now allows letters, numbers, hyphens, and underscores
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9\-_ ]')),
],
txtwidth: MediaQuery.of(context).size.width * 0.15,
borderColor: Color(0xFFE2E8F0),
highlightColor: Color(0xFF50A398),
// txtheight: 30,
isdense: true,
errFieldHgt: 0,
),
),
],
);
}
static final _textStyle = GoogleFonts.inter(
fontSize: 11,
fontWeight: FontWeight.w600,
);
}