import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:http/http.dart' as http; import 'package:Intaleq/constant/box_name.dart'; import 'package:Intaleq/constant/colors.dart'; import 'package:Intaleq/constant/links.dart'; import 'package:Intaleq/constant/style.dart'; import 'package:Intaleq/controller/functions/crud.dart'; import 'package:Intaleq/main.dart'; import 'package:Intaleq/views/widgets/elevated_btn.dart'; import 'package:http_parser/http_parser.dart'; import 'package:mime/mime.dart'; import '../../../constant/api_key.dart'; import '../../../env/env.dart'; import '../../../print.dart'; import '../../../views/widgets/mydialoug.dart'; import '../../functions/encrypt_decrypt.dart'; class ComplaintController extends GetxController { bool isLoading = false; final formKey = GlobalKey(); final complaintController = TextEditingController(); List feedBack = []; Map? passengerReport; Map? driverReport; var isUploading = false.obs; var uploadSuccess = false.obs; String audioLink = ''; // سيتم تخزين رابط الصوت هنا بعد الرفع @override void onInit() { super.onInit(); getLatestRidesForPassengers(); } // --- دالة مخصصة لعرض إشعارات Snackbar بشكل جميل --- void _showCustomSnackbar(String title, String message, {bool isError = false}) { Get.snackbar( '', // العنوان سيتم التعامل معه عبر titleText '', // الرسالة سيتم التعامل معها عبر messageText titleText: Text(title.tr, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16)), messageText: Text(message.tr, style: const TextStyle(color: Colors.white, fontSize: 14)), backgroundColor: isError ? AppColor.redColor.withOpacity(0.95) : const Color.fromARGB(255, 6, 148, 79).withOpacity(0.95), icon: Icon(isError ? Icons.error_outline : Icons.check_circle_outline, color: Colors.white, size: 28), borderRadius: 12, margin: const EdgeInsets.all(15), padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 18), snackPosition: SnackPosition.BOTTOM, duration: const Duration(seconds: 4), colorText: Colors.white, ); } // --- هذه الدالة تبقى كما هي لجلب بيانات الرحلة --- getLatestRidesForPassengers() async { isLoading = true; update(); var res = await CRUD().get(link: AppLink.getFeedBack, payload: { 'passengerId': box.read(BoxName.passengerID).toString(), }); if (res != 'failure') { var d = jsonDecode(res)['message']; feedBack = d; } isLoading = false; update(); } // --- تم تحديث الهيدر في هذه الدالة --- Future uploadAudioFile(File audioFile) async { try { isUploading.value = true; update(); var uri = Uri.parse('${AppLink.IntaleqSyriaServer}/upload_audio.php'); var request = http.MultipartRequest('POST', uri); String token = r(box.read(BoxName.jwt)).toString().split(Env.addd)[0]; var mimeType = lookupMimeType(audioFile.path); // ** التعديل: تم استخدام نفس هيدر التوثيق ** request.headers.addAll({ 'Authorization': 'Bearer $token', }); request.files.add( await http.MultipartFile.fromPath( 'audio', audioFile.path, contentType: mimeType != null ? MediaType.parse(mimeType) : null, ), ); var response = await request.send(); var responseBody = await http.Response.fromStream(response); if (response.statusCode == 200) { var jsonResponse = jsonDecode(responseBody.body); if (jsonResponse['status'] == 'Audio file uploaded successfully.') { uploadSuccess.value = true; audioLink = jsonResponse['link']; // تخزين الرابط في المتغير Get.back(); // استخدام الـ Snackbar الجديد _showCustomSnackbar('Success', 'Audio uploaded successfully.'); } else { uploadSuccess.value = false; _showCustomSnackbar('Error', 'Failed to upload audio file.', isError: true); } } else { uploadSuccess.value = false; _showCustomSnackbar('Error', 'Server error: ${response.statusCode}', isError: true); } } catch (e) { uploadSuccess.value = false; _showCustomSnackbar( 'Error', 'An application error occurred during upload.', isError: true); } finally { isUploading.value = false; update(); } } // --- الدالة الجديدة التي تتصل بالسكريبت الجديد --- Future submitComplaintToServer() async { // 1. التحقق من صحة الفورم if (!formKey.currentState!.validate() || complaintController.text.isEmpty) { // استخدام الـ Snackbar الجديد _showCustomSnackbar( 'Error', 'Please describe your issue before submitting.', isError: true); return; } // 2. التحقق من وجود بيانات الرحلة if (feedBack.isEmpty) { // استخدام الـ Snackbar الجديد _showCustomSnackbar( 'Error', 'Ride information not found. Please refresh the page.', isError: true); return; } isLoading = true; update(); try { // 3. استخراج البيانات المطلوبة final rideId = feedBack[0]['id'].toString(); // ! تأكد أن اسم حقل ID صحيح final complaint = complaintController.text; String token = r(box.read(BoxName.jwt)).toString().split(Env.addd)[0]; // 4. استدعاء سكربت PHP الجديد باستخدام http.post final response = await http.post( Uri.parse(AppLink.add_solve_all), headers: {'Authorization': 'Bearer $token'}, body: { 'ride_id': rideId, 'complaint_text': complaint, 'audio_link': audioLink, }, ); Log.print('Server Response: ${response.body}'); if (response.statusCode != 200) { _showCustomSnackbar( 'Error', 'Failed to connect to the server. Please try again.', isError: true); return; } // 5. التعامل مع محتوى الرد من الخادم final responseData = jsonDecode(response.body); if (responseData['status'] == 'success') { passengerReport = responseData['data']['passenger_response']; driverReport = responseData['data']['driver_response']; update(); MyDialogContent().getDialog( 'Success'.tr, Text('Your complaint has been submitted.'.tr), () { Get.back(); complaintController.clear(); audioLink = ''; formKey.currentState?.reset(); }); } else { String errorMessage = responseData['message'] ?? 'An unknown server error occurred'.tr; _showCustomSnackbar('Submission Failed', errorMessage, isError: true); } } catch (e) { Log.print("Submit Complaint Error: $e"); _showCustomSnackbar('Error', 'An application error occurred.'.tr, isError: true); } finally { isLoading = false; update(); } } }