nhance_partner/lib/presentation/screens/Masters/Insurers/insurer.dart

278 lines
7.6 KiB
Dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:nhance_partner/data/utils/toastNotification.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';
class Insurer extends ConsumerStatefulWidget {
final String? id;
final Map<String, dynamic>? data;
final VoidCallback onSubmit;
const Insurer({
super.key,
this.id,
this.data,
required this.onSubmit,
});
@override
ConsumerState<Insurer> createState() => InsurerState();
}
class InsurerState extends ConsumerState<Insurer> {
final _formKey = GlobalKey<FormState>();
late ApiService apiService;
List<String> tabHeader = ['name', 'code'];
String? _token;
dynamic selectedId;
Map<String, TextEditingController> controllers = {};
bool get _isEdit => selectedId != null;
Map<String, dynamic> dataDetails() {
final data = <String, dynamic>{
'name': controllers['name']?.text.trim(),
'short_name': controllers['code']?.text.trim(),
};
if (_isEdit) {
data['id'] = selectedId.toString();
}
return data;
}
@override
void initState() {
super.initState();
apiService = ApiService();
for (final field in tabHeader) {
controllers[field] = TextEditingController();
}
_initializeToken();
updateData();
}
void updateData() {
if (widget.data == null) return;
final data = widget.data!;
selectedId = data['id'];
controllers['name']?.text = data['name']?.toString() ?? '';
controllers['code']?.text = data['short_name']?.toString() ?? '';
}
Future<void> _initializeToken() async {
_token = await AuthService.getToken();
}
Future<void> handleSave() async {
final nameEmpty =
controllers['name'] == null || controllers['name']!.text.trim().isEmpty;
final codeEmpty =
controllers['code'] == null || controllers['code']!.text.trim().isEmpty;
if (nameEmpty && codeEmpty) {
ToastHelper.showWarningToast(
context,
'Insurer and Short Name are required',
);
return;
}
if (nameEmpty) {
ToastHelper.showWarningToast(context, 'Insurer is required');
return;
}
if (codeEmpty) {
ToastHelper.showWarningToast(context, 'Short Name is required');
return;
}
if (!_formKey.currentState!.validate()) return;
await createUserData(dataDetails());
}
void refresh() {
widget.onSubmit();
setState(() {
selectedId = null;
for (final controller in controllers.values) {
controller.clear();
}
});
}
Future<void> createUserData(Map<String, dynamic> data) async {
if (_token == null) {
throw Exception('Token not found. Please log in.');
}
try {
final response = await http.post(
Uri.parse('${Env.apiUrl}master/saveInsurer'),
headers: {
'Authorization': 'Bearer $_token',
'Content-Type': 'application/json',
'app-signature': Env.App_Signature,
},
body: jsonEncode(data),
);
if (response.statusCode == 200) {
final responseBody = jsonDecode(response.body);
final message = responseBody['message']?.toString() ??
(_isEdit
? 'Insurer updated successfully.'
: 'Insurer created successfully.');
if (responseBody['status'] == 200 ||
responseBody['status'] == 'success') {
refresh();
if (mounted) {
ToastHelper.showSuccessToast(context, message);
}
} else if (mounted) {
showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(_isEdit ? 'Insurer Update Failed' : 'Insurer Save Failed'),
content: Text(message),
actions: [
TextButton(
child: const Text('OK'),
onPressed: () => Navigator.of(context).pop(),
),
],
);
},
);
}
} else if (response.statusCode == 403) {
await apiService.clearLocalStorageAndRedirect();
}
} catch (e) {
if (mounted) {
ToastHelper.showWarningToast(context, 'Error saving insurer: $e');
}
}
}
@override
void dispose() {
for (final controller in controllers.values) {
controller.dispose();
}
super.dispose();
}
@override
Widget build(BuildContext context) {
return SelectionArea(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
buildFormFields(),
const SizedBox(width: 5),
InkWell(
onTap: handleSave,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 6),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
color: const Color(0xFF2E7D6E),
),
child: Text(
'Save',
style: GoogleFonts.inter(color: Colors.white, fontSize: 10),
),
),
),
const SizedBox(width: 5),
InkWell(
onTap: refresh,
child: Container(
padding: const EdgeInsets.all(6.0),
decoration: BoxDecoration(
color: const Color(0xFF2E7D6E),
borderRadius: BorderRadius.circular(5.0),
),
child: const Icon(Icons.refresh, size: 13, color: Colors.white),
),
),
],
),
);
}
Widget buildFormFields() {
return Form(
key: _formKey,
child: Row(
children: [
buildName(),
const SizedBox(width: 10),
buildShortName(),
],
),
);
}
Widget buildName() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Insurer *', style: _textStyle),
const SizedBox(width: 10),
ThemedFormInlineField(
controller: controllers['name']!,
validator: (value) => Validators.requiredField(value, 'name'),
txtwidth: MediaQuery.of(context).size.width * 0.15,
borderColor: const Color(0xFFE2E8F0),
highlightColor: const Color(0xFF50A398),
isdense: true,
errFieldHgt: 0,
),
],
);
}
Widget buildShortName() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Short Name *', style: _textStyle),
const SizedBox(width: 10),
ThemedFormInlineField(
controller: controllers['code']!,
validator: (value) => Validators.requiredField(value, 'code'),
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9\-_ ]')),
],
txtwidth: MediaQuery.of(context).size.width * 0.15,
borderColor: const Color(0xFFE2E8F0),
highlightColor: const Color(0xFF50A398),
isdense: true,
errFieldHgt: 0,
),
],
);
}
static final _textStyle = GoogleFonts.inter(
fontSize: 11,
fontWeight: FontWeight.w600,
);
}