334 lines
9.7 KiB
Dart
334 lines
9.7 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:frontend/utils/auth_utils.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
import 'package:http/http.dart' as http;
|
|
|
|
import '../config/apiUrl.dart';
|
|
import '../services/apiService.dart';
|
|
|
|
class CommentModal extends StatefulWidget {
|
|
final String planId;
|
|
final Color layoutColorForUser;
|
|
final String role;
|
|
const CommentModal({
|
|
Key? key,
|
|
required this.planId,
|
|
required this.layoutColorForUser,
|
|
required this.role,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
CommentModalState createState() => CommentModalState();
|
|
}
|
|
|
|
class CommentModalState extends State<CommentModal> {
|
|
Map<String, dynamic>? remarksData;
|
|
int? remarksId;
|
|
dynamic userId;
|
|
late final role;
|
|
bool isLoading = true;
|
|
String? errorMessage;
|
|
bool editRemarks = false;
|
|
TextEditingController commentController = TextEditingController();
|
|
|
|
final ApiService apiService = ApiService();
|
|
|
|
// Map<String, dynamic> getData() {
|
|
// final map = {
|
|
// "plan_id": int.parse(widget.planId),
|
|
// "remarks": commentController.text,
|
|
// "created_by": userId,
|
|
// "is_active": 1,
|
|
// };
|
|
//
|
|
// if (remarksId != null) {
|
|
// map["id"] = remarksId; // Add 'id' only if available
|
|
// }
|
|
//
|
|
// return map;
|
|
// }
|
|
|
|
Map<String, dynamic> getData({int isActive = 1}) {
|
|
final map = {
|
|
"plan_id": int.parse(widget.planId),
|
|
"remarks": commentController.text,
|
|
// "created_by": userId,
|
|
"is_active": isActive,
|
|
};
|
|
|
|
return map;
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
loadRemarks();
|
|
}
|
|
|
|
Future<void> loadRemarks() async {
|
|
try {
|
|
final userIdString = await getUserId(); // getUserId returns String?
|
|
if (userIdString == null) {
|
|
throw Exception('User ID not found.');
|
|
}
|
|
|
|
role = await getRoleUser();
|
|
|
|
print("Role - $role");
|
|
print("RoleuserId - $userId");
|
|
|
|
userId = int.tryParse(userIdString);
|
|
if (userId == null) {
|
|
throw Exception('Invalid user ID format.');
|
|
}
|
|
|
|
// if (role != null && (role == 'Org Admin' || role == 'Travel Admin' || role == )) {
|
|
final data = await getRemarks(userId);
|
|
|
|
setState(() {
|
|
remarksData = data;
|
|
|
|
isLoading = false;
|
|
});
|
|
print("Remarks -");
|
|
print("Remarks - ${jsonEncode(remarksData)}");
|
|
// } else {
|
|
// apiService.logout(context);
|
|
// }
|
|
} catch (e) {
|
|
setState(() {
|
|
errorMessage = e.toString();
|
|
isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
Future<Map<String, dynamic>> getRemarks(int userId) async {
|
|
// final String apiUrldata =
|
|
// '$apiUrl/getRemarksByPlanId?plan_id=${widget.planId}&user_id=$userId';
|
|
|
|
final String apiUrldata;
|
|
|
|
if (role == "Travel Agent") {
|
|
apiUrldata =
|
|
'$apiUrl/api/plans/getRemarksByPlanId?plan_id=${widget.planId}&user_id=$userId';
|
|
} else {
|
|
apiUrldata =
|
|
'$apiUrl/api/plans/getRemarksByPlanId?plan_id=${widget.planId}';
|
|
}
|
|
|
|
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',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
print("Res1 ....");
|
|
final data = json.decode(response.body);
|
|
|
|
// Check if 'data' is empty or doesn't contain valid remarks
|
|
if (!data.containsKey('data') ||
|
|
data['data'] == null ||
|
|
data['data'].isEmpty) {
|
|
editRemarks = true; // Set the flag to true if data is empty
|
|
} else {
|
|
print("DAta available ");
|
|
updateData(data);
|
|
editRemarks = false; // Otherwise, no need to create remarks
|
|
}
|
|
|
|
print("Res1 - $data");
|
|
if (!data.containsKey('data') || data['data'] is! Map) {
|
|
throw Exception(
|
|
"Invalid response format: 'data' field is missing or not a Map",
|
|
);
|
|
}
|
|
return data['data'];
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await apiService.logout(context);
|
|
return {};
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
throw Exception('Failed to load remarks');
|
|
}
|
|
}
|
|
|
|
Future<void> postRemarksData({int isActive = 1}) async {
|
|
// final remarksData = getData();
|
|
|
|
final remarksData = getData(isActive: isActive);
|
|
|
|
print("remarksId - $remarksId");
|
|
|
|
if (remarksId != null) {
|
|
remarksData["id"] = remarksId;
|
|
remarksData["updated_by"] = userId;
|
|
} else {
|
|
remarksData["created_by"] = userId;
|
|
}
|
|
|
|
print("Remarks Data - remarksData");
|
|
|
|
final String apiUrldata = '$apiUrl/api/plans/addOrEditPlanRemark';
|
|
|
|
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',
|
|
'app-signature': 'ts-traveltool-2025-signature-123456',
|
|
},
|
|
body: jsonEncode(remarksData), // Convert map to JSON
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
print("Plan submitted successfully!");
|
|
print("Response: ${response.body}");
|
|
} else if (response.statusCode == 403) {
|
|
print("403-FORB");
|
|
await apiService.logout(context);
|
|
return null;
|
|
// throw Exception('Failed to load users');
|
|
} else {
|
|
print("Failed to submit plan. Status: ${response.statusCode}");
|
|
print("Error: ${response.body}");
|
|
}
|
|
} catch (e) {
|
|
print(" Error submitting plan: $e");
|
|
}
|
|
}
|
|
|
|
void updateData(dynamic data) {
|
|
if (data['data'] != null && data['data'].isNotEmpty) {
|
|
final remarksData = data['data'][0]; // Take the first item from the list
|
|
|
|
print("remarksData - $remarksData");
|
|
// Now update your local fields
|
|
commentController.text = remarksData['remarks'] ?? '';
|
|
|
|
// If you need to update other fields like created_by, you can do that too
|
|
userId = remarksData['created_by'] ?? userId;
|
|
// remarksId = remarksData['id'];
|
|
remarksId = int.tryParse(remarksData['id'].toString());
|
|
|
|
print("remarksId1- $remarksId");
|
|
// If plan_id needs to be updated (usually it doesn't change), you can do it too
|
|
// widget.planId = remarksData['plan_id'].toString(); // If widget.planId is mutable
|
|
|
|
setState(() {}); // Refresh the UI if needed
|
|
}
|
|
}
|
|
|
|
Widget build(BuildContext context) {
|
|
// You can also make a TextEditingController if you want to collect input
|
|
|
|
return AlertDialog(
|
|
backgroundColor: Colors.white,
|
|
contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 10),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
// Row 1: Title + Edit + Delete buttons
|
|
Row(
|
|
children: [
|
|
Text(
|
|
'Comment',
|
|
style: GoogleFonts.poppins(fontSize: 18, color: Colors.black),
|
|
),
|
|
const Spacer(),
|
|
if (widget.role == "Travel Agent")
|
|
IconButton(
|
|
icon: const Icon(Icons.edit, size: 20),
|
|
onPressed: () {
|
|
setState(() {
|
|
editRemarks = !editRemarks;
|
|
});
|
|
},
|
|
),
|
|
if (widget.role == "Travel Agent")
|
|
IconButton(
|
|
icon: const Icon(Icons.delete, size: 20),
|
|
onPressed: () async {
|
|
await postRemarksData(
|
|
isActive: 0,
|
|
); // Marks the remark as deleted
|
|
Navigator.of(context).pop();
|
|
},
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 10),
|
|
|
|
// Row 2: TextField for comment
|
|
TextField(
|
|
controller: commentController,
|
|
maxLines: 5,
|
|
enabled: editRemarks,
|
|
decoration: InputDecoration(
|
|
hintText: 'Enter your comment...',
|
|
hintStyle: GoogleFonts.poppins(fontSize: 12, color: Colors.grey),
|
|
border: OutlineInputBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
),
|
|
style: GoogleFonts.poppins(fontSize: 12, color: Colors.black),
|
|
),
|
|
const SizedBox(height: 20),
|
|
|
|
// Row 3: OK button
|
|
editRemarks
|
|
? SizedBox(
|
|
width: double.infinity,
|
|
child: ElevatedButton(
|
|
onPressed: () {
|
|
postRemarksData();
|
|
// You can get text from commentController.text
|
|
Navigator.of(context).pop(); // Close the modal
|
|
},
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: widget.layoutColorForUser,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
),
|
|
child: Text(
|
|
'OK',
|
|
style: GoogleFonts.poppins(
|
|
fontSize: 13,
|
|
color: Colors.white,
|
|
),
|
|
),
|
|
),
|
|
)
|
|
: SizedBox.shrink(),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|