From d23020188e1d2b794c95332afdb45ea6a51c9408 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Tue, 27 Aug 2024 10:49:43 +0300 Subject: [PATCH] 8/27/1 --- .env | 4 + android/app/build.gradle | 16 +- android/app/google-services.json | 16 -- firebase.json | 2 +- firepit-log.txt | 24 +++ ios/Runner/Info.plist | 4 +- lib/constant/box_name.dart | 3 + lib/constant/links.dart | 73 +++++--- .../auth/captin/invit_controller.dart | 109 ++++++++---- .../auth/captin/login_captin_controller.dart | 2 + .../captin/register_captin_controller.dart | 6 +- lib/controller/auth/google_sign.dart | 18 +- lib/controller/firebase/firbase_messge.dart | 17 ++ .../firebase/local_notification.dart | 113 +++++++++---- lib/controller/functions/crud.dart | 12 +- lib/controller/functions/gemeni.dart | 91 +++++++++- .../location_background_controller.dart | 6 +- .../functions/location_controller.dart | 141 +++++++++++----- lib/controller/functions/package_info.dart | 6 + lib/controller/functions/upload_image.dart | 5 +- lib/controller/functions/vibrate.dart | 15 ++ .../home/captin/contact_us_controller.dart | 78 +++++++++ .../help/maintain_center_controller.dart | 22 +++ .../home/captin/home_captain_controller.dart | 8 +- .../home/captin/map_driver_controller.dart | 50 ++++-- .../home/captin/order_request_controller.dart | 16 +- .../payment/captain_wallet_controller.dart | 2 +- lib/controller/local/translations.dart | 128 ++++++++++++++ .../ride_available_controller.dart | 2 +- lib/firebase_options.dart | 2 +- lib/main.dart | 3 +- lib/views/auth/captin/contact_us_page.dart | 101 +++++++++++ .../auth/captin/invite_driver_screen.dart | 42 ++++- lib/views/auth/captin/login_captin.dart | 2 +- lib/views/home/Captin/About Us/about_us.dart | 101 +++++++++++ .../Captin/About Us/frequantly_question.dart | 145 ++++++++++++++++ .../{ => About Us}/settings_captain.dart | 75 ++++++++- .../home/Captin/About Us/using_app_page.dart | 109 ++++++++++++ .../Captin/home_captain/drawer_captain.dart | 18 +- .../home/Captin/home_captain/home_captin.dart | 157 +++++++++++------- .../widget/left_menu_map_captain.dart | 44 ++--- .../home/Captin/maintain_center_page.dart | 111 +++++++++++++ .../orderCaptin/order_request_page.dart | 21 ++- .../home/my_wallet/card_wallet_widget.dart | 10 +- lib/views/home/my_wallet/walet_captain.dart | 3 + .../home/my_wallet/weekly_payment_page.dart | 131 ++++++++------- lib/views/widgets/my_textField.dart | 120 +++++++------ lib/views/widgets/mydialoug.dart | 120 +++++++++---- 48 files changed, 1872 insertions(+), 432 deletions(-) create mode 100644 firepit-log.txt create mode 100644 lib/controller/functions/vibrate.dart create mode 100644 lib/controller/home/captin/contact_us_controller.dart create mode 100644 lib/controller/home/captin/help/maintain_center_controller.dart create mode 100644 lib/views/auth/captin/contact_us_page.dart create mode 100644 lib/views/home/Captin/About Us/about_us.dart create mode 100644 lib/views/home/Captin/About Us/frequantly_question.dart rename lib/views/home/Captin/{ => About Us}/settings_captain.dart (53%) create mode 100644 lib/views/home/Captin/About Us/using_app_page.dart create mode 100644 lib/views/home/Captin/maintain_center_page.dart diff --git a/.env b/.env index 7f10590..f58dabb 100644 --- a/.env +++ b/.env @@ -15,6 +15,10 @@ secretKey=zg_ropj_57Iiv6MFCBFq3C2n6IXlmjykpxDmW93SW3vvXh68UA9T5FORTWgWsT37StKsOP stripe_publishableKe=vg_ropj_57Iiv6MFCBFq3C2n6kNJnZByV6nuDtXe9IjEPOfhmpDtWmt3MLR0gQpiHcQmAFMUPrZc3QiCDjxBZLbxDC3efxWxz33bWH1ZgrsXrXlBl llamaKey=RR-EuyoFDUvfRDBj46fZKAtKJ3voM8Mt768cPeJV7GNdAkPTKdY8Odm9n4ggGqI5GyoXrXlBl serverPHP=https://api.sefer.live/sefer +seferAlexandriaServer=https://seferalexandria.site/sefer +seferPaymentServer=https://seferpw.shop/sefer +seferCairoServer=https://sefer.click/sefer +seferGizaServer=https://sefergiza.site/sefer cohere=Aulwd8y5SPWos0hJhG0toUf8gOhUUrpf5Q2TPmVGXrXlBl claudeAiAPI=zg-qbc-qvo39-xWOxIGwWTOzCFBnIYSKKhfyz_KVAvrH-6_4ZEJL68G_QBH26oeTOMMoQug9KuOjjKSP_A4S3SUDlbxR9duVzoQ-MkX_UQQQXrXlBl payPalClientId=QALymfNI5Tzt4s-ysoz6vD4_nqX0SUtkC_qYV-Ugk5gaM_8Z-kg4L53k8Uux_4jEWXDkNpXGSWPpIzDFXrXlBl diff --git a/android/app/build.gradle b/android/app/build.gradle index 291639d..8873286 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -54,22 +54,12 @@ android { // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. minSdk = 23 targetSdk = flutter.targetSdkVersion - versionCode = 68 - versionName = '1.5.68' + versionCode = 77 + versionName = '1.5.77' multiDexEnabled =true } -// defaultConfig { -// // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). -// applicationId ="com.sefer_driver" -// // You can update the following values to match your application needs. -// // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. -// minSdkVersion= 23 -// targetSdk= 34 -// versionCode= 63 -// versionName ='1.5.63' -// // manifestPlaceholders = [mapsApiKey: 'android/app/src/main/AndroidManifest.xml'] -// } + signingConfigs { release { diff --git a/android/app/google-services.json b/android/app/google-services.json index 2009fef..55da396 100644 --- a/android/app/google-services.json +++ b/android/app/google-services.json @@ -93,14 +93,6 @@ "certificate_hash": "9bf3876c66e490f30cd7982fa972d8e52e0edbb6" } }, - { - "client_id": "594687661098-4f8qbb4r223su1pphor33l3oe0ie2v46.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "com.mobileapp.store.ride", - "certificate_hash": "765bbb7c5d30bc58a7ba44372db614d6bbe6e34d" - } - }, { "client_id": "594687661098-2u640akrb3k7sak5t0nqki6f4v6hq1bq.apps.googleusercontent.com", "client_type": 3 @@ -173,14 +165,6 @@ } }, "oauth_client": [ - { - "client_id": "594687661098-7mj1ngkp5aodosos3gsr4252qfemuvan.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "com.sefer_driver", - "certificate_hash": "765bbb7c5d30bc58a7ba44372db614d6bbe6e34d" - } - }, { "client_id": "594687661098-op7a9cpgm9dilgh8nl48bu6aor55f7qj.apps.googleusercontent.com", "client_type": 1, diff --git a/firebase.json b/firebase.json index 4f7fa9b..3a6505c 100644 --- a/firebase.json +++ b/firebase.json @@ -1 +1 @@ -{"functions":[{"source":"functions","codebase":"default","ignore":["node_modules",".git","firebase-debug.log","firebase-debug.*.log"],"predeploy":["npm --prefix \"$RESOURCE_DIR\" run lint"]}],"flutter":{"platforms":{"android":{"default":{"projectId":"ride-b1bd8","appId":"1:594687661098:android:b7ce96c17eb928ca595f53","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"ride-b1bd8","appId":"1:594687661098:ios:4f236057ba0383b0595f53","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"ride-b1bd8","configurations":{"android":"1:594687661098:android:b7ce96c17eb928ca595f53","ios":"1:594687661098:ios:4f236057ba0383b0595f53","macos":"1:594687661098:ios:6f69eee1449be943595f53","web":"1:594687661098:web:62d8388476ec91ec595f53","windows":"1:594687661098:web:d9f43a2091395d87595f53"}}},"macos":{"default":{"projectId":"ride-b1bd8","appId":"1:594687661098:ios:6f69eee1449be943595f53","uploadDebugSymbols":false,"fileOutput":"macos/Runner/GoogleService-Info.plist"}}}}} \ No newline at end of file +{"functions":[{"source":"functions","codebase":"default","ignore":["node_modules",".git","firebase-debug.log","firebase-debug.*.log"],"predeploy":["npm --prefix \"$RESOURCE_DIR\" run lint"]}],"flutter":{"platforms":{"android":{"default":{"projectId":"ride-b1bd8","appId":"1:594687661098:android:46557bd4f534b5bb595f53","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"ride-b1bd8","appId":"1:594687661098:ios:4f236057ba0383b0595f53","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"ride-b1bd8","configurations":{"android":"1:594687661098:android:46557bd4f534b5bb595f53","ios":"1:594687661098:ios:4f236057ba0383b0595f53","macos":"1:594687661098:ios:6f69eee1449be943595f53","web":"1:594687661098:web:62d8388476ec91ec595f53","windows":"1:594687661098:web:d9f43a2091395d87595f53"}}},"macos":{"default":{"projectId":"ride-b1bd8","appId":"1:594687661098:ios:6f69eee1449be943595f53","uploadDebugSymbols":false,"fileOutput":"macos/Runner/GoogleService-Info.plist"}}}}} \ No newline at end of file diff --git a/firepit-log.txt b/firepit-log.txt new file mode 100644 index 0000000..bd8ecc1 --- /dev/null +++ b/firepit-log.txt @@ -0,0 +1,24 @@ +Welcome to firepit v1.1.0! +Doing JSON parses for version checks at /snapshot/firepit/vendor/node_modules/firebase-tools/package.json +is-ci,jsdoc,mime,rc,rimraf,yaml,abbrev,abort-controller,accepts,acorn,acorn-jsx,agent-base,aggregate-error,ajv,ajv-formats,ansi-align,ansi-escapes,ansi-regex,ansi-styles,ansicolors,anymatch,archiver,archiver-utils,argparse,array-flatten,arrify,as-array,ast-types,async,async-lock,asynckit,balanced-match,base64-js,basic-auth,basic-auth-connect,basic-ftp,bignumber.js,binary-extensions,bl,bluebird,body-parser,boxen,brace-expansion,braces,buffer,buffer-crc32,buffer-equal-constant-time,bytes,cacache,call-bind,call-me-maybe,camelcase,cardinal,catharsis,chalk,chardet,chokidar,chownr,ci-info,cjson,clean-stack,cli-boxes,cli-cursor,cli-spinners,cli-table,cli-table3,cli-width,cliui,clone,color,color-convert,color-name,color-string,colorette,colors,colorspace,combined-stream,commander,compress-commons,compressible,compression,concat-map,config-chain,configstore,connect,content-disposition,content-type,cookie,cookie-signature,core-util-is,cors,crc-32,crc32-stream,cross-env,cross-spawn,crypto-random-string,csv-parse,data-uri-to-buffer,debug,deep-equal-in-any-order,deep-extend,deep-freeze,deep-is,defaults,define-data-property,degenerator,delayed-stream,depd,destroy,discontinuous-range,dot-prop,duplexify,eastasianwidth,ecdsa-sig-formatter,ee-first,emoji-regex,enabled,encodeurl,encoding,end-of-stream,entities,env-paths,err-code,es-define-property,es-errors,escalade,escape-goat,escape-html,escape-string-regexp,escodegen,eslint-visitor-keys,espree,esprima,estraverse,esutils,etag,event-target-shim,events-listener,exegesis,exegesis-express,exponential-backoff,express,extend,external-editor,fast-deep-equal,fast-json-stable-stringify,fast-levenshtein,fast-text-encoding,fast-url-parser,fecha,figures,filesize,fill-range,finalhandler,firebase-tools,fn.name,foreground-child,form-data,forwarded,fresh,fs-constants,fs-extra,fs-minipass,fs.realpath,function-bind,fuzzy,gaxios,gcp-metadata,get-caller-file,get-intrinsic,get-stdin,get-uri,glob,glob-parent,glob-slash,glob-slasher,global-dirs,google-auth-library,google-gax,google-p12-pem,googleapis-common,gopd,graceful-fs,gtoken,has-flag,has-property-descriptors,has-proto,has-symbols,has-yarn,hasown,heap-js,http-cache-semantics,http-errors,http-proxy-agent,https-proxy-agent,iconv-lite,ieee754,import-lazy,imurmurhash,indent-string,inflight,inherits,ini,inquirer,inquirer-autocomplete-prompt,install-artifact-from-github,ip-address,ip-regex,ipaddr.js,is-arrayish,is-binary-path,is-extglob,is-fullwidth-code-point,is-glob,is-installed-globally,is-interactive,is-lambda,is-npm,is-number,is-obj,is-path-inside,is-stream,is-stream-ended,is-typedarray,is-unicode-supported,is-url,is-wsl,is-yarn-global,is2,isarray,isexe,isomorphic-fetch,jackspeak,jju,join-path,js-yaml,js2xmlparser,jsbn,json-bigint,json-parse-helpfulerror,json-ptr,json-schema-traverse,jsonfile,jsonwebtoken,jwa,jws,klaw,kuler,lazystream,leven,levn,libsodium,libsodium-wrappers,linkify-it,lodash,lodash._objecttypes,lodash.camelcase,lodash.defaults,lodash.difference,lodash.flatten,lodash.includes,lodash.isboolean,lodash.isinteger,lodash.isnumber,lodash.isobject,lodash.isplainobject,lodash.isstring,lodash.mapvalues,lodash.once,lodash.snakecase,lodash.union,log-symbols,logform,long,lru-cache,make-dir,make-fetch-happen,markdown-it,markdown-it-anchor,marked,marked-terminal,mdurl,media-typer,merge-descriptors,methods,mime-db,mime-types,mimic-fn,minimatch,minimist,minipass,minipass-collect,minipass-fetch,minipass-flush,minipass-pipeline,minipass-sized,minizlib,mkdirp,moo,morgan,ms,mute-stream,nan,nearley,negotiator,netmask,nice-try,node-emoji,node-fetch,node-forge,node-gyp,nopt,normalize-path,object-assign,object-hash,object-inspect,on-finished,on-headers,once,one-time,onetime,open,openapi3-ts,optionator,ora,os-tmpdir,p-defer,p-limit,p-map,p-throttle,pac-proxy-agent,pac-resolver,parseurl,path-is-absolute,path-key,path-scurry,path-to-regexp,pg,pg-cloudflare,pg-connection-string,pg-int8,pg-pool,pg-protocol,pg-types,pgpass,picocolors,picomatch,portfinder,postgres-array,postgres-bytea,postgres-date,postgres-interval,prelude-ls,proc-log,process-nextick-args,progress,promise-breaker,promise-retry,proto-list,proto3-json-serializer,protobufjs,protobufjs-cli,proxy-addr,proxy-agent,proxy-from-env,pump,punycode,pupa,qs,railroad-diagrams,randexp,range-parser,raw-body,re2,readable-stream,readdir-glob,readdirp,redeyed,registry-auth-token,registry-url,require-directory,require-from-string,requizzle,restore-cursor,ret,retry,retry-request,router,run-async,rxjs,safe-buffer,safe-stable-stringify,safer-buffer,semver,semver-diff,send,serve-static,set-function-length,setprototypeof,shebang-command,shebang-regex,side-channel,signal-exit,simple-swizzle,smart-buffer,socks,socks-proxy-agent,sort-any,source-map,split2,sprintf-js,sql-formatter,ssri,stack-trace,statuses,stream-chain,stream-json,stream-shift,string-width,string-width-cjs,string_decoder,strip-ansi,strip-ansi-cjs,strip-json-comments,superstatic,supports-color,supports-hyperlinks,tar,tar-stream,tcp-port-used,text-hex,through,tmp,to-regex-range,toidentifier,toxic,tr46,triple-beam,tslib,type-check,type-fest,type-is,typedarray-to-buffer,uc.micro,uglify-js,underscore,undici-types,unique-filename,unique-slug,unique-string,universal-analytics,universalify,unpipe,update-notifier-cjs,uri-js,url-join,url-template,util-deprecate,utils-merge,uuid,valid-url,vary,wcwidth,webidl-conversions,whatwg-fetch,whatwg-url,which,widest-line,winston,winston-transport,word-wrap,wrap-ansi,wrap-ansi-cjs,wrappy,write-file-atomic,ws,xdg-basedir,xmlcreate,xtend,y18n,yallist,yargs,yargs-parser,yocto-queue,zip-stream,@apidevtools,@babel,@colors,@dabh,@google-cloud,@googleapis,@grpc,@isaacs,@jsdevtools,@jsdoc,@npmcli,@opentelemetry,@pkgjs,@pnpm,@protobufjs,@tootallnate,@types +Installed ft@13.8.0 and packaged ft@13.8.0 +Checking for npm/bin/npm-cli install at /Users/hamzaaleghwairyeen/.cache/firebase/tools/lib/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /Users/hamzaaleghwairyeen/.cache/firebase/tools/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /snapshot/firepit/node_modules/npm/bin/npm-cli +Found npm/bin/npm-cli install. +Checking for npm/bin/npm-cli install at /Users/hamzaaleghwairyeen/.cache/firebase/tools/lib/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /Users/hamzaaleghwairyeen/.cache/firebase/tools/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /snapshot/firepit/node_modules/npm/bin/npm-cli +Found npm/bin/npm-cli install. +Runtime binaries created. +/usr/local/bin/firebase +/usr/local/bin/firebase,/snapshot/firepit/firepit.js,apps:sdkconfig,ios,1:594687661098:ios:4f236057ba0383b0595f53,--json +Checking for npm/bin/npm-cli install at /Users/hamzaaleghwairyeen/.cache/firebase/tools/lib/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /Users/hamzaaleghwairyeen/.cache/firebase/tools/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /snapshot/firepit/node_modules/npm/bin/npm-cli +Found npm/bin/npm-cli install. +Checking for npm/bin/npm-cli install at /Users/hamzaaleghwairyeen/.cache/firebase/tools/lib/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /Users/hamzaaleghwairyeen/.cache/firebase/tools/node_modules/npm/bin/npm-cli +Checking for npm/bin/npm-cli install at /snapshot/firepit/node_modules/npm/bin/npm-cli +Found npm/bin/npm-cli install. +ShellJSInternalError: ENOENT: no such file or directory, chmod '/Users/hamzaaleghwairyeen/.cache/firebase/runtime/npm.bat' \ No newline at end of file diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 09237cf..7e708d0 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -33,7 +33,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 52 + 56 CFBundleSignature ???? CFBundleURLTypes @@ -48,7 +48,7 @@ CFBundleVersion - 4.0.52 + 4.0.56 FirebaseAppDelegateProxyEnabled NO GMSApiKey diff --git a/lib/constant/box_name.dart b/lib/constant/box_name.dart index d4331d9..e604d39 100644 --- a/lib/constant/box_name.dart +++ b/lib/constant/box_name.dart @@ -4,10 +4,12 @@ class BoxName { static const String googlaMapApp = "googlaMapApp"; static const String lang = "lang"; + static const String isvibrate = "isvibrate"; static const String myListString = "myListString"; static const String myList = "myList"; static const String bodyOrder = "bodyOrder"; static const String gender = "gender"; + static const String IsSavedPhones = "IsSavedPhones"; static const String carType = "carType"; static const String isFirstTime = "isFirstTime"; static const String deviceInfo = "deviceInfo"; @@ -68,6 +70,7 @@ class BoxName { static const String stripePublishableKey = 'stripe_publishableKe'; static const String apiKeyRun = 'apiKeyRun'; static const String serverAPI = 'serverAPI'; + static const String serverChosen = 'serverChosen'; static const String secretKey = 'secretKey'; static const String basicAuthCredentials = 'basicAuthCredentials'; static const String mapAPIKEY = 'mapAPIKEY'; diff --git a/lib/constant/links.dart b/lib/constant/links.dart index aa78f5d..0d19747 100644 --- a/lib/constant/links.dart +++ b/lib/constant/links.dart @@ -1,23 +1,39 @@ -import 'package:SEFER/constant/api_key.dart'; import 'package:SEFER/env/env.dart'; +import '../main.dart'; +import 'box_name.dart'; + class AppLink { - static final String server = Env.serverPHP; + static final String seferPaymentServer0 = Env.seferPaymentServer; + static final String seferPaymentServer = '${Env.seferCairoServer}/ride'; + static final String seferAlexandriaServer = Env.seferAlexandriaServer; + static final String seferCairoServer = Env.seferCairoServer; + static final String seferGizaServer = Env.seferGizaServer; + + static final String endPoint = box.read(BoxName.serverChosen); + static final String server = Env.seferCairoServer; + // static final String server = Env.serverPHP; + static String googleMapsLink = 'https://maps.googleapis.com/maps/api/'; static String llama = 'https://api.llama-api.com/chat/completions'; static String gemini = 'https://generativelanguage.googleapis.com/v1beta3/models/text-bison-001:generateText'; static String test = "$server/test.php"; - //===============firebase========================== + //===============contact========================== + static String savePhones = "$server/ride/egyptPhones/add.php"; + static String getPhones = "$server/ride/egyptPhones/get.php"; + + ////===============firebase========================== static String getTokens = "$server/ride/firebase/get.php"; + static String getDriverToken = "$server/ride/firebase/getDriverToken.php"; static String addTokens = "$server/ride/firebase/add.php"; static String addTokensDriver = "$server/ride/firebase/addDriver.php"; //=======================Wallet=================== - static String wallet = '$server/ride/passengerWallet'; - static String walletDriver = '$server/ride/driverWallet'; + static String wallet = '$seferPaymentServer/passengerWallet'; + static String walletDriver = '$seferPaymentServer/driverWallet'; static String getAllPassengerTransaction = "$wallet/getAllPassengerTransaction.php"; static String getWalletByPassenger = "$wallet/getWalletByPassenger.php"; @@ -49,10 +65,13 @@ class AppLink { ////=======================cancelRide=================== static String ride = '$server/ride'; static String addCancelRideFromPassenger = "$server/ride/cancelRide/add.php"; + static String addCancelTripFromDriverAfterApplied = + "$server/ride/cancelRide/addCancelTripFromDriverAfterApplied.php"; static String cancelRide = "$server/ride/cancelRide/get.php"; //-----------------ridessss------------------ static String addRides = "$ride/rides/add.php"; static String getRides = "$ride/rides/get.php"; + static String getTripCountByCaptain = "$ride/rides/getTripCountByCaptain.php"; static String getRideOrderID = "$ride/rides/getRideOrderID.php"; static String getRideStatus = "$ride/rides/getRideStatus.php"; static String getapiKey = "$ride/apiKey/get.php"; @@ -74,21 +93,26 @@ class AppLink { static String addKazanPercent = "$ride/kazan/add.php"; ////-----------------DriverPayment------------------ - static String addDrivePayment = "$ride/payment/add.php"; - static String updatePaymetToPaid = "$ride/payment/updatePaymetToPaid.php"; + static String addDrivePayment = "$seferPaymentServer/payment/add.php"; + static String updatePaymetToPaid = + "$seferPaymentServer/payment/updatePaymetToPaid.php"; - static String addSeferWallet = "$ride/seferWallet/add.php"; - static String getSeferWallet = "$ride/seferWallet/get.php"; - static String addDriverPaymentPoints = "$ride/driverPayment/add.php"; + static String addSeferWallet = "$seferPaymentServer/seferWallet/add.php"; + static String getSeferWallet = "$seferPaymentServer/seferWallet/get.php"; + static String addDriverPaymentPoints = + "$seferPaymentServer/driverPayment/add.php"; static String addPaymentTokenDriver = - "$ride/driverWallet/addPaymentToken.php"; //driverWallet/addPaymentToken.php + "$seferPaymentServer/driverWallet/addPaymentToken.php"; //driverWallet/addPaymentToken.php static String addPaymentTokenPassenger = - "$ride/passengerWallet/addPaymentTokenPassenger.php"; - static String getDriverPaymentPoints = "$ride/driverWallet/get.php"; - static String getDriverPaymentToday = "$ride/payment/get.php"; - static String getCountRide = "$ride/payment/getCountRide.php"; - static String getAllPaymentFromRide = "$ride/payment/getAllPayment.php"; - static String getAllPaymentVisa = "$ride/payment/getAllPaymentVisa.php"; + "$seferPaymentServer/passengerWallet/addPaymentTokenPassenger.php"; + static String getDriverPaymentPoints = + "$seferPaymentServer/driverWallet/get.php"; + static String getDriverPaymentToday = "$seferPaymentServer/payment/get.php"; + static String getCountRide = "$server/ride/payment/getCountRide.php"; + static String getAllPaymentFromRide = + "$seferPaymentServer/payment/getAllPayment.php"; + static String getAllPaymentVisa = + "$seferPaymentServer/payment/getAllPaymentVisa.php"; //-----------------Passenger NotificationCaptain------------------ static String addNotificationPassenger = @@ -143,8 +167,9 @@ class AppLink { static String updateLicense = "$ride/license/updateFeedBack.php"; //-----------------RegisrationCar------------------ static String addRegisrationCar = "$ride/RegisrationCar/add.php"; - static String getRegisrationCar = "$ride/RegisrationCar/get.php"; - static String updateRegisrationCar = "$ride/RegisrationCar/update.php"; + static String getRegisrationCar = "$endPoint/ride/RegisrationCar/get.php"; + static String updateRegisrationCar = + "$endPoint/ride/RegisrationCar/update.php"; //-----------------DriverOrder------------------ @@ -165,7 +190,8 @@ class AppLink { static String sendEmailToPassengerForTripDetails = "$ride/rides/emailToPassengerTripDetail.php"; static String sendEmailToDrivertransaction = - "https://api.sefer.live/sefer/Admin/sendEmailToDrivertransaction.php"; + "$seferPaymentServer0/Admin/sendEmailToDrivertransaction.php"; + // "https://api.sefer.live/sefer/Admin/sendEmailToDrivertransaction.php"; // =========================================== static String pathImage = "$server/upload/types/"; static String uploadImage = "$server/uploadImage.php"; @@ -180,11 +206,18 @@ class AppLink { //==================certifcate========== static String location = '$server/ride/location'; static String getCarsLocationByPassenger = "$location/get.php"; + static String addpassengerLocation = "$location/addpassengerLocation.php"; + static String getLatestLocationPassenger = + "$location/getLatestLocationPassenger.php"; static String getFemalDriverLocationByPassenger = "$location/getFemalDriver.php"; static String getDriverCarsLocationToPassengerAfterApplied = "$location/getDriverCarsLocationToPassengerAfterApplied.php"; static String addCarsLocationByPassenger = "$location/add.php"; + static String addCarsLocationGizaEndpoint = + "https://sefergiza.site/archive%20(1)/add.php"; + static String addCarsLocationAlexandriaEndpoint = "$location/add.php"; + static String addCarsLocationCairoEndpoint = "$location/add.php"; static String deleteCarsLocationByPassenger = "$location/delete.php"; static String updateCarsLocationByPassenger = "$location/update.php"; static String getTotalDriverDuration = "$location/getTotalDriverDuration.php"; diff --git a/lib/controller/auth/captin/invit_controller.dart b/lib/controller/auth/captin/invit_controller.dart index b02c2d7..96c956a 100644 --- a/lib/controller/auth/captin/invit_controller.dart +++ b/lib/controller/auth/captin/invit_controller.dart @@ -35,44 +35,64 @@ class InviteController extends GetxController { var data = jsonDecode(response); driverInvitationData = data['message']; update(); - // print('driverInitationData: $driverInitationData'); } - } catch (e) { - print('Error fetching driver stats: $e'); + } catch (e) {} + } + + void selectPhone(String phone) { + if (box.read(BoxName.countryCode) == 'Egypt') { + invitePhoneController.text = phone; + update(); + Get.back(); } } - Future pickContact() async { + Future saveContactsToServer() async { + try { + // TODO: Implement the actual server upload logic here + // Simulating a server request + await Future.delayed(Duration(seconds: 2)); + Get.snackbar('Success'.tr, + '${selectedContacts.length} contacts saved to server'.tr); + } catch (e) { + Get.snackbar('Error'.tr, + 'An error occurred while saving contacts to server: $e'.tr); + } + } + + List contacts = []; + List selectedContacts = []; + RxList> contactMaps = >[].obs; + + Future pickContacts() async { try { - print('Requesting contact permission...'); if (await FlutterContacts.requestPermission(readonly: true)) { - print('Permission granted. Opening external contact picker...'); - final Contact? contact = await FlutterContacts.openExternalPick(); - if (contact != null) { - print('Contact picked: ${contact.displayName}'); - if (contact.phones.isNotEmpty) { - print('Phone number found: ${contact.phones.first.number}'); - invitePhoneController.text = contact.phones.first.number; - update(); - } else { - print('Selected contact has no phone number.'); - Get.snackbar('No phone number'.tr, - 'The selected contact does not have a phone number.'.tr); - } - } else { - print('No contact selected or picker was cancelled.'); - Get.snackbar('No contact selected'.tr, 'Please select a contact'.tr); + final List fetchedContacts = + await FlutterContacts.getContacts(withProperties: true); + contacts = fetchedContacts; + + // Convert contacts to a list of maps + contactMaps.value = fetchedContacts.map((contact) { + return { + 'name': contact.displayName, + 'phones': + contact.phones.map((phone) => phone.normalizedNumber).toList(), + 'emails': contact.emails.map((email) => email.address).toList(), + }; + }).toList(); + update(); + + if (contacts.isEmpty) { + Get.snackbar('No contacts available'.tr, + 'Please add contacts to your phone.'.tr); } } else { - print('Permission denied by user or system.'); Get.snackbar('Permission denied'.tr, - 'Contact permission is required to pick a contact'.tr); + 'Contact permission is required to pick contacts'.tr); } } catch (e) { - print('Error picking contact: $e'); - print('Stack trace: ${StackTrace.current}'); Get.snackbar( - 'Error'.tr, 'An error occurred while picking a contact: $e'.tr); + 'Error'.tr, 'An error occurred while picking contacts: $e'.tr); } } @@ -116,6 +136,33 @@ class InviteController extends GetxController { ); } + savePhoneToServer() async { + for (var i = 0; i < contactMaps.length; i++) { + var phones = contactMaps[i]['phones']; + if (phones != null && phones.isNotEmpty && phones[0].isNotEmpty) { + var res = await CRUD().post(link: AppLink.savePhones, payload: { + "name": contactMaps[i]['name'] ?? 'none', + "phones": phones[0] ?? 'none', + "phones2": phones.join(', ') ?? + 'none', // Convert List to a comma-separated string + }); + if (res != 'failure') {} + } else {} + } + } + + String formatPhoneNumber(String input) { + // Remove any non-digit characters + String digitsOnly = input.replaceAll(RegExp(r'\D'), ''); + + // Ensure the number starts with the country code + if (digitsOnly.startsWith('20')) { + digitsOnly = digitsOnly.substring(1); + } + + return digitsOnly; + } + void sendInvite() async { if (invitePhoneController.text.isEmpty) { Get.snackbar('Error', 'Please enter an phone address'.tr); @@ -123,11 +170,13 @@ class InviteController extends GetxController { } // try { + String phoneNumber = formatPhoneNumber(invitePhoneController.text); + var response = await CRUD().post(link: AppLink.addInviteDriver, payload: { "driverId": box.read(BoxName.driverID), - "inviterDriverPhone": '+2${invitePhoneController.text}' + "inviterDriverPhone": phoneNumber }); - Log.print('response: ${response}'); + if (response != 'failure') { var d = jsonDecode(response); Get.snackbar('Success', 'Invite sent successfully'.tr); @@ -142,8 +191,7 @@ class InviteController extends GetxController { '*Android:* https://play.google.com/store/apps/details?id=com.sefer_driver\n\n\n' '*iOS:* https://apps.apple.com/ae/app/sefer-driver/id6502189302'; - launchCommunication( - 'whatsapp', '+2${invitePhoneController.text}', message); + launchCommunication('whatsapp', '+2$phoneNumber', message); invitePhoneController.clear(); } else { @@ -152,7 +200,6 @@ class InviteController extends GetxController { duration: const Duration(seconds: 4)); } // } catch (e) { - // print('Error sending invite: $e'); // Get.snackbar('Error', 'An error occurred'.tr); // } } diff --git a/lib/controller/auth/captin/login_captin_controller.dart b/lib/controller/auth/captin/login_captin_controller.dart index 132e639..4cd34d9 100644 --- a/lib/controller/auth/captin/login_captin_controller.dart +++ b/lib/controller/auth/captin/login_captin_controller.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:SEFER/constant/colors.dart'; import 'package:SEFER/controller/functions/location_background_controller.dart'; +import 'package:SEFER/print.dart'; import 'package:SEFER/views/auth/captin/cards/sms_signup.dart'; import 'package:SEFER/views/widgets/elevated_btn.dart'; import 'package:flutter/material.dart'; @@ -54,6 +55,7 @@ class LoginDriverController extends GetxController { 'email': email, 'id': driverID, }); + print(res); if (res == 'failure') { //Failure diff --git a/lib/controller/auth/captin/register_captin_controller.dart b/lib/controller/auth/captin/register_captin_controller.dart index ec5742c..2e443f6 100644 --- a/lib/controller/auth/captin/register_captin_controller.dart +++ b/lib/controller/auth/captin/register_captin_controller.dart @@ -80,8 +80,8 @@ class RegisterCaptainController extends GetxController { } bool isValidEgyptianPhoneNumber(String phoneNumber) { - // Remove any whitespace from the phone number - phoneNumber = phoneNumber.replaceAll(RegExp(r'\s+'), ''); + // Remove any non-digit characters (spaces, dashes, etc.) + phoneNumber = phoneNumber.replaceAll(RegExp(r'\D+'), ''); // Check if the phone number has exactly 11 digits if (phoneNumber.length != 11) { @@ -89,7 +89,7 @@ class RegisterCaptainController extends GetxController { } // Check if the phone number starts with 010, 011, 012, or 015 - RegExp validPrefixes = RegExp(r'^01[0125]'); + RegExp validPrefixes = RegExp(r'^01[0125]\d{8}$'); return validPrefixes.hasMatch(phoneNumber); } diff --git a/lib/controller/auth/google_sign.dart b/lib/controller/auth/google_sign.dart index fe67d1f..b86f693 100644 --- a/lib/controller/auth/google_sign.dart +++ b/lib/controller/auth/google_sign.dart @@ -86,18 +86,26 @@ class GoogleSignInHelper { static Future signInFromLogin() async { try { final GoogleSignInAccount? googleUser = await _googleSignIn.signIn(); + if (googleUser != null) { await _handleSignUp(googleUser); - await Get.find().loginUsingCredentials( - box.read(BoxName.driverID).toString(), - box.read(BoxName.emailDriver).toString(), - ); + + // Add detailed debug print statements + final driverID = box.read(BoxName.driverID)?.toString() ?? 'Unknown ID'; + final emailDriver = + box.read(BoxName.emailDriver)?.toString() ?? 'Unknown Email'; + + // print('Driver ID: $driverID'); + // print('Email Driver: $emailDriver'); + + await Get.find() + .loginUsingCredentials(driverID, emailDriver); } + return googleUser; } catch (error) { Get.snackbar('Google Sign-In error', '$error', backgroundColor: AppColor.redColor); - // Log error details print('Google Sign-In error: $error'); return null; } diff --git a/lib/controller/firebase/firbase_messge.dart b/lib/controller/firebase/firbase_messge.dart index 798091e..55f0073 100644 --- a/lib/controller/firebase/firbase_messge.dart +++ b/lib/controller/firebase/firbase_messge.dart @@ -136,6 +136,8 @@ class FirebaseMessagesController extends GetxController { // 'Cancel Trip'.tr, 'Passenger Cancel Trip'.tr, 'cancel', ''); // } cancelTripDialog(); + } else if (message.notification!.title == 'Cancel') { + cancelTripDialog1(); } else if (message.notification!.title! == 'token change') { // NotificationController() // .showNotification('token change'.tr, 'token change', 'cancel'); @@ -316,6 +318,21 @@ class FirebaseMessagesController extends GetxController { })); } + Future cancelTripDialog1() { + return Get.defaultDialog( + barrierDismissible: false, + title: 'Passenger Cancel Trip'.tr, + middleText: + 'Trip Cancelled. The cost of the trip will be added to your wallet.' + .tr, + confirm: MyElevatedButton( + title: 'Ok'.tr, + onPressed: () { + box.write(BoxName.rideStatus, 'Cancel'); + Get.offAll(HomeCaptain()); + })); + } + // Future driverArrivePassengerDialoge() { // return Get.defaultDialog( // barrierDismissible: false, diff --git a/lib/controller/firebase/local_notification.dart b/lib/controller/firebase/local_notification.dart index ddfe21b..4efe567 100644 --- a/lib/controller/firebase/local_notification.dart +++ b/lib/controller/firebase/local_notification.dart @@ -1,14 +1,15 @@ import 'dart:convert'; -import 'package:SEFER/constant/box_name.dart'; import 'package:SEFER/constant/colors.dart'; import 'package:SEFER/views/home/Captin/orderCaptin/order_request_page.dart'; -import 'package:SEFER/views/home/my_wallet/walet_captain.dart'; +import 'package:SEFER/views/home/Captin/orderCaptin/order_speed_request.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:get/get.dart'; import '../../main.dart'; import '../../print.dart'; +import '../../views/notification/notification_captain.dart'; +import '../home/captin/home_captain_controller.dart'; class NotificationController extends GetxController { final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = @@ -31,10 +32,10 @@ class NotificationController extends GetxController { // Create a notification channel const AndroidNotificationChannel channel = AndroidNotificationChannel( - 'order_channel', // Channel ID - 'Order Notifications', // Channel name + 'dynamic_channel', // Channel ID + 'Dynamic Notifications', // Channel name description: - 'This channel is used for order notifications.', // Channel description + 'This channel is used for various types of notifications.', // Channel description importance: Importance.max, ); @@ -56,7 +57,7 @@ class NotificationController extends GetxController { ); AndroidNotificationDetails android = - AndroidNotificationDetails('order_channel', 'Order Notifications', + AndroidNotificationDetails('dynamic_channel', 'Dynamic Notifications', importance: Importance.max, priority: Priority.high, styleInformation: bigTextStyleInformation, @@ -68,6 +69,7 @@ class NotificationController extends GetxController { color: AppColor.primaryColor, showProgress: true, showWhen: true, + timeoutAfter: title == 'Order' ? 14500 : 6000, subText: message, actions: [ AndroidNotificationAction( @@ -83,42 +85,93 @@ class NotificationController extends GetxController { NotificationDetails details = NotificationDetails(android: android); await _flutterLocalNotificationsPlugin.show(0, title, message, details, - payload: payLoad); - - // payload: 'order_page_payload'); + payload: jsonEncode({'title': title, 'data': payLoad})); } // Callback when the notification is tapped void onDidReceiveNotificationResponse(NotificationResponse response) { - // jsonDecode(response.payload); + _handleNotificationResponse(response); + } + + // Callback when the notification is tapped while the app is in the background + void onDidReceiveBackgroundNotificationResponse( + NotificationResponse response) { + _handleNotificationResponse(response); + } + + // Handle notification response for both foreground and background + void _handleNotificationResponse(NotificationResponse response) { print('Notification tapped!'); + Log.print('response.payload: ${response.payload}'); if (response.payload != null) { print('Notification payload: ${response.payload}'); - // if (response.payload != 'order_page_payload') { - // Log.print('arguments: ${box.read(BoxName.rideArguments)}'); - closeOverLay(); - Get.to(() => OrderRequestPage(), - arguments: {'myListString': response.payload}); - // } + var payloadData = jsonDecode(response.payload.toString()); + + if (payloadData is Map) { + String title = payloadData['title']; + var data = payloadData['data']; + + switch (title) { + case 'Order': + _handleOrderNotification(data); + break; + case 'OrderSpeed': + _handleOrderSpeedNotification(data); + break; + case 'ADS': + _handleADSNotification(); + break; + default: + Log.print('Unknown notification type'); + } + } else { + Log.print('Invalid payload format'); + } + } else { + Log.print('Payload is null'); } } + void _handleOrderNotification(dynamic data) { + if (data is String) { + var orderData = jsonDecode(data); + if (orderData is List && orderData.length == 34) { + closeOverLay(); + Get.put(HomeCaptainController()).changeRideId(); + Get.to(() => OrderRequestPage(), arguments: {'myListString': data}); + } else { + Log.print('Invalid order data'); + } + } else { + Log.print('Invalid order payload'); + } + } + + void _handleOrderSpeedNotification(dynamic data) { + if (data is String) { + var orderData = jsonDecode(data); + if (orderData is List && orderData.length == 34) { + closeOverLay(); + Get.put(HomeCaptainController()).changeRideId(); + Get.to(() => OrderSpeedRequest(), arguments: {'myListString': data}); + } else { + Log.print('Invalid order data'); + } + } else { + Log.print('Invalid order payload'); + } + } + + void _handleADSNotification() { + // var orderData = jsonDecode(data); + closeOverLay(); + Get.to( + () => const NotificationCaptain(), + ); + } + void onDidReceiveLocalNotification( int id, String? title, String? body, String? payload) async { // display a dialog with the notification details, tap ok to go to another page } - // Callback when the notification is tapped while the app is in the background - void onDidReceiveBackgroundNotificationResponse( - NotificationResponse response) { - print('Notification tapped while app is in background!'); - if (response.payload != null) { - print('Notification payload: ${response.payload}'); - if (response.payload == 'order') { - Get.to(() => OrderRequestPage(), - arguments: box.read(BoxName.rideArguments)); - closeOverLay(); - Log.print('arguments: ${box.read(BoxName.rideArguments)}'); - } - } - } } diff --git a/lib/controller/functions/crud.dart b/lib/controller/functions/crud.dart index ec554dd..aaed62b 100644 --- a/lib/controller/functions/crud.dart +++ b/lib/controller/functions/crud.dart @@ -29,9 +29,9 @@ class CRUD { }, ); // if (response.statusCode == 200) { - // Log.print('response: ${response.request}'); - // Log.print('response: ${response.body}'); - // Log.print('response: ${payload}'); + Log.print('response: ${response.request}'); + Log.print('response: ${response.body}'); + Log.print('response: ${payload}'); var jsonData = jsonDecode(response.body); if (jsonData['status'] == 'success') { return response.body; @@ -101,7 +101,9 @@ class CRUD { var extractedString = await arabicTextExtractByVisionAndAI(imagePath: imagePath); var json = jsonDecode(extractedString); + var textValues = extractTextFromLines(json); + Log.print('textValues: ${textValues}'); // await Get.put(AI()).geminiAiExtraction(prompt, textValues); await Get.put(AI()).anthropicAI(textValues, prompt, imagePath); } @@ -145,6 +147,8 @@ class CRUD { http.StreamedResponse response = await request.send(); if (response.statusCode == 200) { + // Log.print( + // 'response.stream.bytesToString(): ${await response.stream.bytesToString()}'); return await response.stream.bytesToString(); } else {} } @@ -227,6 +231,8 @@ class CRUD { ); Log.print('response: ${response.request}'); Log.print('response: ${response.body}'); + Log.print('response: ${response.statusCode}'); + Log.print('response: ${response.reasonPhrase}'); Log.print('response: ${payload}'); var jsonData = jsonDecode(response.body); if (response.statusCode == 200) { diff --git a/lib/controller/functions/gemeni.dart b/lib/controller/functions/gemeni.dart index 446844d..3c75d33 100644 --- a/lib/controller/functions/gemeni.dart +++ b/lib/controller/functions/gemeni.dart @@ -250,6 +250,39 @@ class AI extends GetxController { } } + String extractDOB(String nationalNumber) { + if (nationalNumber.length != 14) { + throw ArgumentError('National number must be 14 digits long.'); + } + + // Extract the first digit to determine the century + String firstDigit = nationalNumber[0]; + + // Extract year, month, and day parts + String yearPart = nationalNumber.substring(1, 3); + String monthPart = nationalNumber.substring(3, 5); + String dayPart = nationalNumber.substring(5, 7); + + // Determine the year based on the first digit + int yearPrefix; + if (firstDigit == '2') { + yearPrefix = 1900; + } else if (firstDigit == '3') { + yearPrefix = 2000; + } else { + throw ArgumentError('Invalid first digit in national number.'); + } + + // Construct the full year + int year = yearPrefix + int.parse(yearPart); + + // Format the date as YYYY-MM-DD + String dob = + '$year-${monthPart.padLeft(2, '0')}-${dayPart.padLeft(2, '0')}'; + + return dob; + } + Future addDriverEgypt() async { isLoading = true; update(); @@ -295,7 +328,8 @@ class AI extends GetxController { 'religion': responseIdEgyptBack['religion']?.toString() ?? 'Not specified', 'status': 'yet', - 'birthdate': responseIdEgyptFront['dob']?.toString() ?? 'Not specified', + 'birthdate': extractDOB( + responseIdEgyptDriverLicense['national_number'].toString()), 'maritalStatus': responseIdEgyptBack['maritalStatus']?.toString() ?? 'Not specified', 'site': responseIdEgyptDriverLicense['address']?.toString() ?? @@ -321,6 +355,12 @@ class AI extends GetxController { if (status1['status'] == 'success') { isDriverSaved = true; + // CRUD().post( + // link: '${AppLink.seferGizaServer}/auth/captin/register.php', + // payload: payload); + // CRUD().post( + // link: '${AppLink.seferAlexandriaServer}/auth/captin/register.php', + // payload: payload); Get.snackbar('Success', 'Driver data saved successfully', backgroundColor: AppColor.greenColor); } else { @@ -376,6 +416,55 @@ class AI extends GetxController { isCarSaved = true; Get.snackbar('Success', 'message', backgroundColor: AppColor.greenColor); + // CRUD().post( + // link: + // '${AppLink.seferAlexandriaServer}/ride/RegisrationCar/add.php', + // payload: { + // 'driverID': box.read(BoxName.driverID), + // 'vin': responseIdCardDriverEgyptBack['chassis'].toString(), + // 'car_plate': + // responseIdCardDriverEgyptFront['car_plate'].toString(), + // 'make': responseIdCardDriverEgyptBack['make'].toString(), + // 'model': responseIdCardDriverEgyptBack['model'], + // 'year': responseIdCardDriverEgyptBack['year'].toString(), + // 'expiration_date': + // responseIdCardDriverEgyptFront['LicenseExpirationDate'] + // .toString(), + // 'color': responseIdCardDriverEgyptBack['color'], + // 'owner': responseIdCardDriverEgyptFront['owner'], + // 'color_hex': + // responseIdCardDriverEgyptBack['color_hex'].toString(), + // 'address': responseIdCardDriverEgyptFront['address'].toString(), + // 'displacement': + // responseIdCardDriverEgyptBack['engine'].toString(), + // 'fuel': responseIdCardDriverEgyptBack['fuel'].toString(), + // 'registration_date': + // '${responseIdCardDriverEgyptBack['inspection_date']}', + // }); + // CRUD().post( + // link: '${AppLink.seferGizaServer}/ride/RegisrationCar/add.php', + // payload: { + // 'driverID': box.read(BoxName.driverID), + // 'vin': responseIdCardDriverEgyptBack['chassis'].toString(), + // 'car_plate': + // responseIdCardDriverEgyptFront['car_plate'].toString(), + // 'make': responseIdCardDriverEgyptBack['make'].toString(), + // 'model': responseIdCardDriverEgyptBack['model'], + // 'year': responseIdCardDriverEgyptBack['year'].toString(), + // 'expiration_date': + // responseIdCardDriverEgyptFront['LicenseExpirationDate'] + // .toString(), + // 'color': responseIdCardDriverEgyptBack['color'], + // 'owner': responseIdCardDriverEgyptFront['owner'], + // 'color_hex': + // responseIdCardDriverEgyptBack['color_hex'].toString(), + // 'address': responseIdCardDriverEgyptFront['address'].toString(), + // 'displacement': + // responseIdCardDriverEgyptBack['engine'].toString(), + // 'fuel': responseIdCardDriverEgyptBack['fuel'].toString(), + // 'registration_date': + // '${responseIdCardDriverEgyptBack['inspection_date']}', + // }); } } catch (e) {} } diff --git a/lib/controller/functions/location_background_controller.dart b/lib/controller/functions/location_background_controller.dart index 1a18f94..c5456ea 100644 --- a/lib/controller/functions/location_background_controller.dart +++ b/lib/controller/functions/location_background_controller.dart @@ -26,9 +26,9 @@ class LocationBackgroundController extends GetxController { Future configureBackgroundLocation() async { await BackgroundLocation.setAndroidNotification( - title: "Background Location", - message: "Tracking location...", - icon: "@mipmap/launcher_icon", + title: 'Location Tracking Active'.tr, + message: 'Your location is being tracked in the background.'.tr, + icon: '@mipmap/launcher_icon', ); // Set the location update interval to 5 seconds diff --git a/lib/controller/functions/location_controller.dart b/lib/controller/functions/location_controller.dart index 53c160c..f41232a 100644 --- a/lib/controller/functions/location_controller.dart +++ b/lib/controller/functions/location_controller.dart @@ -10,6 +10,8 @@ import 'package:SEFER/controller/functions/crud.dart'; import 'package:SEFER/controller/home/payment/captain_wallet_controller.dart'; import 'package:SEFER/main.dart'; +import '../../print.dart'; + // LocationController.dart class LocationController extends GetxController { LocationData? _currentLocation; @@ -40,6 +42,36 @@ class LocationController extends GetxController { totalPoints = Get.put(CaptainWalletController()).totalPoints.toString(); // isActive = Get.put(HomeCaptainController()).isActive; + } // Function to determine which area the coordinates belong to + + String getLocationArea(double latitude, double longitude) { + // Giza Boundary Check + if (latitude >= 29.904975 && + latitude <= 30.143372 && + longitude >= 30.787030 && + longitude <= 31.238843) { + // box.write(BoxName.serverChosen, AppLink.seferGizaServer); + return 'Giza'; + } + // Cairo Boundary Check + else if (latitude >= 29.918901 && + latitude <= 30.198857 && + longitude >= 31.215009 && + longitude <= 31.532186) { + // box.write(BoxName.serverChosen, AppLink.seferCairoServer); + return 'Cairo'; + } + // Alexandria Boundary Check + else if (latitude >= 30.396286 && + latitude <= 31.654458 && + longitude >= 29.041139 && + longitude <= 32.626259) { + // box.write(BoxName.serverChosen, AppLink.seferAlexandriaServer); + return 'Alexandria'; + } + + // Return 'Unknown' if outside defined areas + return 'Unknown'; } Future startLocationUpdates() async { @@ -53,53 +85,69 @@ class LocationController extends GetxController { if (isActive) { if (double.parse(totalPoints) > -3000) { await getLocation(); + String endpoint; - // if (box.read(BoxName.driverID) != null) { - await CRUD() - .post(link: AppLink.addCarsLocationByPassenger, payload: { - 'driver_id': box.read(BoxName.driverID).toString(), - 'latitude': myLocation.latitude.toString(), - 'longitude': myLocation.longitude.toString(), - 'heading': heading.toString(), - 'speed': (speed * 3.6).toStringAsFixed(1), - 'distance': totalDistance == 0 - ? '0' - : totalDistance < 1 - ? totalDistance.toStringAsFixed(3) - : totalDistance.toStringAsFixed(1), - 'status': box.read(BoxName.statusDriverLocation).toString() - }); - // Animate camera to user location (optional) - // if (Get.find().rideId == 'rideId') { - // Get.find() - // .mapController! - // .animateCamera(CameraUpdate.newLatLng(LatLng( - // Get.find().myLocation.latitude, - // Get.find().myLocation.longitude, - // ))); + switch ( + getLocationArea(myLocation.latitude, myLocation.longitude)) { + case 'Cairo': + endpoint = AppLink.addCarsLocationCairoEndpoint; + break; + case 'Giza': + endpoint = AppLink.addCarsLocationGizaEndpoint; + break; + case 'Alexandria': + endpoint = AppLink.addCarsLocationAlexandriaEndpoint; + break; + default: + print('Location outside Cairo, Giza, or Alexandria'); + endpoint = AppLink.addCarsLocationByPassenger; + return; + } + if (box.read(BoxName.driverID) != null) { + await CRUD().post(link: endpoint, payload: { + 'driver_id': box.read(BoxName.driverID).toString(), + 'latitude': myLocation.latitude.toString(), + 'longitude': myLocation.longitude.toString(), + 'heading': heading.toString(), + 'speed': (speed * 3.6).toStringAsFixed(1), + 'distance': totalDistance == 0 + ? '0.0' + : totalDistance < 1 + ? totalDistance.toStringAsFixed(3) + : totalDistance.toStringAsFixed(1), + 'status': box.read(BoxName.statusDriverLocation).toString() + }); + // Animate camera to user location (optional) + // if (Get.find().rideId == 'rideId') { + // Get.find() + // .mapController! + // .animateCamera(CameraUpdate.newLatLng(LatLng( + // Get.find().myLocation.latitude, + // Get.find().myLocation.longitude, + // ))); + } + Get.find() + .mapHomeCaptainController! + .animateCamera(CameraUpdate.newLatLng(LatLng( + Get.find().myLocation.latitude, + Get.find().myLocation.longitude, + ))); + // if (Get.find().rideId == '0') { + // await sql.insertData({ + // 'driver_id': box.read(BoxName.driverID), + // 'latitude': myLocation.latitude.toString(), + // 'longitude': myLocation.longitude.toString(), + // 'created_at': DateTime.now().toString(), + // }, TableName.carLocations); + // } else { + // await sql.insertData({ + // 'order_id': Get.find().rideId, + // 'created_at': DateTime.now().toString(), + // 'lat': myLocation.latitude.toString(), + // 'lng': myLocation.longitude.toString(), + // }, TableName.rideLocation); + // } } - Get.find() - .mapHomeCaptainController! - .animateCamera(CameraUpdate.newLatLng(LatLng( - Get.find().myLocation.latitude, - Get.find().myLocation.longitude, - ))); - // if (Get.find().rideId == '0') { - // await sql.insertData({ - // 'driver_id': box.read(BoxName.driverID), - // 'latitude': myLocation.latitude.toString(), - // 'longitude': myLocation.longitude.toString(), - // 'created_at': DateTime.now().toString(), - // }, TableName.carLocations); - // } else { - // await sql.insertData({ - // 'order_id': Get.find().rideId, - // 'created_at': DateTime.now().toString(), - // 'lat': myLocation.latitude.toString(), - // 'lng': myLocation.longitude.toString(), - // }, TableName.rideLocation); - // } - // } // } @@ -151,10 +199,13 @@ class LocationController extends GetxController { (_locationData.latitude != null && _locationData.longitude != null ? LatLng(_locationData.latitude!, _locationData.longitude!) : null)!; + getLocationArea(_locationData.latitude!, _locationData.longitude!); speed = _locationData.speed!; heading = _locationData.heading!; // Calculate the distance between the current location and the previous location if (Get.find().rideId == 'rideId') { + Log.print( + 'Get.find().rideId: ${Get.find().rideId}'); if (previousTime > 0) { double distance = calculateDistanceInKmPerHour( previousTime, _locationData.time, speed); diff --git a/lib/controller/functions/package_info.dart b/lib/controller/functions/package_info.dart index ef8da45..ece683a 100644 --- a/lib/controller/functions/package_info.dart +++ b/lib/controller/functions/package_info.dart @@ -64,6 +64,12 @@ void showUpdateDialog(BuildContext context) { Navigator.of(context).pop(); }, ), + CupertinoDialogAction( + child: Text('Cancel'.tr), + onPressed: () async { + Navigator.of(context).pop(); + }, + ), ], ); }, diff --git a/lib/controller/functions/upload_image.dart b/lib/controller/functions/upload_image.dart index d046f5d..09339c0 100644 --- a/lib/controller/functions/upload_image.dart +++ b/lib/controller/functions/upload_image.dart @@ -14,6 +14,7 @@ import 'package:path_provider/path_provider.dart' as path_provider; import '../../constant/box_name.dart'; import '../../constant/colors.dart'; import '../../main.dart'; +import '../../print.dart'; class ImageController extends GetxController { File? myImage; @@ -138,6 +139,7 @@ class ImageController extends GetxController { File compressedImage = await compressImage(processedImage); print('link =$link'); + Log.print('link: ${link}'); await uploadImage( compressedImage, @@ -238,7 +240,7 @@ class ImageController extends GetxController { uploadImage(File file, Map data, String link) async { var request = http.MultipartRequest( 'POST', - Uri.parse(link), //'https://ride.mobile-app.store/uploadImage1.php' + Uri.parse(link), ); var length = await file.length(); @@ -268,6 +270,7 @@ class ImageController extends GetxController { var myrequest = await request.send(); var res = await http.Response.fromStream(myrequest); if (res.statusCode == 200) { + Log.print('jsonDecode(res.body): ${jsonDecode(res.body)}'); return jsonDecode(res.body); } else { throw Exception( diff --git a/lib/controller/functions/vibrate.dart b/lib/controller/functions/vibrate.dart new file mode 100644 index 0000000..de2510c --- /dev/null +++ b/lib/controller/functions/vibrate.dart @@ -0,0 +1,15 @@ +import 'package:get/get.dart'; + +import '../../constant/box_name.dart'; +import '../../main.dart'; + +class HomePageController extends GetxController { + late bool isVibrate = box.read(BoxName.isvibrate) ?? true; + + void changeVibrateOption(bool value) { + isVibrate = box.read(BoxName.isvibrate) ?? true; + isVibrate = value; + box.write(BoxName.isvibrate, value); + update(); + } +} diff --git a/lib/controller/home/captin/contact_us_controller.dart b/lib/controller/home/captin/contact_us_controller.dart new file mode 100644 index 0000000..8e200b8 --- /dev/null +++ b/lib/controller/home/captin/contact_us_controller.dart @@ -0,0 +1,78 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_font_icons/flutter_font_icons.dart'; +import 'package:get/get.dart'; + +import '../../../constant/colors.dart'; +import '../../functions/launch.dart'; + +class ContactUsController extends GetxController { + final String phone1 = '+201018805430'; + final String phone2 = '+201080182934'; + final TimeOfDay workStartTime = const TimeOfDay(hour: 12, minute: 0); + final TimeOfDay workEndTime = const TimeOfDay(hour: 19, minute: 0); + + bool _isWithinWorkTime(TimeOfDay now) { + return (now.hour > workStartTime.hour || + (now.hour == workStartTime.hour && + now.minute >= workStartTime.minute)) && + (now.hour < workEndTime.hour || + (now.hour == workEndTime.hour && now.minute <= workEndTime.minute)); + } + + void showContactDialog(BuildContext context) { + TimeOfDay now = TimeOfDay.now(); + + showCupertinoModalPopup( + context: context, + builder: (context) => CupertinoActionSheet( + title: Text('Contact Us'.tr), + message: Text('Choose a contact option'.tr), + actions: [ + if (_isWithinWorkTime(now)) + CupertinoActionSheetAction( + child: Text(phone1), + onPressed: () => makePhoneCall( + phone1, + ), + ), + if (_isWithinWorkTime(now)) + CupertinoActionSheetAction( + child: Text(phone2), + onPressed: () => makePhoneCall(phone2), + ), + if (!_isWithinWorkTime(now)) + CupertinoActionSheetAction( + child: Text( + 'Work time is from 12:00 - 19:00.\nYou can send a WhatsApp message or email.' + .tr), + onPressed: () => Navigator.pop(context), + ), + CupertinoActionSheetAction( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + const Icon( + FontAwesome.whatsapp, + color: AppColor.greenColor, + ), + Text('Send WhatsApp Message'.tr), + ], + ), + onPressed: () => + launchCommunication('whatsapp', phone1, 'Hello'.tr), + ), + CupertinoActionSheetAction( + child: Text('Send Email'.tr), + onPressed: () => + launchCommunication('email', 'support@sefer.live', 'Hello'.tr), + ), + ], + cancelButton: CupertinoActionSheetAction( + child: Text('Cancel'.tr), + onPressed: () => Navigator.pop(context), + ), + ), + ); + } +} diff --git a/lib/controller/home/captin/help/maintain_center_controller.dart b/lib/controller/home/captin/help/maintain_center_controller.dart new file mode 100644 index 0000000..4ba9660 --- /dev/null +++ b/lib/controller/home/captin/help/maintain_center_controller.dart @@ -0,0 +1,22 @@ +import 'dart:convert'; + +import 'package:SEFER/constant/box_name.dart'; +import 'package:SEFER/constant/links.dart'; +import 'package:SEFER/controller/functions/crud.dart'; +import 'package:SEFER/main.dart'; +import 'package:get/get.dart'; + +class MaintainCenterController extends GetxController { + bool isLoading = false; + Map tripCount = {}; + + Future getTripCountByCaptain() async { + var res = await CRUD().get(link: AppLink.getTripCountByCaptain, payload: { + "driver_id": box.read(BoxName.driverID).toString(), + }); + if (res != 'failure') { + tripCount = jsonDecode(res)['message']; + update(); + } + } +} diff --git a/lib/controller/home/captin/home_captain_controller.dart b/lib/controller/home/captin/home_captain_controller.dart index 6ae98f6..d7c5633 100644 --- a/lib/controller/home/captin/home_captain_controller.dart +++ b/lib/controller/home/captin/home_captain_controller.dart @@ -219,12 +219,12 @@ class HomeCaptainController extends GetxController { void onInit() async { // await locationBackController.requestLocationPermission(); - await addToken(); + addToken(); await getlocation(); onButtonSelected(); - await getDriverRate(); - await getKazanPercent(); - await getPaymentToday(); + getDriverRate(); + getKazanPercent(); + getPaymentToday(); getCountRideToday(); getAllPayment(); startPeriodicExecution(); diff --git a/lib/controller/home/captin/map_driver_controller.dart b/lib/controller/home/captin/map_driver_controller.dart index c8cafb1..ebc13e9 100644 --- a/lib/controller/home/captin/map_driver_controller.dart +++ b/lib/controller/home/captin/map_driver_controller.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:convert'; import 'package:SEFER/controller/home/captin/home_captain_controller.dart'; +import 'package:SEFER/controller/home/captin/order_request_controller.dart'; import 'package:SEFER/views/widgets/mydialoug.dart'; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; @@ -15,6 +16,7 @@ import '../../../constant/api_key.dart'; import '../../../constant/box_name.dart'; import '../../../constant/colors.dart'; import '../../../constant/links.dart'; +import '../../../constant/table_names.dart'; import '../../../main.dart'; import '../../../views/Rate/rate_passenger.dart'; import '../../../views/home/Captin/home_captain/home_captin.dart'; @@ -169,15 +171,15 @@ class MapDriverController extends GetxController { cancelTripFromDriverAfterApplied() async { if (formKeyCancel.currentState!.validate()) { - await CRUD().post(link: AppLink.updateRides, payload: { + CRUD().post(link: AppLink.updateRides, payload: { "id": rideId.toString(), // Convert to String "status": 'CancelFromDriverAfterApply' }); - await CRUD().post(link: AppLink.addCancelRideFromPassenger, payload: { - "rideID": rideId.toString(), - "driverID": box.read(BoxName.driverID).toString(), - "passengerID": passengerId.toString(), - "note": cancelTripCotroller.text.toString() + CRUD().post(link: AppLink.addCancelTripFromDriverAfterApplied, payload: { + "order_id": rideId.toString(), + "driver_id": box.read(BoxName.driverID).toString(), + "status": 'reject After Applied', + "notes": cancelTripCotroller.text.toString() }); FirebaseMessagesController().sendNotificationToDriverMAP( "Cancel Trip from driver".tr, @@ -187,6 +189,12 @@ class MapDriverController extends GetxController { [], 'cancel.wav', ); + sql.insertData({ + 'order_id': rideId, + 'created_at': DateTime.now().toString(), + 'driver_id': box.read(BoxName.driverID).toString(), + }, TableName.driverOrdersRefuse); + Get.put(OrderRequestController()).getRefusedOrderByCaptain(); Get.offAll(HomeCaptain()); } } @@ -407,15 +415,29 @@ class MapDriverController extends GetxController { updateLocation(); } - calculateDistanceBetweenDriverAndPassengerLocation() { + calculateDistanceBetweenDriverAndPassengerLocation() async { Get.put(LocationController()); - double distance2 = Geolocator.distanceBetween( - latLngPassengerLocation.latitude, - latLngPassengerLocation.longitude, - Get.find().myLocation.latitude, - Get.find().myLocation.longitude, - ); - return distance2; + var res = await CRUD().get( + link: AppLink.getLatestLocationPassenger, payload: {'rideId': rideId}); + if (res != 'failure') { + var passengerLatestLocationString = jsonDecode(res)['message']; + + double distance2 = Geolocator.distanceBetween( + double.parse(passengerLatestLocationString[0]['lat'].toString()), + double.parse(passengerLatestLocationString[0]['lng'].toString()), + Get.find().myLocation.latitude, + Get.find().myLocation.longitude, + ); + return distance2; + } else { + double distance2 = Geolocator.distanceBetween( + latLngPassengerLocation.latitude, + latLngPassengerLocation.longitude, + Get.find().myLocation.latitude, + Get.find().myLocation.longitude, + ); + return distance2; + } } addWaitingTimeCostFromPassengerToDriverWallet() async { diff --git a/lib/controller/home/captin/order_request_controller.dart b/lib/controller/home/captin/order_request_controller.dart index 794e2ce..25971af 100644 --- a/lib/controller/home/captin/order_request_controller.dart +++ b/lib/controller/home/captin/order_request_controller.dart @@ -186,14 +186,14 @@ class OrderRequestController extends GetxController { }); // applied = true; - if (box.read(BoxName.gender).toString() != 'Female') { - sql.insertData({ - 'order_id': orderID, - 'created_at': DateTime.now().toString(), - 'driver_id': box.read(BoxName.driverID).toString(), - }, TableName.driverOrdersRefuse); - getRefusedOrderByCaptain(); - } + // if (box.read(BoxName.gender).toString() != 'Female') { + // sql.insertData({ + // 'order_id': orderID, + // 'created_at': DateTime.now().toString(), + // 'driver_id': box.read(BoxName.driverID).toString(), + // }, TableName.driverOrdersRefuse); + // getRefusedOrderByCaptain(); + // } update(); // Get.back(); // Get.offAll(HomeCaptain()); diff --git a/lib/controller/home/payment/captain_wallet_controller.dart b/lib/controller/home/payment/captain_wallet_controller.dart index 14e6410..9347b1e 100644 --- a/lib/controller/home/payment/captain_wallet_controller.dart +++ b/lib/controller/home/payment/captain_wallet_controller.dart @@ -111,7 +111,7 @@ class CaptainWalletController extends GetxController { // isLoading = false; if (res != 'failure') { walletDate = jsonDecode(res); - totalAmount = walletDate['message'][0]['total_amount'].toString(); + totalAmount = walletDate['message'][0]['total_amount'] ?? '0'; update(); var res1 = await CRUD().get( link: AppLink.getAllPaymentVisa, diff --git a/lib/controller/local/translations.dart b/lib/controller/local/translations.dart index 937c5bf..2e95b1d 100644 --- a/lib/controller/local/translations.dart +++ b/lib/controller/local/translations.dart @@ -286,6 +286,134 @@ class MyTranslation extends Translations { "is reviewing your order. They may need more information or a higher price.": "يتم مراجعة طلبك. قد يحتاجون إلى مزيد من المعلومات أو سعر أعلى.", "FullName": "الاسم الكامل", + "Cancel Trip from driver": "إلغاء الرحلة من السائق", + "If you want order to another person": "إذا كنت تريد الطلب لشخص آخر", + "We will look for a new driver.\nPlease wait.": + "سنبحث عن سائق جديد.\nمن فضلك انتظر.", + "No, I want to cancel this trip": "لا، أريد إلغاء هذه الرحلة", + "Attention": "تنبيه", + 'Trip Cancelled. The cost of the trip will be added to your wallet.': + "تم إلغاء الرحلة. سيتم إضافة تكلفة الرحلة إلى محفظتك.", + "Trip Cancelled. The cost of the trip will be deducted from your wallet.": + "تم إلغاء الرحلة. سيتم خصم تكلفة الرحلة من محفظتك.", + "You will be charged for the cost of the driver coming to your location.": + "سيتم خصم تكلفة قدوم السائق إلى موقعك.", + "reject your order.": "رفض طلبك.", + "Location Tracking Active": "تعقب الموقع نشط", + "Your location is being tracked in the background.": + "يتم تتبع موقعك في الخلفية.", + "Maintenance Center": "‏مركز الصيانة", + "Order Under Review": "الطلب قيد المراجعة", + "When you complete 600 trips, you will be eligible to receive offers for maintenance of your car.": + "عندما تكمل 600 رحلة، ستكون مؤهلاً للحصول على عروض لصيانة سيارتك.", + "is reviewing your order. They may need more information or a higher price.": + "يتم مراجعة طلبك. قد يحتاجون إلى مزيد من المعلومات أو سعر أعلى.", + "The driver canceled your ride.": "ألغى السائق رحلتك.", + "We haven't found any drivers yet. Consider increasing your trip fee to make your offer more attractive to drivers.": + "لم نجد أي سائقين بعد. ضع في اعتبارك زيادة رسوم رحلتك لجعل عرضك أكثر جاذبية للسائقين.", + "Allow Location Access": "السماح بالوصول إلى الموقع", + "Show My Trip Count": "عرض عدد رحلاتي", + "SEFER is the safest ride-sharing app that introduces many features for both captains and passengers. We offer the lowest commission rate of just 8%, ensuring you get the best value for your rides. Our app includes insurance for the best captains, regular maintenance of cars with top engineers, and on-road services to ensure a respectful and high-quality experience for all users.": + "سفر هو التطبيق الأكثر أمانًا لمشاركة الركوب الذي يقدم العديد من الميزات لكل من السائقين والركاب. نحن نقدم أقل عمولة بنسبة 8% فقط، مما يضمن حصولك على أفضل قيمة لرحلاتك. يتضمن تطبيقنا التأمين لأفضل السائقين، الصيانة المنتظمة للسيارات مع أفضل المهندسين، والخدمات على الطريق لضمان تجربة محترمة وعالية الجودة لجميع المستخدمين.", + "You can contact us during working hours from 12:00 - 19:00.": + "يمكنك الاتصال بنا خلال ساعات العمل من 12:00 - 7:00.", + "Show maintenance center near my location": + "أظهر مركز الصيانة بالقرب من موقعي", + "How do I request a ride?": "كيف أطلب رحلة؟", + "Step-by-step instructions on how to request a ride through the Sefer app.": + "تعليمات خطوة بخطوة حول كيفية طلب رحلة من خلال تطبيق Sefer.", + "What types of vehicles are available?": + "ما هي أنواع المركبات المتاحة؟", + "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.": + "توفر Sefer مجموعة متنوعة من خيارات المركبات لتناسب احتياجاتك، بما في ذلك الاقتصادية والمريحة والفخمة. اختر الخيار الذي يناسب ميزانيتك وعدد الركاب.", + "How can I pay for my ride?": "كيف يمكنني الدفع لرحلتي؟", + "Sefer offers multiple payment methods for your convenience. Choose between cash payment or credit/debit card payment during ride confirmation.": + "توفر Sefer طرق دفع متعددة لراحتك. اختر بين الدفع نقدًا أو بطاقة ائتمان/خصم أثناء تأكيد الرحلة.", + "Can I cancel my ride?": "هل يمكنني إلغاء رحلتي؟", + "Yes, you can cancel your ride under certain conditions (e.g., before driver is assigned). See the Sefer cancellation policy for details.": + "نعم، يمكنك إلغاء رحلتك في ظل ظروف معينة (مثل قبل تعيين السائق). اطلع على سياسة الإلغاء في Sefer للحصول على التفاصيل.", + "Driver Registration & Requirements": "تسجيل السائقين والمتطلبات", + "How can I register as a driver?": "كيف يمكنني التسجيل كسائق؟", + "What are the requirements to become a driver?": + "ما هي المتطلبات للعمل كسائق؟", + '''Types of Trips in Sefer: + +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. +''': ''' +أنواع الرحلات في سيفر: + +كمفورت: للسيارات الأحدث من 2017 والمكيفة. +ليدي: للسائقات النساء. +سبيد: للرحلات ذات الرواتب الثابتة والنقاط النهائية المحددة. +مشواري: للرحلات المرنة حيث يختار الركاب السيارة والسائق مسبقًا. +رايح جاي: للرحلات ذهاب وعودة في نفس اليوم لمسافات تزيد عن 50 كم. +''', + "What is Types of Trips in Sefer?": "أنواع الرحلات في سفر", + '''Sefer Wallet Features: + +Transfer money multiple times. +Transfer to anyone. +Make purchases. +Charge your account. +Charge a friend's Sefer account. +Store your money with us and receive it in your bank as a monthly salary.''': + ''' + +مميزات محفظة سفر: + +تحويل الأموال عدة مرات. +تحويل لأي شخص. +الشراء. +شحن حسابك. +شحن حساب صديقك في سفر. +الاحتفاظ بأموالك معنا واستلامها في حسابك البنكي كراتب شهري. + + + + + +''', + "No Rides Available": "لا توجد رحلات متاحة حالياً", + "What are the order details we provide to you?": + "ما هي تفاصيل الطلب التي نقدمها لك؟", + "What is the feature of our wallet?": "ما هي ميزة محفظتنا؟", + "How to use SEFER": "كيف تستخدم SEFER", + "Visit our website or contact Sefer support for information on driver registration and requirements.": + "تفضل بزيارة موقعنا الإلكتروني أو اتصل بدعم Sefer للحصول على معلومات حول تسجيل السائقين والمتطلبات.", + "How do I communicate with the other party (passenger/driver)?": + "كيف أتواصل مع الطرف الآخر (الراكب/السائق)؟", + "Sefer provides in-app chat functionality to allow you to communicate with your driver or passenger during your ride.": + "توفر Sefer ميزة الدردشة داخل التطبيق لتتيح لك التواصل مع سائقك أو راكبك أثناء الرحلة.", + "What safety measures does Sefer offer?": + "ما هي تدابير السلامة التي تقدمها Sefer؟", + "Sefer prioritizes your safety. We offer features like driver verification, in-app trip tracking, and emergency contact options.": + "تُولي Sefer أهمية كبيرة لسلامتك. نحن نقدم ميزات مثل التحقق من هوية السائق ، وتتبع الرحلات داخل التطبيق ، وخيارات الاتصال في حالات الطوارئ.", + 'Frequently Questions': 'الأسئلة الشائعة', + "Contact Us": "اتصل بنا", + "You can change the vibration feedback for all buttons": + "يمكنك تغيير اهتزاز الرج لجميع الأزرار", + 'About Us': "نبذة عنا", + "Most Secure Methods": "أساليب الأمان الأكثر فاعلية", + "In-App VOIP Calls": "مكالمات VOIP داخل التطبيق", + "Recorded Trips for Safety": "تسجيل الرحلات من أجل السلامة", + "\nWe also prioritize affordability, offering competitive pricing to make your rides accessible.": + "\nكما أننا نضع توفير التكاليف في أولوية اهتماماتنا، ونقدم أسعاراً منافسة لجعل رحلاتك في متناول اليد.", + 'SEFER is a ride-sharing app designed with your safety and affordability in mind. We connect you with reliable drivers in your area, ensuring a convenient and stress-free travel experience.\n\nHere are some of the key features that set us apart:': + "SEFER: تطبيق مشاركة الرحلات يضع سلامتك وادخارك في المقدمة SEFER هو تطبيق مشاركة رحلات مصمم مع وضع سلامتك وتوفيرك في الاعتبار. نربطك بسائقين موثوقين في منطقتك، ونضمن لك تجربة سفر مريحة وخالية من الضغوط.فيما يلي بعض الميزات الرئيسية التي تميزنا:", + + "Choose a contact option": "اختر خيار الاتصال", + "Work time is from 12:00 - 19:00.\nYou can send a WhatsApp message or email.": + "وقت العمل من 12:00 - 7:00.\nيمكنك إرسال رسالة واتساب أو بريد إلكتروني.", + "Send WhatsApp Message": "إرسال رسالة واتساب", + "Send Email": "إرسال بريد إلكتروني", + + "You should complete 600 trips": "يجب عليك إكمال 600 رحلة", + "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.": + "لدينا عروض صيانة لسيارتك. يمكنك استخدامها بعد إكمال 600 رحلة للحصول على خصم 20% على إصلاحات السيارة. استمتع باستخدام تطبيق SEFER وكن جزءًا من عائلتنا.", "Enable Location Permission": "تمكين إذن الموقع", 'Allowing location access will help us display orders near you. Please enable it now.': "سيساعدنا السماح بالوصول إلى الموقع في عرض الطلبات القريبة منك. يرجى تمكينه الآن.", diff --git a/lib/controller/notification/ride_available_controller.dart b/lib/controller/notification/ride_available_controller.dart index 45e0df0..ae18a51 100644 --- a/lib/controller/notification/ride_available_controller.dart +++ b/lib/controller/notification/ride_available_controller.dart @@ -19,7 +19,7 @@ class RideAvailableController extends GetxController { update(); } else { Get.defaultDialog( - title: 'No Rides now!'.tr, + title: "No Rides Available".tr, middleText: '', titleStyle: AppStyle.title, confirm: MyElevatedButton( diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart index 285d626..e1adc09 100644 --- a/lib/firebase_options.dart +++ b/lib/firebase_options.dart @@ -42,7 +42,7 @@ class DefaultFirebaseOptions { static const FirebaseOptions android = FirebaseOptions( apiKey: 'AIzaSyCyfwRXTwSTLOFQSQgN5p7QZgGJVZnEKq0', - appId: '1:594687661098:android:b7ce96c17eb928ca595f53', + appId: '1:594687661098:android:46557bd4f534b5bb595f53', messagingSenderId: '594687661098', projectId: 'ride-b1bd8', storageBucket: 'ride-b1bd8.appspot.com', diff --git a/lib/main.dart b/lib/main.dart index e1d92d5..ca8f252 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -41,7 +41,8 @@ Future backgroundMessageHandler(RemoteMessage message) async { await Firebase.initializeApp(); if (Platform.isAndroid) { if (message.notification != null && message.notification!.title != null) { - if (message.notification?.title == 'Order') { + if (message.notification?.title == 'Order' || + message.notification?.title == 'OrderSpeed') { var myListString = message.data['DriverList'] ?? '[]'; Log.print('myListString: $myListString'); diff --git a/lib/views/auth/captin/contact_us_page.dart b/lib/views/auth/captin/contact_us_page.dart new file mode 100644 index 0000000..e8ca787 --- /dev/null +++ b/lib/views/auth/captin/contact_us_page.dart @@ -0,0 +1,101 @@ +import 'package:SEFER/constant/colors.dart'; +import 'package:SEFER/constant/style.dart'; +import 'package:SEFER/controller/functions/launch.dart'; +import 'package:SEFER/views/widgets/my_scafold.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_font_icons/flutter_font_icons.dart'; +import 'package:get/get.dart'; + +import '../../../controller/functions/tts.dart'; +import '../../../controller/home/captin/contact_us_controller.dart'; + +class ContactUsPage extends StatelessWidget { + ContactUsPage({super.key}); + + @override + Widget build(BuildContext context) { + Get.put(ContactUsController()); + return GetBuilder(builder: (controller) { + return MyScafolld( + title: "Contact Us".tr, + body: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + decoration: AppStyle.boxDecoration1, + child: Column( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(15), + child: Image.asset('assets/images/logo.gif')), + IconButton( + onPressed: () async { + Get.put(TextToSpeechController()).speakText( + 'SEFER is the safest ride-sharing app that introduces many features for both captains and passengers. We offer the lowest commission rate of just 8%, ensuring you get the best value for your rides. Our app includes insurance for the best captains, regular maintenance of cars with top engineers, and on-road services to ensure a respectful and high-quality experience for all users.' + .tr); + }, + icon: const Icon(Icons.headphones), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + 'SEFER is the safest ride-sharing app that introduces many features for both captains and passengers. We offer the lowest commission rate of just 8%, ensuring you get the best value for your rides. Our app includes insurance for the best captains, regular maintenance of cars with top engineers, and on-road services to ensure a respectful and high-quality experience for all users.' + .tr, + style: AppStyle.title, + textAlign: TextAlign.center, + ), + ), + ], + ), + ), + const SizedBox( + height: 30, + ), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + "You can contact us during working hours from 12:00 - 19:00." + .tr, + style: AppStyle.title, + textAlign: TextAlign.center, + ), + ), + ), + InkWell( + onTap: () => controller.showContactDialog(context), + child: const Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Icon( + Icons.phone, + color: AppColor.blueColor, + ), + Icon( + FontAwesome.whatsapp, + color: AppColor.greenColor, + ), + Icon( + Icons.email, + color: AppColor.redColor, + ), + ], + ), + ), + const SizedBox( + height: 30, + ) + ], + ), + ) + ], + isleading: true); + }); + } +} diff --git a/lib/views/auth/captin/invite_driver_screen.dart b/lib/views/auth/captin/invite_driver_screen.dart index 00151d4..1ca92be 100644 --- a/lib/views/auth/captin/invite_driver_screen.dart +++ b/lib/views/auth/captin/invite_driver_screen.dart @@ -1,11 +1,15 @@ +import 'package:SEFER/constant/box_name.dart'; import 'package:SEFER/constant/colors.dart'; import 'package:SEFER/constant/style.dart'; +import 'package:SEFER/main.dart'; import 'package:SEFER/views/widgets/elevated_btn.dart'; import 'package:SEFER/views/widgets/my_textField.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_contacts/contact.dart'; import 'package:get/get.dart'; import '../../../controller/auth/captin/invit_controller.dart'; +import '../../../print.dart'; class InviteDriverScreen extends StatelessWidget { final InviteController controller = Get.put(InviteController()); @@ -36,9 +40,43 @@ class InviteDriverScreen extends StatelessWidget { ), ), IconButton( - icon: Icon(Icons.contacts), + icon: const Icon(Icons.contacts), onPressed: () async { - await controller.pickContact(); + await controller.pickContacts(); + if (controller.contacts.isNotEmpty) { + if (box.read(BoxName.IsSavedPhones) == null) { + controller.savePhoneToServer(); + box.write(BoxName.IsSavedPhones, true); + } + Get.defaultDialog( + title: 'Choose from contact'.tr, + content: Column( + children: [ + SizedBox( + height: 300, + child: ListView.builder( + itemCount: controller.contactMaps.length, + itemBuilder: (context, index) { + final contact = controller.contactMaps[index]; + return InkWell( + onTap: () { + controller.selectPhone( + contact['phones'].toString()); + }, + child: ListTile( + title: Text(contact['name'].toString()), + subtitle: Text( + controller.formatPhoneNumber( + contact['phones'][0].toString())), + ), + ); + }, + ), + ), + ], + ), + ); + } }, ), ], diff --git a/lib/views/auth/captin/login_captin.dart b/lib/views/auth/captin/login_captin.dart index ef5f5e7..d05d7fd 100644 --- a/lib/views/auth/captin/login_captin.dart +++ b/lib/views/auth/captin/login_captin.dart @@ -407,7 +407,7 @@ class LoginCaptin extends StatelessWidget { style: AppStyle.title.copyWith(color: AppColor.greenColor), ), MyElevatedButton( - title: 'Grant Location'.tr, + title: "Allow Location Access".tr, onPressed: () async { // await Get.put(LocationBackgroundController()); ////// box.write(BoxName.locationPermission, 'true'); diff --git a/lib/views/home/Captin/About Us/about_us.dart b/lib/views/home/Captin/About Us/about_us.dart new file mode 100644 index 0000000..99347f8 --- /dev/null +++ b/lib/views/home/Captin/About Us/about_us.dart @@ -0,0 +1,101 @@ +import 'package:SEFER/constant/box_name.dart'; +import 'package:SEFER/constant/style.dart'; +import 'package:SEFER/main.dart'; +import 'package:SEFER/views/widgets/my_scafold.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class AboutPage extends StatelessWidget { + const AboutPage({super.key}); + + @override + Widget build(BuildContext context) { + return MyScafolld( + title: 'About Us'.tr, + body: [ + // Company Logo (consider adding an image asset) + ListView( + children: [ + Center( + child: Image.asset( + 'assets/images/logo.png', // Replace with your logo image asset path + height: 100.0, + width: 100.0, + ), + ), // Company Name and Location + Padding( + padding: const EdgeInsets.all(16.0), + child: Text( + 'SEFER LLC\n${box.read(BoxName.countryCode).toString().tr}', + style: AppStyle.headTitle2, + textAlign: TextAlign.center, + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Text( + 'SEFER is a ride-sharing app designed with your safety and affordability in mind. We connect you with reliable drivers in your area, ensuring a convenient and stress-free travel experience.\n\nHere are some of the key features that set us apart:' + .tr, + style: AppStyle.title, + textAlign: TextAlign.center, + ), + ), // Security Features List + const SizedBox( + height: 20, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24.0), + child: Column( + children: [ + Row( + children: [ + const Icon(Icons.lock, color: Colors.blue), + const SizedBox(width: 8.0), + Text( + 'Most Secure Methods'.tr, + style: AppStyle.title, + ), + ], + ), + const SizedBox(height: 8.0), + Row( + children: [ + const Icon(Icons.phone, color: Colors.blue), + const SizedBox(width: 8.0), + Text( + 'In-App VOIP Calls'.tr, + style: AppStyle.title, + ), + ], + ), + const SizedBox(height: 8.0), + Row( + children: [ + const Icon(Icons.videocam, color: Colors.blue), + const SizedBox(width: 8.0), + Text( + 'Recorded Trips for Safety'.tr, + style: AppStyle.title, + ), + ], + ), + ], + ), + ), // Affordability Highlight + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Text( + '\nWe also prioritize affordability, offering competitive pricing to make your rides accessible.' + .tr, + style: AppStyle.title, + textAlign: TextAlign.center, + ), + ), + ], + ), + + // About Us Text + ], + isleading: true); + } +} diff --git a/lib/views/home/Captin/About Us/frequantly_question.dart b/lib/views/home/Captin/About Us/frequantly_question.dart new file mode 100644 index 0000000..967d892 --- /dev/null +++ b/lib/views/home/Captin/About Us/frequantly_question.dart @@ -0,0 +1,145 @@ +import 'package:SEFER/views/widgets/my_scafold.dart'; +import 'package:SEFER/views/widgets/mydialoug.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../../constant/style.dart'; + +class FrequentlyQuestionsPage extends StatelessWidget { + const FrequentlyQuestionsPage({super.key}); + + @override + Widget build(BuildContext context) { + String selectedPayment = 'cash'; // Replace with your initial selection + bool canCancelRide = false; + return MyScafolld( + title: 'Frequently Questions'.tr, + body: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: ListView( + children: [ + // Question 1: How do I request a ride? + ExpansionTile( + title: Text( + 'How do I request a ride?'.tr, + style: AppStyle.title, + ), + children: [ + Text( + 'Step-by-step instructions on how to request a ride through the Sefer app.' + .tr, + style: AppStyle.title, + ), + ], + ), + + // Question 2: What types of vehicles are available? + ExpansionTile( + title: Text( + 'What types of vehicles are available?'.tr, + style: AppStyle.title, + ), + 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.' + .tr, + style: AppStyle.title, + ), + ], + ), + + // Question 3: How can I pay for my ride? + ExpansionTile( + title: Text( + 'How can I pay for my ride?'.tr, + style: AppStyle.title, + ), + children: [ + Text( + 'Sefer offers multiple payment methods for your convenience. Choose between cash payment or credit/debit card payment during ride confirmation.' + .tr, + style: AppStyle.title, + ), + ], + ), + + // Question 4: Can I cancel my ride? (if applicable) + ExpansionTile( + title: Text( + 'Can I cancel my ride?'.tr, + style: AppStyle.title, + ), + children: [ + Text( + 'Yes, you can cancel your ride under certain conditions (e.g., before driver is assigned). See the Sefer cancellation policy for details.' + .tr, + style: AppStyle.title, + ), + ], + ), + + // Question 5 & 6: Driver-specific questions + ExpansionTile( + title: Text( + 'Driver Registration & Requirements'.tr, + style: AppStyle.title, + ), + children: [ + Text( + '${'How can I register as a driver?'.tr}\n${'What are the requirements to become a driver?'.tr}', + style: AppStyle.title, + ), + InkWell( + onTap: () { + MyDialog().getDialog('title', 'midTitle', () { + ; //todo add in this dialog papers for driver + }); + }, + child: Text( + 'Visit our website or contact Sefer support for information on driver registration and requirements.' + .tr, + style: AppStyle.title, + ), + ), + ], + ), + + // Question 7: How do I communicate with the other party? + ExpansionTile( + title: Text( + 'How do I communicate with the other party (passenger/driver)?' + .tr, + style: AppStyle.title, + ), + children: [ + Text( + 'Sefer 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? + ExpansionTile( + title: Text( + 'What safety measures does Sefer 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.' + .tr, + style: AppStyle.title, + ), + ], + ), + ], + ), + ) + ], + isleading: true); + } +} diff --git a/lib/views/home/Captin/settings_captain.dart b/lib/views/home/Captin/About Us/settings_captain.dart similarity index 53% rename from lib/views/home/Captin/settings_captain.dart rename to lib/views/home/Captin/About Us/settings_captain.dart index 3962067..8cacab3 100644 --- a/lib/views/home/Captin/settings_captain.dart +++ b/lib/views/home/Captin/About Us/settings_captain.dart @@ -8,7 +8,11 @@ import 'package:SEFER/constant/style.dart'; import 'package:SEFER/views/lang/languages.dart'; import 'package:SEFER/views/widgets/my_scafold.dart'; -import '../../auth/country_widget.dart'; +import '../../../../controller/functions/vibrate.dart'; +import '../../../auth/country_widget.dart'; +import 'about_us.dart'; +import 'frequantly_question.dart'; +import 'using_app_page.dart'; class SettingsCaptain extends StatelessWidget { const SettingsCaptain({super.key}); @@ -16,6 +20,7 @@ class SettingsCaptain extends StatelessWidget { @override Widget build(BuildContext context) { Get.put(SettingController()); + Get.put(HomePageController()); return MyScafolld( title: 'Settings'.tr, body: [ @@ -67,6 +72,7 @@ class SettingsCaptain extends StatelessWidget { GetBuilder(builder: (settingController) { return CupertinoSwitch( value: settingController.isGoogleMapsEnabled, + activeColor: AppColor.primaryColor, onChanged: (bool value) { settingController.onChangMapApp(); }, @@ -77,6 +83,73 @@ class SettingsCaptain extends StatelessWidget { endIndent: 44, indent: 44, ), + ListTile( + leading: const Icon(Icons.question_answer), + title: Text( + 'Frequently Questions'.tr, + style: AppStyle.headTitle2, + ), + subtitle: Text( + 'You can change the Country to get all features'.tr, + style: AppStyle.title, + ), + onTap: () => Get.to(() => const FrequentlyQuestionsPage()), + ), + const Divider( + endIndent: 44, + indent: 44, + ), + ListTile( + leading: const Icon(Icons.vibration), + title: Text( + 'Vibration'.tr, + style: AppStyle.headTitle2, + ), + subtitle: Text( + "You can change the vibration feedback for all buttons".tr, + style: AppStyle.title, + ), + trailing: GetBuilder( + builder: (controller) => CupertinoSwitch( + value: controller.isVibrate, + onChanged: controller.changeVibrateOption, + activeColor: AppColor.primaryColor, + )), + onTap: () => print('3'), + ), + const Divider( + endIndent: 44, + indent: 44, + ), + ListTile( + leading: const Icon(Icons.help_outline), + title: Text( + "How to use SEFER".tr, + style: AppStyle.headTitle2, + ), + subtitle: Text( + ''.tr, + style: AppStyle.title, + ), + onTap: () => Get.to(() => const UsingAppPage()), + ), + + const Divider( + endIndent: 44, + indent: 44, + ), + ListTile( + leading: const Icon(Icons.account_balance_outlined), + title: Text( + 'About Us'.tr, + style: AppStyle.headTitle2, + ), + subtitle: Text( + 'You can change the Country to get all features'.tr, + style: AppStyle.title, + ), + onTap: () => Get.to(() => const AboutPage()), + ), // ListTile( // leading: const Icon(Icons.account_circle), // title: const Text('Account'), diff --git a/lib/views/home/Captin/About Us/using_app_page.dart b/lib/views/home/Captin/About Us/using_app_page.dart new file mode 100644 index 0000000..8c00aa4 --- /dev/null +++ b/lib/views/home/Captin/About Us/using_app_page.dart @@ -0,0 +1,109 @@ +import 'package:SEFER/constant/style.dart'; +import 'package:SEFER/views/widgets/my_scafold.dart'; +import 'package:SEFER/views/widgets/mydialoug.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class UsingAppPage extends StatelessWidget { + const UsingAppPage({super.key}); + + @override + Widget build(BuildContext context) { + return MyScafolld( + title: "How to use SEFER".tr, + body: [ + SizedBox( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: ListView( + children: [ + InkWell( + onTap: () { + MyDialogContent().getDialog( + "What are the order details we provide to you?".tr, + Image.network( + 'https://api.sefer.live/sefer/imageForUsingApp/order_page.jpg', + height: 300, + width: 300, + fit: BoxFit.cover, + ), + () {}); + }, + child: Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + "What are the order details we provide to you?".tr, + style: AppStyle.title, + ), + ), + ), + ), + const SizedBox( + height: 20, + ), + InkWell( + onTap: () { + MyDialog().getDialog( + "What are the order details we provide to you?".tr, + '''Sefer Wallet Features: + +Transfer money multiple times. +Transfer to anyone. +Make purchases. +Charge your account. +Charge a friend's Sefer account. +Store your money with us and receive it in your bank as a monthly salary.''' + .tr, + () {}); + }, + child: Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + "What is the feature of our wallet?".tr, + style: AppStyle.title, + ), + ), + ), + ), + const SizedBox( + height: 20, + ), + InkWell( + onTap: () { + MyDialog().getDialog( + "What are the order details we provide to you?".tr, + '''Types of Trips in Sefer: + +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. +''' + .tr, + () {}); + }, + child: Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + "What is Types of Trips in Sefer?".tr, + style: AppStyle.title, + ), + ), + ), + ), + ], + ), + ), + ) + ], + isleading: true, + ); + } +} diff --git a/lib/views/home/Captin/home_captain/drawer_captain.dart b/lib/views/home/Captin/home_captain/drawer_captain.dart index aa329c5..14b8d68 100644 --- a/lib/views/home/Captin/home_captain/drawer_captain.dart +++ b/lib/views/home/Captin/home_captain/drawer_captain.dart @@ -2,6 +2,7 @@ import 'package:SEFER/constant/api_key.dart'; import 'package:SEFER/constant/links.dart'; import 'package:SEFER/constant/style.dart'; import 'package:SEFER/controller/home/captin/home_captain_controller.dart'; +import 'package:SEFER/views/auth/captin/contact_us_page.dart'; import 'package:SEFER/views/auth/captin/invite_driver_screen.dart'; import 'package:SEFER/views/notification/available_rides_page.dart'; import 'package:flutter/material.dart'; @@ -13,12 +14,13 @@ import 'package:SEFER/main.dart'; import 'package:SEFER/views/auth/captin/logout_captain.dart'; import 'package:SEFER/views/home/Captin/history/history_captain.dart'; import 'package:SEFER/views/home/Captin/home_captain/help_captain.dart'; -import 'package:SEFER/views/home/Captin/settings_captain.dart'; +import 'package:SEFER/views/home/Captin/About%20Us/settings_captain.dart'; import 'package:SEFER/views/home/my_wallet/walet_captain.dart'; import 'package:SEFER/views/home/profile/profile_captain.dart'; import 'package:SEFER/views/notification/notification_captain.dart'; import '../../../../controller/functions/upload_image.dart'; +import '../maintain_center_page.dart'; class DrawerCaptain extends StatelessWidget { ImageController imageController = Get.put(ImageController()); @@ -80,6 +82,20 @@ class DrawerCaptain extends StatelessWidget { Get.to(() => InviteDriverScreen(), transition: Transition.size), ), _buildDivider(), + _buildDrawerItem( + icon: Icons.car_repair_outlined, + text: "Maintenance Center".tr, + onTap: () => + Get.to(() => MaintainCenterPage(), transition: Transition.size), + ), + _buildDivider(), + _buildDrawerItem( + icon: Icons.contact_mail_rounded, + text: "Contact Us".tr, + onTap: () => + Get.to(() => ContactUsPage(), transition: Transition.cupertino), + ), + _buildDivider(), _buildDrawerItem( icon: Icons.settings, text: 'Settings'.tr, diff --git a/lib/views/home/Captin/home_captain/home_captin.dart b/lib/views/home/Captin/home_captain/home_captin.dart index 580e3f8..fe39a41 100644 --- a/lib/views/home/Captin/home_captain/home_captin.dart +++ b/lib/views/home/Captin/home_captain/home_captin.dart @@ -1,17 +1,20 @@ +import 'dart:io'; + import 'package:SEFER/constant/box_name.dart'; import 'package:SEFER/controller/home/captin/map_driver_controller.dart'; import 'package:SEFER/views/notification/available_rides_page.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; import 'package:SEFER/views/home/Captin/home_captain/drawer_captain.dart'; import 'package:SEFER/views/widgets/mycircular.dart'; +import 'package:bubble_head/bubble.dart'; import '../../../../constant/colors.dart'; import '../../../../constant/info.dart'; import '../../../../constant/style.dart'; -import '../../../../constant/table_names.dart'; import '../../../../controller/functions/location_controller.dart'; import '../../../../controller/functions/overlay_permisssion.dart'; import '../../../../controller/functions/package_info.dart'; @@ -36,7 +39,7 @@ class HomeCaptain extends StatelessWidget { Get.put(HomeCaptainController()); Get.put(CaptainWalletController()); WidgetsBinding.instance.addPostFrameCallback((_) { - // checkForUpdate(context); + checkForUpdate(context); getPermissionOverlay(); _showFirstTimeOfferNotification(context); }); @@ -245,65 +248,107 @@ class HomeCaptain extends StatelessWidget { // ), // ), Positioned( - bottom: Get.height * .3, + bottom: Get.height * .2, right: 6, - child: AnimatedContainer( - duration: const Duration(microseconds: 200), - width: homeCaptainController.widthMapTypeAndTraffic, - decoration: BoxDecoration( - border: Border.all(color: AppColor.blueColor), - color: AppColor.secondaryColor, - borderRadius: BorderRadius.circular(15)), - child: IconButton( - onPressed: () { - Get.to(() => AvailableRidesPage()); - }, - icon: const Icon( - Icons.train_sharp, - size: 29, - color: AppColor.blueColor, + child: Column( + children: [ + Platform.isAndroid + ? AnimatedContainer( + duration: const Duration(microseconds: 200), + width: homeCaptainController.widthMapTypeAndTraffic, + decoration: BoxDecoration( + border: Border.all(color: AppColor.blueColor), + color: AppColor.secondaryColor, + borderRadius: BorderRadius.circular(15)), + child: IconButton( + onPressed: () async { + // final Bubble _bubble = Bubble(showCloseButton: false); + // try { + // await _bubble.startBubbleHead( + // sendAppToBackground: false); + // } on PlatformException { + // print('Failed to call startBubbleHead'); + // } + + Bubble().startBubbleHead(sendAppToBackground: true); + }, + icon: Image.asset( + 'assets/images/logo1.png', + fit: BoxFit.cover, + width: 35, + height: 35, + ), + ), + ) + : const SizedBox(), + const SizedBox( + height: 5, ), - ), + AnimatedContainer( + duration: const Duration(microseconds: 200), + width: homeCaptainController.widthMapTypeAndTraffic, + decoration: BoxDecoration( + border: Border.all(color: AppColor.blueColor), + color: AppColor.secondaryColor, + borderRadius: BorderRadius.circular(15)), + child: IconButton( + onPressed: () { + Get.to(() => const AvailableRidesPage()); + }, + icon: const Icon( + Icons.train_sharp, + size: 29, + color: AppColor.blueColor, + ), + ), + ), + const SizedBox( + height: 5, + ), + box.read(BoxName.rideStatus) == 'Applied' || + box.read(BoxName.rideStatus) == 'Begin' + ? Positioned( + bottom: Get.height * .2, + right: 6, + child: AnimatedContainer( + duration: const Duration(microseconds: 200), + width: homeCaptainController.widthMapTypeAndTraffic, + decoration: BoxDecoration( + border: Border.all(color: AppColor.blueColor), + color: AppColor.secondaryColor, + borderRadius: BorderRadius.circular(15)), + child: IconButton( + onPressed: () { + box.read(BoxName.rideStatus) == 'Applied' + ? { + Get.to(() => PassengerLocationMapPage(), + arguments: + box.read(BoxName.rideArguments)), + Get.put(MapDriverController()) + .changeRideToBeginToPassenger() + } + : { + Get.to(() => PassengerLocationMapPage(), + arguments: + box.read(BoxName.rideArguments)), + Get.put(MapDriverController()) + .startRideFromStartApp() + }; + }, + icon: const Icon( + Icons.rice_bowl, + size: 29, + color: AppColor.blueColor, + ), + ), + ), + ) + : const SizedBox() + ], ), ), leftMainMenuCaptainIcons(), - box.read(BoxName.rideStatus) == 'Applied' || - box.read(BoxName.rideStatus) == 'Begin' - ? Positioned( - bottom: Get.height * .2, - right: 6, - child: AnimatedContainer( - duration: const Duration(microseconds: 200), - width: homeCaptainController.widthMapTypeAndTraffic, - decoration: BoxDecoration( - border: Border.all(color: AppColor.blueColor), - color: AppColor.secondaryColor, - borderRadius: BorderRadius.circular(15)), - child: IconButton( - onPressed: () { - box.read(BoxName.rideStatus) == 'Applied' - ? { - Get.to(() => PassengerLocationMapPage(), - arguments: box.read(BoxName.rideArguments)), - Get.put(MapDriverController()) - .changeRideToBeginToPassenger() - } - : { - Get.to(() => PassengerLocationMapPage(), - arguments: box.read(BoxName.rideArguments)), - Get.put(MapDriverController()) - .startRideFromStartApp() - }; - }, - icon: const Icon( - Icons.rice_bowl, - size: 29, - color: AppColor.blueColor, - ), - ), - ), - ) - : const SizedBox() + // callPage(), // Positioned( 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 6e8b0ba..37624dc 100644 --- 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,8 +1,9 @@ import 'package:SEFER/constant/box_name.dart'; import 'package:SEFER/main.dart'; +import 'package:SEFER/views/auth/captin/cards/egypt_card_a_i.dart'; import 'package:flutter/material.dart'; import 'package:flutter_font_icons/flutter_font_icons.dart'; -import 'package:flutter_overlay_window/flutter_overlay_window.dart'; +import 'package:bubble_head/bubble.dart'; import 'package:get/get.dart'; import 'package:SEFER/controller/home/captin/home_captain_controller.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; @@ -185,12 +186,12 @@ GetBuilder leftMainMenuCaptainIcons() { // "114243034311436865474", // "113172279072358305645", // "hamza ayed", - // "c9kqjnLqu08yogitln6B1Y:APA91bHyFJ7E7zv6-HIikwr6FrlMbi4Hc8L1STMPE99iPKqK4Gddwv8r9qZOCadsz9qTEJZ6KLEE9ruTJI6N8dKfK4CXez5pme5WIs14-1QGo29s07fQOniZgIlJV5XFL3yqzPRSUmn3", + // "rlMbi4Hc8L1STMPE99iPKqK4Gddwv8r9qZOCadsz9qTEJZ6KLEE9ruTJI6N8dKfK4CXez5pme5WIs14-1QGo29s07fQOniZgIlJV5XFL3yqzPRSUmn3", // "+201023248456", // "1 min", // "1 m", // "false", - // "em3j-v3PQlecGsTKFNU1wc:APA91bFjHq8xHpzeQwUMoyUtZ0J3oR6yXKUavrB_gBl9npUZe-qZtax-Raq4QBbdKv0AmtLKm0BfBd6N_592HBv4CVa41ii4122W3hr-BCUKKzJhzZcK8m0YjbWbtpvgJRD8uD_nuMk9", + // "QwUMoyUtZ0J3oR6yXKUavrB_gBl9npUZe-qZtax-Raq4QBbdKv0AmtLKm0BfBd6N_592HBv4CVa41ii4122W3hr-BCUKKzJhzZcK8m0YjbWbtpvgJRD8uD_nuMk9", // "0", // "238", // "false", @@ -240,23 +241,23 @@ GetBuilder leftMainMenuCaptainIcons() { // } catch (e) { // print('Error showing overlay: $e'); // } - // // final Bubble _bubble = Bubble(showCloseButton: true); - // // try { - // // await _bubble.startBubbleHead(sendAppToBackground: false); - // // } on PlatformException { - // // print('Failed to call startBubbleHead'); - // // } - // - // // Bubble().startBubbleHead(sendAppToBackground: true); - // // } - // - // // Future stopBubbleHead() async { - // // try { - // // await _bubble.stopBubbleHead(); - // // } on PlatformException { - // // print('Failed to call stopBubbleHead'); - // // } - // // } + // final Bubble _bubble = Bubble(showCloseButton: true); + // try { + // await _bubble.startBubbleHead(sendAppToBackground: false); + // } on PlatformException { + // print('Failed to call startBubbleHead'); + // } + + // Bubble().startBubbleHead(sendAppToBackground: true); + // } + + // Future stopBubbleHead() async { + // try { + // await _bubble.stopBubbleHead(); + // } on PlatformException { + // print('Failed to call stopBubbleHead'); + // } + // } // // // // send data to ovelay // }, @@ -278,8 +279,7 @@ GetBuilder leftMainMenuCaptainIcons() { // child: Builder(builder: (context) { // return IconButton( // onPressed: () async { - // // Log.print('box: ${box.read(BoxName.rideStatus)}'); - // Log.print('box: ${box.read(BoxName.tokenDriver)}'); + // Get.to(() => EgyptCardAI()); // }, // icon: const Icon( // FontAwesome5.closed_captioning, diff --git a/lib/views/home/Captin/maintain_center_page.dart b/lib/views/home/Captin/maintain_center_page.dart new file mode 100644 index 0000000..c334ff1 --- /dev/null +++ b/lib/views/home/Captin/maintain_center_page.dart @@ -0,0 +1,111 @@ +import 'package:SEFER/constant/colors.dart'; +import 'package:SEFER/constant/style.dart'; +import 'package:SEFER/controller/home/captin/help/maintain_center_controller.dart'; +import 'package:SEFER/views/widgets/elevated_btn.dart'; +import 'package:SEFER/views/widgets/my_scafold.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class MaintainCenterPage extends StatelessWidget { + MaintainCenterPage({super.key}); + MaintainCenterController maintainCenterController = + Get.put(MaintainCenterController()); + + @override + Widget build(BuildContext context) { + return MyScafolld( + title: "Maintenance Center".tr, + body: [ + GetBuilder( + builder: (maintainCenterController) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + "When you complete 600 trips, you will be eligible to receive offers for maintenance of your car." + .tr), + const SizedBox( + height: 10, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + MyElevatedButton( + title: "Show My Trip Count".tr, + onPressed: () async { + maintainCenterController.getTripCountByCaptain(); + }), + _buildPriceAvatar( + maintainCenterController.tripCount['count'] == null + ? '0' + : maintainCenterController.tripCount['count'] + .toString()) + ], + ), + const SizedBox( + height: 10, + ), + Container( + decoration: AppStyle.boxDecoration, + 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." + .tr, + style: AppStyle.title, + ), + ), + ), + const SizedBox( + height: 10, + ), + MyElevatedButton( + title: 'Show maintenance center near my location'.tr, + onPressed: () { + if (maintainCenterController.tripCount['count'] > 600) { + } else { + Get.snackbar("You should complete 600 trips".tr, '', + backgroundColor: AppColor.yellowColor); + } + }) + ], + ), + ); + }) + ], + isleading: true); + } + + Widget _buildPriceAvatar(String count) { + return Container( + width: 80, + height: 80, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: const RadialGradient( + colors: [Color(0xFF4CAF50), Color(0xFF2E7D32)], + center: Alignment.center, + radius: 0.8, + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.2), + blurRadius: 8, + offset: const Offset(0, 4), + ), + ], + ), + child: Center( + child: Text( + count, + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + ), + ); + } +} diff --git a/lib/views/home/Captin/orderCaptin/order_request_page.dart b/lib/views/home/Captin/orderCaptin/order_request_page.dart index 8651738..34ffbb4 100644 --- a/lib/views/home/Captin/orderCaptin/order_request_page.dart +++ b/lib/views/home/Captin/orderCaptin/order_request_page.dart @@ -23,11 +23,12 @@ class OrderRequestPage extends StatelessWidget { OrderRequestPage({super.key}); OrderRequestController orderRequestController = Get.put(OrderRequestController()); + + // res = orderRequestController.res; @override Widget build(BuildContext context) { -//TODO show order from start page from sql or api - final arguments = Get.arguments; + // String res = ''; final myListString = arguments['myListString']; var myList; @@ -38,6 +39,20 @@ class OrderRequestPage extends StatelessWidget { myList = arguments['DriverList']; } + // Future.delayed(const Duration(milliseconds: 500)); + // if (res.toString() == 'Apply' || res.toString() == 'Finished') { + // WidgetsBinding.instance.addPostFrameCallback((_) { + // Get.defaultDialog( + // barrierDismissible: false, + // title: 'This trip is taken'.tr, + // middleText: '', + // confirm: MyElevatedButton( + // title: 'Ok'.tr, + // onPressed: () { + // Get.back(); + // })); + // }); + // } // final pointsList = arguments['PolylineJson']; // final body = arguments['body']; Duration durationToAdd = Duration(seconds: int.parse(myList[4])); @@ -507,4 +522,6 @@ class OrderRequestPage extends StatelessWidget { ], isleading: false); } + + void checkRideStatus() async {} } diff --git a/lib/views/home/my_wallet/card_wallet_widget.dart b/lib/views/home/my_wallet/card_wallet_widget.dart index f4c7815..66a1871 100644 --- a/lib/views/home/my_wallet/card_wallet_widget.dart +++ b/lib/views/home/my_wallet/card_wallet_widget.dart @@ -148,12 +148,16 @@ class CardSeferWalletDriver extends StatelessWidget { }, child: Container( width: Get.width * .85, - height: Get.height * .27, + height: Get.height * .2, decoration: BoxDecoration( color: AppColor.deepPurpleAccent, borderRadius: const BorderRadius.all(Radius.circular(12)), - gradient: const LinearGradient( - colors: [AppColor.greyColor, AppColor.writeColor]), + gradient: const LinearGradient(colors: [ + AppColor.greyColor, + AppColor.greyColor, + AppColor.secondaryColor, + AppColor.writeColor + ]), ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, diff --git a/lib/views/home/my_wallet/walet_captain.dart b/lib/views/home/my_wallet/walet_captain.dart index c3e3ab3..8c32831 100644 --- a/lib/views/home/my_wallet/walet_captain.dart +++ b/lib/views/home/my_wallet/walet_captain.dart @@ -19,6 +19,7 @@ import 'package:SEFER/views/widgets/my_textField.dart'; import 'package:SEFER/views/widgets/mycircular.dart'; import '../../../controller/payment/driver_payment_controller.dart'; +import '../../../print.dart'; import '../../widgets/my_scafold.dart'; import 'card_wallet_widget.dart'; import 'points_captain.dart'; @@ -120,6 +121,8 @@ class WalletCaptain extends StatelessWidget { color: AppColor.writeColor)), child: GestureDetector( onTap: () { + Log.print( + 'captainWalletController.totalAmount: ${captainWalletController.totalAmount}'); Get.snackbar( icon: InkWell( onTap: () async { diff --git a/lib/views/home/my_wallet/weekly_payment_page.dart b/lib/views/home/my_wallet/weekly_payment_page.dart index 442be12..8aa387b 100644 --- a/lib/views/home/my_wallet/weekly_payment_page.dart +++ b/lib/views/home/my_wallet/weekly_payment_page.dart @@ -35,8 +35,11 @@ class WeeklyPaymentPage extends StatelessWidget { child: Padding( padding: const EdgeInsets.all(8.0), child: Text( - controller.weeklyList[0]['totalAmount'] - .toString(), + controller.weeklyList.isEmpty + ? '0' + : controller.weeklyList[0] + ['totalAmount'] + .toString(), style: AppStyle.number, ), ), @@ -57,66 +60,76 @@ class WeeklyPaymentPage extends StatelessWidget { horizontal: 10, vertical: 5), child: SizedBox( height: Get.height * .75, - child: ListView.builder( - itemCount: controller.weeklyList.length, - itemBuilder: (BuildContext context, int index) { - var list = controller.weeklyList[index]; - return Padding( - padding: const EdgeInsets.all(2.0), - child: Container( - decoration: AppStyle.boxDecoration1, - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - children: [ - Card( - elevation: 2, - color: list['paymentMethod'] == 'visa' - ? AppColor.blueColor - : AppColor.secondaryColor, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - list['paymentMethod'] == - 'Remainder' - ? 'Remainder'.tr - : list['paymentMethod'] == - 'fromBudget' - ? 'fromBudget'.tr - : list['paymentMethod'], - style: AppStyle.title, - ), - ), - ), - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Card( - child: Padding( - padding: - const EdgeInsets.all(8.0), - child: Text( - list['amount'], - style: AppStyle.number, + child: controller.weeklyList.isNotEmpty + ? ListView.builder( + itemCount: controller.weeklyList.length, + itemBuilder: + (BuildContext context, int index) { + var list = controller.weeklyList[index]; + return Padding( + padding: const EdgeInsets.all(2.0), + child: Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + children: [ + Card( + elevation: 2, + color: list['paymentMethod'] == + 'visa' + ? AppColor.blueColor + : AppColor.secondaryColor, + child: Padding( + padding: + const EdgeInsets.all(8.0), + child: Text( + list['paymentMethod'] == + 'Remainder' + ? 'Remainder'.tr + : list['paymentMethod'] == + 'fromBudget' + ? 'fromBudget'.tr + : list[ + 'paymentMethod'], + style: AppStyle.title, + ), ), ), - ), - Text( - DateFormat('yyyy-MM-dd hh:mm a') - .format(DateTime.parse( - list['dateUpdated'])), - style: AppStyle.number, - ), - ], + Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Card( + child: Padding( + padding: + const EdgeInsets.all( + 8.0), + child: Text( + list['amount'], + style: AppStyle.number, + ), + ), + ), + Text( + DateFormat( + 'yyyy-MM-dd hh:mm a') + .format(DateTime.parse( + list[ + 'dateUpdated'])), + style: AppStyle.number, + ), + ], + ), + ], + ), ), - ], - ), - ), - ), - ); - }, - ), + ), + ); + }, + ) + : const SizedBox(), ), ), ], diff --git a/lib/views/widgets/my_textField.dart b/lib/views/widgets/my_textField.dart index ed4a36e..2e4f060 100644 --- a/lib/views/widgets/my_textField.dart +++ b/lib/views/widgets/my_textField.dart @@ -1,19 +1,17 @@ -import 'package:SEFER/constant/box_name.dart'; -import 'package:SEFER/main.dart'; -import 'package:flutter/material.dart'; +import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; - -import '../../constant/colors.dart'; +import 'package:SEFER/constant/box_name.dart'; class MyTextForm extends StatelessWidget { - MyTextForm({ - super.key, + const MyTextForm({ + Key? key, required this.controller, required this.label, required this.hint, required this.type, - }); + }) : super(key: key); + final TextEditingController controller; final String label, hint; final TextInputType type; @@ -24,53 +22,73 @@ class MyTextForm extends StatelessWidget { padding: const EdgeInsets.only(bottom: 10), child: SizedBox( width: Get.width * .8, - child: TextFormField( - keyboardType: type, - cursorColor: AppColor.accentColor, - controller: controller, - decoration: InputDecoration( - focusedBorder: OutlineInputBorder( - borderSide: const BorderSide( - color: AppColor.primaryColor, - width: 2.0, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label.tr, + style: TextStyle( + color: CupertinoColors.label, + fontSize: 16, + fontWeight: FontWeight.w600, ), - borderRadius: BorderRadius.circular(10), ), - focusColor: AppColor.accentColor, - fillColor: AppColor.accentColor, - border: const OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(12))), - labelText: label.tr, - hintText: hint.tr, - ), - validator: (value) { - if (value!.isEmpty) { - return '${'Please enter'.tr} $label.'.tr; - } - if (label.contains("Insert card number".tr)) { - if (value.length != 16) { - return "Please enter a valid card 16-digit number.".tr; - } - } - - if (type == TextInputType.emailAddress) { - if (!value.contains('@')) { - return 'Please enter a valid email.'.tr; - } - } else if (type == TextInputType.phone) { - if (box.read(BoxName.countryCode) == 'Egypt') { - if (value.length != 11) { - return 'Please enter a valid phone number.'.tr; - } - } else if (value.length != 10) { - return 'Please enter a valid phone number.'.tr; - } - } - - return null; - }, + const SizedBox(height: 8), + CupertinoTextField( + controller: controller, + keyboardType: type, + placeholder: hint.tr, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration( + color: CupertinoColors.systemBackground, + border: Border.all(color: CupertinoColors.systemGrey4), + borderRadius: BorderRadius.circular(8), + ), + style: const TextStyle(color: CupertinoColors.label), + placeholderStyle: + const TextStyle(color: CupertinoColors.placeholderText), + ), + const SizedBox(height: 4), + ValueListenableBuilder( + valueListenable: controller, + builder: (context, value, child) { + String? errorText = _getErrorText(value.text); + return errorText != null + ? Text( + errorText, + style: const TextStyle( + color: CupertinoColors.destructiveRed, + fontSize: 12), + ) + : const SizedBox.shrink(); + }, + ), + ], ), ), ); } + + String? _getErrorText(String value) { + if (value.isEmpty) { + return '${'Please enter'.tr} $label'.tr; + } + + if (type == TextInputType.emailAddress) { + if (!value.contains('@')) { + return 'Please enter a valid email.'.tr; + } + } else if (type == TextInputType.phone) { + final box = GetStorage(); + if (box.read(BoxName.countryCode) == 'Egypt') { + if (value.length != 11) { + return 'Please enter a valid phone number.'.tr; + } + } else if (value.length != 10) { + return 'Please enter a valid phone number.'.tr; + } + } + + return null; + } } diff --git a/lib/views/widgets/mydialoug.dart b/lib/views/widgets/mydialoug.dart index 5fb23b7..20dfb5c 100644 --- a/lib/views/widgets/mydialoug.dart +++ b/lib/views/widgets/mydialoug.dart @@ -1,43 +1,103 @@ import 'dart:ui'; - -import 'package:flutter/material.dart'; +import 'package:flutter/cupertino.dart'; import 'package:get/get.dart'; - -import '../../constant/colors.dart'; -import '../../constant/style.dart'; -import '../../controller/functions/tts.dart'; -import 'elevated_btn.dart'; +import 'package:SEFER/constant/colors.dart'; +import 'package:SEFER/constant/style.dart'; +import 'package:SEFER/controller/functions/tts.dart'; class MyDialog extends GetxController { void getDialog(String title, String? midTitle, VoidCallback onPressed) { final textToSpeechController = Get.put(TextToSpeechController()); - Get.defaultDialog( - title: title, - titleStyle: AppStyle.title, - middleTextStyle: AppStyle.title, - content: Column( - children: [ - IconButton( + + Get.dialog( + BackdropFilter( + filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), + child: CupertinoAlertDialog( + title: Text( + title, + style: AppStyle.title.copyWith( + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + content: Column( + children: [ + CupertinoButton( onPressed: () async { await textToSpeechController.speakText(title ?? midTitle!); }, - icon: const Icon(Icons.headphones)), - Text( - midTitle!, - style: AppStyle.title, - ) + child: const Icon(CupertinoIcons.headphones, + color: AppColor.primaryColor), + ), + Text( + midTitle!, + style: AppStyle.title.copyWith(fontSize: 16), + ), + ], + ), + actions: [ + CupertinoDialogAction( + child: Text('Cancel', style: TextStyle(color: AppColor.redColor)), + onPressed: () { + Get.back(); + }, + ), + CupertinoDialogAction( + child: + Text('OK'.tr, style: TextStyle(color: AppColor.greenColor)), + onPressed: onPressed, + ), ], ), - confirm: MyElevatedButton( - title: 'Ok'.tr, - onPressed: onPressed, - kolor: AppColor.greenColor, - ), - cancel: MyElevatedButton( - title: 'Cancel', - kolor: AppColor.redColor, - onPressed: () { - Get.back(); - })); + ), + barrierDismissible: false, + ); + } +} + +class MyDialogContent extends GetxController { + void getDialog(String title, Widget? content, VoidCallback onPressed) { + final textToSpeechController = Get.put(TextToSpeechController()); + + Get.dialog( + BackdropFilter( + filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), + child: CupertinoAlertDialog( + title: Text( + title, + style: AppStyle.title.copyWith( + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + content: Column( + children: [ + CupertinoButton( + onPressed: () async { + await textToSpeechController.speakText(title); + }, + child: const Icon(CupertinoIcons.headphones, + color: AppColor.primaryColor), + ), + content! + ], + ), + actions: [ + CupertinoDialogAction( + child: Text('Cancel', style: TextStyle(color: AppColor.redColor)), + onPressed: () { + Get.back(); + }, + ), + CupertinoDialogAction( + child: + Text('OK'.tr, style: TextStyle(color: AppColor.greenColor)), + onPressed: onPressed, + ), + ], + ), + ), + barrierDismissible: false, + ); } }