278 lines
7.6 KiB
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,
|
|
);
|
|
}
|