Implemented Razorpay Payment Gateway integration - April 17, 2026, 5:56 PM
This commit is contained in:
parent
ece167ea75
commit
41d7cfa8c6
@ -45,6 +45,10 @@ android {
|
|||||||
getByName("release") {
|
getByName("release") {
|
||||||
// TODO: Replace with your release signing config
|
// TODO: Replace with your release signing config
|
||||||
signingConfig = signingConfigs.getByName("debug")
|
signingConfig = signingConfigs.getByName("debug")
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
|
"proguard-rules.pro"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
android/app/proguard-rules.pro
vendored
Normal file
5
android/app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
-keepclassmembers class * {
|
||||||
|
@android.webkit.JavascriptInterface <methods>;
|
||||||
|
}
|
||||||
|
-keep class com.razorpay.** {*;}
|
||||||
|
-dontwarn com.razorpay.**
|
||||||
@ -117,6 +117,12 @@ PODS:
|
|||||||
- permission_handler_apple (9.3.0):
|
- permission_handler_apple (9.3.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- PromisesObjC (2.4.0)
|
- PromisesObjC (2.4.0)
|
||||||
|
- razorpay-core-pod (1.0.6)
|
||||||
|
- razorpay-pod (1.5.3):
|
||||||
|
- razorpay-core-pod (= 1.0.6)
|
||||||
|
- razorpay_flutter (1.1.10):
|
||||||
|
- Flutter
|
||||||
|
- razorpay-pod
|
||||||
- SDWebImage (5.21.7):
|
- SDWebImage (5.21.7):
|
||||||
- SDWebImage/Core (= 5.21.7)
|
- SDWebImage/Core (= 5.21.7)
|
||||||
- SDWebImage/Core (5.21.7)
|
- SDWebImage/Core (5.21.7)
|
||||||
@ -140,6 +146,7 @@ DEPENDENCIES:
|
|||||||
- open_filex (from `.symlinks/plugins/open_filex/ios`)
|
- open_filex (from `.symlinks/plugins/open_filex/ios`)
|
||||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||||
|
- razorpay_flutter (from `.symlinks/plugins/razorpay_flutter/ios`)
|
||||||
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
||||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
|
|
||||||
@ -156,6 +163,8 @@ SPEC REPOS:
|
|||||||
- GoogleUtilities
|
- GoogleUtilities
|
||||||
- nanopb
|
- nanopb
|
||||||
- PromisesObjC
|
- PromisesObjC
|
||||||
|
- razorpay-core-pod
|
||||||
|
- razorpay-pod
|
||||||
- SDWebImage
|
- SDWebImage
|
||||||
- SwiftyGif
|
- SwiftyGif
|
||||||
|
|
||||||
@ -184,6 +193,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||||
permission_handler_apple:
|
permission_handler_apple:
|
||||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||||
|
razorpay_flutter:
|
||||||
|
:path: ".symlinks/plugins/razorpay_flutter/ios"
|
||||||
sqflite_darwin:
|
sqflite_darwin:
|
||||||
:path: ".symlinks/plugins/sqflite_darwin/darwin"
|
:path: ".symlinks/plugins/sqflite_darwin/darwin"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
@ -213,6 +224,9 @@ SPEC CHECKSUMS:
|
|||||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||||
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
|
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
|
||||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||||
|
razorpay-core-pod: 6da5fb4ed280279d665507fdb50e213d793a5fe2
|
||||||
|
razorpay-pod: 4385cf844aa29389313b741e20c72fe668970d49
|
||||||
|
razorpay_flutter: 0e98e4fcaae27ad50e011d85f66d85e0a008754a
|
||||||
SDWebImage: e9fc87c1aab89a8ab1bbd74eba378c6f53be8abf
|
SDWebImage: e9fc87c1aab89a8ab1bbd74eba378c6f53be8abf
|
||||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import Flutter
|
import Flutter
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import Firebase
|
||||||
|
|
||||||
@main
|
@main
|
||||||
@objc class AppDelegate: FlutterAppDelegate {
|
@objc class AppDelegate: FlutterAppDelegate {
|
||||||
@ -7,6 +8,7 @@ import UIKit
|
|||||||
_ application: UIApplication,
|
_ application: UIApplication,
|
||||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
|
FirebaseApp.configure()
|
||||||
GeneratedPluginRegistrant.register(with: self)
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
|
|
||||||
if #available(iOS 10.0, *) {
|
if #available(iOS 10.0, *) {
|
||||||
|
|||||||
@ -27,4 +27,5 @@ class ConstsApi {
|
|||||||
"$baseUrl/api/notification/un_read_count";
|
"$baseUrl/api/notification/un_read_count";
|
||||||
static const String dashboard = "$baseUrl/api/get_dashboard_data";
|
static const String dashboard = "$baseUrl/api/get_dashboard_data";
|
||||||
static const String proformaaccept = "$baseUrl/api/proforma/accept";
|
static const String proformaaccept = "$baseUrl/api/proforma/accept";
|
||||||
|
static const String payNow = "$baseUrl/api/pay_now";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -861,6 +861,36 @@ debugPrint('📦 KYC Response Body: ${response.body}');
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> payNow({required int id}) async {
|
||||||
|
try {
|
||||||
|
final token = await _localStore.getToken();
|
||||||
|
final uri = Uri.parse(ConstsApi.payNow).replace(
|
||||||
|
queryParameters: {'id': id.toString()},
|
||||||
|
);
|
||||||
|
|
||||||
|
final response = await http.post(
|
||||||
|
uri,
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer $token',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final data = jsonDecode(response.body);
|
||||||
|
debugPrint("🚀 Pay Now API Response: $data");
|
||||||
|
print("🚀 Pay Now API Response: $data"); // Force print as well
|
||||||
|
|
||||||
|
if (response.statusCode != 200 && response.statusCode != 201) {
|
||||||
|
throw data['message'] ?? 'Failed to process payment';
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('❌ Pay Now API Error: $e');
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> proformaaccept({required int proformaId}) async {
|
Future<void> proformaaccept({required int proformaId}) async {
|
||||||
try {
|
try {
|
||||||
final token = await _localStore.getToken();
|
final token = await _localStore.getToken();
|
||||||
|
|||||||
70
lib/services/razorpay_service.dart
Normal file
70
lib/services/razorpay_service.dart
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import 'package:razorpay_flutter/razorpay_flutter.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
class RazorpayService {
|
||||||
|
late Razorpay _razorpay;
|
||||||
|
final Function(PaymentSuccessResponse)? onSuccess;
|
||||||
|
final Function(PaymentFailureResponse)? onFailure;
|
||||||
|
final Function(ExternalWalletResponse)? onExternalWallet;
|
||||||
|
|
||||||
|
RazorpayService({
|
||||||
|
this.onSuccess,
|
||||||
|
this.onFailure,
|
||||||
|
this.onExternalWallet,
|
||||||
|
}) {
|
||||||
|
_razorpay = Razorpay();
|
||||||
|
_razorpay.on(Razorpay.EVENT_PAYMENT_SUCCESS, _handlePaymentSuccess);
|
||||||
|
_razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, _handlePaymentError);
|
||||||
|
_razorpay.on(Razorpay.EVENT_EXTERNAL_WALLET, _handleExternalWallet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handlePaymentSuccess(PaymentSuccessResponse response) {
|
||||||
|
debugPrint("✅ Razorpay Payment Success: ${response.paymentId}");
|
||||||
|
onSuccess?.call(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handlePaymentError(PaymentFailureResponse response) {
|
||||||
|
debugPrint("❌ Razorpay Payment Error: ${response.code} - ${response.message}");
|
||||||
|
onFailure?.call(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleExternalWallet(ExternalWalletResponse response) {
|
||||||
|
debugPrint("💰 Razorpay External Wallet: ${response.walletName}");
|
||||||
|
onExternalWallet?.call(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void openCheckout({
|
||||||
|
required String key,
|
||||||
|
required dynamic amount,
|
||||||
|
required String orderId,
|
||||||
|
required String description,
|
||||||
|
String? contact,
|
||||||
|
String? email,
|
||||||
|
}) {
|
||||||
|
var options = {
|
||||||
|
'key': key,
|
||||||
|
'amount': amount,
|
||||||
|
'name': 'Taxglide',
|
||||||
|
'order_id': orderId,
|
||||||
|
'description': description,
|
||||||
|
'theme': {'color': '#61277A'},
|
||||||
|
'prefill': {
|
||||||
|
'contact': contact ?? '',
|
||||||
|
'email': email ?? '',
|
||||||
|
},
|
||||||
|
'external': {
|
||||||
|
'wallets': ['paytm']
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
_razorpay.open(options);
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint("❌ Error opening Razorpay: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
_razorpay.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -14,6 +14,8 @@ import 'package:taxglide/model/detail_model.dart';
|
|||||||
import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart';
|
import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart';
|
||||||
import 'package:taxglide/view/Main_controller/main_controller.dart';
|
import 'package:taxglide/view/Main_controller/main_controller.dart';
|
||||||
import 'package:taxglide/view/screens/history/completed_live_chat_screen.dart';
|
import 'package:taxglide/view/screens/history/completed_live_chat_screen.dart';
|
||||||
|
import 'package:taxglide/services/razorpay_service.dart';
|
||||||
|
import 'package:razorpay_flutter/razorpay_flutter.dart';
|
||||||
|
|
||||||
class DetailScreen extends ConsumerStatefulWidget {
|
class DetailScreen extends ConsumerStatefulWidget {
|
||||||
final int id;
|
final int id;
|
||||||
@ -30,13 +32,33 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
String? _downloadedInvoicePath;
|
String? _downloadedInvoicePath;
|
||||||
|
|
||||||
bool _isWebSocketInitialized = false; // Add this flag
|
bool _isWebSocketInitialized = false; // Add this flag
|
||||||
|
late RazorpayService _razorpayService;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
_razorpayService = RazorpayService(
|
||||||
|
onSuccess: _handlePaymentSuccess,
|
||||||
|
onFailure: _handlePaymentFailure,
|
||||||
|
);
|
||||||
_initializeWebSocket(); // Initialize WebSocket
|
_initializeWebSocket(); // Initialize WebSocket
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _handlePaymentSuccess(PaymentSuccessResponse response) {
|
||||||
|
ValidationPopup().showSuccessMessage(
|
||||||
|
context,
|
||||||
|
"Payment successful! ID: ${response.paymentId}",
|
||||||
|
);
|
||||||
|
ref.invalidate(serviceDetailProvider(widget.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handlePaymentFailure(PaymentFailureResponse response) {
|
||||||
|
ValidationPopup().showErrorMessage(
|
||||||
|
context,
|
||||||
|
"Payment failed: ${response.message}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Add this method
|
// Add this method
|
||||||
Future<void> _initializeWebSocket() async {
|
Future<void> _initializeWebSocket() async {
|
||||||
if (_isWebSocketInitialized) return;
|
if (_isWebSocketInitialized) return;
|
||||||
@ -82,6 +104,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
_razorpayService.dispose();
|
||||||
// Optionally disconnect WebSocket when leaving screen
|
// Optionally disconnect WebSocket when leaving screen
|
||||||
// DetailsWebscokect().disconnect();
|
// DetailsWebscokect().disconnect();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
@ -639,20 +662,26 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'Date: ',
|
text: 'Date: ',
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles.semiBold
|
||||||
|
.copyWith(
|
||||||
fontSize: width * 0.035,
|
fontSize: width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing: 0.04 * 13.97,
|
||||||
color: const Color(0xFF111827),
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: data.createdDate ?? "-",
|
text: data.createdDate ?? "-",
|
||||||
style: AppTextStyles.regular.copyWith(
|
style: AppTextStyles.regular
|
||||||
|
.copyWith(
|
||||||
fontSize: width * 0.035,
|
fontSize: width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing: 0.04 * 13.97,
|
||||||
color: const Color(0xFF111827),
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -668,20 +697,26 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'Payment : ',
|
text: 'Payment : ',
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles.semiBold
|
||||||
|
.copyWith(
|
||||||
fontSize: width * 0.035,
|
fontSize: width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing: 0.04 * 13.97,
|
||||||
color: const Color(0xFF111827),
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: data.paymentStatus ?? "-",
|
text: data.paymentStatus ?? "-",
|
||||||
style: AppTextStyles.regular.copyWith(
|
style: AppTextStyles.regular
|
||||||
|
.copyWith(
|
||||||
fontSize: width * 0.035,
|
fontSize: width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing: 0.04 * 13.97,
|
||||||
color: const Color(0xFF111827),
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -891,9 +926,9 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
if (data.paymentStatus == "Un Paid" &&
|
if (data.paymentStatus == "Un Paid" &&
|
||||||
!(data.serviceStatus ?? "")
|
!(data.serviceStatus ?? "").toLowerCase().contains(
|
||||||
.toLowerCase()
|
"cancelled",
|
||||||
.contains("cancelled")) ...[
|
)) ...[
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
vertical: 31,
|
vertical: 31,
|
||||||
@ -926,7 +961,8 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Payment Advice",
|
"Payment Advice",
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles.semiBold
|
||||||
|
.copyWith(
|
||||||
fontSize: width * 0.042,
|
fontSize: width * 0.042,
|
||||||
height: 1.4,
|
height: 1.4,
|
||||||
letterSpacing: 0.03 * 16,
|
letterSpacing: 0.03 * 16,
|
||||||
@ -945,22 +981,34 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'Date: ',
|
text: 'Date: ',
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles
|
||||||
fontSize: width * 0.035,
|
.semiBold
|
||||||
|
.copyWith(
|
||||||
|
fontSize:
|
||||||
|
width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing:
|
||||||
color: const Color(0xFF111827),
|
0.04 * 13.97,
|
||||||
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text:
|
text:
|
||||||
data.createdDate ??
|
data.createdDate ??
|
||||||
"-",
|
"-",
|
||||||
style: AppTextStyles.regular.copyWith(
|
style: AppTextStyles
|
||||||
fontSize: width * 0.035,
|
.regular
|
||||||
|
.copyWith(
|
||||||
|
fontSize:
|
||||||
|
width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing:
|
||||||
color: const Color(0xFF111827),
|
0.04 * 13.97,
|
||||||
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -976,22 +1024,34 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'Payment : ',
|
text: 'Payment : ',
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles
|
||||||
fontSize: width * 0.035,
|
.semiBold
|
||||||
|
.copyWith(
|
||||||
|
fontSize:
|
||||||
|
width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing:
|
||||||
color: const Color(0xFF111827),
|
0.04 * 13.97,
|
||||||
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text:
|
text:
|
||||||
data.paymentStatus ??
|
data.paymentStatus ??
|
||||||
"-",
|
"-",
|
||||||
style: AppTextStyles.regular.copyWith(
|
style: AppTextStyles
|
||||||
fontSize: width * 0.035,
|
.regular
|
||||||
|
.copyWith(
|
||||||
|
fontSize:
|
||||||
|
width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing:
|
||||||
color: const Color(0xFF111827),
|
0.04 * 13.97,
|
||||||
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1009,17 +1069,23 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Total Amount",
|
"Total Amount",
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles.semiBold
|
||||||
|
.copyWith(
|
||||||
fontSize: width * 0.04,
|
fontSize: width * 0.04,
|
||||||
color: const Color(0xFF111827),
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"₹ ${data.paymentAmount ?? '0'}",
|
"₹ ${data.paymentAmount ?? '0'}",
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles.semiBold
|
||||||
|
.copyWith(
|
||||||
fontFamily: 'Roboto',
|
fontFamily: 'Roboto',
|
||||||
fontSize: width * 0.045,
|
fontSize: width * 0.045,
|
||||||
color: const Color(0xFF111827),
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1029,7 +1095,37 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
CommanButton(text: 'Pay Now', onPressed: () {}),
|
CommanButton(
|
||||||
|
text: 'Pay Now',
|
||||||
|
onPressed: () async {
|
||||||
|
try {
|
||||||
|
final response = await ApiRepository()
|
||||||
|
.payNow(
|
||||||
|
id: int.parse(data.id.toString()),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response['status'] == 'success') {
|
||||||
|
_razorpayService.openCheckout(
|
||||||
|
key: response['razorpay_key'],
|
||||||
|
amount: response['amount'],
|
||||||
|
orderId: response['order_id'],
|
||||||
|
description:
|
||||||
|
"Payment for Service ID: ${data.id}",
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
validationPopup.showErrorMessage(
|
||||||
|
context,
|
||||||
|
"Failed to initiate payment",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
validationPopup.showErrorMessage(
|
||||||
|
context,
|
||||||
|
e.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1066,7 +1162,8 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Payment Advice",
|
"Payment Advice",
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles.semiBold
|
||||||
|
.copyWith(
|
||||||
fontSize: width * 0.042,
|
fontSize: width * 0.042,
|
||||||
height: 1.4,
|
height: 1.4,
|
||||||
letterSpacing: 0.03 * 16,
|
letterSpacing: 0.03 * 16,
|
||||||
@ -1085,22 +1182,34 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'Date: ',
|
text: 'Date: ',
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles
|
||||||
fontSize: width * 0.035,
|
.semiBold
|
||||||
|
.copyWith(
|
||||||
|
fontSize:
|
||||||
|
width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing:
|
||||||
color: const Color(0xFF111827),
|
0.04 * 13.97,
|
||||||
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text:
|
text:
|
||||||
data.createdDate ??
|
data.createdDate ??
|
||||||
"-",
|
"-",
|
||||||
style: AppTextStyles.regular.copyWith(
|
style: AppTextStyles
|
||||||
fontSize: width * 0.035,
|
.regular
|
||||||
|
.copyWith(
|
||||||
|
fontSize:
|
||||||
|
width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing:
|
||||||
color: const Color(0xFF111827),
|
0.04 * 13.97,
|
||||||
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1116,22 +1225,34 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'Payment: ',
|
text: 'Payment: ',
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles
|
||||||
fontSize: width * 0.035,
|
.semiBold
|
||||||
|
.copyWith(
|
||||||
|
fontSize:
|
||||||
|
width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing:
|
||||||
color: const Color(0xFF111827),
|
0.04 * 13.97,
|
||||||
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text:
|
text:
|
||||||
data.paymentStatus ??
|
data.paymentStatus ??
|
||||||
"-",
|
"-",
|
||||||
style: AppTextStyles.regular.copyWith(
|
style: AppTextStyles
|
||||||
fontSize: width * 0.035,
|
.regular
|
||||||
|
.copyWith(
|
||||||
|
fontSize:
|
||||||
|
width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing:
|
||||||
color: const Color(0xFF111827),
|
0.04 * 13.97,
|
||||||
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1149,17 +1270,23 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Total Amount",
|
"Total Amount",
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles.semiBold
|
||||||
|
.copyWith(
|
||||||
fontSize: width * 0.04,
|
fontSize: width * 0.04,
|
||||||
color: const Color(0xFF111827),
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"₹ ${data.paymentAmount ?? '0'}",
|
"₹ ${data.paymentAmount ?? '0'}",
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles.semiBold
|
||||||
|
.copyWith(
|
||||||
fontFamily: 'Roboto',
|
fontFamily: 'Roboto',
|
||||||
fontSize: width * 0.045,
|
fontSize: width * 0.045,
|
||||||
color: const Color(0xFF111827),
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1232,22 +1359,27 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'proforma Number : ',
|
text: 'proforma Number : ',
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles.semiBold
|
||||||
|
.copyWith(
|
||||||
fontSize: width * 0.035,
|
fontSize: width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing:
|
||||||
|
0.04 * 13.97,
|
||||||
color: const Color(
|
color: const Color(
|
||||||
0xFF111827,
|
0xFF111827,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: data.proformaNumber ??
|
text:
|
||||||
|
data.proformaNumber ??
|
||||||
"-",
|
"-",
|
||||||
style: AppTextStyles.regular.copyWith(
|
style: AppTextStyles.regular
|
||||||
|
.copyWith(
|
||||||
fontSize: width * 0.035,
|
fontSize: width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing:
|
||||||
|
0.04 * 13.97,
|
||||||
color: const Color(
|
color: const Color(
|
||||||
0xFF111827,
|
0xFF111827,
|
||||||
),
|
),
|
||||||
@ -1267,20 +1399,26 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'proforma Status : ',
|
text: 'proforma Status : ',
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles.semiBold
|
||||||
|
.copyWith(
|
||||||
fontSize: width * 0.035,
|
fontSize: width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing: 0.04 * 13.97,
|
||||||
color: const Color(0xFF111827),
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: data.proformaStatus ?? "-",
|
text: data.proformaStatus ?? "-",
|
||||||
style: AppTextStyles.regular.copyWith(
|
style: AppTextStyles.regular
|
||||||
|
.copyWith(
|
||||||
fontSize: width * 0.035,
|
fontSize: width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing: 0.04 * 13.97,
|
||||||
color: const Color(0xFF111827),
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1294,20 +1432,26 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
children: [
|
children: [
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: 'Subject : ',
|
text: 'Subject : ',
|
||||||
style: AppTextStyles.semiBold.copyWith(
|
style: AppTextStyles.semiBold
|
||||||
|
.copyWith(
|
||||||
fontSize: width * 0.035,
|
fontSize: width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing: 0.04 * 13.97,
|
||||||
color: const Color(0xFF111827),
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: data.subject ?? "-",
|
text: data.subject ?? "-",
|
||||||
style: AppTextStyles.regular.copyWith(
|
style: AppTextStyles.regular
|
||||||
|
.copyWith(
|
||||||
fontSize: width * 0.035,
|
fontSize: width * 0.035,
|
||||||
height: 1.3,
|
height: 1.3,
|
||||||
letterSpacing: 0.04 * 13.97,
|
letterSpacing: 0.04 * 13.97,
|
||||||
color: const Color(0xFF111827),
|
color: const Color(
|
||||||
|
0xFF111827,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -1662,7 +1806,9 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
),
|
),
|
||||||
if (data.chatId != null &&
|
if (data.chatId != null &&
|
||||||
data.chatId!.isNotEmpty &&
|
data.chatId!.isNotEmpty &&
|
||||||
!(data.serviceStatus ?? "").toLowerCase().contains("cancelled"))
|
!(data.serviceStatus ?? "").toLowerCase().contains(
|
||||||
|
"cancelled",
|
||||||
|
))
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
horizontal: 20,
|
horizontal: 20,
|
||||||
@ -1758,7 +1904,9 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(height: 80.0 + MediaQuery.of(context).padding.bottom),
|
SizedBox(
|
||||||
|
height: 80.0 + MediaQuery.of(context).padding.bottom,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -7,15 +7,60 @@ import 'package:taxglide/view/Main_controller/main_controller.dart';
|
|||||||
import 'package:taxglide/view/screens/history/detail_screen.dart';
|
import 'package:taxglide/view/screens/history/detail_screen.dart';
|
||||||
import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart';
|
import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart';
|
||||||
import 'package:taxglide/view/screens/history/completed_live_chat_screen.dart';
|
import 'package:taxglide/view/screens/history/completed_live_chat_screen.dart';
|
||||||
|
import 'package:taxglide/services/razorpay_service.dart';
|
||||||
|
import 'package:razorpay_flutter/razorpay_flutter.dart';
|
||||||
|
import 'package:taxglide/consts/validation_popup.dart';
|
||||||
|
import 'package:taxglide/controller/api_repository.dart';
|
||||||
|
|
||||||
class PendingScreen extends ConsumerWidget {
|
class PendingScreen extends ConsumerStatefulWidget {
|
||||||
final String status;
|
final String status;
|
||||||
|
|
||||||
const PendingScreen({super.key, required this.status});
|
const PendingScreen({super.key, required this.status});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
ConsumerState<PendingScreen> createState() => _PendingScreenState();
|
||||||
final pendingAsync = ref.watch(serviceHistoryNotifierProvider(status));
|
}
|
||||||
|
|
||||||
|
class _PendingScreenState extends ConsumerState<PendingScreen> {
|
||||||
|
late RazorpayService _razorpayService;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_razorpayService = RazorpayService(
|
||||||
|
onSuccess: _handlePaymentSuccess,
|
||||||
|
onFailure: _handlePaymentFailure,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handlePaymentSuccess(PaymentSuccessResponse response) {
|
||||||
|
ValidationPopup().showSuccessMessage(
|
||||||
|
context,
|
||||||
|
"Payment successful! ID: ${response.paymentId}",
|
||||||
|
);
|
||||||
|
ref
|
||||||
|
.read(serviceHistoryNotifierProvider(widget.status).notifier)
|
||||||
|
.fetchServiceHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handlePaymentFailure(PaymentFailureResponse response) {
|
||||||
|
ValidationPopup().showErrorMessage(
|
||||||
|
context,
|
||||||
|
"Payment failed: ${response.message}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_razorpayService.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final pendingAsync = ref.watch(
|
||||||
|
serviceHistoryNotifierProvider(widget.status),
|
||||||
|
);
|
||||||
final size = MediaQuery.of(context).size;
|
final size = MediaQuery.of(context).size;
|
||||||
final width = size.width;
|
final width = size.width;
|
||||||
final height = size.height;
|
final height = size.height;
|
||||||
@ -23,9 +68,11 @@ class PendingScreen extends ConsumerWidget {
|
|||||||
// 🔄 Silent refresh when notification trigger changes
|
// 🔄 Silent refresh when notification trigger changes
|
||||||
ref.listen(notificationTriggerProvider, (previous, next) {
|
ref.listen(notificationTriggerProvider, (previous, next) {
|
||||||
if (previous != null && next != previous) {
|
if (previous != null && next != previous) {
|
||||||
debugPrint("🔔 Silent refresh triggered for PendingScreen ($status)");
|
debugPrint(
|
||||||
|
"🔔 Silent refresh triggered for PendingScreen (${widget.status})",
|
||||||
|
);
|
||||||
ref
|
ref
|
||||||
.read(serviceHistoryNotifierProvider(status).notifier)
|
.read(serviceHistoryNotifierProvider(widget.status).notifier)
|
||||||
.fetchServiceHistory(isSilent: true);
|
.fetchServiceHistory(isSilent: true);
|
||||||
ref.invalidate(countProvider);
|
ref.invalidate(countProvider);
|
||||||
}
|
}
|
||||||
@ -36,7 +83,9 @@ class PendingScreen extends ConsumerWidget {
|
|||||||
final list = data.data ?? [];
|
final list = data.data ?? [];
|
||||||
if (list.isEmpty) {
|
if (list.isEmpty) {
|
||||||
// Using Get's capitalize extension explicitly
|
// Using Get's capitalize extension explicitly
|
||||||
return Center(child: Text("No ${status.capitalizeFirst} Requests"));
|
return Center(
|
||||||
|
child: Text("No ${widget.status.capitalizeFirst} Requests"),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ListView.separated(
|
return ListView.separated(
|
||||||
@ -202,11 +251,13 @@ class PendingScreen extends ConsumerWidget {
|
|||||||
item.chatId != null &&
|
item.chatId != null &&
|
||||||
item.chatId.toString().isNotEmpty &&
|
item.chatId.toString().isNotEmpty &&
|
||||||
item.chatId.toString() != "0") ...[
|
item.chatId.toString() != "0") ...[
|
||||||
|
|
||||||
/// 💬 Chat Icon with Badge
|
/// 💬 Chat Icon with Badge
|
||||||
Builder(builder: (context) {
|
Builder(
|
||||||
|
builder: (context) {
|
||||||
final chatIdStr = item.chatId.toString();
|
final chatIdStr = item.chatId.toString();
|
||||||
final countAsync = ref.watch(countProvider(chatIdStr));
|
final countAsync = ref.watch(
|
||||||
|
countProvider(chatIdStr),
|
||||||
|
);
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@ -214,22 +265,44 @@ class PendingScreen extends ConsumerWidget {
|
|||||||
if (chatid == 0) return;
|
if (chatid == 0) return;
|
||||||
|
|
||||||
if (item.status == 'In Progress') {
|
if (item.status == 'In Progress') {
|
||||||
Get.to(() => LiveChatScreen(
|
Get.to(
|
||||||
|
() => LiveChatScreen(
|
||||||
fileid: item.id.toString(),
|
fileid: item.id.toString(),
|
||||||
chatid: chatid,
|
chatid: chatid,
|
||||||
))?.then((_) {
|
),
|
||||||
ref.read(notificationTriggerProvider.notifier).state++;
|
)?.then((_) {
|
||||||
ref.invalidate(chatMessagesProvider(chatid));
|
ref
|
||||||
ref.invalidate(countProvider(chatIdStr));
|
.read(
|
||||||
|
notificationTriggerProvider
|
||||||
|
.notifier,
|
||||||
|
)
|
||||||
|
.state++;
|
||||||
|
ref.invalidate(
|
||||||
|
chatMessagesProvider(chatid),
|
||||||
|
);
|
||||||
|
ref.invalidate(
|
||||||
|
countProvider(chatIdStr),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Get.to(() => CompletedLiveChatScreen(
|
Get.to(
|
||||||
|
() => CompletedLiveChatScreen(
|
||||||
fileid: item.id.toString(),
|
fileid: item.id.toString(),
|
||||||
chatid: chatid,
|
chatid: chatid,
|
||||||
))?.then((_) {
|
),
|
||||||
ref.read(notificationTriggerProvider.notifier).state++;
|
)?.then((_) {
|
||||||
ref.invalidate(chatMessagesProvider(chatid));
|
ref
|
||||||
ref.invalidate(countProvider(chatIdStr));
|
.read(
|
||||||
|
notificationTriggerProvider
|
||||||
|
.notifier,
|
||||||
|
)
|
||||||
|
.state++;
|
||||||
|
ref.invalidate(
|
||||||
|
chatMessagesProvider(chatid),
|
||||||
|
);
|
||||||
|
ref.invalidate(
|
||||||
|
countProvider(chatIdStr),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -246,7 +319,9 @@ class PendingScreen extends ConsumerWidget {
|
|||||||
color: const Color(0xFF61277A),
|
color: const Color(0xFF61277A),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: Colors.black.withOpacity(0.25),
|
color: Colors.black.withOpacity(
|
||||||
|
0.25,
|
||||||
|
),
|
||||||
blurRadius: 8.08,
|
blurRadius: 8.08,
|
||||||
offset: const Offset(0, 4.14),
|
offset: const Offset(0, 4.14),
|
||||||
),
|
),
|
||||||
@ -268,12 +343,16 @@ class PendingScreen extends ConsumerWidget {
|
|||||||
top: -4,
|
top: -4,
|
||||||
right: -4,
|
right: -4,
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(
|
||||||
decoration: const BoxDecoration(
|
4,
|
||||||
|
),
|
||||||
|
decoration:
|
||||||
|
const BoxDecoration(
|
||||||
color: Colors.red,
|
color: Colors.red,
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
constraints: const BoxConstraints(
|
constraints:
|
||||||
|
const BoxConstraints(
|
||||||
minWidth: 16,
|
minWidth: 16,
|
||||||
minHeight: 16,
|
minHeight: 16,
|
||||||
),
|
),
|
||||||
@ -283,22 +362,24 @@ class PendingScreen extends ConsumerWidget {
|
|||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight:
|
||||||
|
FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink(),
|
: const SizedBox.shrink(),
|
||||||
loading: () => const SizedBox.shrink(),
|
loading: () => const SizedBox.shrink(),
|
||||||
error: (_, __) => const SizedBox.shrink(),
|
error: (_, __) =>
|
||||||
|
const SizedBox.shrink(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}),
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
]
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -432,8 +513,37 @@ class PendingScreen extends ConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () async {
|
||||||
// Add payment functionality here
|
try {
|
||||||
|
final response = await ref
|
||||||
|
.read(apiRepositoryProvider)
|
||||||
|
.payNow(
|
||||||
|
id: int.parse(item.id.toString()),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response['status'] == 'success') {
|
||||||
|
_razorpayService.openCheckout(
|
||||||
|
key: response['razorpay_key'],
|
||||||
|
amount: response['amount'],
|
||||||
|
orderId: response['order_id'],
|
||||||
|
description:
|
||||||
|
"Payment for Service ID: ${item.id}",
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ValidationPopup().showErrorMessage(
|
||||||
|
context,
|
||||||
|
"Failed to initiate payment",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// Error handled in repository/notifier or via snackbar
|
||||||
|
Get.snackbar(
|
||||||
|
'Error',
|
||||||
|
e.toString(),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
colorText: Colors.white,
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
height: height * 0.055,
|
height: height * 0.055,
|
||||||
|
|||||||
16
pubspec.lock
16
pubspec.lock
@ -257,6 +257,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.7"
|
version: "2.0.7"
|
||||||
|
eventify:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: eventify
|
||||||
|
sha256: b829429f08586cc2001c628e7499e3e3c2493a1d895fd73b00ecb23351aa5a66
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -944,6 +952,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.2.0"
|
||||||
|
razorpay_flutter:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: razorpay_flutter
|
||||||
|
sha256: "2057bfaa769813f58bdc23b9cdc4d5ea493e92154f216f1d2edac507d0936b31"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.4"
|
||||||
redux:
|
redux:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
@ -41,6 +41,7 @@ dependencies:
|
|||||||
flutter_local_notifications: ^18.0.1
|
flutter_local_notifications: ^18.0.1
|
||||||
curved_labeled_navigation_bar: ^2.0.6
|
curved_labeled_navigation_bar: ^2.0.6
|
||||||
http_parser: ^4.1.2
|
http_parser: ^4.1.2
|
||||||
|
razorpay_flutter: ^1.4.4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user