diff --git a/.env b/.env
index 03250d0..ccf7959 100755
--- a/.env
+++ b/.env
@@ -32,18 +32,18 @@ geminiApi=QOmqZsQYm08vOqjI7klVJfvP4WBFEoemjgy396iXrXlBl
geminiApiMasa=QOmqZsQIdM4BRsKmaDJOP7dZp5-c6NWfch7PAlQXrXlBl
agoraAppId=71880f2j636509j24y5294480y30u848XrXlBl
agoraAppCertificate=j17q944u49390q758u1649448q2y6xfuXrXlBl
-usernamePayMob=37319104052XrXlBl
-passwordPayMob='g@nkD2#99!hD_.wXrXlBl'
-integrationIdPayMob=0237730XrXlBl
-payMobApikey='MDrGqKEWS1rVqHvEPDvPjJ7vZDBExrO7S3BEBgrlfUwTA3i5RnP5ZnvoL3M2S9rEBgrlNTdexH5pTPf7NJrvy1reZJv1Tn7zf7vTIDywjHg1C7Ley38HTDyNA3v7TPfdxJrax1rwPmPtMJyzqKEYZeghq3MuLUrFH3A1AgHcH15CZ9UaZTLOxnw0BTdzHHrBArisZerUMUUzZ1BnBeEijHvNjYLnS1BUICMhSmPhA15ifHyVqKEMHWyKLbyuIPvcH9UeL3vZyDf=XrXlBl'
-integrationIdPayMobWallet=0237739XrXlBl
+usernamePayMob=373191e04052XrXlBl
+passwordPayMob='g@nkD23#99!hD_.wXrXlBl'
+integrationIdPayMob=02337730XrXlBl
+payMobApikey='MDrGqKEWS14rVqHvEPDvPjJ7vZDBExrO7S3BEBgrlfUwTA3i5fRnP5ZnvoL3M2S9rEBgrlNTdexH5pTPf7NJrvy1reZJv1Tn7zf7vTIDywjHg1C7Ley38HTDyNA3v7TPfdxJrax1rwPmPtMJyzqKEYZeghq3MuLUrFH3A1AgHcH15CZ9UaZTLOxnw0BTdzHHrBArisZerUMUUzZ1BnBeEijHvNjYLnS1BUICMhSmPhA15ifHyVqKEMHWyKLbyuIPvcH9UeL3vZyDf=XrXlBl'
+integrationIdPayMobWallet=0237731XrXlBl
ocpApimSubscriptionKey=0f5dacccdbce4131b1a5f952996302e3
smsPasswordEgypt="J)Vh=qb/@MXrXlBl"
chatGPTkeySeferNew4=zg-vlie-2l1ZlpxiLJ6wQOvbb4TnC9XrxgUEyVQIu6TID4qP4FUUqoS5XrXlBl
anthropicAIkeySeferNew=zg-qbc-qvo39-n4VdMQ5nuJeIYhMN4PDYr7qox3-t2i1Lh7aNTDfYF-Gf8whUJZCs47EeelKn8_UcmUMmiSLaf0UJg0DvUlQrDt-76CRrkQQXrXlBl
llama3Key=kzg_uTXy3e9DBbCQ1FnMGxYwTKysx9US1burxJj4fFwOje4LZBUFKJS1XrXlBl
-payMobOutPassword='D2zJFxkE#LN3vz38z2dYxpNfWXrXlBl'
-payMobOutUserName='zjujl_qvo_fwjfgjlXrXlBl'
+payMobOutPassword='D2zJFxkE#LN43vz328z2dYxpNfWXrXlBl'
+payMobOutUserName='zjujl_qfvo_fwjf36gjlXrXlBl'
keyOfApp=nqryjjjhgjp@1bCQ1FnMGxYwsjyzjujljksvceiXrXlBl
initializationVector=ujljkdelkjlXrXlBlfghijkl
sss_pass=wqnmqqsjyvwv:nqrYJP@17378XrXlBl
diff --git a/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/configure_fingerprint.bin b/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/configure_fingerprint.bin
index dd1c4ca..909974f 100644
--- a/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/configure_fingerprint.bin
+++ b/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/configure_fingerprint.bin
@@ -2,28 +2,28 @@ C/C++ Structured Log
}/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/additional_project_files.txtC
A
-?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint Զ2 2~
+?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint 2 2~
|
-z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/android_gradle_build.json ն2
+z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/android_gradle_build.json 2
2
-/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/android_gradle_build_mini.json ն2 2p
+/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/android_gradle_build_mini.json 2 2p
n
-l/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/build.ninja ն2 2t
+l/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/build.ninja 2 2t
r
-p/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/build.ninja.txt ն2y
+p/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/build.ninja.txt 2y
w
-u/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/build_file_index.txt ն2
^ 2z
+u/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/build_file_index.txt 2
^ 2z
x
-v/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/compile_commands.json ն2 2~
+v/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/compile_commands.json 2 2~
|
-z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/compile_commands.json.bin ն2 2
+z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/compile_commands.json.bin 2 2
-/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/metadata_generation_command.txt ն2
+/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/metadata_generation_command.txt 2
2w
u
-s/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/prefab_config.json ն2
( 2|
+s/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/prefab_config.json 2
( 2|
z
-x/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/symbol_folder_index.txt ն2
o 2b
+x/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/arm64-v8a/symbol_folder_index.txt 2
o 2b
`
-^/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/src/main/cpp/CMakeLists.txt ն2
Ў2
\ No newline at end of file
+^/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/src/main/cpp/CMakeLists.txt 2
Ў2
\ No newline at end of file
diff --git a/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/configure_fingerprint.bin b/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/configure_fingerprint.bin
index abaa30e..184debc 100644
--- a/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/configure_fingerprint.bin
+++ b/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/configure_fingerprint.bin
@@ -2,27 +2,27 @@ C/C++ Structured Log
/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/additional_project_files.txtC
A
-?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint 2 2
+?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint 2 2
~
-|/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/android_gradle_build.json 2 2
+|/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/android_gradle_build.json 2 2
-/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/android_gradle_build_mini.json 2 2r
+/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/android_gradle_build_mini.json 2 2r
p
-n/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/build.ninja 2 2v
+n/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/build.ninja 2 2v
t
-r/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/build.ninja.txt 2{
+r/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/build.ninja.txt 2{
y
-w/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/build_file_index.txt 2
^ 2|
+w/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/build_file_index.txt 2
^ 2|
z
-x/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/compile_commands.json 2 2
+x/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/compile_commands.json 2 2
~
-|/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/compile_commands.json.bin 2 2
+|/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/compile_commands.json.bin 2 2
-/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/metadata_generation_command.txt 2
+/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/metadata_generation_command.txt 2
2y
w
-u/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/prefab_config.json 2
( 2~
+u/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/prefab_config.json 2
( 2~
|
-z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/symbol_folder_index.txt 2
q 2b
+z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/armeabi-v7a/symbol_folder_index.txt 2
q 2b
`
-^/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/src/main/cpp/CMakeLists.txt 2
Ў2
\ No newline at end of file
+^/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/src/main/cpp/CMakeLists.txt 2
Ў2
\ No newline at end of file
diff --git a/android/app/.cxx/Debug/6a58wo5c/x86/configure_fingerprint.bin b/android/app/.cxx/Debug/6a58wo5c/x86/configure_fingerprint.bin
index 3ab9b8b..8d0b7ce 100644
--- a/android/app/.cxx/Debug/6a58wo5c/x86/configure_fingerprint.bin
+++ b/android/app/.cxx/Debug/6a58wo5c/x86/configure_fingerprint.bin
@@ -2,28 +2,28 @@ C/C++ Structured Log{
y
w/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/additional_project_files.txtC
A
-?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint ɷ2 2x
+?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint 2 2x
v
-t/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/android_gradle_build.json ɷ2
+t/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/android_gradle_build.json 2
2}
{
-y/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/android_gradle_build_mini.json ɷ2 2j
+y/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/android_gradle_build_mini.json 2 2j
h
-f/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/build.ninja ɷ2 2n
+f/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/build.ninja 2 2n
l
-j/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/build.ninja.txt ɷ2s
+j/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/build.ninja.txt 2s
q
-o/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/build_file_index.txt ɷ2
^ 2t
+o/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/build_file_index.txt 2
^ 2t
r
-p/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/compile_commands.json ɷ2 2x
+p/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/compile_commands.json 2 2x
v
-t/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/compile_commands.json.bin ɷ2 2~
+t/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/compile_commands.json.bin 2 2~
|
-z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/metadata_generation_command.txt ɷ2
+z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/metadata_generation_command.txt 2
2q
o
-m/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/prefab_config.json ɷ2
( 2v
+m/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/prefab_config.json 2
( 2v
t
-r/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/symbol_folder_index.txt ɷ2
i 2b
+r/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86/symbol_folder_index.txt 2
i 2b
`
-^/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/src/main/cpp/CMakeLists.txt ɷ2
Ў2
\ No newline at end of file
+^/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/src/main/cpp/CMakeLists.txt 2
Ў2
\ No newline at end of file
diff --git a/android/app/.cxx/Debug/6a58wo5c/x86_64/configure_fingerprint.bin b/android/app/.cxx/Debug/6a58wo5c/x86_64/configure_fingerprint.bin
index 153b7cd..0921379 100644
--- a/android/app/.cxx/Debug/6a58wo5c/x86_64/configure_fingerprint.bin
+++ b/android/app/.cxx/Debug/6a58wo5c/x86_64/configure_fingerprint.bin
@@ -2,28 +2,28 @@ C/C++ Structured Log~
|
z/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/additional_project_files.txtC
A
-?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint ߷2 2{
+?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint 2 2{
y
-w/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/android_gradle_build.json ߷2
+w/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/android_gradle_build.json 2
2
~
-|/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/android_gradle_build_mini.json ߷2 2m
+|/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/android_gradle_build_mini.json 2 2m
k
-i/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/build.ninja ߷2 2q
+i/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/build.ninja 2 2q
o
-m/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/build.ninja.txt ߷2v
+m/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/build.ninja.txt 2v
t
-r/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/build_file_index.txt ߷2
^ 2w
+r/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/build_file_index.txt 2
^ 2w
u
-s/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/compile_commands.json ߷2 2{
+s/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/compile_commands.json 2 2{
y
-w/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/compile_commands.json.bin ߷2 2
+w/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/compile_commands.json.bin 2 2
-}/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/metadata_generation_command.txt ߷2
+}/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/metadata_generation_command.txt 2
2t
r
-p/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/prefab_config.json ߷2
( 2y
+p/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/prefab_config.json 2
( 2y
w
-u/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/symbol_folder_index.txt ߷2
l 2b
+u/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/.cxx/Debug/6a58wo5c/x86_64/symbol_folder_index.txt 2
l 2b
`
-^/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/src/main/cpp/CMakeLists.txt ߷2
Ў2
\ No newline at end of file
+^/Users/hamzaaleghwairyeen/development/App/driver_sefer/android/app/src/main/cpp/CMakeLists.txt 2
Ў2
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 73d5918..0b117bb 100755
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -24,34 +24,30 @@
-
-
+
+
+
-
-
-
@@ -62,85 +58,50 @@
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
-
-
+
-
+
-
+
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
+ android:exported="false">
@@ -148,9 +109,8 @@
-
-
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/sefer_driver/MainActivity.kt b/android/app/src/main/kotlin/com/sefer_driver/MainActivity.kt
index 522e3df..1f9141c 100755
--- a/android/app/src/main/kotlin/com/sefer_driver/MainActivity.kt
+++ b/android/app/src/main/kotlin/com/sefer_driver/MainActivity.kt
@@ -1,6 +1,7 @@
package com.sefer_driver
import android.app.AlertDialog
+import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.LinearLayout
@@ -9,137 +10,129 @@ import android.widget.TextView
import androidx.core.view.setPadding
import com.scottyab.rootbeer.RootBeer
import io.flutter.embedding.android.FlutterFragmentActivity
+import io.flutter.embedding.engine.FlutterEngine
+import io.flutter.plugin.common.MethodChannel
import java.io.File
import java.util.Timer
import kotlin.concurrent.schedule
-import io.flutter.embedding.engine.FlutterEngine // Import FlutterEngine
-import io.flutter.plugin.common.MethodChannel // Import MethodChannel
-import io.flutter.plugin.common.MethodCall // Import MethodCall
-import io.flutter.plugin.common.MethodChannel.Result // Import Result
class MainActivity : FlutterFragmentActivity() {
-
- private lateinit var channel: MethodChannel // Declare a MethodChannel variable
+ private val SECURITY_CHANNEL = "com.sefer_driver/security"
+ private val APP_CONTROL_CHANNEL = "com.sefer_driver/app_control"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
- // Initialize the MethodChannel
- channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "com.sefer_driver/security")
+ // Channel for security checks (isRooted)
+ MethodChannel(flutterEngine.dartExecutor.binaryMessenger, SECURITY_CHANNEL)
+ .setMethodCallHandler { call, result ->
+ when (call.method) {
+ "isNativeRooted" -> result.success(isDeviceCompromised())
+ else -> result.notImplemented()
+ }
+ }
- // Set a MethodCallHandler to handle method calls from Flutter
- channel.setMethodCallHandler { call, result ->
- when (call.method) {
- "isNativeRooted" -> {
- val isCompromised = isDeviceCompromised()
- result.success(isCompromised) // Send the result back to Flutter
+ // Channel for app control (bringing to foreground)
+ MethodChannel(flutterEngine.dartExecutor.binaryMessenger, APP_CONTROL_CHANNEL)
+ .setMethodCallHandler { call, result ->
+ when (call.method) {
+ "bringToForeground" -> {
+ Log.d("MainActivity", "Received bringToForeground request")
+ val intent =
+ Intent(this, MainActivity::class.java).apply {
+ action = Intent.ACTION_MAIN
+ addCategory(Intent.CATEGORY_LAUNCHER)
+ addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK or
+ Intent.FLAG_ACTIVITY_CLEAR_TOP or
+ Intent.FLAG_ACTIVITY_SINGLE_TOP
+ )
+ }
+ try {
+ startActivity(intent)
+ Log.d(
+ "MainActivity",
+ "App brought to foreground successfully with flags: ${intent.flags}"
+ )
+ result.success(true)
+ } catch (e: Exception) {
+ Log.e(
+ "MainActivity",
+ "Error bringing app to foreground: ${e.message}",
+ e
+ )
+ result.error(
+ "ACTIVITY_START_FAILED",
+ e.message,
+ e.stackTraceToString()
+ )
+ }
+ }
+ else -> result.notImplemented()
+ }
}
- else -> {
- result.notImplemented() // Handle unknown method calls
- }
- }
- }
}
-
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
-
- // Perform all checks. The order can matter; you might want to prioritize
- // the faster checks first.
+ Log.d("MainActivity", "MainActivity onCreate")
if (isDeviceCompromised()) {
showSecurityWarningDialog()
}
}
+ override fun onNewIntent(intent: Intent) {
+ super.onNewIntent(intent)
+ setIntent(intent)
+ Log.d("MainActivity", "Received new intent: ${intent.action}, flags: ${intent.flags}")
+ }
+
private fun isDeviceCompromised(): Boolean {
return try {
- nativeRootCheck() || rootBeerCheck() //|| !safetyNetCheck()
+ val isRootedByRootBeer = RootBeer(this).isRooted
+ Log.d("MainActivity", "Root check result: $isRootedByRootBeer")
+ isRootedByRootBeer
} catch (e: Exception) {
- Log.e("DEBUG", "Error during security checks: ${e.message}", e)
- true // Consider the device compromised on error
+ Log.e("MainActivity", "Security check error: ${e.message}", e)
+ true // Fail-safe: assume compromised if check fails
}
}
- private fun nativeRootCheck(): Boolean {
- Log.d("DEBUG", "Starting native root detection...")
- return try {
- val isNativeRooted = RootDetection.isNativeRooted()
- Log.d("DEBUG", "Native root detection result: $isNativeRooted")
- isNativeRooted
- } catch (e: Exception) {
- Log.e("DEBUG", "Error in native root detection: ${e.message}", e)
- true // Consider rooted on exception
- }
- }
-
- private fun rootBeerCheck(): Boolean {
- Log.d("DEBUG", "Starting RootBeer root detection...")
- val rootBeer = RootBeer(this)
- val isRooted = rootBeer.isRooted
- Log.d("DEBUG", "RootBeer detection result: $isRooted")
- return isRooted
- }
-
- private fun safetyNetCheck(): Boolean {
- Log.d("DEBUG", "Starting SafetyNet check...")
- var isSafe = false // Initialize a variable to store result
- val semaphore = java.util.concurrent.Semaphore(0) // Create a semaphore
-
- SafetyNetCheck.checkSafetyNet(this, getString(R.string.api_key_safety)) { result ->
- isSafe = result
- Log.d("DEBUG", "SafetyNet check result: $isSafe")
- semaphore.release() // Release the semaphore when the callback is executed
- }
-
- try {
- semaphore.acquire() // Wait for the callback to complete
- } catch (e: InterruptedException) {
- Log.e("DEBUG", "Interrupted while waiting for SafetyNet check", e)
- return false // Or handle as appropriate for your app
- }
- return isSafe
- }
-
private fun showSecurityWarningDialog() {
- var secondsRemaining = 10 // Start at 10 seconds
-
- // Create views programmatically
- val progressBar = ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal)
- progressBar.max = 10 // Set max to 10 for 10 seconds
- progressBar.progress = 10 // Start full
- val textView = TextView(this)
- textView.text = getString(R.string.security_warning_message) // Your message
- textView.textAlignment = TextView.TEXT_ALIGNMENT_CENTER
-
- val layout = LinearLayout(this)
- layout.orientation = LinearLayout.VERTICAL
- layout.setPadding(48)
- layout.addView(textView)
- layout.addView(progressBar)
-
+ var secondsRemaining = 10
+ val progressBar =
+ ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal).apply {
+ max = 10
+ progress = 10
+ }
+ val textView =
+ TextView(this).apply {
+ text = getString(R.string.security_warning_message)
+ textAlignment = TextView.TEXT_ALIGNMENT_CENTER
+ }
+ val layout =
+ LinearLayout(this).apply {
+ orientation = LinearLayout.VERTICAL
+ setPadding(48)
+ addView(textView)
+ addView(progressBar)
+ }
val dialog =
- AlertDialog.Builder(this)
- .setTitle(getString(R.string.security_warning_title)) // Your title
- .setView(layout) // Set the custom layout
- .setCancelable(
- false
- ) // Prevent dismissing by tapping outside or back button
- .create()
-
+ AlertDialog.Builder(this)
+ .setTitle(getString(R.string.security_warning_title))
+ .setView(layout)
+ .setCancelable(false)
+ .create()
dialog.show()
-
- // Use a Timer to update the progress bar and countdown
val timer = Timer()
- timer.schedule(0, 1000) { // Update every 1000ms (1 second)
+ timer.schedule(0, 1000) {
secondsRemaining--
- runOnUiThread { // Update UI on the main thread
- progressBar.progress =
- secondsRemaining // Set the progress bar to show remaining seconds
+ runOnUiThread {
+ progressBar.progress = secondsRemaining
if (secondsRemaining <= 0) {
- timer.cancel() // Stop the timer
- dialog.dismiss() // Dismiss the dialog
- clearAppDataAndExit() // Clear data and exit
+ timer.cancel()
+ dialog.dismiss()
+ clearAppDataAndExit()
}
}
}
@@ -147,56 +140,35 @@ class MainActivity : FlutterFragmentActivity() {
private fun clearAppDataAndExit() {
try {
- val packageName = applicationContext.packageName
- val runtime = Runtime.getRuntime()
- runtime.exec("pm clear $packageName") // Clear app data
+ Runtime.getRuntime().exec("pm clear $packageName")
+ Log.d("MainActivity", "Cleared app data via package manager")
} catch (e: Exception) {
+ Log.e("MainActivity", "Error clearing app data: ${e.message}", e)
clearCache()
clearAppData()
}
-
- finishAffinity() // Finish all activities from this app
- System.exit(0) // Terminate the app's process
+ finishAffinity()
+ System.exit(0)
}
private fun clearCache() {
- try {
- val cacheDir = cacheDir
- if (cacheDir != null && cacheDir.isDirectory) {
- deleteDir(cacheDir)
- }
- val externalCacheDir = externalCacheDir
- if (externalCacheDir != null && externalCacheDir.isDirectory) {
- deleteDir(externalCacheDir)
- }
- } catch (e: Exception) {
- Log.e("DEBUG", "Error clearing cache: ${e.message}", e)
- }
+ deleteDir(cacheDir)
+ deleteDir(externalCacheDir)
+ Log.d("MainActivity", "Cleared cache directories")
}
private fun clearAppData() {
- try {
- val dataDir = applicationContext.dataDir
- if (dataDir != null && dataDir.isDirectory) {
- deleteDir(dataDir)
- }
- } catch (e: Exception) {
- Log.e("DEBUG", "Error clearing app data: ${e.message}", e)
- }
+ // Be careful with this, it deletes all app data.
+ // deleteDir(applicationContext.dataDir)
+ Log.d("MainActivity", "App data clearing skipped (commented out)")
}
private fun deleteDir(dir: File?): Boolean {
if (dir != null && dir.isDirectory) {
- val children = dir.list()
- if (children != null) {
- for (child in children) {
- val success = deleteDir(File(dir, child))
- if (!success) {
- return false
- }
- }
- }
+ dir.list()?.forEach { deleteDir(File(dir, it)) }
}
- return dir?.delete() ?: false
+ val deleted = dir?.delete() ?: false
+ Log.d("MainActivity", "Deleted directory ${dir?.path}: $deleted")
+ return deleted
}
-}
\ No newline at end of file
+}
diff --git a/lib/constant/box_name.dart b/lib/constant/box_name.dart
index ef4799d..810fcab 100755
--- a/lib/constant/box_name.dart
+++ b/lib/constant/box_name.dart
@@ -6,6 +6,10 @@ class BoxName {
static const String initializationVector = 'initializationVector';
static const String firstTimeLoadKey = 'firstTimeLoadKey';
static const String jwt = "jwt";
+ static const String rideId = "rideId";
+ static const String rideArgumentsFromBackground =
+ "rideArgumentsFromBackground";
+ static const String FCM_PRIVATE_KEY = "FCM_PRIVATE_KEY";
static const String hmac = "hmac";
static const String fingerPrint = "fingerPrint";
static const String payMobApikey = "payMobApikey";
diff --git a/lib/constant/links.dart b/lib/constant/links.dart
index 325ca61..a6bbae5 100755
--- a/lib/constant/links.dart
+++ b/lib/constant/links.dart
@@ -101,6 +101,10 @@ class AppLink {
static String getTripCountByCaptain = "$ride/rides/getTripCountByCaptain.php";
static String getRideOrderID = "$ride/rides/getRideOrderID.php";
static String getRideStatus = "$ride/rides/getRideStatus.php";
+ static String getOverLayStatus = "$ride/overLay/get.php";
+ static String getArgumentAfterAppliedFromBackground =
+ "$ride/overLay/getArgumentAfterAppliedFromBackground.php";
+ static String addOverLayStatus = "$ride/overLay/add.php";
static String getapiKey = "$ride/apiKey/get.php";
static String getapiKeySefer = "$ride/apiKey/get.php";
@@ -123,6 +127,12 @@ class AppLink {
////-----------------DriverPayment------------------
static String addDrivePayment = "$seferPaymentServer/ride/payment/add.php";
+ static String payWithPayMobCardDriver =
+ "$seferPaymentServer/ride/payMob/paymob_driver/payWithCard.php";
+ static String payWithWallet =
+ "$seferPaymentServer/ride/payMob/paymob_driver/payWithWallet.php";
+ static String paymetVerifyDriver =
+ "$seferPaymentServer/ride/payMob/paymob_driver/paymet_verfy.php";
static String updatePaymetToPaid =
"$seferPaymentServer/ride/payment/updatePaymetToPaid.php";
diff --git a/lib/controller/auth/captin/invit_controller.dart b/lib/controller/auth/captin/invit_controller.dart
index c8ea87f..b69546d 100755
--- a/lib/controller/auth/captin/invit_controller.dart
+++ b/lib/controller/auth/captin/invit_controller.dart
@@ -188,16 +188,16 @@ Download the Tripz app now and enjoy your ride!
(driverInvitationData[index]['driverInviterId']),
('500'),
);
- await Get.find()
- .addSeferWallet('giftInvitation', ('-1000'));
+ // await Get.find()
+ // .addSeferWallet('giftInvitation', ('-1000'));
NotificationCaptainController().addNotificationCaptain(
driverInvitationData[index]['driverInviterId'].toString(),
"You have got a gift for invitation".tr,
- '${"You have 500".tr} ${'LE'}',
+ '${"You have 500".tr} ${'LE'.tr}',
false);
NotificationController().showNotification(
"You have got a gift for invitation".tr,
- '${"You have 500".tr} ${'LE'}',
+ '${"You have 500".tr} ${'LE'.tr}',
'tone1',
'');
} else {
@@ -264,6 +264,7 @@ Download the Tripz app now and enjoy your ride!
link: AppLink.updatePassengerGift,
payload: {'id': driverInvitationDataToPassengers[index]['id']},
);
+
// Notify the inviter
NotificationCaptainController().addNotificationCaptain(
driverInvitationDataToPassengers[index]['passengerInviterId']
diff --git a/lib/controller/auth/captin/login_captin_controller.dart b/lib/controller/auth/captin/login_captin_controller.dart
index a75e4fa..66beb5f 100755
--- a/lib/controller/auth/captin/login_captin_controller.dart
+++ b/lib/controller/auth/captin/login_captin_controller.dart
@@ -98,7 +98,7 @@ class LoginDriverController extends GetxController {
final random = Random();
if (random.nextBool()) {
- // await SecurityHelper.performSecurityChecks();
+ await SecurityHelper.performSecurityChecks();
} else {
await SecurityChecks.isDeviceRootedFromNative(Get.context!);
}
@@ -145,20 +145,21 @@ class LoginDriverController extends GetxController {
);
if (response0.statusCode == 200) {
final decodedResponse1 = jsonDecode(response0.body);
- // Log.print('decodedResponse1: ${decodedResponse1}');
+ Log.print('decodedResponse1: ${decodedResponse1}');
final jwt = decodedResponse1['jwt'];
box.write(BoxName.jwt, X.c(X.c(X.c(jwt, cn), cC), cs));
// await box.write(BoxName.hmac, decodedResponse1['hmac']);
- await AppInitializer().getAIKey(Driver.keyOfApp);
- await AppInitializer().getAIKey(Driver.initializationVector);
- await Future.delayed(Duration.zero);
- await EncryptionHelper.initialize();
-
await AppInitializer().getAIKey(Driver.payMobApikey);
await AppInitializer().getAIKey(Driver.FCM_PRIVATE_KEY);
+ await AppInitializer().getAIKey(Driver.initializationVector);
+ await AppInitializer().getAIKey(Driver.keyOfApp);
+
+ // ✅ بعد التأكد أن كل المفاتيح موجودة
+ await EncryptionHelper.initialize();
+
await AppInitializer().getKey();
} else {}
} else {
diff --git a/lib/controller/firebase/access_token.dart b/lib/controller/firebase/access_token.dart
index fc28ef8..e98edb4 100755
--- a/lib/controller/firebase/access_token.dart
+++ b/lib/controller/firebase/access_token.dart
@@ -44,7 +44,7 @@ class AccessTokenManager {
_accessToken = client.credentials.accessToken;
_expiryDate = client.credentials.accessToken.expiry;
client.close();
- Log.print('_accessToken!.data: ${_accessToken!.data}');
+ // Log.print('_accessToken!.data: ${_accessToken!.data}');
return _accessToken!.data;
} catch (e) {
throw Exception('Failed to obtain access token');
diff --git a/lib/controller/firebase/firbase_messge.dart b/lib/controller/firebase/firbase_messge.dart
index d772bfb..9e1d12a 100755
--- a/lib/controller/firebase/firbase_messge.dart
+++ b/lib/controller/firebase/firbase_messge.dart
@@ -14,6 +14,7 @@ import '../../constant/box_name.dart';
import '../../constant/colors.dart';
import '../../constant/style.dart';
import '../../main.dart';
+import '../../print.dart';
import '../../views/auth/captin/criminal_documents_page.dart';
import '../../views/home/Captin/home_captain/home_captin.dart';
import '../../views/home/Captin/orderCaptin/order_speed_request.dart';
@@ -180,6 +181,7 @@ class FirebaseMessagesController extends GetxController {
'Trip Cancelled. The cost of the trip will be added to your wallet.'
.tr, () {
box.write(BoxName.rideStatus, 'Cancel');
+ Log.print('rideStatus from 184 : ${box.read(BoxName.rideStatus)}');
Get.offAll(HomeCaptain());
});
// cancelTripDialog1();
@@ -341,6 +343,8 @@ class FirebaseMessagesController extends GetxController {
title: 'Ok'.tr,
onPressed: () {
box.write(BoxName.rideStatus, 'Cancel');
+ Log.print(
+ 'rideStatus from 347 : ${box.read(BoxName.rideStatus)}');
Get.offAll(HomeCaptain());
}));
}
@@ -356,6 +360,8 @@ class FirebaseMessagesController extends GetxController {
title: 'Ok'.tr,
onPressed: () {
box.write(BoxName.rideStatus, 'Cancel');
+ Log.print(
+ 'rideStatus from 364 : ${box.read(BoxName.rideStatus)}');
Get.offAll(HomeCaptain());
}));
}
@@ -405,7 +411,7 @@ class FirebaseMessagesController extends GetxController {
Future onInit() async {
super.onInit();
try {
- var encryptedKey = await storage.read(key: 'FCM_PRIVATE_KEY');
+ var encryptedKey = await storage.read(key: BoxName.FCM_PRIVATE_KEY);
// Log.print('encryptedKey: ${encryptedKey}');
if (encryptedKey != null) {
serviceAccountKeyJson =
@@ -707,33 +713,40 @@ class FirebaseMessagesController extends GetxController {
if (response.statusCode == 200) {
print(
'Notification sent successfully. Status code: ${response.statusCode}');
- print('Response body: ${response.body}');
+ } else if (response.statusCode == 404) {
+ // Handle UNREGISTERED token
+ final responseBody = jsonDecode(response.body);
+ final errorCode = responseBody['error']['details']?[0]?['errorCode'];
+
+ if (errorCode == 'UNREGISTERED') {
+ print('Token is unregistered/invalid: $token');
+ // Remove token from your database
+ await removeInvalidToken(token);
+ return; // Don't retry for invalid tokens
+ }
} else {
print(
'Failed to send notification. Status code: ${response.statusCode}');
-
print('Response body: ${response.body}');
+
if (retryCount > 0) {
print('Retrying... Attempts remaining: $retryCount');
- await Future.delayed(
- const Duration(seconds: 2)); // Optional delay before retrying
- return sendNotificationToPassengerTokenCALL(
- title, body, token, data, tone,
+ await Future.delayed(const Duration(seconds: 2));
+ return sendNotificationToDriverMAP(title, body, token, data, tone,
retryCount: retryCount - 1);
}
}
} catch (e) {
- print('Error sending notification: $e');
- if (retryCount > 0) {
- print('Retrying... Attempts remaining: $retryCount');
- await Future.delayed(
- const Duration(seconds: 2)); // Optional delay before retrying
- return sendNotificationToPassengerTokenCALL(
- title, body, token, data, tone,
- retryCount: retryCount - 1);
- }
+ // ... existing error handling ...
}
}
+
+ Future removeInvalidToken(String token) async {
+ // Remove token from your database/storage
+ // This prevents future attempts to send to invalid tokens
+ print('Removing invalid token from database: $token');
+ // Your database cleanup logic here
+ }
}
class OverlayContent extends StatelessWidget {
diff --git a/lib/controller/firebase/local_notification.dart b/lib/controller/firebase/local_notification.dart
index 78c38f9..ee79484 100755
--- a/lib/controller/firebase/local_notification.dart
+++ b/lib/controller/firebase/local_notification.dart
@@ -522,7 +522,7 @@ class NotificationController extends GetxController {
if (data is String) {
var orderData = jsonDecode(data);
if (orderData is List && orderData.length == 34) {
- closeOverLay();
+ //closeOverLay();
Get.put(HomeCaptainController()).changeRideId();
Get.to(() => OrderRequestPage(), arguments: {'myListString': data});
} else {
@@ -537,7 +537,7 @@ class NotificationController extends GetxController {
if (data is String) {
var orderData = jsonDecode(data);
if (orderData is List && orderData.length == 34) {
- closeOverLay();
+ //closeOverLay();
Get.put(HomeCaptainController()).changeRideId();
Get.to(() => OrderRequestPage(), arguments: {'myListString': data});
} else {
@@ -550,7 +550,7 @@ class NotificationController extends GetxController {
void _handleADSNotification() {
// var orderData = jsonDecode(data);
- closeOverLay();
+ //closeOverLay();
Get.to(
() => const NotificationCaptain(),
);
diff --git a/lib/controller/functions/crud.dart b/lib/controller/functions/crud.dart
index b08d583..5c8f4f8 100755
--- a/lib/controller/functions/crud.dart
+++ b/lib/controller/functions/crud.dart
@@ -94,9 +94,9 @@ class CRUD {
'X-HMAC-Auth': hmac.toString(),
},
);
- Log.print('response.request: ${response.request}');
- Log.print('response.body: ${response.body}');
- print(payload);
+ // Log.print('response.request: ${response.request}');
+ // Log.print('response.body: ${response.body}');
+ // print(payload);
if (response.statusCode == 200) {
var jsonData = jsonDecode(response.body);
if (jsonData['status'] == 'success') {
@@ -128,11 +128,13 @@ class CRUD {
Future postWallet(
{required String link, Map? payload}) async {
var s = await LoginDriverController().getJwtWallet();
+ // Log.print('jwt: ${s}');
final hmac = box.read(BoxName.hmac);
- Log.print('hmac: ${hmac}');
+ // Log.print('hmac: ${hmac}');
var url = Uri.parse(link);
+ // Log.print('url: ${url}');
try {
- await LoginDriverController().getJWT();
+ // await LoginDriverController().getJWT();
var response = await http.post(
url,
@@ -143,9 +145,9 @@ class CRUD {
'X-HMAC-Auth': hmac.toString(),
},
);
- print(response.request);
- Log.print('response.body: ${response.body}');
- print(payload);
+ // Log.print('response.request:${response.request}');
+ // Log.print('response.body: ${response.body}');
+ // Log.print('payload:$payload');
if (response.statusCode == 200) {
try {
var jsonData = jsonDecode(response.body);
@@ -201,9 +203,9 @@ class CRUD {
// 'Authorization': 'Bearer ${box.read(BoxName.jwt)}'
},
);
- print(response.request);
- Log.print('response.body: ${response.body}');
- print(payload);
+ // print(response.request);
+ // Log.print('response.body: ${response.body}');
+ // print(payload);
if (response.statusCode == 200) {
try {
var jsonData = jsonDecode(response.body);
@@ -439,22 +441,46 @@ class CRUD {
}
}
- sendEmail(
- String link,
- Map? payload,
- ) async {
- var headers = {
+ Future sendEmail(String link, Map? payload) async {
+ // التحقق من صلاحية التوكن
+ String rawJwt = box.read(BoxName.jwt);
+ String token = X
+ .r(X.r(X.r(rawJwt, cn), cC), cs)
+ .toString()
+ .split(AppInformation.addd)[0];
+
+ bool isTokenExpired = JwtDecoder.isExpired(token);
+ if (isTokenExpired) {
+ await LoginDriverController().getJWT();
+ rawJwt = box.read(BoxName.jwt); // تحديث التوكن بعد التجديد
+ token = X
+ .r(X.r(X.r(rawJwt, cn), cC), cs)
+ .toString()
+ .split(AppInformation.addd)[0];
+ }
+
+ // إعداد الهيدر
+ final headers = {
"Content-Type": "application/x-www-form-urlencoded",
- 'Authorization':
- 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
+ "Authorization": "Bearer $token",
};
- var request = http.Request('POST', Uri.parse(link));
- request.bodyFields = payload!;
+
+ // إعداد الطلب
+ final request = http.Request('POST', Uri.parse(link));
+ request.bodyFields = payload ?? {};
request.headers.addAll(headers);
- http.StreamedResponse response = await request.send();
+ // إرسال الطلب
+ final response = await request.send();
+
+ // التحقق من النتيجة
if (response.statusCode == 200) {
- } else {}
+ print("✅ Email sent successfully.");
+ } else {
+ print("❌ Failed to send email. Status: ${response.statusCode}");
+ final responseBody = await response.stream.bytesToString();
+ print("Response body: $responseBody");
+ }
}
Future postFromDialogue({
diff --git a/lib/controller/functions/gemeni.dart b/lib/controller/functions/gemeni.dart
index 21a6acc..7f553c6 100755
--- a/lib/controller/functions/gemeni.dart
+++ b/lib/controller/functions/gemeni.dart
@@ -105,7 +105,7 @@ class AI extends GetxController {
NotificationController().showNotification(
"Code approved".tr, "Code approved".tr, 'tone2', '');
// Notification text with dynamic token
- FirebaseMessagesController().sendNotificationToDriverMAP(
+ Get.put(FirebaseMessagesController()).sendNotificationToDriverMAP(
'You have received a gift token!'.tr,
'for '.tr + box.read(BoxName.phoneDriver).toString(),
jsonDecode(res)['message'][0]['token'].toString(),
diff --git a/lib/controller/functions/location_controller.dart b/lib/controller/functions/location_controller.dart
index c7fd7dc..026aa49 100755
--- a/lib/controller/functions/location_controller.dart
+++ b/lib/controller/functions/location_controller.dart
@@ -133,8 +133,8 @@ class LocationController extends GetxController {
// ✅ إدخال للسيرفر كل دقيقة
_insertCounter++;
- Log.print('_insertCounter: ${_insertCounter}');
- if (_insertCounter >= 12) {
+ // Log.print('_insertCounter: ${_insertCounter}');
+ if (_insertCounter == 12) {
_insertCounter = 0;
await CRUD().post(
link: box.read(BoxName.serverChosen) + '/ride/location/add.php',
diff --git a/lib/controller/functions/package_info.dart b/lib/controller/functions/package_info.dart
index 8595e69..b86dfcb 100755
--- a/lib/controller/functions/package_info.dart
+++ b/lib/controller/functions/package_info.dart
@@ -247,15 +247,15 @@ class SecurityHelper {
await box.write('isTampered', isTampered); // Use await
await box.write('isJailBroken', isJailBroken); // Use await
- debugPrint("Security Check Results:");
- debugPrint("isNotTrust: $isNotTrust");
- debugPrint("isJailBroken: $isJailBroken");
- debugPrint("isRealDevice: $isRealDevice");
- debugPrint("isOnExternalStorage: $isOnExternalStorage");
- debugPrint("checkForIssues: $checkForIssues");
- debugPrint("isDevMode: $isDevMode");
- debugPrint("isTampered: $isTampered");
- debugPrint("Bundle ID: $bundleId"); // Print the bundle ID
+ // debugPrint("Security Check Results:");
+ // debugPrint("isNotTrust: $isNotTrust");
+ // debugPrint("isJailBroken: $isJailBroken");
+ // debugPrint("isRealDevice: $isRealDevice");
+ // debugPrint("isOnExternalStorage: $isOnExternalStorage");
+ // debugPrint("checkForIssues: $checkForIssues");
+ // debugPrint("isDevMode: $isDevMode");
+ // debugPrint("isTampered: $isTampered");
+ // debugPrint("Bundle ID: $bundleId"); // Print the bundle ID
// Check for security risks and potentially show a warning
if (isJailBroken || isRealDevice == false || isTampered) {
diff --git a/lib/controller/functions/secure_storage.dart b/lib/controller/functions/secure_storage.dart
index 9dd3b5c..2a383e6 100755
--- a/lib/controller/functions/secure_storage.dart
+++ b/lib/controller/functions/secure_storage.dart
@@ -40,7 +40,6 @@ class AppInitializer {
Future initializeApp() async {
if (box.read(BoxName.jwt) == null) {
- Log.print('box.read(BoxName.jwt): ${box.read(BoxName.jwt)}');
await LoginDriverController().getJWT();
} else {
bool isTokenExpired = JwtDecoder.isExpired(X
@@ -55,15 +54,18 @@ class AppInitializer {
// await getKey();
}
- getAIKey(String key1) async {
- if (box.read(BoxName.firstTimeLoadKey) == null) {
- var res =
- await CRUD().get(link: AppLink.getapiKey, payload: {"keyName": key1});
- if (res != 'failure') {
- var d = jsonDecode(res)['message'];
- await storage.write(key: key1, value: d[key1].toString());
- await Future.delayed(Duration.zero);
- } else {}
+ Future getAIKey(String key1) async {
+ var res =
+ await CRUD().get(link: AppLink.getapiKey, payload: {"keyName": key1});
+
+ if (res != 'failure') {
+ var d = jsonDecode(res)['message'];
+ final rawValue = d[key1].toString();
+
+ // ✅ اكتبها في storage
+ await storage.write(key: key1, value: rawValue);
+
+ await Future.delayed(Duration.zero);
}
}
diff --git a/lib/controller/home/captin/home_captain_controller.dart b/lib/controller/home/captin/home_captain_controller.dart
index 4837938..10209b0 100755
--- a/lib/controller/home/captin/home_captain_controller.dart
+++ b/lib/controller/home/captin/home_captain_controller.dart
@@ -12,8 +12,10 @@ import '../../../constant/links.dart';
import '../../../constant/style.dart';
import '../../../constant/table_names.dart';
import '../../../main.dart';
+import '../../../print.dart';
import '../../../views/home/my_wallet/walet_captain.dart';
import '../../../views/widgets/elevated_btn.dart';
+import '../../firebase/firbase_messge.dart';
import '../../functions/crud.dart';
import '../../functions/location_background_controller.dart';
import '../../functions/location_controller.dart';
@@ -264,7 +266,7 @@ class HomeCaptainController extends GetxController {
@override
void onInit() async {
// await locationBackController.requestLocationPermission();
-
+ Get.put(FirebaseMessagesController());
addToken();
await getlocation();
onButtonSelected();
@@ -429,6 +431,7 @@ class HomeCaptainController extends GetxController {
void changeToAppliedRide(String status) {
box.write(BoxName.rideStatus, status);
+ Log.print('rideStatus from homcaptain : ${box.read(BoxName.rideStatus)}');
update();
}
diff --git a/lib/controller/home/captin/map_driver_controller.dart b/lib/controller/home/captin/map_driver_controller.dart
index a04e7f7..07ab0a5 100755
--- a/lib/controller/home/captin/map_driver_controller.dart
+++ b/lib/controller/home/captin/map_driver_controller.dart
@@ -25,6 +25,7 @@ import '../../firebase/firbase_messge.dart';
import '../../functions/crud.dart';
import '../../functions/encrypt_decrypt.dart';
import '../../functions/location_controller.dart';
+import '../../functions/tts.dart';
class MapDriverController extends GetxController {
bool isLoading = true;
@@ -174,7 +175,7 @@ class MapDriverController extends GetxController {
cancelTripFromDriverAfterApplied() async {
if (formKeyCancel.currentState!.validate()) {
box.write(BoxName.statusDriverLocation, 'off');
- FirebaseMessagesController().sendNotificationToDriverMAP(
+ Get.find().sendNotificationToDriverMAP(
"Cancel Trip from driver",
"Trip Cancelled from driver. We are looking for a new driver. Please wait."
.tr,
@@ -235,6 +236,8 @@ class MapDriverController extends GetxController {
'created_at': DateTime.now().toString(),
'driver_id': box.read(BoxName.driverID).toString(),
}, TableName.driverOrdersRefuse);
+ box.write(BoxName.rideStatus, 'Cancel');
+ Log.print('rideStatus from map 240 : ${box.read(BoxName.rideStatus)}');
Get.find().getRefusedOrderByCaptain();
Get.offAll(() => HomeCaptain());
}
@@ -242,6 +245,7 @@ class MapDriverController extends GetxController {
void startTimerToShowPassengerInfoWindowFromDriver() async {
if (box.read(BoxName.rideStatus) == 'Begin') {
+ Log.print('rideStatus from map 248 : ${box.read(BoxName.rideStatus)}');
isPassengerInfoWindow = false;
} else {
isPassengerInfoWindow = true;
@@ -298,6 +302,7 @@ class MapDriverController extends GetxController {
void driverGoToPassenger() async {
changeRideToBeginToPassenger();
box.write(BoxName.rideStatus, 'Applied');
+ Log.print('rideStatus from map 304 : ${box.read(BoxName.rideStatus)}');
update();
await CRUD().post(
link: "${AppLink.seferCairoServer}/ride/rides/update.php",
@@ -315,7 +320,7 @@ class MapDriverController extends GetxController {
}
// Get.find().changeToAppliedRide('Applied');
- FirebaseMessagesController().sendNotificationToDriverMAP(
+ Get.find().sendNotificationToDriverMAP(
'Driver Is Going To Passenger'.tr,
box.read(BoxName.nameDriver).toString(), //todo name driver
tokenPassenger,
@@ -392,6 +397,7 @@ class MapDriverController extends GetxController {
// todo ride details
// Get.find().changeToAppliedRide('Begin');
box.write(BoxName.rideStatus, 'Begin');
+ Log.print('rideStatus from map 399 : ${box.read(BoxName.rideStatus)}');
// Get.find().update();
update();
await CRUD().post(link: AppLink.updateRides, payload: {
@@ -418,7 +424,7 @@ class MapDriverController extends GetxController {
'status': 'Begin'
});
}
- FirebaseMessagesController().sendNotificationToDriverMAP(
+ Get.find().sendNotificationToDriverMAP(
'Trip is Begin'.tr,
box.read(BoxName.nameDriver).toString(),
tokenPassenger,
@@ -584,17 +590,29 @@ class MapDriverController extends GetxController {
}
}
- void finishRideFromDriver() {
+ Future finishRideFromDriver() async {
double distanceToDestination = Geolocator.distanceBetween(
- latLngPassengerLocation.latitude,
- latLngPassengerLocation.longitude,
+ latLngPassengerDestination.latitude,
+ latLngPassengerDestination.longitude,
Get.find().myLocation.latitude,
Get.find().myLocation.longitude,
);
+ final originalDistanceM = double.parse(distance.toString()) * 1000;
- if (distanceToDestination > (double.parse(distance.toString()) / 3)) {
- Log.print('distanceToDestination: ${distanceToDestination}');
+ // 2. احسب المسافة التي قطعها السائق حتى الآن
+ final movedDistanceM = originalDistanceM - distanceToDestination;
+ // 3. عتبة ثلث المسافة
+ final oneThirdDistanceM = originalDistanceM / 3;
+
+ // Logging للتتبع
+ Log.print('originalDistanceM: $originalDistanceM');
+ Log.print('distanceToDestinationM: $distanceToDestination');
+ Log.print('movedDistanceM: $movedDistanceM');
+ Log.print('oneThirdDistanceM: $oneThirdDistanceM');
+
+ // 4. إذا لم يقطع السائق ثلث المسافة، نعرض التأكيد
+ if (movedDistanceM < oneThirdDistanceM) {
MyDialog().getDialog(
'Are you sure to exit ride?'.tr,
'',
@@ -603,33 +621,39 @@ class MapDriverController extends GetxController {
finishRideFromDriver1();
},
);
- } else {
+ } /////
+
+ else {
+ final textToSpeechController = Get.put(TextToSpeechController());
MyDialog().getDialog(
"You haven't moved sufficiently!".tr,
'',
() => Get.back(),
);
+ await textToSpeechController
+ .speakText("You haven't moved sufficiently!".tr);
}
}
String paymentToken = '';
Future generateTokenDriver(String amount) async {
- var res = await CRUD().post(link: AppLink.addPaymentTokenDriver, payload: {
+ var res =
+ await CRUD().postWallet(link: AppLink.addPaymentTokenDriver, payload: {
'driverID': box.read(BoxName.driverID).toString(),
'amount': amount.toString(),
});
- var d = jsonDecode(res);
+ var d = (res);
return d['message'];
}
String paymentTokenPassenger = '';
Future generateTokenPassenger(String amount) async {
- var res =
- await CRUD().post(link: AppLink.addPaymentTokenPassenger, payload: {
+ var res = await CRUD()
+ .postWallet(link: AppLink.addPaymentTokenPassenger, payload: {
'passengerId': passengerId,
'amount': amount.toString(),
});
- var d = jsonDecode(res);
+ var d = (res);
return d['message'];
}
@@ -638,6 +662,7 @@ class MapDriverController extends GetxController {
isRideStarted = false;
isPriceWindow = false;
box.write(BoxName.rideStatus, 'Finished');
+ Log.print('rideStatus from map 664 : ${box.read(BoxName.rideStatus)}');
// Calculate totalCost more concisely
if (price < 20) {
@@ -699,7 +724,8 @@ class MapDriverController extends GetxController {
if (walletChecked == 'true') {
paymentToken = await generateTokenPassenger(
((-1) * double.parse(paymentAmount)).toString());
- futures.add(CRUD().post(link: AppLink.addPassengersWallet, payload: {
+ futures
+ .add(CRUD().postWallet(link: AppLink.addPassengersWallet, payload: {
'passenger_id': (passengerId),
'balance': ((-1) * double.parse(paymentAmount)).toString(),
'token': paymentToken,
@@ -707,7 +733,7 @@ class MapDriverController extends GetxController {
}
paymentToken = await generateTokenDriver(paymentAmount.toString());
- futures.add(CRUD().post(link: AppLink.addDrivePayment, payload: {
+ futures.add(CRUD().postWallet(link: AppLink.addDrivePayment, payload: {
'rideId': (rideId),
'amount': paymentAmount,
'payment_method':
@@ -720,7 +746,8 @@ class MapDriverController extends GetxController {
if (double.parse(passengerWalletBurc) < 0) {
final paymentToken1 = await generateTokenPassenger(
((-1) * double.parse(passengerWalletBurc)).toString());
- futures.add(CRUD().post(link: AppLink.addPassengersWallet, payload: {
+ futures
+ .add(CRUD().postWallet(link: AppLink.addPassengersWallet, payload: {
'passenger_id': (passengerId),
'token': paymentToken1,
'balance': ((-1) * double.parse(passengerWalletBurc)).toString()
@@ -730,7 +757,8 @@ class MapDriverController extends GetxController {
double pointsSubtraction = double.parse(paymentAmount) * (-1) * 0.08;
final paymentToken2 =
await generateTokenDriver((pointsSubtraction).toStringAsFixed(0));
- futures.add(CRUD().post(link: AppLink.addDriversWalletPoints, payload: {
+ futures
+ .add(CRUD().postWallet(link: AppLink.addDriversWalletPoints, payload: {
'paymentID': 'rideId${(rideId)}',
'amount': (pointsSubtraction).toStringAsFixed(0),
'paymentMethod': paymentMethod,
@@ -743,7 +771,7 @@ class MapDriverController extends GetxController {
Get.put(DriverBehaviorController()).sendSummaryToServer(driverId, rideId);
// Send notification (this likely depends on previous steps)
- FirebaseMessagesController().sendNotificationToDriverMAP(
+ Get.find().sendNotificationToDriverMAP(
"Driver Finish Trip".tr,
'${'you will pay to Driver'.tr} $paymentAmount \$',
tokenPassenger,
@@ -862,7 +890,7 @@ class MapDriverController extends GetxController {
// 'driverID': box.read(BoxName.driverID).toString(),
// });
// Future.delayed(const Duration(milliseconds: 300));
- // FirebaseMessagesController().sendNotificationToDriverMAP(
+ // Get.find().sendNotificationToDriverMAP(
// "Driver Finish Trip".tr,
// '${'you will pay to Driver'.tr} $paymentAmount \$',
// tokenPassenger,
@@ -1362,7 +1390,8 @@ class MapDriverController extends GetxController {
void onInit() async {
mapAPIKEY = await storage.read(key: BoxName.mapAPIKEY);
// Get the passenger location from the arguments.
- // await argumentLoading();
+ await argumentLoading();
+ Get.put(FirebaseMessagesController());
runGoogleMapDirectly();
addCustomCarIcon();
addCustomPassengerIcon();
diff --git a/lib/controller/home/payment/captain_wallet_controller.dart b/lib/controller/home/payment/captain_wallet_controller.dart
index e4669cc..1262d6b 100755
--- a/lib/controller/home/payment/captain_wallet_controller.dart
+++ b/lib/controller/home/payment/captain_wallet_controller.dart
@@ -82,7 +82,7 @@ class CaptainWalletController extends GetxController {
//get new driver details
isNewTransfer = true;
update();
- var res = await CRUD().getWallet(
+ var res = await CRUD().get(
link: AppLink.getDriverDetails,
payload: {'driver_phone': '+2${newDriverPhoneController.text}'});
isNewTransfer = false;
@@ -155,7 +155,7 @@ class CaptainWalletController extends GetxController {
'driverID': box.read(BoxName.driverID).toString(),
'amount': amount.toString(),
});
- var d = jsonDecode(res);
+ var d = (res);
return d['message'];
}
@@ -168,14 +168,14 @@ class CaptainWalletController extends GetxController {
'amount': amount.toString(),
'payment_method': paymentMethod.toString(),
});
- var d = jsonDecode(res);
+ var d = (res);
// paymentID = d['message'].toString();
return d['message'];
}
Future addDriverWallet(String paymentMethod, point, count) async {
paymentToken = await generateToken(count);
- var paymentID = await getPaymentId(paymentMethod, point);
+ var paymentID = await getPaymentId(paymentMethod, point.toString());
await CRUD().postWallet(link: AppLink.addDriversWalletPoints, payload: {
'driverID': box.read(BoxName.driverID).toString(),
'paymentID': paymentID.toString(),
@@ -245,7 +245,8 @@ class CaptainWalletController extends GetxController {
'payment_method': paymentMethod.toString(),
'passengerID': paymentMethod,
});
- await addSeferWallet(paymentMethod, (double.parse(point) * -1).toString());
+ await addSeferWallet(paymentMethod,
+ (double.parse(point) * -2).toString()); // deduct 2 from sefer wallet
}
Future addSeferWallet(String paymentMethod, String point) async {
@@ -290,7 +291,7 @@ class CaptainWalletController extends GetxController {
'paymentMethod': paymentMethod2.toString(),
});
if (res1 != 'failure') {
- FirebaseMessagesController().sendNotificationToDriverMAP(
+ Get.find().sendNotificationToDriverMAP(
'Transfer',
'${'You have transfer to your wallet from'.tr}'
'${box.read(BoxName.nameDriver)}',
diff --git a/lib/controller/home/payment/paymob_payout.dart b/lib/controller/home/payment/paymob_payout.dart
index 3ca1676..26029b5 100755
--- a/lib/controller/home/payment/paymob_payout.dart
+++ b/lib/controller/home/payment/paymob_payout.dart
@@ -1,15 +1,12 @@
import 'dart:convert';
import 'package:local_auth/local_auth.dart';
-import 'package:sefer_driver/constant/api_key.dart';
import 'package:sefer_driver/constant/box_name.dart';
import 'package:sefer_driver/main.dart';
import 'package:sefer_driver/views/widgets/error_snakbar.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
-import 'package:secure_string_operations/secure_string_operations.dart';
-import '../../../constant/char_map.dart';
import '../../../constant/links.dart';
import '../../../views/widgets/mydialoug.dart';
import '../../functions/crud.dart';
@@ -19,39 +16,8 @@ class PaymobPayout extends GetxController {
bool isLoading = false;
String dropdownValue = 'etisalat';
- Future getToken() async {
- var headers = {
- 'Content-Type': 'application/x-www-form-urlencoded',
- // 'Cookie':
- // 'csrftoken=74iZJ8XYyuTm5WRq2W4tpWX5eqoJLZVK5QhuDrChWpDtzpgGA269bbCWuEcW85t4'
- };
- var payMobOutClientSecrret =
- X.r(X.r(X.r(await getAIKey(KN.pmobsec), cn), cC), cs);
- var payMobOutClientId =
- X.r(X.r(X.r(await getAIKey(KN.pmobid), cn), cC), cs);
- var body = {
- 'grant_type': 'password',
- 'username': AK.payMobOutUserName,
- 'password': AK.payMobOutPassword,
- 'client_id': payMobOutClientId,
- 'client_secret': payMobOutClientSecrret
- };
- var res = await http.post(
- Uri.parse('https://payouts.paymobsolutions.com/api/secure/o/token/'),
- headers: headers,
- body: body,
- );
- String token = '';
- if (res.statusCode == 200) {
- var decode = jsonDecode(res.body);
- token = decode['access_token'];
- }
- return token;
- }
-
int payOutFee = 5;
- payToDriverWallet(
- String token, String amount, String issuer, String msisdn) async {
+ payToDriverWallet(String amount, String issuer, String msisdn) async {
bool isAvailable = await LocalAuthentication().isDeviceSupported();
if (isAvailable) {
// Authenticate the user
@@ -62,21 +28,18 @@ class PaymobPayout extends GetxController {
sensitiveTransaction: true,
));
if (didAuthenticate) {
- var headers = {
- 'Authorization': 'Bearer $token',
- 'Content-Type': 'application/json',
- };
- var body = json.encode({
- "amount": amount, //"10.00",
- "issuer": issuer, //"vodafone",
- "msisdn": msisdn, // "01023456789"
- });
- var res = await http.post(
- Uri.parse('https://payouts.paymobsolutions.com/api/secure/disburse/'),
- headers: headers,
- body: body,
- );
- var dec = jsonDecode(res.body);
+ var dec = await CRUD().postWallet(
+ link:
+ 'wl.tripz-egypt.com/v1/main/ride/payMob/paymob_driver/paymob_payout.php',
+ payload: {
+ "issuer": issuer,
+ "method": "wallet",
+ "amount": amount, //9.0,
+ "full_name":
+ '${box.read(BoxName.nameDriver)} ${box.read(BoxName.lastNameDriver)}',
+ "msisdn": msisdn, //"01010101010",
+ "bank_transaction_type": "cash_transfer"
+ });
if (dec['disbursement_status'] == 'successful') {
var paymentToken = await Get.find()
.generateToken(
@@ -149,8 +112,8 @@ class PaymobPayout extends GetxController {
} else {}
}
- payToDriverBankAccount(String token, String amount, String bankCardNumber,
- String bankCode) async {
+ payToDriverBankAccount(
+ String amount, String bankCardNumber, String bankCode) async {
bool isAvailable = await LocalAuthentication().isDeviceSupported();
if (isAvailable) {
// Authenticate the user
@@ -161,12 +124,9 @@ class PaymobPayout extends GetxController {
sensitiveTransaction: true,
));
if (didAuthenticate) {
- var headers = {
- 'Authorization': 'Bearer $token',
- 'Content-Type': 'application/json',
- };
var body = {
"issuer": "bank_card",
+ "method": "bank_card",
"amount": amount, //9.0,
"full_name":
'${box.read(BoxName.nameDriver)} ${box.read(BoxName.lastNameDriver)}',
@@ -174,12 +134,11 @@ class PaymobPayout extends GetxController {
"bank_code": bankCode, //"CIB",
"bank_transaction_type": "cash_transfer"
};
- var res = await http.post(
- Uri.parse('https://payouts.paymobsolutions.com/api/secure/disburse/'),
- headers: headers,
- body: body,
+ var dec = await CRUD().postWallet(
+ link:
+ 'wl.tripz-egypt.com/v1/main/ride/payMob/paymob_driver/paymob_payout.php',
+ payload: body,
);
- var dec = jsonDecode(res.body);
if (dec['disbursement_status'] == 'successful') {
var paymentToken = await Get.find()
.generateToken(
@@ -236,8 +195,7 @@ class PaymobPayout extends GetxController {
sensitiveTransaction: true,
));
if (didAuthenticate) {
- String token = await getToken();
- await payToDriverWallet(token, amount, issuer, msisdn);
+ await payToDriverWallet(amount, issuer, msisdn);
} else {
MyDialog().getDialog('Authentication failed'.tr, ''.tr, () {
Get.back();
@@ -263,8 +221,7 @@ class PaymobPayout extends GetxController {
sensitiveTransaction: true,
));
if (didAuthenticate) {
- String token = await getToken();
- await payToDriverBankAccount(token, amount, bankCardNumber, bankCode);
+ await payToDriverBankAccount(amount, bankCardNumber, bankCode);
} else {
MyDialog().getDialog('Authentication failed'.tr, ''.tr, () {
Get.back();
diff --git a/lib/controller/local/translations.dart b/lib/controller/local/translations.dart
index d83ebaa..3f3dfef 100755
--- a/lib/controller/local/translations.dart
+++ b/lib/controller/local/translations.dart
@@ -65,6 +65,17 @@ class MyTranslation extends Translations {
"Order Applied": "تم تطبيق الطلب",
//firebase above
+
+ "payment_success": "تمت العملية بنجاح",
+ "transaction_id": "رقم العملية",
+ "amount_paid": "المبلغ المدفوع",
+ "bonus_added": "البونص المضاف",
+ "points": "نقطة",
+ "transaction_failed": "فشل العملية",
+ "connection_failed": "فشل الاتصال",
+ "server_error": "خطأ في الخادم",
+ "server_error_message": "حدث خطأ أثناء الاتصال بالخادم",
+
"cancel": "إلغاء", "Syria": "سوريا",
"Security Warning": "تحذير أمني",
"Potential security risks detected. The application will close in @seconds seconds.":
@@ -75,7 +86,28 @@ class MyTranslation extends Translations {
"Security Warning": "⚠️ تحذير أمني",
"Potential security risks detected. The application may not function correctly.":
"تم اكتشاف ثغرات أمنية على هذا الجهاز. للحفاظ على أمان بياناتك، سيتم حذف جميع البيانات وإغلاق التطبيق.",
+ "How to use Tripz": "كيفية استخدام Tripz",
+ "What are the order details we provide to you?":
+ "ما هي تفاصيل الطلب التي نوفرها لك؟",
+ "Tripz Wallet Features:\n\nTransfer money multiple times.\nTransfer to anyone.\nMake purchases.\nCharge your account.\nCharge a friend's Tripz account.\nStore your money with us and receive it in your bank as a monthly salary.":
+ "ميزات محفظة Tripz:\n\nتحويل الأموال عدة مرات.\nالتحويل إلى أي شخص.\nإجراء عمليات شراء.\nشحن حسابك.\nشحن حساب Tripz لصديق.\nقم بتخزين أموالك معنا واستلامها في بنكك كراتب شهري.",
+ "What is the feature of our wallet?": "ما هي مميزات محفظتنا؟",
+ "What is Types of Trips in Tripz?": "ما هي أنواع الرحلات في Tripz؟",
+ '''Types of Trips in Tripz:
+Comfort: For cars newer than 2017 with air conditioning.
+Lady: For girl drivers.
+Speed: For fixed salary and endpoints.
+Mashwari: For flexible trips where passengers choose the car and driver with prior arrangements.
+Raih Gai: For same-day return trips longer than 50km.
+''': """أنواع الرحلات في Tripz:
+
+راحة: للسيارات الأحدث من 2017 مع تكييف الهواء.
+للسائقات الإناث.
+سبيد: براتب ثابت ونقاط نهاية محددة.
+مشاوير: للرحلات المرنة حيث يختار الركاب السيارة والسائق باتفاق مسبق.
+رحّي غاي: للرحلات ذات العودة في نفس اليوم التي تزيد عن 50 كم.
+""",
"I will go now": "هروح دلوقتي",
"Yes": "أيوة",
"No,I want": "لا، أنا عاوز",
diff --git a/lib/controller/rate/rate_conroller.dart b/lib/controller/rate/rate_conroller.dart
index 0c32825..c29d8f2 100755
--- a/lib/controller/rate/rate_conroller.dart
+++ b/lib/controller/rate/rate_conroller.dart
@@ -67,7 +67,7 @@ class RateController extends GetxController {
'driverID': box.read(BoxName.driverID).toString(),
});
- FirebaseMessagesController().sendNotificationToDriverMAP(
+ Get.find().sendNotificationToDriverMAP(
'Wallet Added'.tr,
'Wallet Added${(remainingFee).toStringAsFixed(0)}'.tr,
Get.find().tokenPassenger,
diff --git a/lib/main.dart b/lib/main.dart
index e0d5df4..6fe9d86 100755
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,9 +1,6 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
-import 'dart:math';
-import 'package:sefer_driver/constant/box_name.dart';
-import 'package:sefer_driver/controller/payment/paymob/paymob_response.dart';
import 'package:sefer_driver/views/home/Captin/orderCaptin/order_request_page.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
@@ -15,103 +12,102 @@ import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:flutter/services.dart';
-import 'package:permission_handler/permission_handler.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
import 'constant/api_key.dart';
import 'constant/info.dart';
-import 'constant/notification.dart';
import 'controller/firebase/firbase_messge.dart';
import 'controller/firebase/local_notification.dart';
import 'controller/functions/encrypt_decrypt.dart';
-import 'controller/functions/location_controller.dart';
import 'controller/functions/secure_storage.dart';
import 'controller/local/local_controller.dart';
import 'controller/local/translations.dart';
-import 'controller/payment/paymob/paymob_wallet.dart';
import 'firebase_options.dart';
import 'models/db_sql.dart';
import 'print.dart';
import 'splash_screen_page.dart';
+import 'views/home/Captin/driver_map_page.dart';
import 'views/home/Captin/orderCaptin/order_over_lay.dart';
+//--- Global Variables ---
final box = GetStorage();
const storage = FlutterSecureStorage();
-final PaymobPayment paymobPayment = PaymobPayment();
-final PaymobPaymentWallet paymobPaymentWallet = PaymobPaymentWallet();
DbSql sql = DbSql.instance;
-
final GlobalKey navigatorKey = GlobalKey();
+const platform = MethodChannel('com.sefer_driver/app_control');
+
+//--- Entry Points for Background/Terminated States ---
@pragma('vm:entry-point')
Future backgroundMessageHandler(RemoteMessage message) async {
WidgetsFlutterBinding.ensureInitialized();
- await Firebase.initializeApp();
+ await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
+ await GetStorage.init();
+
if (!await FlutterOverlayWindow.isPermissionGranted()) {
- // بإمكانك تجاهل الطلب في الخلفية والاكتفاء بالتنبيه
Log.print("Overlay permission not granted; showing only notification.");
}
+
if (Platform.isAndroid) {
if (message.notification != null && message.notification!.title != null) {
Log.print('message.notification!.title: ${message.notification!.title}');
- if (message.notification?.title == 'طلب' ||
+ if (message.notification?.title == 'Order' ||
message.notification?.title == 'OrderSpeed') {
var myListString = message.data['DriverList'] ?? '[]';
Log.print('myListString: $myListString');
- // Decode the JSON string to a list
List myList;
try {
myList = jsonDecode(myListString) as List;
- Log.print('myList: ${myList}');
} catch (e) {
Log.print('Error decoding JSON: $e');
myList = [];
}
- await Future.delayed(const Duration(seconds: 1));
-
bool isOverlayActive = await FlutterOverlayWindow.isActive();
if (isOverlayActive) {
- await FlutterOverlayWindow.closeOverlay();
+ await FlutterOverlayWindow.shareData(myList);
+ } else {
+ await FlutterOverlayWindow.showOverlay(
+ enableDrag: true,
+ flag: OverlayFlag.focusPointer,
+ positionGravity: PositionGravity.auto,
+ height: 1400,
+ width: WindowSize.matchParent,
+ startPosition: const OverlayPosition(0, -30),
+ );
+ await FlutterOverlayWindow.shareData(myList);
}
- await FlutterOverlayWindow.shareData(myList);
- await FlutterOverlayWindow.showOverlay(
- enableDrag: true,
- flag: OverlayFlag.focusPointer,
- // visibility: NotificationVisibility.visibilityPublic,
- positionGravity: PositionGravity.auto,
- height: 1300,
- width: WindowSize.matchParent,
- startPosition: const OverlayPosition(0, -40),
- );
+
+ // It's better to manage notifications in one place if possible
+ // but this is fine if it works for you.
NotificationController().showNotification(
message.notification!.title.toString(),
message.notification!.body.toString(),
'order',
myListString,
);
-
- await FlutterOverlayWindow.shareData(myList);
+ } else {
+ // Handle other types of notifications
+ FirebaseMessagesController().fireBaseTitles(message);
}
- } else {
- FirebaseMessagesController().fireBaseTitles(message);
}
}
}
@pragma('vm:entry-point')
void notificationTapBackground(NotificationResponse notificationResponse) {
- // handle background notification taps here
- print('Notification tapped in background!');
+ Log.print('Notification tapped in background!');
NotificationController().handleNotificationResponse(notificationResponse);
- // You can add your logic here to handle the notification tap
}
@pragma('vm:entry-point')
void overlayMain() async {
WidgetsFlutterBinding.ensureInitialized();
-
+ await GetStorage.init();
+ await Firebase.initializeApp(
+ options: DefaultFirebaseOptions.currentPlatform,
+ );
runApp(const MaterialApp(
debugShowCheckedModeBanner: false,
home: OrderOverlay(),
@@ -119,12 +115,12 @@ void overlayMain() async {
}
Future closeOverLay() async {
- // FlutterOverlayWindow.closeOverlay();
bool isOverlayActive = await FlutterOverlayWindow.isActive();
if (isOverlayActive) {
await FlutterOverlayWindow.closeOverlay();
}
}
+//--- Main Application ---
void main() async {
WidgetsFlutterBinding.ensureInitialized();
@@ -136,21 +132,29 @@ void main() async {
DeviceOrientation.portraitDown,
]);
- runApp(MyApp());
+ runApp(const MyApp());
}
class MyApp extends StatefulWidget {
+ const MyApp({Key? key}) : super(key: key);
+
@override
_MyAppState createState() => _MyAppState();
}
-class _MyAppState extends State {
+class _MyAppState extends State with WidgetsBindingObserver {
@override
void initState() {
super.initState();
+ WidgetsBinding.instance.addObserver(this);
_initApp();
}
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
Future _initApp() async {
try {
await Firebase.initializeApp(
@@ -159,62 +163,23 @@ class _MyAppState extends State {
await initializer.initializeApp();
await EncryptionHelper.initialize();
- if (Platform.isAndroid || Platform.isIOS) {
- Get.put(
- NotificationController()); // Initialize NotificationController here
- await FirebaseMessaging.instance.requestPermission();
- FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
- await NotificationController().initNotifications();
+ Get.put(NotificationController());
+ Get.put(FirebaseMessagesController());
- // Generate a random index to pick a message
- final random = Random();
- final randomMessage =
- driverMessages[random.nextInt(driverMessages.length)];
- // Schedule the notification with the random message
- NotificationController().scheduleNotificationsForSevenDays(
- randomMessage.split(':')[0],
- randomMessage.split(':')[1],
- "ding",
- );
+ await FirebaseMessaging.instance.requestPermission();
+ FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
+ await NotificationController().initNotifications();
- await Future.wait([
- FirebaseMessagesController().getNotificationSettings(),
- FirebaseMessagesController().getToken(),
- ]);
+ // You can add your other initializations here
+ // For example:
- // PermissionStatus status1 = await Permission.location.status;
- // if (status1.isGranted) {
- // await LocationController().startLocationUpdates();
- // }
- }
-
- String? key = (await storage.read(key: BoxName.payMobApikey));
- if (key != null) {
- String? apiKey = (key);
- if (apiKey != null) {
- PaymobPayment.instance.initialize(
- // Use .instance
- apiKey: apiKey,
- integrationID: int.parse(AK.integrationIdPayMob),
- userTokenExpiration: 200,
- iFrameID: 837992,
- );
-
- PaymobPaymentWallet.instance.initialize(
- // Use .instance
- apiKey: apiKey,
- integrationID: int.parse(AK.integrationIdPayMobWallet),
- userTokenExpiration: 200,
- iFrameID: 837992,
- );
- }
- }
+ // Your other startup logic...
} catch (e) {
- print("Error initializing app: $e");
- // Handle initialization errors appropriately. Maybe show an error message to the user.
+ Log.print("Error during _initApp: $e");
}
}
+ //--- Build Method ---
@override
Widget build(BuildContext context) {
LocaleController localController = Get.put(LocaleController());
@@ -231,105 +196,11 @@ class _MyAppState extends State {
GetPage(
name: '/order-page',
page: () => OrderRequestPage(),
- arguments: box.read(BoxName.rideArguments),
),
+ GetPage(
+ name: '/passenger-location-map',
+ page: () => PassengerLocationMapPage()),
],
);
}
}
-
-// void main() async {
-// WidgetsFlutterBinding.ensureInitialized();
-// await WakelockPlus.enable();
-//
-// await GetStorage.init();
-//
-// final AppInitializer initializer = AppInitializer();
-//
-// await initializer.initializeApp();
-// await Future.delayed(Duration.zero);
-// await EncryptionHelper.initialize();
-//
-// Stripe.publishableKey = AK.publishableKeyStripe;
-//
-// PermissionStatus status1 = await Permission.location.status;
-// // if (status1.isGranted) {
-// await LocationController().startLocationUpdates();
-// // }
-//
-// if (Platform.isAndroid || Platform.isIOS) {
-// NotificationController notificationController =
-// Get.put(NotificationController());
-// await Firebase.initializeApp(
-// options: DefaultFirebaseOptions.currentPlatform,
-// );
-// await FirebaseMessagesController().requestFirebaseMessagingPermission();
-//
-// FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
-//
-// await notificationController.initNotifications();
-//
-// // Generate a random index to pick a message
-// final random = Random();
-// final randomMessage = driverMessages[random.nextInt(driverMessages.length)];
-//
-// // Schedule the notification with the random message
-// notificationController.scheduleNotificationsForSevenDays(
-// randomMessage.split(':')[0],
-// randomMessage.split(':')[1],
-// "ding",
-// );
-//
-// await Future.wait([
-// FirebaseMessagesController().getNotificationSettings(),
-// FirebaseMessagesController().getToken(),
-// ]);
-// // await FacebookAuth.instance.init();
-// SystemChrome.setPreferredOrientations([
-// DeviceOrientation.portraitUp,
-// DeviceOrientation.portraitDown,
-// ]);
-// }
-//
-// String? key = (await storage.read(key: BoxName.payMobApikey));
-//
-// String? apiKey = EncryptionHelper.instance.decryptData(key!);
-// PaymobPayment.instance.initialize(
-// apiKey: apiKey,
-// integrationID: int.parse(AK.integrationIdPayMob),
-// userTokenExpiration: 200,
-// iFrameID: 837992,
-// );
-//
-// PaymobPaymentWallet.instance.initialize(
-// apiKey: apiKey,
-// integrationID: int.parse(AK.integrationIdPayMobWallet),
-// userTokenExpiration: 200,
-// iFrameID: 837992,
-// );
-// runApp(MyApp());
-// }
-//
-// class MyApp extends StatelessWidget {
-// @override
-// Widget build(BuildContext context) {
-// LocaleController localController = Get.put(LocaleController());
-// return GetMaterialApp(
-// navigatorKey: navigatorKey,
-// title: AppInformation.appName,
-// translations: MyTranslation(),
-// debugShowCheckedModeBanner: false,
-// locale: localController.language,
-// theme: localController.appTheme,
-// initialRoute: '/',
-// getPages: [
-// GetPage(name: '/', page: () => SplashScreen()),
-// GetPage(
-// name: '/order-page',
-// page: () => OrderRequestPage(),
-// arguments: box.read(BoxName.rideArguments),
-// ),
-// ],
-// );
-// }
-// }
diff --git a/lib/models/model/order_data.dart b/lib/models/model/order_data.dart
index f75530d..62ea9d9 100755
--- a/lib/models/model/order_data.dart
+++ b/lib/models/model/order_data.dart
@@ -1,16 +1,18 @@
-// lib/models/order_data.dart
+// lib/models/model/order_data.dart
class OrderData {
final String customerName;
- final double tripDistanceKm; // المسافة الكلية للرحلة بالكيلومتر
+ final String customerToken;
+ final double tripDistanceKm; // The total trip distance in kilometers
final String price;
final String startLocationAddress;
final String endLocationAddress;
- final double distanceToPassengerKm; // المسافة إلى الراكب بالكيلومتر
- final int tripDurationMinutes; // مدة الرحلة الكلية بالدقائق (مقربة لأعلى)
+ final double
+ distanceToPassengerKm; // The distance to the passenger in kilometers
+ final int tripDurationMinutes; // Total trip duration in minutes (rounded up)
final int
- durationToPassengerMinutes; // المدة إلى الراكب بالدقائق (مقربة لأعلى)
+ durationToPassengerMinutes; // Duration to reach the passenger in minutes (rounded up)
final String rideType;
final String orderId;
@@ -22,6 +24,7 @@ class OrderData {
OrderData({
required this.customerName,
+ required this.customerToken,
required this.tripDistanceKm,
required this.price,
required this.startLocationAddress,
@@ -37,26 +40,57 @@ class OrderData {
this.rawEndCoordinates,
});
- // دالة مساعدة لتحويل الثواني إلى دقائق وتقريبها لأعلى
+ // --- NEW: Factory constructor to create an instance from a Map ---
+ // This is the missing method that was causing the error.
+ factory OrderData.fromMap(Map map) {
+ return OrderData(
+ // For strings, provide a default value in case the map key is null
+ customerName: map['customerName']?.toString() ?? 'Unknown Customer',
+ customerToken: map['customerToken']?.toString() ?? 'Unknown token',
+
+ // For numbers, cast from 'num' to handle both int and double, with a default value
+ tripDistanceKm: (map['tripDistanceKm'] as num?)?.toDouble() ?? 0.0,
+
+ price: map['price']?.toString() ?? '0',
+ startLocationAddress:
+ map['startLocationAddress']?.toString() ?? 'Unknown Address',
+ endLocationAddress:
+ map['endLocationAddress']?.toString() ?? 'Unknown Address',
+
+ distanceToPassengerKm:
+ (map['distanceToPassengerKm'] as num?)?.toDouble() ?? 0.0,
+
+ tripDurationMinutes: (map['tripDurationMinutes'] as num?)?.toInt() ?? 0,
+ durationToPassengerMinutes:
+ (map['durationToPassengerMinutes'] as num?)?.toInt() ?? 0,
+
+ rideType: map['rideType']?.toString() ?? 'Unknown',
+ orderId: map['orderId']?.toString() ?? 'N/A',
+ passengerId: map['passengerId']?.toString() ?? 'N/A',
+ passengerRate: map['passengerRate']?.toString() ?? 'N/A',
+
+ // For nullable strings, direct access is fine as it returns null if the key doesn't exist
+ rawStartCoordinates: map['rawStartCoordinates'],
+ rawEndCoordinates: map['rawEndCoordinates'],
+ );
+ }
+
+ // A helper function to convert seconds to rounded-up minutes
static int _secondsToRoundedUpMinutes(String secondsString) {
final seconds = double.tryParse(secondsString) ?? 0.0;
if (seconds <= 0) return 0;
return (seconds / 60)
- .ceil(); // .ceil() لتقريب الكسر لأعلى (مثلاً 0.1 دقيقة تصبح 1 دقيقة)
+ .ceil(); // .ceil() rounds up (e.g., 0.1 minutes becomes 1 minute)
}
+ // Your existing factory for creating an instance from a List
factory OrderData.fromList(List list) {
- // بناءً على testList والافتراضات الجديدة:
- // list[4]: durationToRide (مدة الرحلة الكلية بالثواني)
- // list[5]: distance (المسافة الكلية للرحلة بالكيلومتر)
- // list[12]: distanceByPassenger (المسافة إلى الراكب بالمتر)
- // list[15]: durationToPassenger (المدة إلى الراكب بالثواني)
-
double distanceToPassengerMeters =
list.length > 12 ? (double.tryParse(list[12].toString()) ?? 0.0) : 0.0;
return OrderData(
customerName: list.length > 8 ? list[8].toString() : 'Unknown Customer',
+ customerToken: list.length > 9 ? list[9].toString() : 'Unknown token',
tripDistanceKm:
list.length > 5 ? (double.tryParse(list[5].toString()) ?? 0.0) : 0.0,
price: list.length > 2 ? list[2].toString().split('.')[0] : '0',
@@ -66,7 +100,7 @@ class OrderData {
list.length > 30 ? list[30].toString() : 'Unknown Address',
distanceToPassengerKm:
- distanceToPassengerMeters / 1000.0, // تحويل من متر إلى كيلومتر
+ distanceToPassengerMeters / 1000.0, // Convert meters to kilometers
tripDurationMinutes:
list.length > 4 ? _secondsToRoundedUpMinutes(list[4].toString()) : 0,
@@ -102,6 +136,7 @@ class OrderData {
}
}
+ // Getter to parse start coordinates
Map? get startCoordinates {
if (rawStartCoordinates == null) return null;
final parts = rawStartCoordinates!.split(',');
@@ -114,6 +149,7 @@ class OrderData {
return null;
}
+ // Getter to parse end coordinates
Map? get endCoordinates {
if (rawEndCoordinates == null) return null;
final parts = rawEndCoordinates!.split(',');
@@ -126,6 +162,8 @@ class OrderData {
return null;
}
+ // Your existing method to convert the object TO a Map.
+ // This is used to pass the data from the overlay to the main app.
Map toMap() {
return {
'customerName': customerName,
diff --git a/lib/models/overlay_service.dart b/lib/models/overlay_service.dart
new file mode 100644
index 0000000..64d74a3
--- /dev/null
+++ b/lib/models/overlay_service.dart
@@ -0,0 +1,13 @@
+import 'package:flutter/services.dart';
+
+class OverlayMethodChannel {
+ static const _channel = MethodChannel('com.sefer_driver/app_control');
+
+ static Future bringToForeground() async {
+ try {
+ await _channel.invokeMethod('bringToForeground');
+ } on PlatformException catch (e) {
+ print('Error bringing app to foreground: $e');
+ }
+ }
+}
diff --git a/lib/views/auth/country_widget.dart b/lib/views/auth/country_widget.dart
index d739a40..d50517e 100755
--- a/lib/views/auth/country_widget.dart
+++ b/lib/views/auth/country_widget.dart
@@ -104,13 +104,14 @@ class CountryPickerFromSetting extends StatelessWidget {
final List countryOptions = [
'Jordan',
- 'USA',
+ "Syria",
'Egypt',
'Turkey',
'Saudi Arabia',
'Qatar',
'Bahrain',
'Kuwait',
+ 'USA',
];
CountryPickerFromSetting({Key? key}) : super(key: key);
diff --git a/lib/views/home/Captin/About Us/frequantly_question.dart b/lib/views/home/Captin/About Us/frequantly_question.dart
index 385281c..8933590 100755
--- a/lib/views/home/Captin/About Us/frequantly_question.dart
+++ b/lib/views/home/Captin/About Us/frequantly_question.dart
@@ -28,7 +28,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
),
children: [
Text(
- 'Step-by-step instructions on how to request a ride through the Sefer app.'
+ 'Step-by-step instructions on how to request a ride through the Tripz app.'
.tr,
style: AppStyle.title,
),
@@ -43,7 +43,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
),
children: [
Text(
- 'Sefer offers a variety of vehicle options to suit your needs, including economy, comfort, and luxury. Choose the option that best fits your budget and passenger count.'
+ 'Tripz offers a variety of vehicle options to suit your needs, including economy, comfort, and luxury. Choose the option that best fits your budget and passenger count.'
.tr,
style: AppStyle.title,
),
@@ -58,7 +58,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
),
children: [
Text(
- 'Sefer offers multiple payment methods for your convenience. Choose between cash payment or credit/debit card payment during ride confirmation.'
+ 'Tripz offers multiple payment methods for your convenience. Choose between cash payment or credit/debit card payment during ride confirmation.'
.tr,
style: AppStyle.title,
),
@@ -73,7 +73,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
),
children: [
Text(
- 'Yes, you can cancel your ride under certain conditions (e.g., before driver is assigned). See the Sefer cancellation policy for details.'
+ 'Yes, you can cancel your ride under certain conditions (e.g., before driver is assigned). See the Tripz cancellation policy for details.'
.tr,
style: AppStyle.title,
),
@@ -98,7 +98,7 @@ class FrequentlyQuestionsPage extends StatelessWidget {
});
},
child: Text(
- 'Visit our website or contact Sefer support for information on driver registration and requirements.'
+ 'Visit our website or contact Tripz support for information on driver registration and requirements.'
.tr,
style: AppStyle.title,
),
@@ -115,22 +115,22 @@ class FrequentlyQuestionsPage extends StatelessWidget {
),
children: [
Text(
- 'Sefer provides in-app chat functionality to allow you to communicate with your driver or passenger during your ride.'
+ 'Tripz provides in-app chat functionality to allow you to communicate with your driver or passenger during your ride.'
.tr,
style: AppStyle.title,
),
],
),
- // Question 8: What safety measures does Sefer offer?
+ // Question 8: What safety measures does Tripz offer?
ExpansionTile(
title: Text(
- 'What safety measures does Sefer offer?'.tr,
+ 'What safety measures does Tripz offer?'.tr,
style: AppStyle.title,
),
children: [
Text(
- 'Sefer prioritizes your safety. We offer features like driver verification, in-app trip tracking, and emergency contact options.'
+ 'Tripz prioritizes your safety. We offer features like driver verification, in-app trip tracking, and emergency contact options.'
.tr,
style: AppStyle.title,
),
diff --git a/lib/views/home/Captin/About Us/settings_captain.dart b/lib/views/home/Captin/About Us/settings_captain.dart
index f0c6c71..ef06634 100755
--- a/lib/views/home/Captin/About Us/settings_captain.dart
+++ b/lib/views/home/Captin/About Us/settings_captain.dart
@@ -120,7 +120,7 @@ class SettingsCaptain extends StatelessWidget {
CupertinoListTile(
leading: const Icon(CupertinoIcons.hand_raised_fill),
title:
- Text("How to use SEFER".tr, style: AppStyle.headTitle2),
+ Text("How to use Tripz".tr, style: AppStyle.headTitle2),
trailing: const CupertinoListTileChevron(),
onTap: () => Get.to(() => const UsingAppPage()),
),
diff --git a/lib/views/home/Captin/About Us/using_app_page.dart b/lib/views/home/Captin/About Us/using_app_page.dart
index a32d021..002b664 100755
--- a/lib/views/home/Captin/About Us/using_app_page.dart
+++ b/lib/views/home/Captin/About Us/using_app_page.dart
@@ -10,7 +10,7 @@ class UsingAppPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MyScafolld(
- title: "How to use SEFER".tr,
+ title: "How to use Tripz".tr,
body: [
SizedBox(
child: Padding(
@@ -22,12 +22,13 @@ class UsingAppPage extends StatelessWidget {
MyDialogContent().getDialog(
"What are the order details we provide to you?".tr,
Image.network(
- 'https://api.sefer.live/sefer/imageForUsingApp/order_page.jpg',
+ 'https://api.tripz-egypt.com/tripz/imageForUsingApp/order_page.jpg',
height: 300,
width: 300,
fit: BoxFit.cover,
- ),
- () {});
+ ), () {
+ Get.back();
+ });
},
child: Container(
decoration: AppStyle.boxDecoration1,
@@ -47,16 +48,17 @@ class UsingAppPage extends StatelessWidget {
onTap: () {
MyDialog().getDialog(
"What are the order details we provide to you?".tr,
- '''Sefer Wallet Features:
+ '''Tripz Wallet Features:
Transfer money multiple times.
Transfer to anyone.
Make purchases.
Charge your account.
-Charge a friend's Sefer account.
+Charge a friend's Tripz account.
Store your money with us and receive it in your bank as a monthly salary.'''
- .tr,
- () {});
+ .tr, () {
+ Get.back();
+ });
},
child: Container(
decoration: AppStyle.boxDecoration1,
@@ -75,8 +77,8 @@ Store your money with us and receive it in your bank as a monthly salary.'''
InkWell(
onTap: () {
MyDialog().getDialog(
- "What are the order details we provide to you?".tr,
- '''Types of Trips in Sefer:
+ "What is Types of Trips in Tripz?".tr,
+ '''Types of Trips in Tripz:
Comfort: For cars newer than 2017 with air conditioning.
Lady: For girl drivers.
@@ -84,15 +86,16 @@ Speed: For fixed salary and endpoints.
Mashwari: For flexible trips where passengers choose the car and driver with prior arrangements.
Raih Gai: For same-day return trips longer than 50km.
'''
- .tr,
- () {});
+ .tr, () {
+ Get.back();
+ });
},
child: Container(
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
- "What is Types of Trips in Sefer?".tr,
+ "What is Types of Trips in Tripz?".tr,
style: AppStyle.title,
),
),
diff --git a/lib/views/home/Captin/driver_map_page.dart b/lib/views/home/Captin/driver_map_page.dart
index 214b256..86bcaa0 100755
--- a/lib/views/home/Captin/driver_map_page.dart
+++ b/lib/views/home/Captin/driver_map_page.dart
@@ -21,16 +21,20 @@ class PassengerLocationMapPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
- // if (!mapDriverController.initialized) {
- // // Call a method to initialize the controller
-
- // mapDriverController.initialized;
- // } else {
- // Get.put(MapDriverController()).argumentLoading();
-
- // Get.put(MapDriverController())
- // .startTimerToShowPassengerInfoWindowFromDriver();
- // }
+ if (Get.arguments != null && Get.arguments is Map) {
+ // نستخدم addPostFrameCallback لضمان أن هذا الكود يعمل بعد اكتمال بناء الإطار الأول
+ // هذا يعطي GetX وقته لتجهيز كل شيء
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ // نستدعي دالة التهيئة الجديدة ونمرر لها البيانات
+ mapDriverController.argumentLoading();
+ });
+ } else {
+ // في حال عدم وجود arguments، يجب التعامل مع هذا الخطأ
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ Get.snackbar("Error", "No order data found.");
+ Get.back();
+ });
+ }
mapDriverController.argumentLoading();
mapDriverController.startTimerToShowPassengerInfoWindowFromDriver();
diff --git a/lib/views/home/Captin/home_captain/home_captin.dart b/lib/views/home/Captin/home_captain/home_captin.dart
index 5f2c5fa..faf852c 100755
--- a/lib/views/home/Captin/home_captain/home_captin.dart
+++ b/lib/views/home/Captin/home_captain/home_captin.dart
@@ -19,6 +19,7 @@ import '../../../../controller/functions/location_controller.dart';
import '../../../../controller/functions/overlay_permisssion.dart';
import '../../../../controller/functions/package_info.dart';
import '../../../../controller/home/captin/home_captain_controller.dart';
+import '../../../../print.dart';
import '../../../widgets/circle_container.dart';
import '../driver_map_page.dart';
import 'widget/connect.dart';
@@ -482,6 +483,8 @@ class HomeCaptain extends StatelessWidget {
),
GetBuilder(
builder: (homeCaptainController) {
+ Log.print(
+ 'rideStatus from home 486 : ${box.read(BoxName.rideStatus)}');
return box.read(BoxName.rideStatus) == 'Applied' ||
box.read(BoxName.rideStatus) == 'Begin'
? Positioned(
@@ -520,7 +523,7 @@ class HomeCaptain extends StatelessWidget {
};
},
icon: const Icon(
- Icons.rice_bowl,
+ Icons.directions_rounded,
size: 29,
color: AppColor.blueColor,
),
diff --git a/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart b/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart
index 981e2a5..6fbb3bf 100755
--- a/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart
+++ b/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart
@@ -1,13 +1,21 @@
import 'package:sefer_driver/constant/box_name.dart';
import 'package:sefer_driver/controller/firebase/local_notification.dart';
import 'package:sefer_driver/main.dart';
+import 'package:sefer_driver/print.dart';
+import 'package:sefer_driver/views/home/Captin/driver_map_page.dart';
import 'package:sefer_driver/views/home/Captin/orderCaptin/vip_order_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_font_icons/flutter_font_icons.dart';
import 'package:get/get.dart';
import 'package:sefer_driver/controller/home/captin/home_captain_controller.dart';
+import 'package:sefer_driver/views/widgets/error_snakbar.dart';
+import 'package:sefer_driver/views/widgets/mydialoug.dart';
import '../../../../../constant/colors.dart';
+import '../../../../../constant/links.dart';
+import '../../../../../controller/firebase/firbase_messge.dart';
+import '../../../../../controller/functions/crud.dart';
+import '../../../../../controller/home/captin/order_request_controller.dart';
import '../../../../Rate/ride_calculate_driver.dart';
GetBuilder leftMainMenuCaptainIcons() {
@@ -17,6 +25,46 @@ GetBuilder leftMainMenuCaptainIcons() {
left: 6,
child: Column(
children: [
+ AnimatedContainer(
+ duration: const Duration(microseconds: 200),
+ width: controller.widthMapTypeAndTraffic,
+ decoration: BoxDecoration(
+ color: AppColor.secondaryColor,
+ border: Border.all(color: AppColor.blueColor),
+ borderRadius: BorderRadius.circular(15)),
+ child: Builder(builder: (context) {
+ return IconButton(
+ onPressed: () async {
+ await checkForPendingOrderFromServer();
+ box.read(BoxName.rideArgumentsFromBackground) != 'failure'
+ ? Get.to(() => PassengerLocationMapPage(),
+ arguments:
+ box.read(BoxName.rideArgumentsFromBackground))
+ : MyDialog().getDialog(
+ 'Ride info'.tr,
+ 'you dont have accepted ride'.tr,
+ () {
+ Get.back();
+ },
+ );
+ // Log.print(
+ // 'box.read(BoxName.rideArgumentsFromBackground): ${box.read(BoxName.rideArgumentsFromBackground)}');
+ },
+ icon: Icon(
+ Icons.directions_car_rounded,
+ size: 29,
+ color:
+ box.read(BoxName.rideArgumentsFromBackground) == 'failure'
+ ? AppColor.redColor
+ : AppColor.greenColor,
+ ),
+ );
+ }),
+ ),
+
+ const SizedBox(
+ height: 5,
+ ),
AnimatedContainer(
duration: const Duration(microseconds: 200),
width: controller.widthMapTypeAndTraffic,
@@ -89,7 +137,10 @@ GetBuilder leftMainMenuCaptainIcons() {
}),
)
: const SizedBox(),
- // : const SizedBox(),
+ // const SizedBox(
+ // height: 5,
+ // ),
+
// AnimatedContainer(
// duration: const Duration(microseconds: 200),
// width: controller.widthMapTypeAndTraffic,
@@ -100,53 +151,7 @@ GetBuilder leftMainMenuCaptainIcons() {
// child: Builder(builder: (context) {
// return IconButton(
// onPressed: () async {
- // final List testList = const [
- // "32.1117875,36.0669891",
- // "32.1364001,36.0707479",
- // "24.84",
- // "7.56",
- // "436",
- // "4.38",
- // "109270481246447459618",
- // "113172279072358305645",
- // "hamza",
- // "e4QWqe7K607luM7qUMOPCL:APA91bFjX4XBM4I5COJl9fyxCTKJ1ZQpT3vzY7iEbOTuT4uo0-OSCAt5zgVhlhw4aC33s-VhyucDnP1tQGFd9svaazQ8A_SKgolPk3owzug8dCsiXoPeJ0k",
- // "+201010101010",
- // "6",
- // "43",
- // "true",
- // "c2tXiuBJQCSg4CU4IfqYOL:APA91bFA0f8R3QMnPQnPEEdNyjY-jcoKt4nLBHxcLLsmDSuJn5yd4jSvwq7qDIZpkkPkjfjdwdKsGL0-G0aHpPyjfiBvbCwFmlRMCUKftNMNT7MJx2Bp16Y",
- // "6",
- // "1188",
- // "false",
- // "109270481246447459618",
- // "436",
- // "startEnd",
- // "32.12404505187645,36.06566168367863",
- // "",
- // "",
- // "",
- // "",
- // "5.42",
- // "0",
- // "hamzaayedflutter@gmail.com",
- // "4368+PPP، السخنة، الأردن",
- // "43PC+C4G، السخنة، الأردن",
- // "Speed",
- // "8",
- // "5.00"
- // ];
- // await FlutterOverlayWindow.shareData(testList);
- // await FlutterOverlayWindow.showOverlay(
- // enableDrag: true,
- // flag: OverlayFlag.focusPointer,
- // // visibility: NotificationVisibility.visibilityPublic,
- // positionGravity: PositionGravity.auto,
- // height: 1300,
- // width: WindowSize.matchParent,
- // startPosition: const OverlayPosition(0, -90),
- // );
- // debugPrint('Overlay opened: ');
+ // Log.print('phoneDriver: ${box.read(BoxName.phoneDriver)}');
// },
// icon: const Icon(
// FontAwesome5.grin_tears,
@@ -165,3 +170,142 @@ GetBuilder leftMainMenuCaptainIcons() {
),
);
}
+
+void _log(String message) => print(message);
+
+Future checkForPendingOrderFromServer() async {
+ bool _isProcessingOrder = false;
+ if (_isProcessingOrder) return;
+
+ final driverId = box.read(BoxName.driverID)?.toString();
+ if (driverId == null) return; // Can't check without a driver ID
+
+ _isProcessingOrder = true; // Lock
+
+ try {
+ // You need to create this CRUD method
+ var response = await CRUD().post(
+ link: AppLink.getArgumentAfterAppliedFromBackground,
+ payload: {'driver_id': driverId},
+ );
+
+ // Assuming the server returns order data if found, or 'failure'/'none' if not
+ if (response != 'failure') {
+ Log.print('response: ${response}');
+ _log("MAIN_APP_LOG: Pending order DETECTED from server!");
+
+ final Map orderInfoFromServer = response['message'];
+ final Map rideArguments =
+ _transformServerDataToAppArguments(orderInfoFromServer);
+ // 2. Build the new arguments map, matching your Flutter structure
+
+ _log("MAIN_APP_LOG: Constructed rideArguments map successfully.");
+
+/////////////
+ final customerToken = (response)['message']['token_passenger'];
+ final orderId = (response)['message']['ride_id'].toString();
+ Log.print('orderId: ${orderId}');
+ box.write(BoxName.rideArgumentsFromBackground, rideArguments);
+ box.write(BoxName.statusDriverLocation, 'on');
+ box.write(BoxName.rideStatus, 'Apply');
+ Get.put(OrderRequestController()).changeApplied();
+ // MyDialog().getDialog(orderId.toString(), customerToken, () {});
+
+ // Now proceed with the UI flow
+ _sendAcceptanceNotification(customerToken, orderId.toString());
+ // await _bringAppToForegroundAndNavigate(orderId);
+ } else {
+ _log("MAIN_APP_LOG: No pending orders found on server.");
+ box.write(BoxName.rideArgumentsFromBackground, 'failure');
+ }
+ } catch (e) {
+ _log("Error while polling server: $e");
+ } finally {
+ _isProcessingOrder = false; // Release lock
+ }
+}
+
+Map _transformServerDataToAppArguments(
+ Map serverData) {
+ _log("Transforming server data to match app's argument structure.");
+
+ // Helper function to safely get and convert values to String
+ String _getString(String key, [String defaultValue = 'unknown']) {
+ // serverData[key] might be an int, double, or string. .toString() handles all.
+ // If it's null, use the default value.
+ return serverData[key]?.toString() ?? defaultValue;
+ }
+
+ return {
+ 'passengerLocation': _getString('passenger_location'),
+ 'passengerDestination': _getString('passenger_destination'),
+ 'Duration': _getString('duration'),
+ 'totalCost': _getString('total_cost'),
+ 'Distance': _getString('distance'),
+ 'name': _getString('name'),
+ 'phone': _getString('phone'),
+ 'email': _getString('email'),
+ 'tokenPassenger': _getString('token_passenger'),
+ 'direction': _getString('direction_url'),
+ 'DurationToPassenger': _getString('duration_to_passenger'),
+ 'rideId': _getString('ride_id'),
+ 'passengerId': _getString('passenger_id'),
+ 'driverId': _getString('driver_id'),
+ 'durationOfRideValue': _getString('duration_of_ride'),
+ 'paymentAmount': _getString('payment_amount'),
+ 'paymentMethod': _getString('payment_method'),
+ 'passengerWalletBurc': _getString('passenger_wallet_burc'),
+ 'timeOfOrder': _getString('time_of_order'),
+ 'totalPassenger': _getString('total_passenger'),
+ 'carType': _getString('car_type'),
+ 'kazan': _getString('kazan'),
+ 'startNameLocation': _getString('start_name_location'),
+ 'endNameLocation': _getString('end_name_location'),
+
+ // --- Special Handling ---
+
+ // Steps (handle null values by providing an empty string)
+ 'step0': _getString('step0'),
+ 'step1': _getString('step1'),
+ 'step2': _getString('step2'),
+ 'step3': _getString('step3'),
+ 'step4': _getString('step4'),
+
+ // Boolean conversion (1/0 from server to 'true'/'false' string for the app)
+ 'WalletChecked': (serverData['wallet_checked'] == 1).toString(),
+
+ // Logic-based conversion for isHaveSteps
+ // Your app's `rideArguments` expects 'startEnd', so we provide that if has_steps is 1.
+ // You might need to adjust this logic if 'haveSteps' is also a possibility.
+ 'isHaveSteps': (serverData['has_steps'] == 1)
+ ? 'startEnd'
+ : 'noSteps', // Providing a default
+ };
+}
+
+void _sendAcceptanceNotification(String? customerToken, rideId) {
+ try {
+ if (customerToken == null) return;
+ final FirebaseMessagesController _firebaseMessagesController =
+ Get.put(FirebaseMessagesController());
+ _log("Attempting to send acceptance notification to passenger...");
+ List bodyToPassenger = [
+ box.read(BoxName.driverID).toString(),
+ box.read(BoxName.nameDriver).toString(),
+ box.read(BoxName.tokenDriver).toString(),
+ rideId.toString()
+ ];
+
+ // Safely check for customer token
+ final String? token = customerToken;
+ if (token != null && token.isNotEmpty) {
+ _firebaseMessagesController.sendNotificationToDriverMAP('Accepted Ride',
+ 'your ride is applied'.tr, token, bodyToPassenger, 'start.wav');
+ _log("Acceptance notification task was fired.");
+ } else {
+ _log("Could not send notification: Customer token is missing or empty.");
+ }
+ } catch (e) {
+ _log("Error while firing notification task: $e");
+ }
+}
diff --git a/lib/views/home/Captin/maintain_center_page.dart b/lib/views/home/Captin/maintain_center_page.dart
index d0277c4..7640ccf 100755
--- a/lib/views/home/Captin/maintain_center_page.dart
+++ b/lib/views/home/Captin/maintain_center_page.dart
@@ -51,7 +51,7 @@ import 'package:get/get.dart';
// child: Padding(
// padding: const EdgeInsets.all(14),
// child: Text(
-// "We have maintenance offers for your car. You can use them after completing 600 trips to get a 20% discount on car repairs. Enjoy using our SEFER app and be part of our SEFER family."
+// "We have maintenance offers for your car. You can use them after completing 600 trips to get a 20% discount on car repairs. Enjoy using our Tripz app and be part of our Tripz family."
// .tr,
// style: AppStyle.title,
// ),
@@ -186,7 +186,7 @@ class MaintainCenterPage extends StatelessWidget {
),
const SizedBox(height: 8),
Text(
- "We have maintenance offers for your car. You can use them after completing 600 trips to get a 20% discount on car repairs. Enjoy using our SEFER app and be part of our SEFER family."
+ "We have maintenance offers for your car. You can use them after completing 600 trips to get a 20% discount on car repairs. Enjoy using our Tripz app and be part of our Tripz family."
.tr,
style: Theme.of(context)
.textTheme
diff --git a/lib/views/home/Captin/mapDriverWidgets/passenger_info_window.dart b/lib/views/home/Captin/mapDriverWidgets/passenger_info_window.dart
index e1cf89b..18aadfe 100755
--- a/lib/views/home/Captin/mapDriverWidgets/passenger_info_window.dart
+++ b/lib/views/home/Captin/mapDriverWidgets/passenger_info_window.dart
@@ -13,8 +13,11 @@ import 'package:sefer_driver/controller/firebase/firbase_messge.dart';
import 'package:sefer_driver/controller/home/captin/map_driver_controller.dart';
import 'package:sefer_driver/views/widgets/elevated_btn.dart';
+import '../../../../constant/box_name.dart';
import '../../../../constant/style.dart';
import '../../../../controller/functions/launch.dart';
+import '../../../../main.dart';
+import '../../../../print.dart';
class PassengerInfoWindow extends StatelessWidget {
const PassengerInfoWindow({super.key});
@@ -179,7 +182,7 @@ class PassengerInfoWindow extends StatelessWidget {
if (await controller
.calculateDistanceBetweenDriverAndPassengerLocation() <
140) {
- FirebaseMessagesController()
+ Get.find()
.sendNotificationToDriverMAP(
'Hi ,I Arrive your site',
'I Arrive at your site'.tr,
@@ -245,7 +248,7 @@ class PassengerInfoWindow extends StatelessWidget {
MyDialog().getDialog(
'Are you sure to cancel?'.tr, '',
() async {
- FirebaseMessagesController()
+ Get.find()
.sendNotificationToDriverMAP(
'Driver Cancelled Your Trip',
'You will need to pay the cost to the driver, or it will be deducted from your next trip'
@@ -254,6 +257,9 @@ class PassengerInfoWindow extends StatelessWidget {
[],
'cancel.wav',
);
+ Log.print(
+ 'rideStatus from passenge info 261 : ${box.read(BoxName.rideStatus)}');
+ box.write(BoxName.rideStatus, 'Cancel');
await controller
.addWaitingTimeCostFromPassengerToDriverWallet();
controller.isdriverWaitTimeEnd = false;
@@ -296,7 +302,7 @@ class PassengerInfoWindow extends StatelessWidget {
_buildMessageTile(
text: "Where are you, sir?".tr,
onTap: () {
- FirebaseMessagesController().sendNotificationToDriverMAP(
+ Get.find().sendNotificationToDriverMAP(
'message From Driver',
"Where are you, sir?".tr,
controller.tokenPassenger,
@@ -309,7 +315,7 @@ class PassengerInfoWindow extends StatelessWidget {
_buildMessageTile(
text: "I've been trying to reach you but your phone is off.".tr,
onTap: () {
- FirebaseMessagesController().sendNotificationToDriverMAP(
+ Get.find().sendNotificationToDriverMAP(
'message From Driver',
"I've been trying to reach you but your phone is off.".tr,
controller.tokenPassenger,
@@ -324,7 +330,7 @@ class PassengerInfoWindow extends StatelessWidget {
"Please don't be late, I'm waiting for you at the specified location."
.tr,
onTap: () {
- FirebaseMessagesController().sendNotificationToDriverMAP(
+ Get.find().sendNotificationToDriverMAP(
'message From Driver',
"Please don't be late, I'm waiting for you at the specified location."
.tr,
@@ -338,7 +344,7 @@ class PassengerInfoWindow extends StatelessWidget {
_buildMessageTile(
text: "Please don't be late".tr,
onTap: () {
- FirebaseMessagesController().sendNotificationToDriverMAP(
+ Get.find().sendNotificationToDriverMAP(
'message From Driver',
"Please don't be late".tr,
controller.tokenPassenger,
@@ -364,7 +370,8 @@ class PassengerInfoWindow extends StatelessWidget {
),
IconButton(
onPressed: () {
- FirebaseMessagesController().sendNotificationToDriverMAP(
+ Get.find()
+ .sendNotificationToDriverMAP(
'message From Driver',
controller.messageToPassenger.text,
controller.tokenPassenger,
diff --git a/lib/views/home/Captin/mapDriverWidgets/sos_connect.dart b/lib/views/home/Captin/mapDriverWidgets/sos_connect.dart
index c0e8942..cd4a759 100755
--- a/lib/views/home/Captin/mapDriverWidgets/sos_connect.dart
+++ b/lib/views/home/Captin/mapDriverWidgets/sos_connect.dart
@@ -171,7 +171,7 @@ class SosConnect extends StatelessWidget {
} else {
throw 'Could not launch google maps';
}
- };
+ }();
}
void _sendWhatsAppMessage(MapDriverController mapDriverController) {
diff --git a/lib/views/home/Captin/orderCaptin/order_over_lay.dart b/lib/views/home/Captin/orderCaptin/order_over_lay.dart
index c2d4d0c..2575a66 100755
--- a/lib/views/home/Captin/orderCaptin/order_over_lay.dart
+++ b/lib/views/home/Captin/orderCaptin/order_over_lay.dart
@@ -1,31 +1,32 @@
import 'dart:async';
-import 'dart:convert'; // لإضافة jsonEncode إذا احتجت له لاحقًا
import 'package:flutter/material.dart';
import 'package:flutter_overlay_window/flutter_overlay_window.dart';
import 'package:get/get.dart';
import 'package:just_audio/just_audio.dart';
-// تأكد من صحة هذه المسارات
+import 'package:sefer_driver/constant/api_key.dart';
import '../../../../constant/box_name.dart';
import '../../../../constant/links.dart';
+import '../../../../controller/firebase/local_notification.dart';
import '../../../../controller/functions/crud.dart';
-import '../../../../main.dart'; // للحصول على `box`
-import '../../../../models/model/order_data.dart'; // مسار نموذج البيانات المحدث
+import '../../../../main.dart';
+import '../../../../models/model/order_data.dart';
+import '../../../../print.dart';
-// --- الألوان ---
-class OverlayColors {
- static const Color primaryBackground = Color(0xFF2C3E50);
- static const Color cardBackground = Color(0xFF34495E);
- static const Color primaryText = Colors.white;
- static const Color secondaryText = Color(0xFFBDC3C7);
- static const Color accentColor = Color(0xFF1ABC9C);
- static const Color acceptButton = Color(0xFF2ECC71);
- static const Color rejectButton = Color(0xFFE74C3C);
- static const Color highlightColor = Color(0xFFF1C40F);
+// === Enhanced Colors for Better Readability ===
+class AppColors {
+ static const primary = Color(0xFF1A252F);
+ static const card = Color(0xFF2C3E50);
+ static const white = Colors.white;
+ static const gray = Color(0xFFBDC3C7);
+ static const lightGray = Color(0xFFECF0F1);
+ static const accent = Color(0xFF00BCD4);
+ static const accept = Color(0xFF4CAF50);
+ static const reject = Color(0xFFFF5722);
+ static const highlight = Color(0xFFFFC107);
+ static const priceHighlight = Color(0xFF00E676);
+ static const urgentRed = Color(0xFFD32F2F);
}
-// --- OrderData Model (يفترض أنه موجود في ملف منفصل كما هو الحال عادةً) ---
-// class OrderData { ... } // الكود الخاص بـ OrderData الذي قدمته/عدلناه
-
class OrderOverlay extends StatefulWidget {
const OrderOverlay({Key? key}) : super(key: key);
@@ -35,86 +36,60 @@ class OrderOverlay extends StatefulWidget {
class _OrderOverlayState extends State
with WidgetsBindingObserver {
- OrderData? _orderData;
- Timer? _timer;
- int _remainingSeconds = 20; // الوقت الافتراضي للمؤقت بالثواني
- final AudioPlayer _audioPlayer = AudioPlayer();
- bool _buttonsEnabled = true;
+ // === State Variables ===
+ OrderData? orderData;
+ Timer? timer;
+ int remainingSeconds = 10;
+ final AudioPlayer audioPlayer = AudioPlayer();
+ bool buttonsEnabled = true;
+ final String mapApiKey = AK.mapAPIKEY;
+ final CRUD _crud = CRUD();
- final String _googleStaticMapsApiKey =
- "YOUR_GOOGLE_STATIC_MAPS_API_KEY_HERE"; // !!! استبدل هذا بمفتاحك !!!
-
- bool get _canShowStaticMap {
- if (_orderData == null ||
- _googleStaticMapsApiKey == "YOUR_GOOGLE_STATIC_MAPS_API_KEY_HERE") {
- return false;
- }
- final startCoords = _orderData!.startCoordinates;
- final endCoords = _orderData!.endCoordinates;
- return startCoords?['lat'] != null &&
- startCoords?['lng'] != null &&
- endCoords?['lat'] != null &&
- endCoords?['lng'] != null;
+ final NotificationController notificationController =
+ Get.put(NotificationController());
+ // === Getters ===
+ bool get canShowMap {
+ if (orderData == null || mapApiKey.isEmpty) return false;
+ final start = orderData!.startCoordinates;
+ final end = orderData!.endCoordinates;
+ return start?['lat'] != null &&
+ start?['lng'] != null &&
+ end?['lat'] != null &&
+ end?['lng'] != null;
}
+ String get staticMapUrl {
+ if (!canShowMap) return "";
+ final start = orderData!.startCoordinates!;
+ final end = orderData!.endCoordinates!;
+ final startMarker = Uri.encodeComponent("${start['lat']},${start['lng']}");
+ final endMarker = Uri.encodeComponent("${end['lat']},${end['lng']}");
+
+ return "https://maps.googleapis.com/maps/api/staticmap?"
+ "size=600x150&maptype=roadmap"
+ "&markers=color:green%7Clabel:S%7C$startMarker"
+ "&markers=color:red%7Clabel:D%7C$endMarker"
+ "&path=color:0x007bff%7Cweight:5%7C$startMarker%7C$endMarker"
+ "&key=$mapApiKey";
+ }
+
+ // === Lifecycle ===
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
- _setupOverlayListener();
- // // للاختبار، يمكنك إرسال بيانات ثابتة بعد ثانية
- // Future.delayed(Duration(seconds: 1), () {
- // if (mounted) {
- // _processEventData(testList); // تأكد أن testList معرفة إذا كنت تستخدم هذا
- // }
- // });
- }
-
- void _setupOverlayListener() {
FlutterOverlayWindow.overlayListener.listen((event) {
- if (mounted) {
- _processEventData(event);
- }
+ if (mounted) _processEventData(event);
});
}
- void _processEventData(dynamic event) {
- _printToMainApp("Overlay: Received event data: $event");
-
- if (event is List) {
- _printToMainApp("Overlay: Event list length: ${event.length}");
- if (event.length > 33) {
- // مثال للتحقق من الطول قبل الوصول للفهارس
- _printToMainApp("Overlay: list[0] (rawStartCoords): ${event[0]}");
- _printToMainApp(
- "Overlay: list[15] (durationToPassengerSec): ${event[15]}");
- }
-
- try {
- final newOrderData = OrderData.fromList(event);
- _printToMainApp("Overlay: Parsed OrderData: ${newOrderData.toMap()}");
-
- setState(() {
- _orderData = newOrderData;
- _remainingSeconds = 20;
- });
- _resetAndStartTimer();
- } catch (e, s) {
- _printToMainApp("Overlay: Error parsing OrderData: $e\nStackTrace: $s");
- }
- } else if (event is Map && event['type'] == 'close_overlay_request') {
- _closeOverlay();
- } else {
- _printToMainApp(
- "Overlay: Received unexpected data format or type: $event");
- }
- }
-
- // دالة لإرسال رسائل الطباعة للتطبيق الرئيسي
- void _printToMainApp(String message) {
- // قم بتعليق هذه إذا كانت تسبب مشاكل أو إذا لم يكن لديك مستمع في التطبيق الرئيسي
- // FlutterOverlayWindow.shareData({'type': 'debug_log', 'message': "OVERLAY: $message"});
- print("OVERLAY_PRINT: $message"); // اطبعها محليًا أيضًا كاحتياط
+ @override
+ void dispose() {
+ timer?.cancel();
+ _stopAudio();
+ audioPlayer.dispose();
+ WidgetsBinding.instance.removeObserver(this);
+ super.dispose();
}
@override
@@ -124,296 +99,330 @@ class _OrderOverlayState extends State
}
}
+ List myList = [];
+ // === Setup & Listeners ===
+ void _setupOverlayListener() {
+ FlutterOverlayWindow.overlayListener.listen((event) {
+ if (mounted) _processEventData(event);
+ });
+ }
+
+ void _processEventData(dynamic event) {
+ _log("Received event: $event");
+ if (event is List) {
+ try {
+ myList = event;
+ final newOrder = OrderData.fromList(event);
+ _log("Parsed OrderData: ${newOrder.toMap()}");
+ setState(() {
+ orderData = newOrder;
+ });
+ _resetAndStartTimer();
+ } catch (e, s) {
+ _log("Error parsing OrderData: $e\nStackTrace: $s");
+ }
+ } else {
+ _log("Unexpected data format: $event");
+ }
+ }
+
void _checkOverlayStatus() async {
bool isActive = await FlutterOverlayWindow.isActive();
- if (isActive && mounted && _orderData != null) {
- if (_remainingSeconds > 0 && (_timer == null || !_timer!.isActive)) {
+ if (isActive && mounted && orderData != null) {
+ if (remainingSeconds > 0 && (timer == null || !timer!.isActive)) {
_resetAndStartTimer();
}
}
}
+ // === Timer Management ===
void _resetAndStartTimer() {
- _timer?.cancel();
- _audioPlayer.stop();
+ timer?.cancel();
+ audioPlayer.stop();
setState(() {
- _buttonsEnabled = true;
- _remainingSeconds = 20;
+ buttonsEnabled = true;
+ remainingSeconds = _calculateTimerDuration();
});
_playAudio();
_startTimer();
}
- void _startTimer() {
- if (_orderData == null) return;
- if (_remainingSeconds <= 0) _remainingSeconds = 20;
+ int _calculateTimerDuration() {
+ if (orderData?.durationToPassengerMinutes != null &&
+ orderData!.durationToPassengerMinutes > 0) {
+ int duration = orderData!.durationToPassengerMinutes * 60;
+ return duration > 10 ? 10 : duration;
+ }
+ return 10;
+ }
- _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
+ void _startTimer() {
+ if (orderData == null) return;
+ timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (!mounted) {
timer.cancel();
_stopAudio();
return;
}
setState(() {
- if (_remainingSeconds > 0) {
- _remainingSeconds--;
+ if (remainingSeconds > 0) {
+ remainingSeconds--;
} else {
timer.cancel();
_stopAudio();
- if (_buttonsEnabled) {
- _handleOrderTimeout();
- }
+ if (buttonsEnabled) _handleOrderTimeout();
}
});
});
}
+ // === Audio Management ===
void _playAudio() async {
try {
- await _audioPlayer.setAsset('assets/order.mp3', preload: true);
- await _audioPlayer.setLoopMode(LoopMode.one);
- await _audioPlayer.play();
+ await audioPlayer.setAsset('assets/order.mp3', preload: true);
+ await audioPlayer.setLoopMode(LoopMode.one);
+ await audioPlayer.play();
} catch (e) {
- _printToMainApp('Error playing audio: $e');
+ _log('Error playing audio: $e');
}
}
void _stopAudio() {
- _audioPlayer.stop();
+ audioPlayer.stop();
}
- @override
- void dispose() {
- _timer?.cancel();
- _stopAudio();
- _audioPlayer.dispose();
- WidgetsBinding.instance.removeObserver(this);
- super.dispose();
- }
-
- Future _closeOverlay() async {
- _stopAudio();
- if (await FlutterOverlayWindow.isActive()) {
- await FlutterOverlayWindow.closeOverlay();
+ String _getData(int index, {String defaultValue = ''}) {
+ if (myList.length > index && myList[index] != null) {
+ return myList[index].toString();
}
+ return defaultValue;
}
- void _disableButtonsAndProcess() {
- setState(() {
- _buttonsEnabled = false;
- });
- _timer?.cancel();
- _stopAudio();
- }
-
+ // === Order Actions ===
Future _acceptOrder() async {
- if (!_buttonsEnabled || _orderData == null) return;
+ if (!buttonsEnabled || orderData == null) return;
_disableButtonsAndProcess();
- _printToMainApp("Order ACCEPTED: ${_orderData!.orderId}");
- try {
- // هنا يجب أن يكون طلب API الفعلي لقبول الطلب على السيرفر
- // مثال:
- // await CRUD().post(link: AppLink.acceptOrderLink, payload: { ... });
- _printToMainApp(
- "SIMULATING API CALL: Order Accepted on Server for ${_orderData!.orderId}");
+ _log("Order ACCEPTED: ${orderData!.orderId}");
- await _closeOverlay();
- await FlutterOverlayWindow.shareData({
- 'action': 'navigate_to_trip_acceptance',
- 'order_id': _orderData!.orderId,
- 'order_data_map': _orderData!.toMap(),
+ try {
+ final driverId = box.read(BoxName.driverID)?.toString();
+ if (driverId == null) {
+ _log("Error: Driver ID is null. Closing overlay.");
+ await _closeOverlay();
+ return;
+ }
+
+ var res = await CRUD().post(link: AppLink.updateStausFromSpeed, payload: {
+ 'id': orderData!.orderId,
+ 'rideTimeStart': DateTime.now().toString(),
+ 'status': 'Apply',
+ 'driver_id': box.read(BoxName.driverID),
});
- // لا تستدعي launchApplication() إذا كنت ستعتمد على الطريقة الأصلية أو deep link
- } catch (e) {
- _printToMainApp("Error accepting order: $e");
- if (mounted) setState(() => _buttonsEnabled = true);
+ if (AppLink.endPoint != AppLink.seferCairoServer) {
+ CRUD().post(
+ link: "${AppLink.endPoint}/ride/rides/updateStausFromSpeed.php",
+ payload: {
+ 'id': orderData!.orderId,
+ 'rideTimeStart': DateTime.now().toString(),
+ 'status': 'Apply',
+ 'driver_id': box.read(BoxName.driverID),
+ });
+ }
+ final payload = {
+ // بيانات أساسية
+ 'driver_id': driverId,
+ 'status': 'Apply',
+ 'passengerLocation': _getData(0),
+ 'passengerDestination': _getData(1),
+ 'Duration': _getData(4),
+ 'totalCost': _getData(26),
+ 'Distance': _getData(5),
+ 'name': _getData(8),
+ 'phone': _getData(10),
+ 'email': _getData(28),
+ 'WalletChecked': _getData(13),
+ 'tokenPassenger': _getData(9),
+ 'direction': staticMapUrl.toString(),
+ 'DurationToPassenger': _getData(15),
+ 'rideId': orderData!.orderId,
+ 'passengerId': _getData(7),
+ 'durationOfRideValue': _getData(19),
+ 'paymentAmount': _getData(2),
+ 'paymentMethod': _getData(13) == 'true' ? 'visa' : 'cash',
+ 'isHaveSteps': _getData(20),
+ 'step0': myList[21].toString(),
+ 'step1': myList[22].toString(),
+ 'step2': myList[23].toString(),
+ 'step3': myList[24].toString(),
+ 'step4': myList[25].toString(),
+ 'passengerWalletBurc': myList[26].toString(),
+ 'carType': myList[31].toString(),
+ 'kazan': myList[32].toString(),
+ 'startNameLocation': myList[29].toString(),
+ 'endNameLocation': myList[30].toString(),
+ // الحقول الإضافية التي يجب تضمينها
+ 'timeOfOrder': DateTime.now().toIso8601String(),
+ 'totalPassenger': _getData(2),
+ };
+ Log.print('myList: ${myList}');
+ Log.print('payload: ${payload}');
+ CRUD().post(
+ link: AppLink.addOverLayStatus,
+ payload: payload,
+ );
+ if (res != "failure") {
+ // Using rideId (_getData(16)) for order_id consistently
+ CRUD().post(link: AppLink.addDriverOrder, payload: {
+ 'driver_id': driverId, // Driver ID from the order data
+ 'order_id': orderData!.orderId,
+ 'status': 'Apply'
+ });
+
+ if (AppLink.endPoint != AppLink.seferCairoServer) {
+ CRUD().post(
+ link: "${AppLink.endPoint}/ride/driver_order/add.php",
+ payload: {
+ 'driver_id': driverId,
+ 'order_id': orderData!.orderId,
+ 'status': 'Apply'
+ });
+ }
+ _log("Server update successful. Writing to storage.");
+ notificationController.showNotification(
+ "Order Accepted".tr,
+ "Open app and go to passenger".tr,
+ 'ding',
+ '',
+ );
+ await _closeOverlay();
+ } else {
+ _log("Failed to update order status on server: $res");
+ notificationController.showNotification(
+ "Order Accepted by another driver".tr,
+ "Open app and go to passenger".tr,
+ 'ding',
+ '',
+ );
+ await _closeOverlay();
+ }
+ } catch (e, s) {
+ _log(
+ "A critical error occurred during server update: $e\nStackTrace: $s");
+ if (mounted) setState(() => buttonsEnabled = true);
+ return;
}
}
+ // Your list parsing for 'customerToken' should be something like:
+ // customerToken: list.length > a_certain_index ? list[a_certain_index].toString() : null,
Future _rejectOrder() async {
- if (!_buttonsEnabled || _orderData == null) return;
+ if (!buttonsEnabled || orderData == null) return;
_disableButtonsAndProcess();
- _printToMainApp("Order REJECTED: ${_orderData!.orderId}");
+ _log("Order REJECTED: ${orderData!.orderId}");
box.write(BoxName.rideStatus, 'reject');
- await _apiRefuseOrder(_orderData!.orderId);
+ Log.print('rideStatus from overlay 303 : ${box.read(BoxName.rideStatus)}');
+ await _apiRefuseOrder(orderData!.orderId);
await _closeOverlay();
}
void _handleOrderTimeout() {
- if (_orderData == null) return;
- _printToMainApp("Order TIMED OUT: ${_orderData!.orderId}");
+ if (orderData == null) return;
+ _log("Order TIMED OUT: ${orderData!.orderId}");
_rejectOrder();
}
Future _apiRefuseOrder(String orderID) async {
if (orderID == "N/A") {
- _printToMainApp("Cannot refuse order with N/A ID");
- if (mounted) setState(() => _buttonsEnabled = true);
+ _log("Cannot refuse order with N/A ID");
return;
}
try {
- // تأكد من أن box.read(BoxName.driverID) يعيد قيمة صالحة
final driverId = box.read(BoxName.driverID)?.toString();
if (driverId == null) {
- _printToMainApp("Driver ID is null, cannot refuse order.");
- if (mounted) setState(() => _buttonsEnabled = true);
+ _log("Driver ID is null, cannot refuse order");
return;
}
-
- await CRUD().post(link: AppLink.addDriverOrder, payload: {
+ await _crud.post(link: AppLink.addDriverOrder, payload: {
'driver_id': driverId,
'order_id': orderID,
'status': 'Refused'
});
- await CRUD().post(link: AppLink.updateRides, payload: {
+ await _crud.post(link: AppLink.updateRides, payload: {
'id': orderID,
'status': 'Refused',
'driver_id': driverId,
});
- _printToMainApp("Order $orderID refused successfully.");
+ _log("Order $orderID refused successfully");
} catch (e) {
- _printToMainApp("Error in _apiRefuseOrder for $orderID: $e");
- if (mounted) setState(() => _buttonsEnabled = true);
+ _log("Error in _apiRefuseOrder for $orderID: $e");
}
}
+ // === Helper Methods ===
+ void _disableButtonsAndProcess() {
+ setState(() => buttonsEnabled = false);
+ timer?.cancel();
+ _stopAudio();
+ }
+
+ Future _closeOverlay() async {
+ _stopAudio();
+ timer?.cancel();
+ if (await FlutterOverlayWindow.isActive()) {
+ await FlutterOverlayWindow.closeOverlay();
+ }
+ }
+
+ void _log(String message) {
+ // A simple logger to distinguish overlay logs
+ print("OVERLAY_LOG: $message");
+ }
+
+ // === UI Build Methods ===
@override
Widget build(BuildContext context) {
- if (_orderData == null) {
+ // ... (Your entire UI build method remains unchanged) ...
+ // The UI code is excellent and doesn't need modification.
+ if (orderData == null) {
return const Material(
color: Colors.transparent,
child: Center(
- child:
- CircularProgressIndicator(color: OverlayColors.accentColor)));
- }
-
- final order = _orderData!;
- String staticMapUrl = "";
-
- if (_canShowStaticMap) {
- final startCoords = order.startCoordinates!;
- final endCoords = order.endCoordinates!;
- final startMarker =
- Uri.encodeComponent("${startCoords['lat']},${startCoords['lng']}");
- final endMarker =
- Uri.encodeComponent("${endCoords['lat']},${endCoords['lng']}");
- staticMapUrl =
- "https://maps.googleapis.com/maps/api/staticmap?size=600x200&maptype=roadmap" // تقليل الارتفاع قليلاً
- "&markers=color:green%7Clabel:S%7C$startMarker"
- "&markers=color:red%7Clabel:D%7C$endMarker"
- "&path=color:0x007bff%7Cweight:5%7C$startMarker%7C$endMarker"
- "&key=$_googleStaticMapsApiKey";
- _printToMainApp("Generated staticMapUrl: $staticMapUrl");
- } else {
- _printToMainApp(
- "_canShowStaticMap is false. Check API key and coordinates.");
- _printToMainApp("API Key used: $_googleStaticMapsApiKey");
- _printToMainApp("Start Coords: ${order.startCoordinates}");
- _printToMainApp("End Coords: ${order.endCoordinates}");
+ child: CircularProgressIndicator(color: AppColors.accent)));
}
return Material(
- color: Colors.black.withOpacity(0.3), // زيادة الشفافية للخلفية
+ color: Colors.black.withOpacity(0.4),
child: Center(
child: Container(
- // Container رئيسي للـ Overlay card
- margin: const EdgeInsets.symmetric(
- horizontal: 8.0, vertical: 10.0), // هوامش أصغر
- padding: const EdgeInsets.all(12.0), // حشوة أصغر
+ margin: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
+ padding: const EdgeInsets.all(16.0),
decoration: BoxDecoration(
- color: OverlayColors.cardBackground,
- borderRadius: BorderRadius.circular(16.0), // حواف أقل دائرية
+ color: AppColors.card,
+ borderRadius: BorderRadius.circular(20.0),
+ border: Border.all(
+ color: AppColors.accent.withOpacity(0.3), width: 1.5),
boxShadow: [
BoxShadow(
- color: Colors.black.withOpacity(0.45),
- blurRadius: 10,
- spreadRadius: 1,
+ color: Colors.black.withOpacity(0.6),
+ blurRadius: 15,
+ spreadRadius: 2,
)
],
),
- // استخدام IntrinsicHeight لجعل الـ Column يأخذ ارتفاع المحتوى
- // أو يمكنك تحديد ارتفاع ثابت للـ Container إذا كان ذلك مناسبًا
child: SingleChildScrollView(
- // مهم إذا كان المحتوى يمكن أن يتجاوز الارتفاع
child: Column(
- mainAxisSize:
- MainAxisSize.min, // مهم جدًا لجعل Column لا يتمدد بلا حدود
+ mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
- _buildHeaderWithTimer(),
- const SizedBox(height: 10),
-
- if (_canShowStaticMap && staticMapUrl.isNotEmpty)
- ClipRRect(
- borderRadius: BorderRadius.circular(10.0),
- child: Image.network(
- staticMapUrl,
- height: 110, // ارتفاع أقل للخريطة
- fit: BoxFit.cover,
- errorBuilder: (context, error, stackTrace) {
- _printToMainApp(
- "Error loading static map image: $error");
- return Container(
- height: 80, // ارتفاع أقل عند الخطأ
- decoration: BoxDecoration(
- color: OverlayColors.primaryBackground
- .withOpacity(0.25),
- borderRadius: BorderRadius.circular(8),
- ),
- child: Center(
- child: Icon(Icons.map_outlined,
- color: OverlayColors.secondaryText
- .withOpacity(0.6),
- size: 28)),
- );
- },
- loadingBuilder: (context, child, loadingProgress) {
- if (loadingProgress == null) return child;
- return SizedBox(
- height: 110,
- child: Center(
- child: CircularProgressIndicator(
- value: loadingProgress.expectedTotalBytes != null
- ? loadingProgress.cumulativeBytesLoaded /
- loadingProgress.expectedTotalBytes!
- : null,
- color: OverlayColors.accentColor,
- strokeWidth: 2.0,
- ),
- ),
- );
- },
- ),
- ),
- if (_canShowStaticMap && staticMapUrl.isNotEmpty)
- const SizedBox(height: 10),
-
- _buildRideInfoSection(order),
- const SizedBox(height: 10),
-
- _buildLocationDetail(
- icon: Icons.trip_origin_outlined, // تغيير الأيقونة
- label: "نقطة الانطلاق".tr,
- value: order.startLocationAddress,
- iconColor: Colors.greenAccent[400]!,
- ),
- Padding(
- padding: const EdgeInsets.symmetric(
- horizontal: 25.0, vertical: 3.0),
- child: Icon(Icons.more_vert_rounded,
- color: OverlayColors.secondaryText.withOpacity(0.4),
- size: 14),
- ),
- _buildLocationDetail(
- icon: Icons.flag_circle_outlined, // تغيير الأيقونة
- label: "الوجهة النهائية".tr,
- value: order.endLocationAddress,
- iconColor: Colors.redAccent[200]!, // تغيير اللون
- ),
- const SizedBox(height: 10),
- _buildPassengerAndRideTypeRow(order),
- const SizedBox(height: 16), // مسافة أكبر قبل الأزرار
- _buildActionButtons(),
+ _buildQuickHeader(),
+ const SizedBox(height: 12),
+ _buildPrimaryInfo(),
+ const SizedBox(height: 12),
+ if (canShowMap) _buildCompactMap(),
+ if (canShowMap) const SizedBox(height: 12),
+ _buildSecondaryInfo(),
+ const SizedBox(height: 16),
+ _buildEnhancedActionButtons(),
],
),
),
@@ -422,268 +431,377 @@ class _OrderOverlayState extends State
);
}
- Widget _buildHeaderWithTimer() {
- return Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- Flexible(
- // لجعل النص يتكيف مع المساحة
- child: Row(
- mainAxisSize: MainAxisSize.min, // مهم داخل Flexible
+ // All your _build... widget methods (_buildQuickHeader, _buildPrimaryInfo, etc.)
+ // are perfectly fine and do not need to be changed.
+ // ... Paste all your existing _build... methods here ...
+ Widget _buildQuickHeader() {
+ return Container(
+ padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
+ decoration: BoxDecoration(
+ gradient: LinearGradient(
+ colors: [
+ remainingSeconds <= 3
+ ? AppColors.urgentRed
+ : remainingSeconds <= 5
+ ? AppColors.highlight
+ : AppColors.accent,
+ remainingSeconds <= 3
+ ? AppColors.urgentRed.withOpacity(0.7)
+ : remainingSeconds <= 5
+ ? AppColors.highlight.withOpacity(0.7)
+ : AppColors.accent.withOpacity(0.7),
+ ],
+ ),
+ borderRadius: BorderRadius.circular(15),
+ ),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
children: [
- Icon(Icons.local_taxi_sharp,
- color: OverlayColors.highlightColor,
- size: 24), // أيقونة مختلفة
- const SizedBox(width: 6),
- Flexible(
- // لجعل النص يتكيف
- child: Text(
- "طلب توصيل".tr, // نص أقصر
- style: TextStyle(
- color: OverlayColors.primaryText,
- fontSize: 18,
- fontWeight: FontWeight.w500),
- overflow: TextOverflow.ellipsis, // إذا كان النص طويلاً
+ Icon(Icons.drive_eta_rounded, color: AppColors.white, size: 24),
+ const SizedBox(width: 8),
+ Text(
+ "طلب جديد".tr,
+ style: const TextStyle(
+ color: AppColors.white,
+ fontSize: 18,
+ fontWeight: FontWeight.w600),
+ ),
+ ],
+ ),
+ Container(
+ padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
+ decoration: BoxDecoration(
+ color: AppColors.white.withOpacity(0.9),
+ borderRadius: BorderRadius.circular(20),
+ ),
+ child: Text(
+ "$remainingSeconds ث",
+ style: TextStyle(
+ color: remainingSeconds <= 3
+ ? AppColors.urgentRed
+ : remainingSeconds <= 5
+ ? AppColors.highlight
+ : AppColors.accent,
+ fontSize: 20,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+
+ Widget _buildPrimaryInfo() {
+ final order = orderData!;
+ return Container(
+ padding: const EdgeInsets.all(16),
+ decoration: BoxDecoration(
+ color: AppColors.primary.withOpacity(0.6),
+ borderRadius: BorderRadius.circular(12),
+ border: Border.all(
+ color: AppColors.priceHighlight.withOpacity(0.3), width: 1),
+ ),
+ child: Column(
+ children: [
+ // Price and Distance - Most Important Info
+ Row(
+ children: [
+ Expanded(
+ flex: 3,
+ child: _buildHighlightInfo("\$${order.price}", "السعر".tr,
+ Icons.monetization_on_rounded, AppColors.priceHighlight,
+ isLarge: true),
+ ),
+ const SizedBox(width: 12),
+ Expanded(
+ flex: 2,
+ child: _buildHighlightInfo(
+ "${order.tripDistanceKm.toStringAsFixed(1)} كم",
+ "المسافة".tr,
+ Icons.straighten_rounded,
+ AppColors.accent,
),
),
],
),
- ),
- Container(
- padding: const EdgeInsets.symmetric(
- horizontal: 10, vertical: 5), // حشوة أصغر للعداد
- decoration: BoxDecoration(
- color: _remainingSeconds <= 5
- ? OverlayColors.rejectButton.withOpacity(0.75)
- : OverlayColors.primaryBackground.withOpacity(0.7),
- borderRadius: BorderRadius.circular(14),
- border: Border.all(
- color: OverlayColors.accentColor.withOpacity(0.6),
- width: 0.7)),
- child: Text(
- _remainingSeconds.toString(),
- style: TextStyle(
- color: OverlayColors.primaryText,
- fontSize: 17,
- fontWeight: FontWeight.bold,
- fontFeatures: [FontFeature.tabularFigures()]),
- ),
- ),
- ],
- );
- }
-
- Widget _buildRideInfoSection(OrderData order) {
- return Container(
- padding:
- const EdgeInsets.symmetric(vertical: 8, horizontal: 6), // حشوة أصغر
- decoration: BoxDecoration(
- color: OverlayColors.primaryBackground.withOpacity(0.55),
- borderRadius: BorderRadius.circular(8), // حواف أقل دائرية
- ),
- child: Column(
- children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceAround,
- children: [
- Expanded(
- child: _infoChip(
- "السعر".tr,
- "\$${order.price}",
- Icons.attach_money_outlined,
- OverlayColors.highlightColor,
- valueFontSize: 15)),
- Expanded(
- child: _infoChip(
- "مسافة الرحلة".tr,
- "${order.tripDistanceKm.toStringAsFixed(1)} كم",
- Icons.swap_calls_rounded,
- OverlayColors.accentColor,
- valueFontSize: 15)), // أيقونة مختلفة
- ],
- ),
- const SizedBox(height: 6),
- Divider(
- color: OverlayColors.secondaryText.withOpacity(0.15),
- height: 0.5,
- thickness: 0.5), // فاصل أرق
- const SizedBox(height: 6),
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceAround,
- children: [
- Expanded(
- child: _infoChip(
- "لوصولك للراكب".tr,
- "~${order.durationToPassengerMinutes} د",
- Icons.schedule_outlined,
- OverlayColors.secondaryText,
- valueFontSize: 14)), // اختصار "دقيقة"
- Expanded(
- child: _infoChip(
- "مسافة للراكب".tr,
- "${order.distanceToPassengerKm.toStringAsFixed(1)} كم",
- Icons.person_pin_circle_outlined,
- OverlayColors.secondaryText,
- valueFontSize: 14)), // أيقونة مختلفة
- ],
- ),
- if (order.tripDurationMinutes > 0) ...[
- const SizedBox(height: 6),
- Divider(
- color: OverlayColors.secondaryText.withOpacity(0.15),
- height: 0.5,
- thickness: 0.5),
- const SizedBox(height: 6),
- Row(
- // استخدام Row لجعل الـ _infoChip يتمدد
- children: [
- Expanded(
- child: _infoChip(
- "مدة الرحلة".tr,
- "~${order.tripDurationMinutes} د",
- Icons.timelapse_outlined,
- OverlayColors.accentColor,
- valueFontSize: 14) // اختصار
- ),
- ],
- ),
- ]
- ],
- ));
- }
-
- Widget _infoChip(String label, String value, IconData icon, Color iconColor,
- {double valueFontSize = 13}) {
- // تم إزالة Expanded من هنا، ووضعها عند استدعاء _infoChip إذا لزم الأمر
- return Column(
- mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- Icon(icon, color: iconColor, size: 17), // أيقونة أصغر
- const SizedBox(height: 1),
- Text(label,
- style: TextStyle(
- color: OverlayColors.secondaryText.withOpacity(0.85),
- fontSize: 9.5),
- textAlign: TextAlign.center,
- overflow: TextOverflow.ellipsis), // خط أصغر للعنوان
- // const SizedBox(height: 0.5),
- Text(value,
- style: TextStyle(
- color: OverlayColors.primaryText,
- fontSize: valueFontSize,
- fontWeight: FontWeight.w500),
- textAlign: TextAlign.center,
- overflow: TextOverflow.ellipsis), // خط أصغر للقيمة
- ],
- );
- }
-
- Widget _buildLocationDetail({
- required IconData icon,
- required String label,
- required String value,
- Color iconColor = OverlayColors.accentColor,
- }) {
- return Row(
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- Icon(icon, color: iconColor, size: 16), // أيقونة أصغر
- const SizedBox(width: 6),
- Expanded(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisSize: MainAxisSize.min, // مهم
+ const SizedBox(height: 12),
+ Divider(color: AppColors.gray.withOpacity(0.2), thickness: 1),
+ const SizedBox(height: 12),
+ // Passenger Info and ETA
+ Row(
children: [
- Text(
- label,
- style: TextStyle(
- color: OverlayColors.secondaryText.withOpacity(0.75),
- fontSize: 9.5,
- fontWeight: FontWeight.w300),
+ Expanded(
+ flex: 2,
+ child: _buildPassengerQuickInfo(),
),
- Text(
- value,
- style: TextStyle(
- color: OverlayColors.primaryText,
- fontSize: 12.5,
- fontWeight: FontWeight.normal),
- overflow: TextOverflow.ellipsis,
- maxLines: 2,
+ const SizedBox(width: 12),
+ Expanded(
+ child: _buildHighlightInfo(
+ "${order.durationToPassengerMinutes} د",
+ "للوصول".tr,
+ Icons.access_time_filled_rounded,
+ order.durationToPassengerMinutes <= 3
+ ? AppColors.priceHighlight
+ : AppColors.gray,
+ ),
),
],
),
- ),
- ],
+ ],
+ ),
);
}
- Widget _buildPassengerAndRideTypeRow(OrderData order) {
+ Widget _buildHighlightInfo(
+ String value, String label, IconData icon, Color color,
+ {bool isLarge = false}) {
+ return Container(
+ padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
+ decoration: BoxDecoration(
+ color: color.withOpacity(0.1),
+ borderRadius: BorderRadius.circular(10),
+ border: Border.all(color: color.withOpacity(0.3), width: 1),
+ ),
+ child: Column(
+ children: [
+ Icon(icon, color: color, size: isLarge ? 24 : 20),
+ const SizedBox(height: 4),
+ Text(
+ value,
+ style: TextStyle(
+ color: AppColors.white,
+ fontSize: isLarge ? 20 : 16,
+ fontWeight: FontWeight.bold,
+ ),
+ textAlign: TextAlign.center,
+ ),
+ Text(
+ label,
+ style: TextStyle(
+ color: AppColors.lightGray.withOpacity(0.7),
+ fontSize: 11,
+ ),
+ textAlign: TextAlign.center,
+ ),
+ ],
+ ),
+ );
+ }
+
+ Widget _buildPassengerQuickInfo() {
+ final order = orderData!;
+ return Container(
+ padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
+ decoration: BoxDecoration(
+ color: AppColors.highlight.withOpacity(0.1),
+ borderRadius: BorderRadius.circular(10),
+ border:
+ Border.all(color: AppColors.highlight.withOpacity(0.3), width: 1),
+ ),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ children: [
+ Icon(Icons.person_rounded, color: AppColors.highlight, size: 18),
+ const SizedBox(width: 4),
+ Expanded(
+ child: Text(
+ order.customerName,
+ style: const TextStyle(
+ color: AppColors.white,
+ fontSize: 14,
+ fontWeight: FontWeight.w600,
+ ),
+ overflow: TextOverflow.ellipsis,
+ ),
+ ),
+ ],
+ ),
+ const SizedBox(height: 2),
+ Text(
+ order.rideType,
+ style: TextStyle(
+ color: AppColors.lightGray.withOpacity(0.7),
+ fontSize: 11,
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+
+ Widget _buildCompactMap() {
+ return ClipRRect(
+ borderRadius: BorderRadius.circular(12.0),
+ child: Image.network(
+ staticMapUrl,
+ height: 100, // Reduced from 110
+ fit: BoxFit.cover,
+ errorBuilder: (context, error, stackTrace) {
+ return Container(
+ height: 100,
+ decoration: BoxDecoration(
+ color: AppColors.primary.withOpacity(0.3),
+ borderRadius: BorderRadius.circular(12),
+ ),
+ child: const Center(
+ child:
+ Icon(Icons.map_outlined, color: AppColors.gray, size: 32)),
+ );
+ },
+ loadingBuilder: (context, child, loadingProgress) {
+ if (loadingProgress == null) return child;
+ return SizedBox(
+ height: 100,
+ child: Center(
+ child: CircularProgressIndicator(
+ value: loadingProgress.expectedTotalBytes != null
+ ? loadingProgress.cumulativeBytesLoaded /
+ loadingProgress.expectedTotalBytes!
+ : null,
+ color: AppColors.accent,
+ strokeWidth: 2.0,
+ ),
+ ),
+ );
+ },
+ ),
+ );
+ }
+
+ Widget _buildSecondaryInfo() {
+ final order = orderData!;
+ return Container(
+ padding: const EdgeInsets.all(12),
+ decoration: BoxDecoration(
+ color: AppColors.primary.withOpacity(0.4),
+ borderRadius: BorderRadius.circular(10),
+ ),
+ child: Column(
+ children: [
+ _buildLocationRow(
+ Icons.trip_origin_rounded,
+ "من".tr,
+ order.startLocationAddress,
+ Colors.green.shade300,
+ ),
+ const SizedBox(height: 8),
+ _buildLocationRow(
+ Icons.flag_rounded,
+ "إلى".tr,
+ order.endLocationAddress,
+ Colors.red.shade300,
+ ),
+ if (order.tripDurationMinutes > 0) ...[
+ const SizedBox(height: 8),
+ Divider(color: AppColors.gray.withOpacity(0.2), thickness: 0.5),
+ const SizedBox(height: 8),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Icon(Icons.timer_outlined, color: AppColors.accent, size: 16),
+ const SizedBox(width: 4),
+ Text(
+ "مدة الرحلة: ${order.tripDurationMinutes} دقيقة".tr,
+ style: const TextStyle(
+ color: AppColors.lightGray,
+ fontSize: 12,
+ ),
+ ),
+ ],
+ ),
+ ]
+ ],
+ ),
+ );
+ }
+
+ Widget _buildLocationRow(
+ IconData icon, String label, String address, Color iconColor) {
return Row(
children: [
- Expanded(
- child: _buildLocationDetail(
- icon: Icons.person_search_outlined, // أيقونة مختلفة
- label: "الراكب".tr,
- value: order.customerName,
- iconColor: OverlayColors.highlightColor.withOpacity(0.75),
- ),
- ),
+ Icon(icon, color: iconColor, size: 16),
const SizedBox(width: 8),
+ Text(
+ "$label: ",
+ style: TextStyle(
+ color: AppColors.lightGray.withOpacity(0.8),
+ fontSize: 12,
+ fontWeight: FontWeight.w500,
+ ),
+ ),
Expanded(
- child: _buildLocationDetail(
- icon: Icons.category_outlined, // أيقونة مختلفة
- label: "نوع الطلب".tr,
- value: order.rideType,
- iconColor: OverlayColors.accentColor.withOpacity(0.75),
+ child: Text(
+ address,
+ style: const TextStyle(
+ color: AppColors.white,
+ fontSize: 12,
+ ),
+ overflow: TextOverflow.ellipsis,
+ maxLines: 1,
),
),
],
);
}
- Widget _buildActionButtons() {
+ Widget _buildEnhancedActionButtons() {
return Row(
children: [
Expanded(
- child: ElevatedButton.icon(
- icon: const Icon(Icons.close_fullscreen_rounded,
- color: Colors.white, size: 17), // أيقونة مختلفة
- label: Text("رفض".tr,
- style: const TextStyle(
- color: Colors.white,
- fontSize: 13.5,
- fontWeight: FontWeight.w500)),
- onPressed: _buttonsEnabled ? _rejectOrder : null,
+ child: ElevatedButton(
+ onPressed: buttonsEnabled ? _rejectOrder : null,
style: ElevatedButton.styleFrom(
- backgroundColor: OverlayColors.rejectButton.withOpacity(0.85),
- padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 6),
+ backgroundColor: AppColors.reject,
+ foregroundColor: AppColors.white,
+ padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(7)),
- disabledBackgroundColor:
- OverlayColors.rejectButton.withOpacity(0.25),
+ borderRadius: BorderRadius.circular(12)),
+ disabledBackgroundColor: AppColors.reject.withOpacity(0.3),
+ elevation: 3,
+ ),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ const Icon(Icons.close_rounded, size: 20),
+ const SizedBox(width: 6),
+ Text(
+ "رفض".tr,
+ style: const TextStyle(
+ fontSize: 16, fontWeight: FontWeight.w600),
+ ),
+ ],
),
),
),
- const SizedBox(width: 7),
+ const SizedBox(width: 12),
Expanded(
- child: ElevatedButton.icon(
- icon: const Icon(Icons.task_alt_rounded,
- color: Colors.white, size: 17), // أيقونة مختلفة
- label: Text("قبول".tr,
- style: const TextStyle(
- color: Colors.white,
- fontSize: 13.5,
- fontWeight: FontWeight.w500)),
- onPressed: _buttonsEnabled ? _acceptOrder : null,
+ child: ElevatedButton(
+ onPressed: buttonsEnabled ? _acceptOrder : null,
style: ElevatedButton.styleFrom(
- backgroundColor: OverlayColors.acceptButton.withOpacity(0.85),
- padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 6),
+ backgroundColor: AppColors.accept,
+ foregroundColor: AppColors.white,
+ padding: const EdgeInsets.symmetric(vertical: 14),
shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(7)),
- disabledBackgroundColor:
- OverlayColors.acceptButton.withOpacity(0.25),
+ borderRadius: BorderRadius.circular(12)),
+ disabledBackgroundColor: AppColors.accept.withOpacity(0.3),
+ elevation: 3,
+ ),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ const Icon(Icons.check_circle_rounded, size: 20),
+ const SizedBox(width: 6),
+ Text(
+ "قبول".tr,
+ style: const TextStyle(
+ fontSize: 16, fontWeight: FontWeight.w600),
+ ),
+ ],
),
),
),
diff --git a/lib/views/home/Captin/orderCaptin/order_speed_request.dart b/lib/views/home/Captin/orderCaptin/order_speed_request.dart
index 325a924..aa5771f 100755
--- a/lib/views/home/Captin/orderCaptin/order_speed_request.dart
+++ b/lib/views/home/Captin/orderCaptin/order_speed_request.dart
@@ -1,554 +1,603 @@
-import 'dart:convert';
+import 'dart:convert'; // Though not directly used in this version's UI logic, often kept for model interactions.
import 'package:sefer_driver/controller/home/captin/home_captain_controller.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sefer_driver/constant/box_name.dart';
import 'package:sefer_driver/controller/firebase/firbase_messge.dart';
-import 'package:sefer_driver/main.dart';
+import 'package:sefer_driver/main.dart'; // For `box`
import 'package:sefer_driver/views/home/Captin/driver_map_page.dart';
-import 'package:sefer_driver/views/widgets/my_scafold.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
-import '../../../../constant/colors.dart';
-import '../../../../constant/links.dart';
-import '../../../../constant/style.dart';
+import '../../../../constant/colors.dart'; // Your AppColor
+import '../../../../constant/links.dart'; // Your AppLink
+import '../../../../constant/style.dart'; // Your AppStyle
import '../../../../controller/functions/crud.dart';
import '../../../../controller/functions/launch.dart';
import '../../../../controller/home/captin/order_request_controller.dart';
-import '../../../widgets/elevated_btn.dart';
+import '../../../widgets/elevated_btn.dart'; // Your MyElevatedButton
class OrderSpeedRequest extends StatelessWidget {
OrderSpeedRequest({super.key});
- OrderRequestController orderRequestController =
+
+ final OrderRequestController orderRequestController =
Get.put(OrderRequestController());
+
+ // Helper to make myList access more readable and safer
+ String _getData(int index, {String defaultValue = ''}) {
+ if (orderRequestController.myList.length > index &&
+ orderRequestController.myList[index] != null) {
+ return orderRequestController.myList[index].toString();
+ }
+ return defaultValue;
+ }
+
@override
Widget build(BuildContext context) {
- return GetBuilder(
- builder: (orderRequestController) {
- return MyScafolld(
- title: 'Speed Order'.tr,
- body: [
- ListView(
- // crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- // SizedBox(height: 200, child: Text(pointsList.toString())),
- // Text(message.notification!.body.toString()),
- SizedBox(
- height: Get.height * .33,
- child: GoogleMap(
- initialCameraPosition: CameraPosition(
- zoom: 12,
- target: Get.find().myLocation),
- cameraTargetBounds:
- CameraTargetBounds(orderRequestController.bounds),
- myLocationButtonEnabled: true,
- trafficEnabled: false,
- buildingsEnabled: false,
- mapToolbarEnabled: true,
- myLocationEnabled: true,
- markers: {
- Marker(
- markerId: MarkerId('MyLocation'.tr),
- position: LatLng(
- orderRequestController.latPassengerLocation,
- orderRequestController.lngPassengerLocation),
- draggable: true,
- icon: orderRequestController.startIcon),
- Marker(
- markerId: MarkerId('Destination'.tr),
- position: LatLng(
- orderRequestController.latPassengerDestination,
- orderRequestController.lngPassengerDestination),
- draggable: true,
- icon: orderRequestController.endIcon),
- },
- polylines: {
- Polyline(
- zIndex: 1,
- consumeTapEvents: true,
- geodesic: true,
- endCap: Cap.buttCap,
- startCap: Cap.buttCap,
- visible: true,
- polylineId: const PolylineId('routeOrder'),
- points: orderRequestController.pointsDirection,
- color: AppColor.primaryColor,
- width: 2,
- ),
- },
- ),
- ),
- Padding(
- padding: const EdgeInsets.all(8.0),
- child: Card(
- elevation: 3,
- color: orderRequestController.myList[20].toString() ==
- 'haveSteps'
- ? AppColor.greenColor
- : AppColor.secondaryColor,
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceAround,
- children: [
- TextButton.icon(
- onPressed: () {
- String mapUrl =
- 'https://www.google.com/maps/dir/${orderRequestController.myList[0]}/${orderRequestController.myList[1]}/';
- showInBrowser(mapUrl);
- },
- icon: const Icon(Icons.map),
- label:
- orderRequestController.myList[20].toString() ==
- 'haveSteps'
- ? Text(
- 'Trip has Steps'.tr,
- style: AppStyle.title,
- )
- : Text('Payment Method'.tr,
- style: AppStyle.title)),
- Container(
- decoration: AppStyle.boxDecoration.copyWith(
- color:
- orderRequestController.myList[13].toString() ==
- 'true'
- ? AppColor.deepPurpleAccent
- : AppColor.greenColor,
- ),
- child: orderRequestController.myList[13].toString() ==
- 'true' //Visa or Cash Method from notify to driver
- ? Text(
- 'Visa',
- style: AppStyle.title,
- )
- : Text('Cash', style: AppStyle.title),
- )
- ],
- ),
- ),
- ),
+ // Define AppBar first to get its height for body calculations
+ final appBar = AppBar(
+ title: Text('Speed Order'.tr),
+ leading: IconButton(
+ icon: const Icon(Icons.arrow_back),
+ onPressed: () => Get.back(),
+ ),
+ backgroundColor: AppColor.primaryColor, // Example color, adjust as needed
+ elevation: 2.0,
+ );
- Container(
- decoration: AppStyle.boxDecoration1,
- child: Padding(
- padding: const EdgeInsets.all(8.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceAround,
- children: [
- Text(
- double.parse(orderRequestController.myList[2])
- .toStringAsFixed(2),
- style: AppStyle.headTitle2,
- ),
- AnimatedContainer(
- duration: const Duration(seconds: 5),
- curve: Curves.easeInOut,
- child: AnimatedSize(
- duration: const Duration(seconds: 5),
- curve: Curves.easeInOut,
- child: orderRequestController.myList[31]
- .toString() ==
- 'Comfort'
- ? Column(
- mainAxisAlignment:
- MainAxisAlignment.spaceAround,
+ final double appBarHeight = appBar.preferredSize.height;
+ final MediaQueryData mediaQueryData = MediaQuery.of(context);
+ final double screenHeight = mediaQueryData.size.height;
+ final double statusBarHeight = mediaQueryData.padding.top;
+ final double bottomSystemPadding = mediaQueryData.padding.bottom;
+
+ // Calculate available height for the Scaffold's body content
+ // Subtracting status bar, app bar, and bottom system padding (like navigation bar)
+ final double availableBodyHeight =
+ screenHeight - appBarHeight - statusBarHeight - bottomSystemPadding;
+
+ // Define overall padding for the body content
+ const EdgeInsets bodyContentPadding =
+ EdgeInsets.symmetric(horizontal: 10.0, vertical: 8.0);
+
+ // Calculate the height for the main content Column, considering the body's own padding
+ double mainColumnHeight = availableBodyHeight - bodyContentPadding.vertical;
+ if (mainColumnHeight < 0) mainColumnHeight = 0;
+
+ return GetBuilder(
+ builder: (controller) {
+ // Pre-extract data for readability and safety
+ final String price =
+ double.tryParse(_getData(2))?.toStringAsFixed(2) ?? 'N/A';
+ final bool isComfortTrip = _getData(31) == 'Comfort';
+ final String carType = _getData(31).tr;
+
+ final String pickupName = _getData(12);
+ final String pickupDetails = '(${_getData(11)})';
+ final String pickupFullAddress = _getData(29);
+
+ final String dropoffName = _getData(5);
+ final String dropoffDetails = '(${_getData(4)})';
+ final String dropoffFullAddress = _getData(30);
+
+ final String passengerName = _getData(8);
+ final String passengerRating = _getData(33);
+
+ final bool isVisaPayment = _getData(13) == 'true';
+ final bool hasSteps = _getData(20) == 'haveSteps';
+
+ final String mapUrl =
+ 'https://www.google.com/maps/dir/${_getData(0)}/${_getData(1)}/';
+ final String rideId = _getData(16); // Commonly used ID
+
+ return Scaffold(
+ appBar: appBar,
+ backgroundColor: AppColor.secondaryColor ??
+ Colors.grey[100], // Background for the page
+ body: SafeArea(
+ // Ensures content is not obscured by system UI
+ child: Padding(
+ padding:
+ bodyContentPadding, // Apply overall padding to the body's content area
+ child: SizedBox(
+ // Constrain the height of the main layout Column
+ height: mainColumnHeight,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ // --- MAP SECTION ---
+ SizedBox(
+ height:
+ Get.height * 0.28, // Relative to total screen height
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(15.0),
+ child: GoogleMap(
+ initialCameraPosition: CameraPosition(
+ zoom: 12,
+ target:
+ Get.find().myLocation),
+ cameraTargetBounds:
+ CameraTargetBounds(controller.bounds),
+ myLocationButtonEnabled: false,
+ trafficEnabled: false,
+ buildingsEnabled: false,
+ mapToolbarEnabled: false,
+ myLocationEnabled: true,
+ markers: {
+ Marker(
+ markerId: MarkerId('MyLocation'.tr),
+ position: LatLng(
+ controller.latPassengerLocation,
+ controller.lngPassengerLocation),
+ icon: controller.startIcon),
+ Marker(
+ markerId: MarkerId('Destination'.tr),
+ position: LatLng(
+ controller.latPassengerDestination,
+ controller.lngPassengerDestination),
+ icon: controller.endIcon),
+ },
+ polylines: {
+ Polyline(
+ zIndex: 1,
+ consumeTapEvents: true,
+ geodesic: true,
+ endCap: Cap.buttCap,
+ startCap: Cap.buttCap,
+ visible: true,
+ polylineId: const PolylineId('routeOrder'),
+ points: controller.pointsDirection,
+ color: AppColor.primaryColor,
+ width: 3,
+ ),
+ },
+ ),
+ ),
+ ),
+ const SizedBox(height: 8),
+
+ // --- PRICE & TRIP TYPE SECTION ---
+ Card(
+ elevation: 3,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12)),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ vertical: 12.0, horizontal: 16.0),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ price,
+ style: AppStyle.headTitle.copyWith(
+ color: AppColor.primaryColor,
+ fontWeight: FontWeight.bold,
+ fontSize: 28),
+ ),
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.end,
+ children: [
+ Text(
+ carType,
+ style: AppStyle.title.copyWith(
+ color: AppColor.greenColor,
+ fontWeight: FontWeight.bold),
+ ),
+ if (isComfortTrip)
+ Row(
+ children: [
+ const Icon(Icons.ac_unit,
+ color: AppColor.blueColor, size: 18),
+ const SizedBox(width: 4),
+ Text('Air condition Trip'.tr,
+ style: AppStyle.subtitle
+ .copyWith(fontSize: 13)),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ const SizedBox(height: 8),
+
+ // --- EXPANDED SECTION FOR SCROLLABLE (BUT NOT USER-SCROLLABLE) CONTENT ---
+ Expanded(
+ child: SingleChildScrollView(
+ physics:
+ const NeverScrollableScrollPhysics(), // Prevents user scrolling
+ child: Column(
+ mainAxisSize: MainAxisSize
+ .min, // Takes minimum vertical space needed
+ children: [
+ _buildLocationCard(
+ icon: Icons.arrow_circle_up,
+ iconColor: AppColor.greenColor,
+ title: pickupName,
+ subtitle: pickupDetails,
+ fullAddress: pickupFullAddress,
+ ),
+ const SizedBox(height: 8),
+ _buildLocationCard(
+ icon: Icons.arrow_circle_down,
+ iconColor: AppColor.redColor,
+ title: dropoffName,
+ subtitle: dropoffDetails,
+ fullAddress: dropoffFullAddress,
+ ),
+ const SizedBox(height: 8),
+ // --- PAYMENT, STEPS & DIRECTIONS INFO ---
+ Card(
+ elevation: 2,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(10)),
+ child: Padding(
+ padding: const EdgeInsets.all(10.0),
+ child: Row(
+ mainAxisAlignment:
+ MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
children: [
- const Icon(
- Icons.ac_unit,
- color: AppColor.blueColor,
- size: 50,
+ Icon(
+ isVisaPayment
+ ? Icons.credit_card
+ : Icons
+ .payments_outlined, // Using payments_outlined for cash
+ color: isVisaPayment
+ ? AppColor.deepPurpleAccent
+ : AppColor.greenColor,
+ size: 24,
),
+ const SizedBox(width: 8),
Text(
- 'Air condition Trip'.tr,
- style: AppStyle.subtitle,
+ isVisaPayment ? 'Visa'.tr : 'Cash'.tr,
+ style: AppStyle.title.copyWith(
+ fontWeight: FontWeight.w600),
),
],
- )
- : const SizedBox(),
+ ),
+ if (hasSteps)
+ Expanded(
+ child: Row(
+ mainAxisAlignment:
+ MainAxisAlignment.center,
+ children: [
+ const Icon(
+ Icons
+ .format_list_numbered_rtl_outlined,
+ color: AppColor.bronze,
+ size: 24),
+ const SizedBox(width: 4),
+ Flexible(
+ child: Text(
+ 'Trip has Steps'.tr,
+ style: AppStyle.title.copyWith(
+ color: AppColor.bronze,
+ fontSize: 13),
+ overflow: TextOverflow.ellipsis,
+ )),
+ ],
+ ),
+ ),
+ TextButton.icon(
+ style: TextButton.styleFrom(
+ padding: EdgeInsets.zero,
+ tapTargetSize:
+ MaterialTapTargetSize.shrinkWrap,
+ alignment: Alignment.centerRight,
+ ),
+ onPressed: () => showInBrowser(mapUrl),
+ icon: const Icon(
+ Icons.directions_outlined,
+ color: AppColor.blueColor,
+ size: 20),
+ label: Text("Directions".tr,
+ style: AppStyle.subtitle.copyWith(
+ color: AppColor.blueColor,
+ fontSize: 13)),
+ ),
+ ],
+ ),
+ ),
+ ),
+ const SizedBox(height: 8),
+ // --- PASSENGER INFO ---
+ Card(
+ elevation: 2,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(10)),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ horizontal: 16.0, vertical: 10.0),
+ child: Row(
+ children: [
+ const Icon(Icons.person_outline,
+ color: AppColor.greyColor, size: 22),
+ const SizedBox(width: 10),
+ Expanded(
+ child: Text(
+ passengerName,
+ style: AppStyle.title,
+ overflow: TextOverflow.ellipsis,
+ ),
+ ),
+ const SizedBox(width: 10),
+ const Icon(Icons.star_rounded,
+ color: Colors.amber, size: 20),
+ Text(
+ passengerRating,
+ style: AppStyle.title.copyWith(
+ fontWeight: FontWeight.bold),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ // const SizedBox(height: 8), // Spacer before action buttons if needed
+
+ // --- ACTION BUTTONS & TIMER ---
+ Padding(
+ padding: const EdgeInsets.only(top: 8.0, bottom: 5.0),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Expanded(
+ child: MyElevatedButton(
+ kolor: AppColor.greenColor,
+ title: 'Accept Order'.tr,
+ onPressed: () async {
+ Get.put(HomeCaptainController()).changeRideId();
+ box.write(BoxName.statusDriverLocation, 'on');
+ var res = await CRUD().post(
+ link: AppLink.updateStausFromSpeed,
+ payload: {
+ 'id': rideId,
+ 'rideTimeStart':
+ DateTime.now().toString(),
+ 'status': 'Apply',
+ 'driver_id': box.read(BoxName.driverID),
+ });
+ if (AppLink.endPoint !=
+ AppLink.seferCairoServer) {
+ CRUD().post(
+ link:
+ "${AppLink.endPoint}/ride/rides/updateStausFromSpeed.php",
+ payload: {
+ 'id': rideId,
+ 'rideTimeStart':
+ DateTime.now().toString(),
+ 'status': 'Apply',
+ 'driver_id': box.read(BoxName.driverID),
+ });
+ }
+ if (res != "failure") {
+ box.write(BoxName.statusDriverLocation, 'on');
+ controller.changeApplied();
+ List bodyToPassenger = [
+ box.read(BoxName.driverID).toString(),
+ box.read(BoxName.nameDriver).toString(),
+ box.read(BoxName.tokenDriver).toString(),
+ rideId.toString(),
+ ];
+ Get.put(FirebaseMessagesController())
+ .sendNotificationToDriverMAP(
+ 'Accepted Ride',
+ 'your ride is applied'.tr,
+ controller.arguments?['DriverList']
+ ?[9]
+ ?.toString() ??
+ _getData(9), // Safer access
+ bodyToPassenger,
+ 'start.wav');
+
+ // Using rideId (_getData(16)) for order_id consistently
+ CRUD().postFromDialogue(
+ link: AppLink.addDriverOrder,
+ payload: {
+ 'driver_id': _getData(
+ 6), // Driver ID from the order data
+ 'order_id': rideId,
+ 'status': 'Apply'
+ });
+
+ if (AppLink.endPoint !=
+ AppLink.seferCairoServer) {
+ CRUD().post(
+ link:
+ "${AppLink.endPoint}/ride/driver_order/add.php",
+ payload: {
+ 'driver_id': _getData(6),
+ 'order_id': rideId,
+ 'status': 'Apply'
+ });
+ }
+
+ Get.back(); // Go back from order request screen
+ box.write(BoxName.rideArguments, {
+ 'passengerLocation': _getData(0),
+ 'passengerDestination': _getData(1),
+ 'Duration': _getData(4),
+ 'totalCost': _getData(26),
+ 'Distance': _getData(5),
+ 'name': _getData(8),
+ 'phone': _getData(10),
+ 'email': _getData(28),
+ 'WalletChecked': _getData(13),
+ 'tokenPassenger': _getData(9),
+ 'direction': mapUrl,
+ 'DurationToPassenger': _getData(15),
+ 'rideId': rideId,
+ 'passengerId': _getData(7),
+ 'driverId': box
+ .read(BoxName.driverID)
+ .toString(), // Current driver accepting
+ 'durationOfRideValue': _getData(19),
+ 'paymentAmount': _getData(2),
+ 'paymentMethod': _getData(13) == 'true'
+ ? 'visa'
+ : 'cash',
+ 'isHaveSteps': _getData(20),
+ 'step0': _getData(21),
+ 'step1': _getData(22),
+ 'step2': _getData(23),
+ 'step3': _getData(24),
+ 'step4': _getData(25),
+ 'passengerWalletBurc': _getData(26),
+ 'timeOfOrder': DateTime.now().toString(),
+ 'totalPassenger': _getData(
+ 2), // This is likely trip cost for passenger
+ 'carType': _getData(31),
+ 'kazan':
+ _getData(32), // Driver's commission/cut
+ 'startNameLocation': _getData(29),
+ 'endNameLocation': _getData(30),
+ });
+ Get.to(() => PassengerLocationMapPage(),
+ arguments:
+ box.read(BoxName.rideArguments));
+ } else {
+ Get.defaultDialog(
+ title:
+ "This ride is already taken by another driver."
+ .tr,
+ middleText: '',
+ titleStyle: AppStyle.title,
+ middleTextStyle: AppStyle.title,
+ confirm: MyElevatedButton(
+ title: 'Ok'.tr,
+ onPressed: () {
+ Get.back(); // Close dialog
+ Get.back(); // Close order request screen
+ }));
+ }
+ },
),
),
- Text(
- orderRequestController.myList[31].toString().tr,
- style: AppStyle.title
- .copyWith(color: AppColor.greenColor),
+ const SizedBox(width: 10),
+ // --- TIMER ---
+ GetBuilder(
+ id: 'timerUpdate', // Ensure controller calls update(['timerUpdate']) for this
+ builder: (timerCtrl) {
+ final isNearEnd =
+ timerCtrl.remainingTimeSpeed <= 5;
+ return SizedBox(
+ width: 60,
+ height: 60,
+ child: Stack(
+ alignment: Alignment.center,
+ children: [
+ CircularProgressIndicator(
+ value: timerCtrl.progressSpeed,
+ color: isNearEnd
+ ? Colors.redAccent
+ : AppColor.primaryColor,
+ strokeWidth: 5,
+ backgroundColor: Colors.grey.shade300,
+ ),
+ Text('${timerCtrl.remainingTimeSpeed}',
+ style: AppStyle.headTitle2.copyWith(
+ color: isNearEnd
+ ? Colors.redAccent
+ : AppColor.writeColor ??
+ Colors.black,
+ )),
+ ],
+ ),
+ );
+ },
+ ),
+ const SizedBox(width: 10),
+ Expanded(
+ child: MyElevatedButton(
+ title: 'Refuse Order'.tr,
+ onPressed: () async {
+ controller.endTimer();
+ controller.refuseOrder(rideId);
+ controller.addRideToNotificationDriverString(
+ rideId,
+ _getData(29),
+ _getData(30),
+ '${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day}',
+ '${DateTime.now().hour}:${DateTime.now().minute}',
+ _getData(2),
+ _getData(7),
+ 'wait',
+ _getData(31),
+ _getData(33),
+ _getData(2),
+ _getData(5),
+ _getData(4));
+ // Get.back(); // refuseOrder or endTimer should handle navigation if needed.
+ // If not, add Get.back(); here.
+ },
+ kolor: AppColor.redColor,
+ ),
),
],
- )),
- ),
- const SizedBox(
- height: 5,
- ),
- Container(
- height: Get.height * .3,
- width: Get.width * .9,
- decoration: AppStyle.boxDecoration1,
- child: Padding(
- padding:
- const EdgeInsets.symmetric(horizontal: 5, vertical: 1),
- child: ListView(
- // mainAxisAlignment: MainAxisAlignment.spaceBetween,
- // crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- const Icon(
- Icons.arrow_circle_up,
- color: AppColor.greenColor,
- ),
- Text(
- orderRequestController.myList[12] +
- ' ' +
- ' (${orderRequestController.myList[11]}) ',
- style: AppStyle.title,
- ),
- ],
- ),
- Text(
- orderRequestController.myList[29],
- style: AppStyle.title,
- ),
- ],
- ),
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- const Icon(
- Icons.arrow_circle_down,
- color: AppColor.redColor,
- ),
- Text(
- orderRequestController.myList[5] +
- ' ' +
- ' (${orderRequestController.myList[4]}) ',
- style: AppStyle.title,
- ),
- ],
- ),
- Text(
- orderRequestController.myList[30],
- style: AppStyle.title,
- ),
- ],
- ),
- ],
+ ),
),
- ),
+ ],
),
- Padding(
- padding: const EdgeInsets.all(8.0),
- child: RichText(
- text: TextSpan(
- text: "Passenger name: "
- .tr, // Changed text to be more generic
- style: AppStyle.subtitle,
- children: [
- TextSpan(
- text: orderRequestController.myList[8],
- style: AppStyle
- .title), // Assuming orderRequestController.myList[8] holds passenger name
- TextSpan(text: ' (', style: AppStyle.subtitle),
- TextSpan(
- text: orderRequestController.myList[33].toString(),
- style: AppStyle
- .title), // Assuming 'rate' holds the passenger rate
- TextSpan(text: ' ⭐)', style: AppStyle.subtitle),
- ],
+ ),
+ ),
+ ),
+ );
+ },
+ );
+ }
+
+ // Helper widget for location cards to reduce repetition and improve readability
+ Widget _buildLocationCard(
+ {required IconData icon,
+ required Color iconColor,
+ required String title,
+ required String subtitle,
+ required String fullAddress}) {
+ return Card(
+ elevation: 2,
+ shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
+ margin: const EdgeInsets.symmetric(
+ vertical: 4), // Add a little vertical margin between cards
+ child: Padding(
+ padding: const EdgeInsets.all(10.0),
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Icon(icon, color: iconColor, size: 28),
+ const SizedBox(width: 12),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ "$title $subtitle"
+ .trim(), // Trim to avoid extra spaces if subtitle is empty
+ style: AppStyle.title.copyWith(fontWeight: FontWeight.w600),
+ maxLines: 1,
+ overflow: TextOverflow.ellipsis,
+ ),
+ if (fullAddress.isNotEmpty) ...[
+ const SizedBox(height: 3),
+ Text(
+ fullAddress,
+ style: AppStyle.subtitle
+ .copyWith(fontSize: 13, color: AppColor.greyColor),
+ maxLines: 2, // Allow up to 2 lines for address
+ overflow: TextOverflow.ellipsis,
),
- ),
- ),
-
- // Padding(
- // padding: const EdgeInsets.all(4),
- // child: Container(
- // color: AppColor.greenColor.withOpacity(.5),
- // child: Row(
- // mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- // children: [
- // RichText(
- // text: TextSpan(
- // text: 'Cost Of Trip IS '.tr,
- // style: AppStyle.title,
- // children: [
- // TextSpan(
- // text: orderRequestController.myList[26], style: AppStyle.headTitle2),
- // ],
- // ),
- // ),
- // RichText(
- // text: TextSpan(
- // text: 'Total net'.tr,
- // style: AppStyle.title,
- // children: [
- // TextSpan(
- // text: (double.parse(orderRequestController.myList[2]) -
- // double.parse(orderRequestController.myList[32]))
- // .toStringAsFixed(2),
- // style: AppStyle.headTitle2),
- // ],
- // ),
- // ),
- // ],
- // ),
- // ),
- // ),
-
- Padding(
- padding: const EdgeInsets.all(8.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- MyElevatedButton(
- kolor: AppColor.greenColor,
- title: 'Accept Order'.tr,
- onPressed: () async {
- Get.put(HomeCaptainController()).changeRideId();
- box.write(BoxName.statusDriverLocation, 'on');
- var res = await CRUD().post(
- link: AppLink.updateStausFromSpeed,
- payload: {
- 'id': orderRequestController.myList[16],
- 'rideTimeStart': DateTime.now().toString(),
- 'status': 'Apply',
- 'driver_id': box.read(BoxName.driverID),
- });
- if (AppLink.endPoint != AppLink.seferCairoServer) {
- CRUD().post(
- link:
- "${AppLink.endPoint}/ride/rides/updateStausFromSpeed.php",
- payload: {
- 'id': orderRequestController.myList[16],
- 'rideTimeStart': DateTime.now().toString(),
- 'status': 'Apply',
- 'driver_id': box.read(BoxName.driverID),
- });
- }
- if (res != "failure") {
- box.write(BoxName.statusDriverLocation, 'on');
- orderRequestController.changeApplied();
- List bodyToPassenger = [
- box.read(BoxName.driverID).toString(),
- box.read(BoxName.nameDriver).toString(),
- box.read(BoxName.tokenDriver).toString(),
- ];
- FirebaseMessagesController()
- .sendNotificationToPassengerToken(
- 'Accepted Ride',
- 'your ride is applied'.tr,
- orderRequestController
- .arguments['DriverList'][9]
- .toString(),
- bodyToPassenger,
- 'start.wav');
- CRUD().postFromDialogue(
- link: AppLink.addDriverOrder,
- payload: {
- 'driver_id': orderRequestController.myList[6]
- .toString(),
- 'order_id':
- orderRequestController.body.toString(),
- 'status': 'Apply'
- });
- // CRUD().postFromDialogue(
- // link: AppLink.addDriverOrder,
- // payload: {
- // 'driver_id': orderRequestController.myList[6]
- // .toString(),
- // 'order_id': orderRequestController.myList[16]
- // .toString(),
- // 'status': 'Apply'
- // });
-
- if (AppLink.endPoint != AppLink.seferCairoServer) {
- CRUD().post(
- link:
- "${AppLink.endPoint}/ride/driver_order/add.php",
- payload: {
- 'driver_id': orderRequestController
- .myList[6]
- .toString(),
- // box.read(BoxName.driverID).toString(),
- 'order_id': orderRequestController
- .myList[16]
- .toString(),
- 'status': 'Apply'
- });
- }
-
- Get.back();
- box.write(BoxName.rideArguments, {
- 'passengerLocation':
- orderRequestController.myList[0].toString(),
- 'passengerDestination':
- orderRequestController.myList[1].toString(),
- 'Duration':
- orderRequestController.myList[4].toString(),
- 'totalCost':
- orderRequestController.myList[26].toString(),
- 'Distance':
- orderRequestController.myList[5].toString(),
- 'name':
- orderRequestController.myList[8].toString(),
- 'phone':
- orderRequestController.myList[10].toString(),
- 'email':
- orderRequestController.myList[28].toString(),
- 'WalletChecked':
- orderRequestController.myList[13].toString(),
- 'tokenPassenger':
- orderRequestController.myList[9].toString(),
- 'direction':
- 'https://www.google.com/maps/dir/${orderRequestController.myList[0]}/${orderRequestController.myList[1]}/',
- 'DurationToPassenger':
- orderRequestController.myList[15].toString(),
- 'rideId':
- orderRequestController.myList[16].toString(),
- 'passengerId':
- orderRequestController.myList[7].toString(),
- 'driverId':
- orderRequestController.myList[18].toString(),
- 'durationOfRideValue':
- orderRequestController.myList[19].toString(),
- 'paymentAmount':
- orderRequestController.myList[2].toString(),
- 'paymentMethod': orderRequestController.myList[13]
- .toString() ==
- 'true'
- ? 'visa'
- : 'cash',
- 'isHaveSteps':
- orderRequestController.myList[20].toString(),
- 'step0':
- orderRequestController.myList[21].toString(),
- 'step1':
- orderRequestController.myList[22].toString(),
- 'step2':
- orderRequestController.myList[23].toString(),
- 'step3':
- orderRequestController.myList[24].toString(),
- 'step4':
- orderRequestController.myList[25].toString(),
- 'passengerWalletBurc':
- orderRequestController.myList[26].toString(),
- 'timeOfOrder': DateTime.now().toString(),
- 'totalPassenger':
- orderRequestController.myList[2].toString(),
- 'carType':
- orderRequestController.myList[31].toString(),
- 'kazan':
- orderRequestController.myList[32].toString(),
- 'startNameLocation':
- orderRequestController.myList[29].toString(),
- 'endNameLocation':
- orderRequestController.myList[30].toString(),
- });
- Get.to(() => PassengerLocationMapPage(),
- arguments: box.read(BoxName.rideArguments));
- } else {
- Get.defaultDialog(
- title:
- "This ride is already taken by another driver."
- .tr,
- middleText: '',
- titleStyle: AppStyle.title,
- middleTextStyle: AppStyle.title,
- confirm: MyElevatedButton(
- title: 'Ok'.tr,
- onPressed: () {
- Get.back();
- Get.back();
- // Get.back();
- }));
- }
- // });
- // Get.back();
- },
- ),
- GetBuilder(
- builder: (timerController) {
- final isNearEnd =
- timerController.remainingTimeSpeed <=
- 5; // Define a threshold for "near end"
-
- return Stack(
- alignment: Alignment.center,
- children: [
- CircularProgressIndicator(
- value: timerController.progressSpeed,
- // Set the color based on the "isNearEnd" condition
- color: isNearEnd ? Colors.red : Colors.blue,
- ),
- Text(
- '${timerController.remainingTimeSpeed}',
- style: AppStyle.number,
- ),
- ],
- );
- },
- ),
- MyElevatedButton(
- title: 'Refuse Order'.tr,
- onPressed: () async {
- // Get.defaultDialog(
- // title: 'Reject Order'.tr,
- // titleStyle: AppStyle.title,
- // content: Column(
- // children: [
- // IconButton(
- // onPressed: () async {
- // await Get.find()
- // .speakText(
- // 'You can decline a request without any cost'
- // .tr);
- // },
- // icon: const Icon(Icons.headphones),
- // ),
- // Text(
- // 'You can decline a request without any cost'
- // .tr,
- // style: AppStyle.title,
- // )
- // ],
- // ),
- // confirm: MyElevatedButton(
- // title: 'Ok'.tr,
- // onPressed: () {
- // Get.back();
- // Get.back();
- // }));
- orderRequestController.endTimer();
-
- orderRequestController.refuseOrder(
- orderRequestController.myList[16].toString(),
- );
- orderRequestController.addRideToNotificationDriverString(
- orderRequestController.myList[16].toString(),
- orderRequestController.myList[29].toString(),
- orderRequestController.myList[30].toString(),
- '${DateTime.now().year}-${DateTime.now().month}-${DateTime.now().day}',
- '${DateTime.now().hour}:${DateTime.now().minute}',
- orderRequestController.myList[2].toString(),
- orderRequestController.myList[7].toString(),
- 'wait',
- orderRequestController.myList[31].toString(),
- orderRequestController.myList[33].toString(),
- orderRequestController.myList[2].toString(),
- orderRequestController.myList[5].toString(),
- orderRequestController.myList[4].toString());
- },
- kolor: AppColor.redColor,
- ),
- ],
- ),
- )
- ],
- )
+ ]
+ ],
+ ),
+ ),
],
- isleading: true);
- });
+ ),
+ ),
+ );
}
}
diff --git a/lib/views/home/my_wallet/points_captain.dart b/lib/views/home/my_wallet/points_captain.dart
index 5ceccce..53a461a 100755
--- a/lib/views/home/my_wallet/points_captain.dart
+++ b/lib/views/home/my_wallet/points_captain.dart
@@ -1,3 +1,5 @@
+import 'dart:convert';
+
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sefer_driver/constant/colors.dart';
@@ -5,9 +7,13 @@ import 'package:sefer_driver/constant/style.dart';
import 'package:sefer_driver/controller/home/payment/captain_wallet_controller.dart';
import 'package:sefer_driver/controller/payment/payment_controller.dart';
import 'package:sefer_driver/views/widgets/mydialoug.dart';
+import 'package:webview_flutter/webview_flutter.dart';
import '../../../constant/box_name.dart';
+import '../../../constant/links.dart';
+import '../../../controller/functions/crud.dart';
import '../../../main.dart';
+import '../../../print.dart';
import '../../widgets/elevated_btn.dart';
import '../../widgets/my_textField.dart';
@@ -44,21 +50,34 @@ class PointsCaptain extends StatelessWidget {
title: 'Pay with Credit Card'.tr,
onPressed: () async {
Get.back();
- await paymentController.payWithPayMob(
- context,
- pricePoint.toStringAsFixed(2),
- box.read(BoxName.countryCode) == 'Egypt'
- ? 'EGP'
- : 'JOD', () async {
- // await captainWalletController.getPaymentId(
- // 'visa-in', pricePoint);
- await captainWalletController.addDriverWallet(
- 'visa-in', countPoint, pricePoint);
- await captainWalletController.addSeferWallet(
- 'visa-in', pricePoint.toString());
- await captainWalletController
- .getCaptainWalletFromBuyPoints();
- });
+
+ var res = await CRUD().postWallet(
+ // link: AppLink.payWithPayMobWalletPasenger,
+ link: AppLink.payWithPayMobCardDriver,
+ payload: {
+ "amount": pricePoint.toStringAsFixed(2),
+ "email": box.read(BoxName.emailDriver),
+ "first_name": (box
+ .read(BoxName.nameDriver)
+ .toString()
+ .split(' ')[0])
+ .toString(),
+ "last_name": (box
+ .read(BoxName.nameDriver)
+ .toString()
+ .split(' ')[1])
+ .toString(),
+ "phone_number": (box.read(BoxName.phoneDriver)),
+ });
+ // var d = jsonDecode(res);
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (context) => PaymentScreen(
+ iframeUrl: res['message'],
+ countPrice: countPoint.toString()),
+ ),
+ );
}, //51524
),
// Add some spacing between buttons
@@ -88,31 +107,45 @@ class PointsCaptain extends StatelessWidget {
BoxName.phoneWallet,
paymentController
.walletphoneController.text);
- await paymentController.payWithPayMobWallet(
- context,
- pricePoint.toStringAsFixed(2),
- box.read(BoxName.countryCode) == 'Egypt'
- ? 'EGP'
- : 'JOD', () async {
- // await captainWalletController
- // .getPaymentId('visa-in', pricePoint);
- await captainWalletController
- .addDriverWallet('visa-in',
- countPoint, pricePoint);
- await captainWalletController
- .addSeferWallet(
- 'visa-in', pricePoint.toString());
- await captainWalletController
- .getCaptainWalletFromBuyPoints();
- });
+ var res = await CRUD().postWallet(
+ // link: AppLink.payWithPayMobWalletPasenger,
+ link: AppLink.payWithWallet,
+ payload: {
+ "amount":
+ pricePoint.toStringAsFixed(2),
+ "email":
+ box.read(BoxName.emailDriver),
+ "first_name": (box
+ .read(BoxName.nameDriver)
+ .toString()
+ .split(' ')[0])
+ .toString(),
+ "last_name": (box
+ .read(BoxName.nameDriver)
+ .toString()
+ .split(' ')[1])
+ .toString(),
+ "phone_number":
+ (box.read(BoxName.phoneWallet)),
+ });
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (context) =>
+ PaymentScreenWallet(
+ iframeUrl: res['message'],
+ countPrice:
+ countPoint.toString()),
+ ),
+ );
}
- MyDialog().getDialog(
- 'phone number is wrong'.tr,
- '',
- () {
- Get.back();
- },
- );
+ // MyDialog().getDialog(
+ // 'phone number is wrong'.tr,
+ // '',
+ // () {
+ // Get.back();
+ // },
+ // );
// Get.back();
}));
},
@@ -173,3 +206,311 @@ class PointsCaptain extends StatelessWidget {
);
}
}
+
+class PaymentScreen extends StatefulWidget {
+ final String iframeUrl;
+ final String countPrice;
+
+ const PaymentScreen(
+ {required this.iframeUrl, Key? key, required this.countPrice})
+ : super(key: key);
+
+ @override
+ State createState() => _PaymentScreenState();
+}
+
+class _PaymentScreenState extends State {
+ late final WebViewController _controller;
+ final controller = Get.find();
+ @override
+ void initState() {
+ super.initState();
+
+ _controller = WebViewController()
+ ..setJavaScriptMode(JavaScriptMode.unrestricted)
+ ..setNavigationDelegate(NavigationDelegate(
+ onPageFinished: (url) {
+ if (url.contains("success")) {
+ _fetchPaymentStatus(); // ✅ استدعاء الويب هوك بعد نجاح الدفع
+ } else if (url.contains("failed")) {
+ showCustomDialog(
+ title: "Error".tr,
+ message: 'Payment Failed'.tr, // يتم جلب رسالة الخطأ من الخادم
+ isSuccess: false,
+ );
+ }
+ },
+ ))
+ ..loadRequest(Uri.parse(widget.iframeUrl));
+ }
+
+ Future _fetchPaymentStatus() async {
+ final String userId = box.read(BoxName.phoneDriver);
+ await Future.delayed(const Duration(seconds: 2));
+
+ try {
+ final response = await CRUD().postWallet(
+ link: AppLink.paymetVerifyDriver,
+ payload: {
+ 'user_id': userId,
+ 'driverID': box.read(BoxName.driverID),
+ 'paymentMethod': 'visa-in',
+ },
+ );
+
+ if (response != 'failure' && response != 'token_expired') {
+ if (response['status'] == 'success') {
+ final payment = response['message'];
+ final amount = payment['amount'].toString();
+ final bonus = payment['bonus'].toString();
+ final paymentID = payment['paymentID'].toString();
+
+ await controller.getCaptainWalletFromBuyPoints();
+
+ showCustomDialog(
+ title: "payment_success".tr,
+ message:
+ "${"transaction_id".tr}: $paymentID\n${"amount_paid".tr}: $amount EGP\n${"bonus_added".tr}: $bonus ${"points".tr}",
+ isSuccess: true,
+ );
+ } else {
+ showCustomDialog(
+ title: "transaction_failed".tr,
+ message: response['message'].toString(),
+ isSuccess: false,
+ );
+ }
+ } else {
+ showCustomDialog(
+ title: "connection_failed".tr,
+ message: response.toString(),
+ isSuccess: false,
+ );
+ }
+ } catch (e) {
+ showCustomDialog(
+ title: "server_error".tr,
+ message: "server_error_message".tr,
+ isSuccess: false,
+ );
+ }
+ }
+
+ void showCustomDialog({
+ required String title,
+ required String message,
+ required bool isSuccess,
+ }) {
+ showDialog(
+ barrierDismissible: false,
+ context: Get.context!,
+ builder: (BuildContext context) {
+ return AlertDialog(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12.0),
+ ),
+ title: Row(
+ children: [
+ Icon(
+ isSuccess ? Icons.check_circle : Icons.error,
+ color: isSuccess ? Colors.green : Colors.red,
+ ),
+ const SizedBox(width: 8),
+ Text(
+ title,
+ style: TextStyle(
+ color: isSuccess ? Colors.green : Colors.red,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ],
+ ),
+ content: Text(
+ message,
+ style: const TextStyle(fontSize: 16),
+ ),
+ actions: [
+ TextButton(
+ onPressed: () {
+ Navigator.pop(context);
+ Navigator.pop(context);
+ },
+ style: TextButton.styleFrom(
+ backgroundColor: isSuccess ? Colors.green : Colors.red,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(8.0),
+ ),
+ ),
+ child: Text(
+ "OK",
+ style: const TextStyle(color: Colors.white),
+ ),
+ ),
+ ],
+ );
+ },
+ );
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text('إتمام الدفع')),
+ body: WebViewWidget(controller: _controller),
+ );
+ }
+}
+
+class PaymentScreenWallet extends StatefulWidget {
+ final String iframeUrl;
+ final String countPrice;
+
+ const PaymentScreenWallet(
+ {required this.iframeUrl, Key? key, required this.countPrice})
+ : super(key: key);
+
+ @override
+ State createState() => _PaymentScreenWalletState();
+}
+
+class _PaymentScreenWalletState extends State {
+ late final WebViewController _controller;
+ final controller = Get.find();
+ @override
+ void initState() {
+ super.initState();
+
+ _controller = WebViewController()
+ ..setJavaScriptMode(JavaScriptMode.unrestricted)
+ ..setNavigationDelegate(NavigationDelegate(
+ onPageFinished: (url) {
+ if (url.contains("success")) {
+ _fetchPaymentStatus(); // ✅ استدعاء الويب هوك بعد نجاح الدفع
+ } else if (url.contains("failed")) {
+ showCustomDialog(
+ title: "Error".tr,
+ message: 'Payment Failed'.tr, // يتم جلب رسالة الخطأ من الخادم
+ isSuccess: false,
+ );
+ }
+ },
+ ))
+ ..loadRequest(Uri.parse(widget.iframeUrl));
+ }
+
+ Future _fetchPaymentStatus() async {
+ final String userId = '+2' + box.read(BoxName.phoneWallet);
+ await Future.delayed(const Duration(seconds: 2));
+
+ try {
+ final response = await CRUD().postWallet(
+ link: AppLink.paymetVerifyDriver,
+ payload: {
+ 'user_id': userId,
+ 'driverID': box.read(BoxName.driverID),
+ 'paymentMethod': 'visa-in',
+ },
+ );
+
+ if (response != 'failure' && response != 'token_expired') {
+ if (response['status'] == 'success') {
+ final payment = response['message'];
+ final amount = payment['amount'].toString();
+ final bonus = payment['bonus'].toString();
+ final paymentID = payment['paymentID'].toString();
+
+ await controller.getCaptainWalletFromBuyPoints();
+
+ showCustomDialog(
+ title: "payment_success".tr,
+ message:
+ "${"transaction_id".tr}: $paymentID\n${"amount_paid".tr}: $amount EGP\n${"bonus_added".tr}: $bonus ${"points".tr}",
+ isSuccess: true,
+ );
+ } else {
+ showCustomDialog(
+ title: "transaction_failed".tr,
+ message: response['message'].toString(),
+ isSuccess: false,
+ );
+ }
+ } else {
+ showCustomDialog(
+ title: "connection_failed".tr,
+ message: response.toString(),
+ isSuccess: false,
+ );
+ }
+ } catch (e) {
+ showCustomDialog(
+ title: "server_error".tr,
+ message: "server_error_message".tr,
+ isSuccess: false,
+ );
+ }
+ }
+
+ void showCustomDialog({
+ required String title,
+ required String message,
+ required bool isSuccess,
+ }) {
+ showDialog(
+ barrierDismissible: false,
+ context: Get.context!,
+ builder: (BuildContext context) {
+ return AlertDialog(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12.0),
+ ),
+ title: Row(
+ children: [
+ Icon(
+ isSuccess ? Icons.check_circle : Icons.error,
+ color: isSuccess ? Colors.green : Colors.red,
+ ),
+ const SizedBox(width: 8),
+ Text(
+ title,
+ style: TextStyle(
+ color: isSuccess ? Colors.green : Colors.red,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ],
+ ),
+ content: Text(
+ message,
+ style: const TextStyle(fontSize: 16),
+ ),
+ actions: [
+ TextButton(
+ onPressed: () {
+ Navigator.pop(context);
+ Navigator.pop(context);
+ },
+ style: TextButton.styleFrom(
+ backgroundColor: isSuccess ? Colors.green : Colors.red,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(8.0),
+ ),
+ ),
+ child: Text(
+ "OK",
+ style: const TextStyle(color: Colors.white),
+ ),
+ ),
+ ],
+ );
+ },
+ );
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text('إتمام الدفع')),
+ body: WebViewWidget(controller: _controller),
+ );
+ }
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index d66cb90..7199232 100755
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -93,6 +93,7 @@ dependencies:
jwt_decoder: ^2.0.1
jailbreak_root_detection: ^1.1.5
device_info_plus: ^11.3.0
+ # flutter_isolate: ^2.1.0
# lingo_hunter: ^1.0.3
dev_dependencies: