From f08ee61a7e52d72bda963cea0b6475b1f699b83d Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Sun, 21 Sep 2025 15:02:12 +0300 Subject: [PATCH] Initial push to my private server --- android/app/build.gradle | 4 +- assets/images/cashMTN.png | Bin 0 -> 54095 bytes assets/images/shamCash.png | Bin 0 -> 18950 bytes assets/images/syriatel.jpeg | Bin 0 -> 55807 bytes lib/constant/box_name.dart | 1 + lib/constant/links.dart | 6 + .../auth/captin/login_captin_controller.dart | 73 ++-- .../auth/captin/opt_token_controller.dart | 17 +- lib/controller/auth/google_sign.dart | 18 +- .../auth/syria/registration_controller.dart | 281 +++++++++---- lib/controller/functions/crud.dart | 104 ++--- .../functions/location_controller.dart | 5 +- .../functions/overlay_permisssion.dart | 4 +- .../functions/sms_egypt_controller.dart | 2 +- .../home/captin/home_captain_controller.dart | 9 +- .../home/captin/map_driver_controller.dart | 8 +- .../home/captin/navigation_service.dart | 112 +++++ .../navigation/navigation_controller.dart | 126 +++++- .../home/payment/paymob_payout.dart | 81 ++-- .../home/splash_screen_controlle.dart | 2 +- lib/controller/local/translations.dart | 11 +- .../smsPaymnet/pay_out_syria_controller.dart | 45 ++ .../payment/smsPaymnet/payment_services.dart | 397 ++++++++++++++++++ .../profile/captain_profile_controller.dart | 2 +- lib/main.dart | 22 +- lib/views/auth/syria/registration_view.dart | 49 ++- .../widget/left_menu_map_captain.dart | 10 +- .../Captin/orderCaptin/order_over_lay.dart | 27 +- .../orderCaptin/order_request_page.dart | 2 +- .../home/my_wallet/card_wallet_widget.dart | 36 +- lib/views/home/my_wallet/pay_out_screen.dart | 196 +++++++++ lib/views/home/my_wallet/points_captain.dart | 345 ++++++++++++--- 32 files changed, 1622 insertions(+), 373 deletions(-) create mode 100644 assets/images/cashMTN.png create mode 100644 assets/images/shamCash.png create mode 100644 assets/images/syriatel.jpeg create mode 100644 lib/controller/home/captin/navigation_service.dart create mode 100644 lib/controller/payment/smsPaymnet/pay_out_syria_controller.dart create mode 100644 lib/controller/payment/smsPaymnet/payment_services.dart create mode 100644 lib/views/home/my_wallet/pay_out_screen.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index 38365ea..ccbf322 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -46,8 +46,8 @@ android { // For more information, see: https://flutter.dev/to/review-gradle-config. minSdk = 29 targetSdk = 36 - versionCode = 13 - versionName = '1.0.13' + versionCode = 14 + versionName = '1.0.14' multiDexEnabled =true } diff --git a/assets/images/cashMTN.png b/assets/images/cashMTN.png new file mode 100644 index 0000000000000000000000000000000000000000..bae958b5ef3630ffa666fedf11581439ecec2abc GIT binary patch literal 54095 zcmZU51ymee(&*qW0fM^+hXKOC;O?%$Z6LS?cXubaJHcH7!QGwU?(QT!zWw*@zvsPs zPIXn^vaZ{8dT#a9Ot_MQBpNayG5`QTla>-wdB=V4aEJ*1eykair3C;`p_6FQ^t*qiwwTEKL=xi2bp|M7bJi~ zJ+CrOym?r1#RS$!w0nrWf`U=J2jD}TKW;8Gt^s+fV}3y|6jSfn#^{L^K)ETEBuVG( z^sQQ4mOcRmAe2v`fHwl?j`@ZNSZ9bExrQQ_p|BHRG$`*oAzz3WMxdxt-j@4ltG@00 z@h6W3HrZ(K;|GALi-182lAi?Gt~OkNT&Za2G&Ehf5|jTDhH*|u2Z2Z!p0G8H&1R-^ zkpSNx#;ma}%i>sz>!&m-t&gLI6bNB^GrE5>-+&}in{}SQSwO`)A4% zQEW6Cp^rbP`8kk{Z2(HTOvDYE#^x!M)WT-5D~P+g-+|phZVBMeF`xSek)NQ9Fo{Gm zDTbp_$?86hU?P07G5kA)>>$8OYRn&IC3fB2LXojkM^M{)qdyww01|yw{b@agQ1llf zt^h4r6l)0ycN2a7Zepb2h1I7P27}xe9*=1yMEq$o9EGS(nt5zn0)2G|r*=e(i998o z`qy6u?@F*JE)JimK`I?t3<+O0&AvGLmh6-E6-BwOQ7r7M@S72nR*qDUH2%VeVY*O^ zK}sAr*mC2+VM=L{%!t9e!l%Er<+UwYoS!|0NFVU_;2GV4VLN+p4!tHQ*IV0aM>{k# zuZM2QIc{d$f}A>g7(X$BU|0|VOu2qsBx8VOq2JT1b0`;T{K9@1rsUXRe!ZALFr{UU zBy_byF6JwGJmQe#z!S!Ogb>uOV6<^^rdyDz9*NL^QjQ7@0yu;RBgkLZtr}k~A<8Wd zkyKdX6(jbs2H6m`wT9v4jbCug$A~8miOd+M7g%@Lo6;v_3}6q!7i;K8vnTtFf)T1I zsFmfwea=oii09d3B0{$XwZ)JZY46n5BE>y2iZ}Z`G#_}9h9p0V^O;$>%DiG*QC z?l*vElf|AC{Tv128qD-<$j(edtDxZx_m`%k#Zb()nD8ePdLNvOX)3N$PF+d0q}IQ@ zf(!<;lGo!TM+E$W4;7~VVXv&7>kps8biaG{;(`~E-J<`ok zL#h_=!;r5O%Cj443RdSA(j|}wgC(G1lUtX6Z4-0|Q~e78R#*xV&4~Ot49PfriE09o z=t>wm-kus)T4E+nPAq^v&V2~05LG)+jdC?k$5hY}ALO4Y${U|C zNSLQ_=#~`iIK{?EniXN551bZhz}NHF$elm5ZTP_NpDkIPuXpIwKnC-jaG+0)9U&^( zp_ZNrZnWEU3Az%8aj?7=z7kI0U{nilA+obKoCgN7g>DZQx{1^R$O&idPTfg%Lt78a z>0#Y@xDt2;`b)4;FJXg`z&)lSv_`mjK}rfs(mY~3Xb&o%x47b^OtF51pWCz2V%LW| zg^z}3gnNb$hG+GK_W59i7b@1#xhLjJd8r7L1vSJsWH?7ThtJ7-$ZAk!#AOW&@8Z-2 z>58$?Eyl+tu*T=a2`X`ZO2JW-!4a2A6V;Yp7PidO&2?54P--k)P_z3A=E`XMt|M%d zn_aw~_fthx6{vcn6se3|!K_lDv|8e-arSeC&&9@t&!x(vyiLSA_?hKy=lJuy!L$V@ zV>%ggaEjs=;fkWH!nK0Vc|!}Hua}%bgeY9)oP=B~mL0jOhbhkJ-h`cT`U-+lT|yW0 zg%&!Nj$BXaD4Z3X7*_g=r;ElG@>3BrBeObH>Lo4;CuQ8yt1^5_UrO~VJM~@)??vGU z*dX=<&;wWl=mVA#&FIR5I-wpJEZhFf_sn3);4+B$JB6~;7)N2%KpXJcxMddygugdYs34Yhkp!xnW z?ToA4N`VWK0r_4Hv;$t$v(<*xe1|C8IgBP44>yg~{Wf$TxQ!si3VWS@2i@ zpNO1zobYjT5*cKqanEyWT8B4TuM)40H{qQr@oBa*wKKG%+?RG{bT0YSdmr%h@WeVK zILz-<@s;w~6C)EJlbrK$ko1y75@!$_L^b2*aQNIk0(S)YT6y<)&+Oayg*` zvHvjjW0h ziBf^;iD`?+f?^jgL?uGCAn`lAAu36XTil;se{Q9;eR^RUSl}B$F(5Xm)(?)!!sKJU zmm{XK_0ZM(ed6}^n0(cYZH}q{O+TtvIDnKjSOE%l(|wENbzd0v|_~K$hSiLqZDXPd`}Bs01Sn#xE2P zitJ=AuPPB5`gI+O9?e{(?iWr! zgOow-j_{6&jt~3sH#67hvJEt#1XW-ZWGs97Q)6n1RJ*yygsxz{A};OfC&^vaz40gB zOUW)hqk=~Xhpz6D-15z{%06ubh}C$?m~D>9XUK9UU9fPl;8_0w@_y4eFss>Z{m)b8 z(<&}G$_!ouGpB)8M~$cQWqx}9Tt6t%m)Vg)NA-3wp^%2TU!p%Ug3Jf|Ro**XBD`|< zS*5z@OILr_N8i<2>+QPeQGrxsS>I1i42-NVExI+YsTZ_fnpbPx5m6sW7}qpxwZ(O5 zv|Vf(FOJi>bgYmU!Ma4XO%5bhdPi+t3yKE5Rlke8PT-H>`$MWCE+h7%afvi-UbWKH z-5W=`zFyGw%8zn)E;If1vW(nF3Hc%MWwhz%oBr#cXq#WFgcU!^N1L&m@vMD2s2m2< z$d&}>&N-K~n{H-VhO4U5m(o=m&l?+ELR=V6rai>HC(q~B@E%}KEp6>BmYPyqo2|)~ zN|qk1eOLZkA@ra(keHHLKTcl{%7@~I$`Hj5fTF$SwdM83hsU!*MKPKi-5QCXhp$TX zeiZ*umvoM;1k3R2csXxsZPotWnc3;2<4^=!XRN!v?CvIND)eU_^N_ecpH2!3=74)a zPN$U*%L`7~2k37-e~XSfR-Xo37w<*8+WvZ!_Wmfi3U~?Lk0izW!b|5u+PUj_)VJq1 zDrm5!2lC~*{(8_DWc9hKME|0VqT}k;{CqsM8QIpmrSlMdOW{awynXKh^+Ns4{AG2W zrMZgg0p`3}FwE2bC2w=CmoAq>q$T7eZSnq{5c34j?XkcS8Oo^+kl4mbAINJb>YyMg+h@ z5dz@eDX4c4fFk-2EdfOjfce)vGyo8434r~#jKVwqXT-h3KRW+|VG=?B2=8bA*mui? z{*QEDF3f-E!*?D)SXES7`W>s9IGUN+I$78`SF=tbzE2?8OKCd+0Jt>&0F<-}_2s+$ z1xqz8XDxX-UK2YT79&$TV>1>v8~cCk0Kjg%@1%{Hvk|$QjkT>4uNyz*za)6y>3^nK zDarpO;%voFsU@#OE^6m!M$XN`#==G^fJ{zK4t6v(=T#At__zA|89$|kv$H)fE9VJ&k^k39{LeD~YxaGe1(3n4|G8%Z$W3Bq|CGJNmST!(@Ay5*{xzK6kM!^G z4}J%WW|wIBHvm8gAT1`W<_2}@jbNxJnS5We?pe#Un&7E;s#c;YLQa8XNi8IW=z@g8 zG>U7uysmZs_S9Sxj6NEoM=pejr-H57Egc=ZfWSc42RVsBb}p_MF>r(_N666} zP8Lm>ZwJM1Rah^Uw>qR}T~o*b6qH zW#$ovVz9iL1swEGs{ zvF;G_3EMdWKZ{ZUv*ZvTww-&inE6tkE1WR%-!=HO zR!+R!noLh$DPgINCL?3Tp3Ec(R!2A0r06P*X!x4K@x77vv zcfy&85@27@kAz4GfpxVgGbk+?vIG5VdBuux$rkKetWV#We;`rXV~UA`SAt`* z#N9=2!HR?WSwV{w%$vjtxQ)x)`;b-719M`~Q;43=BQc zb`%^+#qVadC*VhJYhaDRV&=WiG0$p@Gb*PdD!WD=Cz16Y(JSQHWvsmm28 zP1t^@OyGA<1P}f%LPVqo`2L^U;A#XgF5#cDemaxR&ah1wRe3|cANifm%b3-AB**SL zBh@)-$?R&7V;O|i?h@jtTMOCrGBojP1-zz^bv2?>=;f&}AD^5EIp=4wF0zQ^5t$TZ zIfn@}K~d5(g}uywK=_Mk&)jl$vgE&*CEDHKxSw``b0j3l4PlF+f9|ZY=+qDGsYNHM zS-zr6T*l8~66c)v`<*X7#Ht@qR!JkZ_d`hi468}J+?P={c7r!miWO~vcIkzqVZQJ^W_FH!vTCNc}pI<$4;b!7uC0qeN!mpDf4Iz{Z>v`&z1q^^r zi{9PXYyqdqH;>6exBGu#O=`!P6aa;=Z8YuNUA|4&;v+l1ymB+edhzSG{#9i!!d-G?N^p!s$`I4uvRKe90& zQ4R3D1ai?3Y25Oj0QYBC?tz@GDO9>HSP^@R+|fI=P3ASLJeBi1!_SV6G&a#gY9w(R zQDW;lQF3-Y9mVy^8v3JEt6-$t&&Q9^PKafs{l?Bg>)iX_h$u~7Ff+hmbu&Ic2wR&g z5F~#5mCBa6CsO*U3z0&oMw#_ZXTban^~jKM1!K1ox)I`tPW!<40ACy06hvqbQ09Kk2BcvA#wVid+-zVa~V^Mn+E| ztxT_61SDunm|B z;G|*{itokf^~FXI?qhR1+3l?1B*y;9p_CZ^?OCjOiN1~4psiPj)ZKQ64u_Q~7B?)h z$Q^8)Ig_bN{)$;`u@6+FW8>D2$sUfzXMWPF)cHnRp*;BZ4Rv6$IHd1^2W%QOJv79& zf-cyH0r7nLlbaF4R$LS?>WqMUu?~|C6Cw5+K-HJ%zaKa^gztlZQz3c#MSCyRO0xde zkcV>5&+bqn7UQQMxPJ7Yb`x!ysTx6daMH{A^Nmy`O$ zk|;`G1)z@gisQ|Nv#f`b?`E>I2YFo{HKNgp(TxZ1Oc;eWdT^{9j(YI&drR0h*^_+V zb2rbvb$fI`zOERjSba=lK%m8?RBriDHggkC--;L=sd03uTYK!r8^afh`Ia1ORZu|U z9KuiR+8Ny`(XOoa-E=a3*m_)O*e%0hy%WFluqBF6_LmIO)LLnh3Iko($sAp11_jm6Td?M4w1gJ~t1le;~ zsIM02Or+%0C@=sH?XNQM7eB1)wC~E+yE_pmi=OP%4#<&}#Qo|A{TEiGK-k3~1d@SS zo3l|Jd$QPS^u~;fO@fs&{Wnv$mIY?ETf$z7J7eNZ;WbT zAVN!k^pV4Q{LrCCeZNH7){b8@OpP@vHgBy$LNxn=6i*YVm@aP1&=pHAJCoe-|5OE` z4EC;&*4eN?avM3-iw@~kD@FS2a4FNj!Al@l_a-El6tonIKzpr`R$GN)O2&Ov(Oe`& z#jx4CQ$TM&G`35C@4xs9Eufm2>JLBhM8 zmR!9yw5wz2yrD3KF9H-g;H(JPx9A_vMZq@8QuO3O=Q0fXU($o+2&batktJA(KPm}8 z3LvtGg$gMURv+V5w2c*d9J-6!VCySqPwL^o9Z<(E)Jg%`AJ&&VT%X|CF+CjXL_W#p7uM-evxA9b@bAB|Qimb#<1? z0c8n0AHkGlE%?I%q*tY69~ zNOB`DKauzZZ_-R9DW0uR2_&-a(PMWc&Wq0ef%I|K9lWVpkHEk8l&Fz<+O_I6cg|~rAb*jNtzw|m*Cv?pL z24Ko!Z{pVsOV@4n^8}{;fz4rs+$vXx#19KoF9#T1>5M7qm=ksKltn|4egqm3kyg+d zPM+3HNC=W1V}5-&y?1*~>hJ3fdz{!@KMx7U`dTLi@BVm;pY=QYEyN z|3#_m680yelQxjeBlx0GKpzjCos%=y2L5SNL!WzubxK%Cs_rF?pJoct!$A#f7dV1bXgGpvRnJpE^(bhIm{BG`SmeT0R!1`6!a_3OQY4NXi z{BF-&_ajpv5Z26_2*x85UATBwH2s=^*}7d8!RSuxHodlfa}grx0ADK-0+w18OWl6&)&l`XuyYF+p1ma?YEECO?5S((&zCe1efJ zl)phz!X)g}N-+fG`pCK~dwI?KkqwM0w^x zHkEa7QxA3#z*VY56)m_QBdaC$Ia^JmE2gHuO?oCwjX(k>FbP$n4@%Fi)WF}aiVK%i zo+-(&aIS^}j53~t>$o-gNuJcfA#h6zt!{sCI(s zG1f7T)HCtBF75DdZK?FiLOw%KE{OC-_c4>HXv~E$?6!3t57|l~-2!`U8!a?*=rlpTZfrfgjm2{lum0f51U@p+Eo|N9vN7%2N2gFP znwY?w^4Y~BZtILyr-{)(le<&%v)G1%DuTTjw@j`(!WM#%mBG z-Ut0~Vcb=mR{SjenDCj=+VfKkD%P$?E~kja-xMn=u7(zuNcYq>Ta*B7mb5?h#Z$Ty z2(P;{-VPJtlyoN60ZYmoRDBM4b6v2OAfW{1WMSu7o@PAIfs) z;P?{BoX|sw)I@CdUhD>O)VyqGP&l6@Zg$9^6U#KUV>ZFp)>a52ZcVv}2#z12D{>gz z`8xF4+85BCrdf#QT^PtXdPKJSCpunsctCP(Q-1-Z+4wqAy z8pAN_RHv@|i;uB2Bg4oGmrnvJ?eN&LX>sQQ1XdI=DP;p%*p%NLE`YV7jb8wPVO%5m zYL|Kx{L@chnq=zeChW-4qp~A1R#c^>?KAdNIUQzG{qk&Y9ICu&KeuO&dHo<+ov7QV z5>7gZT{HtW3S5~31(JvfE%~Aql19UgqG=FI$*t!e5;)bfVl*+{Gx_tgTG#xiXSM2f zI)hA#8lWS4G=uU6V z94Q_K(&#kw7P4JB|G>GBuDSt_5735_H@Rx7&AGvefY{A4@Dm)gVUiloRKzFa!fWJl zUB=;Il$^M|^=axNagDcK_qf5!^0*MH9^<0q+BQ`AdHW$>?&rvj;PRryT!$;^=dFpM zF5a%{a8WtAsCvn=VBp%{NWBX0Ex2Ae8Cex6tfS?^pE=?1UI_pw($NZzxvgR3*m+9} zN=Wy~jn>+cWBzRY;CnSiZH320KvK^mO8?t0N)iLGI!jQK#knEjc{VHqj#Ahl&Dod= z8Vt(wP+M5eTriI-m9fB`BXse!>mMT536cyz2Yj*R2Nj5FQB%)TIm#doEqT(>O^!G2 z)IJavGXN*u$)uC0Dz4T_wf^eQ&42zLT0O%$J01DA0xJl06rT|6x3EA~pYH58(QQWE zNO^v|lb~`$U}Zt7hdt}tzCxXZ(@+Nu4JsWhD8sab??`C8)AVpl{`q;k zXIwB*%rwrbKv-0DcFbvOw)d(uO8x_q>|Ovkgw|s>j%|(r{3q=K4I_0nbK;lQJ)!Aj zJJzV8XP0aLPn}*qeV5R~6aJv}b-H*N@Q_4rH7u3MzV*1A|F^v59qR30)o;2_K%LRlIKw`kX}*-7Lc#?acW3&$A(*+g7y61NK|F ziChlCsvYG|6`{N^ZTaCUeJx(*e-kkB-TTX4Egp`&hJDmYjJ?1;=kt>eEfk0)FCSJ3H9MW%+skO z-{0a8>n)AB0K`%jLE%fMyZoRJ)H%L(cWw=SK=>ZlSB0FVBMW$fiEOsDtMBziHg~Jwbp(8M|%!8a9 z8wUeRbH1Xb&(OJk<$SNeXCtEYrGgmRYmYGf3dQrim1Sdh>M=t%4oo(GEHOME_-IBJ zA(u0+`CFO4Y!~t~oe45Un$q{CJS}e-QPbQS$pfW-4=1{*DRYXWwwfP8SYoM%9iWTdQ6>`dkw zGDbwkOLi^oxwM`i+}=w(k&ee8_`#-u5{nUm36v<$`PIVTGe;7(Ph`;QBDvUjzxB6l z9Ig7SMT)I^Cd-~WP!AcO1pSnK1arQ*m1%M+D2`9$gzN~Y<+w7NxBE&gs=?s$@Pt6U@1KU5p( zhe#y7uN1OdAz5C@nomMtF#*$pM$M<{+y1ZIzaTFf1_3_zky@lL>AXnH=NaiNO%3+*#JcEHV|lRJfoCq#&P3vABccI?DrbHk%Wmq1rAK!2pw>n5<1C|; zb9B1@d77bIdkBxC$uekYhvF#V8&EkUN}skKJ>%8vm=~QQF$t9gQ5KJOL_Cx*AvVuS zs{RS0ANjgygarp;$Jrk$g)%$9V2%?kLY!W|VG5l|9HowryYa{k2fp-FSsFgtR%`Zqi0()gd%Y+>643~i1+8@vjn z9`$diQ`BQ55dnh{$3glI^EspE(iqX%^wy{hRhoa45~L%E91 zqrN64jb-QDZ##9ZDlKK>Dvl1ka_M9afI0rpWxJGZdb z%|?nek<&zagCJ<%;F*;~?G@ZZUiJ7|<=f_U|KGLkN*T>?!OPyL8^q|j$QH_$IYWQM zI*2=mZ`cD=mx@OvT^3Yz&=}JNg04^bnH*^4ap0mT3Bfly(i$bz24b+4NmtoOC9U7? zdGzu;D+J}7o}qa~o}V%uuS{7~=J9eZ`a`E1Zi6(fFWNQdDEgXtS8^myev#!`8htL< z3S6UR2W}J+nh*iv;rzCcW`WaQ+R~iYCBrDp^;DoWiHTHxcu0+_=T#h=TJ-FvhkaID z*53Pd#+v)2hkVy{nNeEqqCS6LeDL!J&eZ>I1?9N#R%l;iL4MSj!NnB-TOfML9iEEqhK^_AFsqhYu{ zM$LsC1=$2h=ZkMxc&~xDQ$Gs_&>4>lBTOTfA@Ly1jrx8YzsEE?)K8&&T~z~J{?ok4 z`MiE>vk^lqb=oyT&yAa3yeU<_8J^MXp6^)d1mo<^Z3M3vWRSxAvG@1TrSLt|FzMt3 z1?Mvq#NJMvHmmrjJIgS&bpEiJf4suYdGPoSp7*}KWtubmZLoWQ2V&nYX9$*^`Mj|} z0{g^lx58ZNH><|MW$xLsXwmR>F%gY&6PT7~JLS)BunL(N7s=$2pXB6Yj2%0$_4G+)b!}}U1euzRN8IXFwrYC;F9dT;O zGhGjY%ih9?-f^(acp`5<^ zk$feI=9j;EVydHnR`fiBDb$HuRN%6fwqBYnO2I}jUEA(TP?>qUXG!2y1l;hYs{@)Rj>hGdb+fBqRWZ3bcPvULrzy;bsYCU)eX1bV~&sfeN8Ne>C*ds|( zjJhl{6Jv+~y%@CPMg!KAX|=!eF6JJBP0o`da6IwBTdrFaHpXwAB^gp^Ffl&G+*W3Z zO!S7`3#K~#n`Cs7FPgc6;mf(;=im1PdrdY?P;Q>JX^g9ZKS2FCNG{s0_x2IDkTOGA za&XARq}9rczfI+{;hAN#Bd-}!of8M^VRD$F@cpn9x?oV*&m1bd>rZnyO+XvDH*+)@~6!yzs z|MuapAGt?NWTe9^7K%o?0u0Hc-Y|KC{n6$XFu2ny9@}014`*9>99ft1_i+MFuSxXy zt2f*e^&%uTl z!RNQg8P{olE~$z2F@SBkybl#T;te5BKQ0 zp?fD)!rr}(8c&H~isBY-=tMTH)?xd#EZJh32On--ttB*0L322#LN?NL6*{`n#EJOn z7D5OQE>%`-ICnRxPC$_=*R15p&)~NfYm?{IGzrg8wGthS)6I;(3TlOux}fi z4r%BO?BSYw*MeSqzS@Rzob&(rD2=~kF|AHiy(^ZX z@@3|6^BVdfct}xBF4yW{G5)wS5bgd?<-l;LP;mo-b3EHadc`aIWDxD-X=lI+KX$(R z`CiB2jRhsmL&!$3Sx+seJ4@)^2S^;Dfy({dK1k&o5Vxu;LA|6gU}pd3Y7*mNd7QE~6# z+1Fo&i?j4H{E_878c82(@-n{!ZCOykmn=A-tj=obfwE@Jhz@j(#b;FXS<1wMXaJcmCJ~ycy`|AQ%1E0X)e3VDmA7UE%{Hd~*yY{<#^b7{S zT%vS^2^)SQ5gS-lq<$>_2LU$lkdE_s5yQJ zd$s-vz$u0QO7LtBhE?om2``JVdB zcm_(y2c_*k3x`uedwxKcNmtfgDD>o%Ohg-EwH32;XO7++tlrX>iy}5n-XnKJ+7@d- zt99^!jZ`$|ZBMV0r!UhDsSGgh>ke*>z{@Y}5ZKWXgFer$3beMj6Q1a+mx{6(yfr1- z1`+?(`1v7Ny@Wj57y9dQ1`l)t{jTAa8*#6G9wx%r# zsO6FFvtC}w&?zOq5+EnG$A2gMg&!Ich1WrVlIp{recWn86>0fBA;3b(*(zr z7&}Y~--h5LZBDw*?@lA>o$gHw7D+wG_A#4fy*~zcrO1r9(W){$Dj1b3?+h~}F}2~- z={*lxw+9=bOUzFD8l;FiyAtn{qQ~ae?Uq<8@%qW+;`Y%NfrS`rl8fP(o}!|lY=sn5 z#GSR=6?5vsZ1GZP^9pmfnjMATzodDZ*z3tB9f^1}y|)a*@r92}Pq8Fv|Fao*xctUd znf8WrAF~$Hw$G@fFAz&cijm*tNd(ta5MYpbB8yQFVKpuDJ${(-Rw8}svpXSj#iYbd zU81rcF!tHBSNM}r!Xb|%fZs-uO5mCe7gx}~EkXZBOq4_PY*RcJ{&*{Z%<=s zX{8FNc7a4?Fm;Rl#q||y_$MEm;De9aN3;U(LV{j*&3xxy>RL_5YP^Y@ZD(J;Yf>&w z`yf&wbouwx=Hzx5;(LaEHrfi=Fnigb1BD7kU5&a;p4(9^+#8g#9_MmMt0R1!W)|Z9 z#O#{xnaxispqkAlU&okOIV1KVHi%CZdbWBpeu0q9gkCf=Om4EYS5O2@gHDBdF;>&4~IZY{9V05c8TJoV-<< zbnuw220s?nkb*;_lPw?S$d7yUB5^lo9@k$v^ zo#>DrDH2=5Fi^gHN!oDX3*gd@&ExUK8qSo6GRq1&DsMItz6n2l{#e2hnsk_Gl7(;K ziyFxM&6w14Xxm*jzS4^*V&5PH4keXmVM?3W-MI!$)aHR=rDsLRNU+@*J3T86a3+JI zoUcGJk-u!0B}Lr7Rsu?Jf(J#)dBChBphV*g~^3WA6S9XF+QlG;o8-)q&yO`Bi^={*t~jgF!L}+ z8w>)e;vN#1QMEnVXt~c^d{r0yiPHCMD_QqeaVqg+$M*AEs(Sw2N-S$$i>P0kA-}hm zS5)+pfZX6qJcdukP%*ZA4O)-7goNavHbk=ikV=8%iBWhW|UTM{rk&pCR%qE}Dcl+oO zUP*+6jrj&%a!f?iquo)ds-0<6`ibK72AX}jx*&60rOP^KglE5$7IEe7f5&ECjSo%i zY_`Q_F_>7Ej?e_mkcOj@7+=hKOF4U!_0PWg4Y95OW#M5=G0>_^&aL-wbtxp*f1aNzo1&B_q&@k4ths{Kdz zVRVPbDO)-D-=plDbpr{0@`Qun89vJgWIQ^Sccj|F0bm-Fff&&&Zms$_;UCvw8u(6f(;=^!JWb(>S!_ zaPHmu<}z?sRuOdSD;Y!IkSW?V@_~`?4tQ-zcZF`K!la-j)20rcw@)A13vZ=|1>Dd4~^ zYb8Gl4Hr?IK~qpKQTcMyRvbc#vkfy}Jka@b-BKV;uk?Tuw`0sNGkQCoa1!_%#Nx~K znYPeDDM611F9hvCjHvjW5jyj`|GAXG+$M+Oos!Qv{7?xD}GH?D%#tP?g zz5UlzGA?`r?IJ4go(Si0Vqk-b6a3ca)~&}Z0W`%N%aJeM`I)0#s@C);@VVRk7CP4O z+h-nsN$*FzVs|3ZcZ6=SwYs*T@5wt`fZ|!?(!Udtb-fmY;o=lc9 zHv4V-734U=onLz-=Gw1OE6h@$Q_ueE{C7+fe;5Y8|JRsr~<`ln_^IM!r`F#Pf4nJAeZg(II&%vPvo>$S$(!=uiD2rm}^VPX6FEbw! zH3{=0&4eR!D{eXOu#>d=IHeOeIAkMn#|chwatpqJnI>ogd?SOpI$(HRPF1FA`q8*; z3pvx{7n)X!TXLzu{tgW&$n^53-rE>Mj}!gu{DVavv}R8-{ufNEQ*R+gCFb!R<-fVW z$8K)kXn|ORUI)$-uYj+Ka6XS|Jy)i~w695tA@=JXvH68txEddk_n_`=p1u`^_(naa zQ}!MF;XApwbMhHe$uoKUP$E^N^{`JCTKqu@>Gtj>dUbxp4(~Vc-q`G5-*p|6?)q&)p)(G*_iafIF5>xXi#WTfq2Q04|k7Wj`+Z&ZWnrY z%ok6i(!7z;#zbs!hs*79Fs#W3Wgbq~IYyfjbe2Q%NV2wGQO`p-c}%~5N;s*)AoWF9 z*v|i)4?rT3lg1r*Ks>kOW||xm{@Xm$dymX`c*QA(0^*f|cZTVJPJ42GZU}R2m1$fz zSUFz4iCqL=$~mt46$?Z-NgzZ>yjg-yRR`YpY5$T%;Z3=Bs1e$U=b>b9`S-G0MveI| zW~i6}4RXUR1)9xN@0>1;|1zfvE@GCO)T~YAJQ`f4N;i8Fa z+p%ghKPFX}nefG^-2x<5e2d5)B2Zdo6{j6hAz3lU#ZJoo)r%@;B1Qx6^Ax8J78fnTj|OyO01GFK+5zS|Kh19`WzmAl8K$n}S;*Yc=#_^C z1XH_$4zp^dXr;IA1)fFpEa962>R6i2kE4?_G21tTx`R@foznsE)mUuloYkF)N8G^E zpZEL-ebKhroZ$ymHksnpJ*)KS7a%9q2{RW(dl}&GU0xhnFiMs-IbLoViGjXyk)Ba? zJI1T_B@`zZvg&rn1giKvotu<#_~l#r&=d3bag^iixiCSEd?qjP;@7Ox`lV8e5bi(7 zKL3VEbm$p3WGQ616I^Nm#xrZQj;-pGsB%z5O7ns!}8*uLhQ*t zvB~FG#+|0p4GLg{($%cYdnuB>Yz0^7-=H%Iinrw{+S8KVz2=h`gJ(hyvi~ydFFHOO zPt(KLZzdm)vhxPQ0TUx6_gUu^E~Ybo@#HPV<*6ZoqHBSNQpO%%ULTYiFKvF0SR#3< z7!xPn;U6a&7}Es1y!2og-#t62KUCjHW||sP=93M>+Hf`AnBTg+|2@I+_wudmv!NJU zN%?hBpXv8sSWV@|Af844Fpr&;z*)>0UT5?fJ$(DfP@Dr_YVZX{lCVAyAEk3+lY zm&(VF|Em{9yyfFt3t{Kh_6vCaKLB(eYvf%aR@!HdCj(7n<#6CN zZ}%`w^;;dH(}k&WR;Qscb@UK>OxUWQms81XBxf1_~p$80}rV+=S^XsQ^+t2wQ;`CSB00tfbON96Dw zsE9wtkBnWMNK}H3=}WO-&D+ti=mbrVt&jaL7Nma4At-&^TY5d)RJUU7iTozRiBG|5 zq%_WZcl{UQ?LXucSys2?pi^j8$Ysz$?7aapb5}sEZ3Q3bN@E@=xTQ@I0KRKLE02I* z|7MmHQyeC<>dYH(&gCDbtusdli;3ySi*kraWE6dT17%HqiEW1o)+qyTcLkdyJFR0X z_~7#$WOio=$hj1hv*@wspw1vI=nSUBp&J19 zT;2WnXE{@@jbElO!~9hrp7AD5Pr%pfy;P}oJ@IeI8Mp(D#e4Y1%t7ne$!Og82{bIb zMAJ6LQY9H1#9+@p^dEVGU%nsUSMM#Tux%jE3Cj^ z{+rRX?rj_uyvj=-DJf(Dgh9?5kF|aWrFo-v^nzrEq`GkqNiQiG6vT3-BX|vH3v2~C zv(1$P9`J>xj$@rDgERP!!>$O2ZD2M3nZNuS~2hmXZQ#Qh; z3|IqiT?e)o=L~6}mlR6_@3A`rQ%Idbm53t!bM`pL&`BYQX$3xc3e$Y1~GKV2Ah1aRvdag4cl7 zfR`nO)oH-XSn&wcEPtA;@`q?587!%M#}j=rLUr%x`?2mMj!~*?&^r1+*EW<5f1C?p zU5TQ3*K?@F8c}lG9r6LKyYmpT4}T7Mkw-QR%g5PpA4G21a+EH-1jX}CWB2fU{bnJK zINaZf{yqPL>48U(JJoJ`pQLKTTw?YG0Xv&R1iM}xxTRzfCvZ*^?2!^ZAqOF!&~hu5 zqjCM^cZ=K$*Cvf<{*Ex2H-G0H9BGTT(lG@(eI0RB3ltE|kc|}rq#1RDe zFV`6YdIB~|ro^(AqA&mR{BW~YryUOVw`2d#d(o8lW#rBOeH7JSiIP`f(z-_CHU5c3 zBY6JVd(bfXWt63M>SX+}_&n5|`89sAUVqf#3{u_d-2W@I@q0{j(es)ggPbd#Rd*Sd zo%#FNx%uZP7`_L2(LI=)=7`P)muKu@O0W#SQyG=SpBPCb~dj6;9uC;f^%oaF_#e1?>sj6ON{jX2m8C_ z!;%2j2e^BSOK|R)D?!}7o&}9TIn^U11763gdeV4R&eG&sdE`vlket%O;RI!4@mx&h zY(UxSZ|YEQ8T#Dcy%Rg1{W|9&AK=Wg-$zyB`N#A|Q6pYwKa=AF*!;lf(a0~=6?t8V z#H-OdaVAc_MPwilx4$~q78*IkRIm1nWDCEqwjPdoZqqlmWt55JQ{ytc!f&LE|Lv@7fz-T>SJ zomndPGn~P;D@4ZW_DU0WKi4ig5!ZkG-?*+-;ZgJSm>r^*{qvEb`%o}_hn5aL0O=GS zNS!kfpo&)mN(EyEkY;iaO?_sW>!AwNK5aPSI4&IOXV|_imafhf;9=Olja+7ii-?U( zUx1aHKJTsPGt%<}4sHE=M5a%`%8l>hOtkeH&hhpmZ|BLecCI+YJ|m$kY9fus+aNGPHnxm%LX}ArT^dqh;sd?{A?LqC12|ua0z}3as%Y_H@pGA z;};%jpof4jZIO_UfWwe3)w7EF9^)$lLyot;lWpIH$1oY9Spj z+`tvH|BirI%@T2LKu8EM)&arQ^@w$Stw{Y5A_RHvKK0!L*rXGAn>P%b^VeHGxRVo6aHJC`kgbFvjCbj z(t}kX$K$sZ4A{eM5KE)HuLCHoSb$aMe*mYSc|O}ubB{?Q&J;mM&G%h9xaQLEFR-v~ zCwXaY2&5K_9!=C)9zD}S-g*vWpQQuZ=rpp9H$5D^7x|ay3?e@eKN~}NAHup5FVrOv z`+GYu#_>KS(QhJm$yZTY#l^4E2DOP*$HURza~Q2Veu}24f962I2%=mVI9Yx!>QDbS z1#_mEaV}m`x^#COM0DRj>F^Et>MWy2`%B)5hSk?{X!u6Q8afMv_U(KUvCdy2dzd3_ zqg-#Q{5&))zYw(x*K?&1cGV8{qx*%gBi8dICs%b5u}R|y%*q*6pkP}-oI?TbmjnuS z$D{Jr0W8fqgOkfGsz&YVH{-IaZ{lhy3qrQ1-yE|;?Ah^sj-B~A7SwULh6SX6%L6E{ z&0Ac85C>r_JifV|!2`egrgJWsuu(BfMhXF(juEJ#1XVAdJk&jEQ z`=3Qu%g;G-a}QRX^F@vvJw8hZiDysSX6$|H->{kLNt( zOZ~GCejDYHAE6R^`IhD&Iex6G;CQY|E^>CXMTL8NI?=W7mx%2DHY&2aSqgL3-%_p; zvhl4b;VL0ro$cs&{yP{yd@oC{VLE~=*=c|-;FX%LRB>jl0*PY~a=~6I1-*4D<0zJg z6NX&r!O0;gtXq#8Kkx^v^3A;f!7(|6yaC$SyA&P17nS7^0$;!`hXZfW860?Nr2^6i zW6+U2fI1x+Ky4h%=`-QYa0csiMxXGAZO$HX*g*IUV>HUiFV*j2Mtw%-1<3Q(U3a4W z;G@Xn!T}r4yoKX+j=!(d5)XO954Syl&gVXdx}q+A7)zpW`V20s`7WGv)^)-%>mgmP z;~X2+{`jYmAANz7oW>DLRiG_#E>1lEHdHsP3=Qtfq)4hzy&d~GTKFfZ9{my95D6}Z zP>cN9)3D(5PjC!YDL(=pM(3V;F|_A@xhf(TLL+LO0|ZNo*=ckbaSZ;svui*L&Cq>k zP#%unWw#;T_xoSq^7(Ujr5}?+$l_JQT;nG`em@8F$#4w;odp^}HUr!qAcadnDWH~1 zx%T-D;0?{EE2AxK0?v>otNa;gLAs}tK{y-Rhq-J^-A(+``avxn1VnxNzk-48=ShDr zmMq^$M=`^|#ggOckTFGLZ9f4H{WTlYF?~Zu%dQ3%egun`v6pC$V|2I=2Y3DorM+L` zh}ceM6-SKbHX+{pN8HoxbbZ6mA+C=EC%uQBM#mObJL9|9exAYv_l85&saSo<-*6aA zxy~@`@7jy@UH4)5;7>VzhU4Mb&~|Tq1vK-^fZKrI0pE4K8qkM%OvxcMTf%71lXV)F zbV&}5y!rRPh^4DfvUA)s$L6RGA*DkPi^9a%H;|JsA9+NT1DFA|P#kzI=;fr&AP!(0 zXvW*!0@?$v<5yXyPt*h)&^hB#ok47*9QpjxV;TpCFXZI3cVh)V*2pnBI*idn|H<`~ zI#99VFFBgD@~Ce@6?`53w6*Nu*re~HZsKdSP8K;XLGHr$qGAWLJOqZ?I$?u^!_c_%Qb_PYS1-)DofC^S& zbzmgj17?uNURy^9@&rNbx?n}097caYw-=_-XTp`>#jAy~001a=Nklxg^8%t09jF67oW8d?4W3=_VXwH9Fk`mp~WvE>7ek|H>^PK(f zvQ*B{;a_2V`=4{2T6T>xtwy;#&SdrVIQhIA=nUbhq?r;(X6YT;`ac-n|0AwX+oPbK zL@i1=&!lm~P268P+%A*3=p7wLaOjzDaY3}lIbVZA-HEmIc7*2)o}&oZ1CBttDIE;W zcM!j77#=u`TCNJ9YPvL&p!1- zROH{!NkOfeU|JQ?l(27U4}2Ef-Wyw(d_V`C!GNCply!jh&qDI$gf54Xw_z&HIb9%J zp?mg-l;M{*&(L@!mpl9`P8WT<*P!0<_~*GeSQWo!UWf&Y%$#bGI^GT$?mf2W{~*!v zU0q>MhFy+4doV z9r!(GQ1GXf45VpkL7Roo@LC?yj3daIG~O>i^)g)W)@#_^e$uS=9D_r|@yz4j;3xb? z=@7Qd)qybtK8EP%3UUe42X#hgNRtmbiFci*Ge~z1;)NU17YJVyCmSsT>o9NKXHdQ1 zB6+Aws~mjh&rnpk9`#GFK5Dn33cXH$TJ~>4R>zl6G6HMnCIP@Hs(cv^$&nawsKtb=E!hqkjA8aY$IS+ZPgE)r~ z$Et2#kISyR1!tUVUWhL2;Q6QyA^RRY|J2{3EPo3sOBrbg%vr!E&pjUDRp3gH0nmH& zFmKR748Mp8k1J`co(!~^vXt{|KjBJ3Rd1e#X8oy*!U<8bdW?A`G+7g}pY)3TE| zr}|V;eq0_>XMgU#zeP#pUQQk5d}(gh*fK#-p7%*EiKbmYqIlT1Zv8b=M=<|J1ioo7${za+#2m#V*$J^|xW=>JzkAX-*|+ z55)oY?cIf44}XJ;EI-0hLcWxTt3U$mnY6S9G_&6IE*XB_vkF;S*NiLQ`2n1J@mteE z_HU2DAvn*N6HSV8wzDUO%Qp((J)j9#EzlLDqS%3V7H3dC-#NT0P?}EF8{!q+PNy#~ zG~b>;_?|u^m&z(dXW^Gn)5vZ&E?yPk>UCS6_%D8NI)z^^*Kv9Ha4(2R9S?^%gUo+8 z^sC=NZsbY!5=FRrT_swxZo=BruSZ?O(u~oVX`?+aJ-fEOBc^ghT@0~jIB{;=&Ha$VQIK-|U zFJRZB-$LJk$LSC<=E;-@a-Pwf#H{z6L!R3|*RJqn=?pT0wxGNY*SzOLERJ2-)IzCeR(t0pGtDUR#x-oK%|}k2pteVL7h73!&@r?Je;kQH-9+yXCYzVuzJ&yX}FK`){ zLtFtn4^w%IQE}>jpuA>rMn|8VoZ#B7yU_deXSqfzm)*&l;<~Y1%c+E8p3ZwO*OJXV zqfQbi!SPN9c07vVJ+~t<$QgB9%qAh-p0yWY@k!TX5$8k9)@GS4fhX9g?rPhQUC;as zU3-4Xy)-!GmCoS3;ngYlmM6S?+RS!^a|U$~>kQ6Wq;$#Ru1?qAdK=z+)jMXjaZZO2 z;K&|pL#?0W9NYa=!ksrYRxi#OjDv`vIE-In1Oe@VIOGh%FJ8+OaSo^y(#hw^xM#D_ zh9~QBaO7f~cpiI{N;zGWL!^7V521_04Az}|IU9e+HUV9Oex3b{47B6fUwsQpbMNF9 z!dw|6QO@0kHe$`2|4G-4&17zW59h{nc3@Tizj5P8u4c}0>WG&}PcgxpuB27^y zF&%a>!aXXUzyJRrXLJi!Iv-NmSXMO~@Eka|;!G~ZnYl#DsE|aNhuwZ?FZOPE04>ja zPumU784UOX?E_}J0l4oB?p}D6UwCxbMnI0wWZ1_vm)3j7`#y@dTyx{B!#9rV5L2-+ zjJJP`tHm7*I0Hja;D)O&rb;6q_Q7gOh9IEjxv&Izj7*RwI#iE_<9JojR-LSjgcahk zaw4x`aJit^Qtt6^3r;@gCSB}ToZ$%P4p(rE(*=uU(nyIYJ}!?@F2le1-akci$qpTm zHor3JfYq?6{HM7>Oqa3)` z-SQM#Io_!tewfo4rZ^gwI}cT!h&31gG23C>8tg?3ij)t6o$W`k{n78DbKm2b9PKu3 z24<%LvJZT>RE-0_5B2~LVWD*E44HU@cHJ!>qC>n>N8SdK#k-u-A$0xDkzT%H|B#i( zRsu}GCqVQ|1_xRJVi=6(-lOrkUs{L;0e2=I(lXG44 C+u}Qk)9I>H@vMEJ@)I~9@@kxL=G81&*ySn;kKxc&2D|ADkN=46(?_`sKXC2@-r$flrO|q|9&d8^cm29;@4LE~3NC1r1 zDZ=2TB}%890$unG&CR=Z;1#+9v|eY>C+Te*)95j>Ld`52ohrgq@taY&;y-o9m<%fG zTcAJe38-T{t<}+WY=Gc%8h@aD-Nd5j*}Aqz_b6&@lJQ3 zhD+beF_diL8mPB$0N{F)foev&O5rb{cHk8N2dg`#ji{>1{PliLhmZzOU+)nVj{gbwf;h}b+qb-)8ES?%xdE#Mya3wc5$FU!EG(+W z&@@HK>zu=#gU%&9zWzYtT=aP11ay$rH{QTu%x_22Y5%A}3~?&scw~$vMIJNK%$U;$ zX+P4#mQ3=)5PR7s*hSgXzMb3SZUO5WT3vCOt**kKZCXxZpYGW*1u`T@Dw*);U04<&i(9+x3$D) zcxZrQj=qSg_Pe;z4Oax`m+7AT%h0gydMsOWM#eCuTDI-EUt)CM_c^VUtNUpkp2IV$ zFT|n~uV$yj`5EOh5k*%|*AeV~_7~Xk$bYe;W}MDox>gm`QW8j;K^?(Xoo18{X~56a zfToR7a;P4;4(Pl3rd#l~>u=y92(_6^6dXxXWU8oVW5V%ytRAly%G}FyW6v~>jIPIc(T!Mp z=I_Zv_AoIM$S?b~$qIC{9kS1JUpLztdw+O%pCPAtYm3730Zd=VNKt(XDO*}{D>^dr0P#SyNZ)Ks{G z(ak~+mx{?>$hN?_@13DWz_|4(E=SpYJ4z?FXsS&t zzE&k9ljWGLuUy^_9f!Ab^|}X9IQa;dd+)?#Rujr<)}p+21($bh;NAnJbWP5x%VPUO zZI5$O4cEG5b!vRHjhm0`LUN2-VsVZIia7PM>O9@5N)|p#ug0h`FX2b3KYe?@hXIZ< zt;ict4Sl&6qhQfHu>VZD{ri? zl`j#NzRYR|emR@Bx&gH343_SJTkf@#BH%rFqsP%zCtnawr@Su(Rq}KFt?$Q`H@w6) zgz07CW`cd6U~8=vtXQ+j^2~lpB>2_$$QDd=-%CKhpqs&z)t;n#uN79VV>j)>Ip2sf zgko%Tkej6+;8$Zh)yP)F#*VNgDMwl3B`90?CT>&3B_G+af4RpHt3P80zJo;Tf0#WP z_!^qv-07ml??&^|)gkp$toru%wqxMg&mnhWH}d!)E}m71zLKlCQT;nmJ#TS{Uv6{+ z>XBX8^U(j}3VjFoy<&n*Y1z}vFE8DVVrYM zQcP#RF>I?e7Wg4hEBNi3o>{6+!n5OXP7`t}%D8rigduQHNYE~MF}(8wA6ADbDaqW` zK4+ClA`|6M+<4bVIro)`qCg8fgT&tfU(Xhhj^@DWfa=pJr@R7Y2XwXC)92AM=yduF zk61C&8N}S-;*TI+^GUWB=I$ex-Fim2BhHa+Uq)3ft03IoHClW*npR)Ij4yi8y-`v{ zY2{j0@t&V^eN}F2#r+)$7k?17&D@QrifxTqMxaVej^$`Qumh8aSp6C1$1J9pH0%qO ze;j4YZ_);JP=}04-N_GMRRdo|PQ07I%0VK3A@bJ#ITkKi&klg__X+_{cl!YxeEw&M zAN&@3fcQ3NRVh`x7zIsNV$+4!bIaR`U=SIvMbGe%%+-DxPu%lmZtT)aXPENd><-xa zCKn*vx_>61`=tRLi20g{M;(LDM6X;6Z1`Ufv4!uL#T(r@5{8I@wX6Ju~ z^NRoIr~vF^HD?c(vRqkmCqHc6fRcqba$^38qWonY((m7Q=wVFk{|8+KqkQGZP|azT zvJ=qDIkr9Xb2g5@hx*hbjCK}=VpV83V6|mxsq@H!mu-lP13t~X#2g`^YFiLXa^TNBLXKmTDW}CdDwW_pX&VVW2q`hkKXf7 z-G?Xd`!@IN+h?jU%qH`u4>XR2W~(^z%z@pjCJ{CYcGo~Ak2pn;=B|xyCW%1J9_kFd z7MtJmk&oiacf9kZeW?~jGIV2L-$%G%2FEhxa>Z{}lMI+8Gy`x2AORV65I(bxAbbv_ z%45N6XjV_a862<3d)LC|h3)7@);U8ke39)MU4%mR$yY7=&+ixS3+pDZhiJwU>rOrS3l1_7wU#ZmA$^oO#EFa?WzZYOloU7riIr3L|^A zKZ%a*cOuz!AFE1II#6ZJCe*LJ1{*fLMS*p+Zw`W;ryscod%5WHaQjxI;@pcufUIB+ zIzyn%;DKD6!o1}b_#7+cmk{DSj575IkEc_vtvrJ^hwv#z&228%cD?y`Zo?JVy~MFh z5~(CdyLN2<7$<=2KvDkWEY9EnDwf!5wJLC*Mh^j^XQBLGufiBDttq{$W(rE#s1pFW(tlc&6$(${wqq zaOFCNQ`m^oWt?-+bo8~3oQ~jG@@4;{pT{J-Pb+fS#^c+y4VR($B(@(`hUYPKaVA>V z?z>Uc^;JnmelKAoxaMq>thr5>rU|a5A$mtghPlw$chJA@9^`T*5&>j1s}A$mUx#I< zT%&WWgSKS4mNv_-ZO>rWlRrlP;jLUkf7k=KdxM97tl$=BAqp6tdD~m(u|N;;r||@x zN3&jxB2Um6c*|;DIo|W(kKpoaUgBt1(VI$6;^1?iLUHz1loduyND>+k1+lfjfz+HC zLuE;G6y*)lM4fX6r;}%;$-VhgomN(82K=t13djk6Kz94!btqr*0fOWrF*oBez`YEH zSx=6R9zg#5_hJbF^=hokBw*|B?dGZ!UqfV&?Xk+Uv7U>f<>qA`Q?$db(%3kj8jN+W|av-|ZMWvYBgn zam*95#kChaV3X#6?9nXvwGq<=(Xzfbx0VDu6Ib>gNNKz*3{wMAN(-h za^+RQN1sPM_V0Lz^M<+Md2To79{dw~t+?U( zi)dgc+1=XNaTv*cf5Ra)kI_tdt8x(b^1or%?)j*$_J?jyazZpKCKE1_?-R8^FycS6=jKELwH8w^L9^FmNMn zh9igfRXOCD?+m;Sv?H91&l7M4>N9jhlWTz@|C=KX z(n=?7UQ;vPdFuyo@mpTjj5+pSKlb;i%6o*13~=RU>k!Tz-MyX_qyd129LECH%KMFK zq01qqisO-c2W&@^Xi2Pt_cknsYwR#`QiYJCHRtmv;W(Xn^PBZP)6cF){)~gvDpAwS zebdHP|dCSM?+vblL=KI+c- zGRhlI2~F%dxNj%M_J0@IJ$EwM?EHfH>}FkkJ(hB;Q}B>g|8~Fd6h^lF3z8F^1Tm}2 zITh@oy9j4rdNUdtm+HdML7DXH!>tFo$Hvb&t@OLxyKch!>TJMk97BN~0KO|F!aRQ4 zz?24IXONP^$qD2vGR%eE8OwyO2jecs;x+4V{d;b~c^A%JV>oIFA;T9oKl&xq=HG|9 zvNo!vas{OXL2G!g@H=K_Ac&RMM8kbcFnWwW(QF(n2!6+J&n_7}2N5YXjpnf%GMR(X zd0#_8{blSGnc1TwJ!n$(Xnp3-x#{8t%v*8oYcdR6!tHK(3&YTbg#<8>~p1p1GPGd<#kmnM{}iyyEkW3x(LqoPwWy{m>;?DuY|!K z>o=W=x3h<7(^+RZ(v0&lImB~M+>W~3pP;UEud#r^g-QkqJ_JlLf;?)BXMizm0-gE?voSOX-KaX*)X(q3_@wn7{aR zEL`#Cbe31`zNhm5_HX|srUtiRw{=sb6zNjK8`$X<+@0n&wYhU z=ufZ*hr>~d7NKnM#W?dVzr)3!!)=YAuvE2VP1h}t-on|cjVsw32)dT4DdZ&%4g&RPKpHi(Zjp&?-XVX1&+6hynHOFV&Z9a+ zirt1=pZhs#vc8L&!mShuID-ag4569&OkGwKhkz^3(r6aYL4C?&bvk){?uDaCkXCw# z6#ElcDwz0ZVJcC`F-%L)clPqypO z77Xn8SFFA8&rvyl_BKw?AOU)8ydT?t#!il@om}{V`#+!#?OAWZ8JFD3-BcGSyDk%X zH<=7JyoGn~3%|ntXTOi!;ivVjo|rB`375ZbI`w9( zTC;(rPUa!OHfI1&L$ z;*g?9O@Ac(NTaA~t5i`{2}%`JQL0L)BtnTQ5mjmPt5Kx(PYa|~qO?J2Q<}7b-~c6c z8tm9L#sM3zU)Wx+z3W|j`+f7ckL_K1)09fNKX&iToS8W@_d9nU_nb4brJ*4xn~Gan zAn*q0ymC>>lE09Og0lwbK|4G)j^(oYMMeguD~4U+Vy>W(fpk9MFnM(xb7^7V$0^kj zh?z;Qk}D&-YhNJVup(5I(HM|#g3lFe<; zO4+(QbE=a0W^jD&z+WDhg2Z)Y1Cc2FoJ7hVgF(>!@Fo&c<;=px&iON^WZCF%;RK)$ zV8o&uAJ*#Hj!X5%R!o;%wS}>fVd=f_D;a$M*XaK_B@l7gWY@PGke&O#>6?OOGD+pn z>sLRN*ME5oNBUxmmMR$#1~n>R0Z+>{4Q>yhJ#qHU?*+PZPocsCRpluG(`B)2UO~cO zpTEYIrc<;!gM8!A_vK6X-Y2!S+11sT6bM#)bMRv+g3kT2xi`^47Wk~*16BoGTRr2^ z3dNyIqabSp!Iu}=v@rM=$5udmw2pwVE~KCiyNI?z5le=oV;n9EcO8_~)xqv5qmv_Y z>FjUdnPLwXj5uC)5%1W#rvKe9`*dcaPp-WAJ-Oqar=`4RM^1&upn)5~Tz}!iC*dUz zhFiE6O1H>d_y`usjhN?apwC7}J zG_MdjaY`sm9^5Y~3yD*>}mEV>}w%j;xJw(4d4j={9DPd5p*C`Co%&(OXVh5$M_2H}w zRy{(zCgH7j%bK+tvf9{^o7-{4CO($Sr=OB-ZBM~|A~zM0TVoOF#kOsEbx6H1?47zhsiea?u!a(kPz$dphzb%g?a0KGNPIv0^34>iTU@5L>H5I1@$_G<= zqx2U&4WpO60Lp*r`Lp!cG}jP+mHN#s%1K$!!kcur>zbZ`w~RNQkuTnRSSo88bE; zOSqxQ*-4v;P07WxSOj;Tl)1@1JQ^tP6|9iZ)&tVK^D9zQw>gj}VqxOeIHqL3!%i7a z7ai}z$O5%+#A~o?VNhVlvvELg)({SjO~XHC<)A}88%F^^*b0h*4Y&!KCJ|G}=3LIb z&4d)14VPC{%a4vdD_gdH!S^xJ$!KnJ7$G!eZ^z4$96KR(l~(K31+%6w(;dTzd0(41 zI@mNVqC^(*V8)4XB5#uB(`$7V9Xdv{*kLM%Kx~(mecyG+hHv)6)8ZecU;>`+@KH4d_mnHE8l`F9VKoX`rMzhz zpY^vtyo8fOd$G+rjXuRrTydqe?*9&sB;J&D#8hUe-Cfez4#&iB)IeM4d8{2$b4f`+ zDKHUFDAzJ6+^Z>=cO>uvU9B;!z!)LIv!%c|3vLY?)wWDwK$60g({KiDz#|NdD#4nG z-yjY?@dK&<{Nhg3au$fLj@KnQdP2gXbE;}Da2-JVgux03S@Hl{v7IRlq~XZGCRtj> z=^k;)XAC-63qyfKV)b$}-YWAYJ7rDHHmR(ly+RqljXiW6w3mn7k!(t6>dS0w28YlW zD|1o{6xMpXFFxEU7+$^i=a*#1-bW<_!Oi6&&vX=q)ho!^S9!2eDuSws>qm(+H0**l z9Xksoc~~xeL=Mhz7*)7*n*AyRSdeNzMNAi$Ojb{xy8!x_&Cm|gIoM-Jy+z$ zzdB@cs7K}@6n0&qM+$dJf<>u#6k*8AW`wI-9jtYO<1mLRB|xzI3wCLQB~%42-y<;}}`s*H2}!Y}bN zPyrc+?R3Y*bJE}4Ag8lTNZbuma{+%M{YnMPDw@L1^5p|D;z*;;CjOv_=+0?dJFzcTGA{r zGB69Ml5o)&Td0?4!CpzPYJ)KBz?SKHE#p#9YoT3&JvU!=|tt zK5|qx*3&7SJDOU0?|;q$K@S|WI8-Awh!c2<;RW0Xh34J`yz_n>TrFDGZEs1nJ zC-tFTyxmd`n02>%fDVqdFxV*->iVR@fHK%HPLoDwYb9QBNJ?uT$*PY}ohuryNAbap zsu80!^p6k1!P*q~oI_cFCfv5GF`BOpbD4fasvopWcH=a?>S&!{avSki3C^oPGj8b8 zc||BktB#P2CFR3DIe#H4sl0Ne;o`c8{{eh4L8rO@PMk?le;zuUZsS$a_+eXBoQmL1 zolfDOy*EjQ4#Er%BDOrHr6C~sh0Eb1w+gn{&<21?SGREI&SG49`JviXm@{6!*Tytit+X`(3-`NsJIdyqO%%-@gF> z0RR85{mj|`06+jqL_t*SeFb1;#r6L8-16e?$-1$|B8wMym*Ubwjg~@%8dd84Ybh;7 zOR>`8v=m)@*=1dmjeGKvmpu3P|IR$wB%58b%O))S=fdXQJ9qBfnYr`L9Gi1AaUK}w z(cQKhEt~&}`Gqe)uLBI8G;~G_?XiSSh#D+fW zcVI6&4cU1$(ChW;Uh0ojKN1O}Zu6VK;7iDizYn{<6R~Iz@mK_i#S*nqt>hp1KUsdF z%B=0EYbjgO4_`e=nodM9>5iyp*UU4+0&0UVtidty3(%zj%jNc#>3Sr&*@8PAVAIE0?Mj}zx zS;Oy?C^z})#Kq1>ll4%wNv9^Rl9fuPrgJ14p1Lltora@NIt7O{x($6$`ZE{en8hij4)T?%aKnW?dkiCo!;7gOkZJQ01TGkdG@rDoxH3 z_Y!G|bd{zOlGmwcnU*R$Q5dgN&$Dp3mw1f7>GBhKQr9E%B%eu^uX|>FYoxKY% zh6V@m`pf^t8!!GF4O=!NDsw`re4eTX$#3$IcZ`{qdPr_3^Qs>;mPV#6Ty`kV`s8Ie zZ21xU9}phT5C*$fA;WnSOj;)!9F-xEs1_@eI!_Ka)tFS8s^%_vq&HH}C5uTmFc7w4 z2utA3{vIl77sG7HNZv{OxLt$rI^IXH_uq&+pF^Idm#bC;;g|vbNCy0|VrcX^&>1qI z)0?1?St~V2lfSB@R%GyemytbSE%Pz-BRsH zmM582Qu0^cBQt$88b&x2M9}X-#6JLpoSYoF8uNZwV}~(!F3RSdjEXtOAv?E-?=>dh zl=x|GYQ%~cU%-F<`563OAD?4=hF2h&d$(!B@~S+^{HcZvPt%c_IQHbzaOtP6M@cFB zVI0R^tq{^70e1s>)_sNpun}gxkFSs_qy{yArDxP3X~`)-^6>u@I8wjTh@Iz&QW9A; zaQJKBGM$6kLvJ53(?|z~!y$Avy@Pn)gRlpmh1KBWY@2#b+N)pz_64A7)B2M6hP!9axSe^?Mpp3 z{8x2R;(6&p^-t9xd9mbgmYOZ_r+Pk_-BoeX2uMaax9NS3f~KQe4%(I|q!00;6A zJkE9mo%M*hwj<){L^S9`oMdWD$UsvODh|E@)8-$I+=5c*bh`9QrLJpNy@$Wu^=Guy zZ9^m+PTxzNsJ2Q63_H?S$@KKKF>aoBuJZ*ShX+#PP=^0hEQU-+v-OO36Ry&qAN}ELcj ztp=*9KkJbChN@+}mYb?ca&I&khF`1u%q#g*|DEq+U{~7;8*s!|#!)+nOHKiGeTG+BwjrVTqwQEL}BVXP%v4NDUwjJV86cIoEM! z`wB9%^3n~E70U1KMElyGASeC`Y?>~TNGA0A%V4bd3@rJF!Nh(MWBnQ6~Bj>8sY_j@DaxM3h_fo&9dy0fo_vG2+KXpBfv|)M* z1oB*R4DdIRNAAgyeqNOmhc}jk(nVKc#^KlRB8*5p@!|f;`$eGP8X7=f`xdmWe;WNw zE1-+H6(|e^hhXL*7h~SC(?+cFfj|I__4WAG_rHySo*t56|&4ID}1{BZv^oWjh4fdd?c?GPFAHuHdVh3vA)67I5`*P$|oCaG~DGUZm zJ|^%8cn7dy#qW_5{4ZI_PF07*$d?bgJ1__+5|tXB=L5lzd}dEzkaC4El{(0I>Yqr8 zd^R$;i!Q;;MW;;21Tnmuy&ezRcf5y|jnBeS{{pn}Afnn#6wEpeGY`80)wQ$I*=6AO z5eUEj@ek3oZ43N-c1$p+b|pI@(Zoa<(#Yho^Nb0pbW#NdlL=RU{);%45~iG-oK*G? z{M~CnNQr{z&h@v#1@4$51^U#x97>d-uXFZ){!B=3nXO5drOc%NjC!tUP4ck^D-f7rB=Za16|cO1&-Z;LG@C4084iz`XjkAq_3szse6eEOJArorjG@Ns1PpN0%T0T z6yeeKD2c2AMuj>Y2E%VHobNyqJx_iPoc}6hr+q%;pkJZ8Zo&II-R)xuXkb1 zn=3HTD`RNqA^ng(q@g^9gUnpNPdrU5w)L8S>Pm9ge33_&aCQ`f6~v&InxCQ=A0QQsyz(VGnOF3o=cJQ#FCK7s;7UV(FmN5 z4!r!}*C>VB0!`EhYu+qOJMK2joIM{_TS9#9^Lp{d>#yUPhyR9_`a1P|qFw55y1d<{ zrE*B$q|TGSLM?pu8{fvFr3dd7xg?M8Ga!6E4~ClWL9F*q6x-WJfI&V_0s!)gsO$o}{mnnNlE0JrmcOpfhE` znpud<%$)RWoVq_*zdnj(UwYzBxSO6w%-crsH#OO_ufS2qpF`b5p{j=8@5jn_-^CM@ zG&OGDnrQl{2C4Rrm6mGA7+^4Q6{?_i`sUld$MI9S*F5Du148Q5vEv1J+U~*h%;!e{ zLV-atu)>LRHcddFl7@jHeJv+)KQVi@8@>f|>BT55ujP%zQNQj{1l#UMjr|>!(4zYi zGAl1adDYxhmZ{$Zqz8flKUTf-3cA+Z1%K}b#Ep5-79WpOFZew2iz-wt1rV#>dk>G_ zcQ<*mEo!U`uYLmjGH!OJ4m(x(M_fxbj<@`hQXGE#iMZ^lYm~Np=hNdm`%r-B>1u+f z<6kI?-VTE{1Z|RZQmtTZg=a{w1ggGCFeF=&SQ!WcUMnypf7^}Uq&{IJAez{@f%bb* zY2V6Hsdvcx8LVYzBQGy8>+si+Jv*m4)a#@IFFTq(?d>aKN zHL40D0I_xRh-xK_kc(t9eq^TJ@YN})W3$fHUp82xj5(AAEB@`K?bJ* zaqnLfD@3x|YIr0Ey(A@vOX4g&c9NM@hD4(LwNUxE{Mb+6=5OD&&l1NE1qi8+v#$;f zYwyC`%!gpr^)p4Pwv%6wJhDotl_K4s#IWOcnYx^sR>#PLCJe(_lC>t9P$)O>GCEbSf*;r|k zE190kH+$h?oIpj~>1Un2&w7^+4G3YNdfL_?+j%oGH1%91#ON*ECZ6vd801N{LW}{3 zfB?eQtX7Cvt*j8I5fHYWFPl0$AbLOm;dBn*y?=cJo!eeUTyH~kJb)NBaCQzMo+U4K zrm>l$z#xjalg~a6XHwK!Rh=Nq_N6mEG$5q$LBEp*f43kPFT-x=P1j>zz#z|bn!iD@ ztMCvz8zw76pj80Tf^bxe__QfNq&xZmJ4pdzWeN~F8)Ej|uMj(gsg_Ycj)AY5ItmPu zCi@;Pxa>-taN6k~%1q@$141ejiG;9e)e|U={s{$!m5P~8D4&vKkYtjTLXkxzkNr$&&y{0x&?AWeh;95kTCB;v~tG0EF-mQzTP*WE>zTDL}j%xlli!SWMM!ugk6ii)bLeP*UpMea91 zNP)dwjRAB&^OaRB#W|FyK==%B23X1w+UE#Cjd^3-ge;SfMyr8| z?-k9gY`}55hG?dtXI-eR=5;U_HMPbMJ!`6p?!})JAl^;^f+SNslPd%PQ8Y@* z^pAV*!j9w$!NH;amsgD#{Os!y*D6CCdiG(}v>CYei#K7`>^a=?kuVF{i>mIDb-w~a zI%1&hB{=JTiz@3I92iN(T(UKZRX_letcL($7#LJCue)W1D8FzFK-`bwBoCpP@qe&Q zA|M<+jc{|9n8j>BUg;vpz7Y37lM*Nx>@(pVXn-a*BwP}raTByg+7WSJ8uU@vtQp8G zoXZKLiJR?xuxI9>pr}f9f@`1!j_w`YXw$|grim1N}w(L@57tB>)+2!j` zP(m6I|M&*llPd&v1Bk~6h!n|`8W^eJp{lnVFi4&PYNZc7<~Uq`9Yx*xL0=ICFvlzQ2n>T#$ODeC`YQfvWJE%kD0lICs!ZsQZ@86+FrXrCt zMRd^4{QaZ?V#nG?(6{5C$gzb`wCp!%s(TNbfv1sW>_?C3dgun9LY{7e(%26K%HfR9 zXB(r)(6%8jHy`#nx1nzRGYERRQChtabC#Z`n!Mq)pTgU>k_L-mgko9TLy&=(HlOD0 zE@X4Ut2z7!=z0HExWYw<>hhp>KFN2;#w4+91x(qqP_pdTaILu(F3o&c$}d52Q32Mx z^dl5#-$rKnX)xD(iDnGr-xHt;{t$msfOzY%1R$Wda)p?W3qHN;3XuRrf~g(>1bP1+ zz#xNv*-^*fl50PWIb@_qd-~Yd>hE_zs2x;}IyA5P0je|Jfz9BQ5w8HC27U@3qX3cs zhs>`)kL~MY0>VcgqR85+NG9#f-%UCo1{)tjp``^*-BB<^TVRQ|!<;!C#yS7T-E;H+ z((q>t^|v9Ca~{QjOVPOTDQJgYg5BuCkaihd+zA+?tBKO;#R?EYcD20qW%PB|A)u{> zCSxIrE9SwLk&i&%n{c)K6B_Fbc)czZO*@?{f*l>}e}|y?aK5(^nX$F7p#kCQ-yz;` zGkp3*&=#DF9J?OQ4PRAcT+pTMx8&q~9V2`FTnZ3x5)f@$UZSfS3O=&t9Ci*%#$-5-!NDk53L zK@jz_9=Rx7^j&y2+yJ+B0RrYDp$WFa;=CW;kO5Im7BY(#WBTFWOz*Var3AcXPr`FwC}{wXZp zXSnyeIU!jk2vRG7v|HcBETyQ- zBmWSqhCZ;KI|h5PCqVQ&dSSBIk!x&&CGaNtf-{g&d4U3i44mdI|3Pp2It1NK)bzKq zPok(<_H{(fbI{xPA_`o$!!++NuofNxU*CIZA|Ui;l1?N?Lt(DDwt1L&B=;t-x)Ou2 zIrKPEi|D``oP@lH#51^~&p}i0Ok~XY5%Thjp(m3)(MJjpZx9fzTV7TxgoZ1G0z~;p z(~ZZtLW}^!2doUjmrb9y02f_(HI^N|Tuns#vpo|6h*SmZx2}Y~?=Iv-o`F%Ehb74* zxxYIwNSEW*~+57C5S5Z2sTC?pddYyJ@&UNXMrr(?!J zrz*)&^Lszz9`#NHqBimkZe*DJs9wyy@C8>sW~pm_23F}UFtxZ~5fB4ongevvMGPUk?(hJ`+)4ABnmpyOu$gXn~TjQB(! zDL}mbNCFTVl1vH^*OQ0X9UuqUK*>`#+8bA6=KN#$Og@I3 zJ!om%gq-|p?uN^Pd$1GE{x0$)i_qP=0eYj2`-zPR)0C!m)-o6#z?CVk^D2EfRJ|# zI-22XdkVVl-;%j>t34At2Y-T|9eynnMW6kvimVu}hiF>;CwQ8vVNt9pzcA02pRTlr4aIS7oq3~OlG=vWIjK4)QRpuo)LY3?68x;BG;l{kVDE1 za64)w^AIpho9H7Ah=*^bFW{Gr-Q0-|`t3b7K3WTIQk(O{7N9e#-M-fa3= zy8QajDDw>2pFI)Bgabl0i@5qW!m<5sGWVH53%Y!0^;srJVX)$qt$RCVx2a7E{;9r zG@Nz8h5JqCFji|O91!wS5gT^5ZG^7l$H<`6$*A$Fx{L(|5zRX6Um1IaX!;up&50F4 z0it~Jc!;q&Zz^r<9!LY?p~MOydI(((Nv0b<2oMQGByo`_oGV36K@m=%_q~(PJ{J`g z6=T12Kc!9zAf&FLpbu-`c^pNd`;o1ovtZd?%D)LlJJFg1Kam7P)%hcs>c&-nf|r0O zuu#rVlF2A5MES{+CU)IV{r&$%F)2X2N!2+~sogKP^u zj{1gE&N>GR7cZXh{+l#F#2F94=NUxX`oBQye2O#ujxoU?q+@?3SBNnH;gJHmIh^CDRK;5$z8v*75eyM*;|uF$er!w6|=7w&i>DBEFHD?2uC2 z36tHQEr2)=WyAJEC_pqkhytzxMKT#>h4|d= z0g=)>m}#4K&Lx*A!@Y7!lqM4l(nTK$Amqi;X`-m=tp6`Gy^qq)hyGEuvN1-3f$T5u z3W)b)h4?!P)CwVh_~jHJq$3Z&V>lohWrd*WhB0qGE*lFFfBiG+$y5tTWa2)K(=WIf zM<0IzYDhB4rmD$4J~BY08amM5i^10aBHHs5Y#|!YX`*oEj0K24!^IV%(A=)Xu2X&2x+tgU>R(C4Vs<@X^d76SI+0?$oSlmB-6?SAPQ1|Snx|^PLWI>#hCfPccuXG z!UMOWk$}*WsZOmBqX8kN8%{?*79Mga&c65(R9DxiExI50k_pOiKmbD8HaO5nx9D%f z*86Kl1iBEpHD^#USDkKlg960gk#B0Jy^t2>gMKjuh;;89SSKk!{3i(rA(>41^Km&z zrs05Cy?Pa%dGsL~I+o#dN|R>I+Phc|6Vd7e1`uKt=kpGtW!oFjn)10{b{Yx_cbfO^ z5J2o855W~e0b&6GQ8~p_PsE`3uw|wJasRDoSf5xS6d*po6A&RfL8z;%!$7}-rtw9n zoi;6P)c9fF|6!g#U;rVFkc~w{g9FOy(_*nIj}ocIr2%2;AP+&yO<5tP0FmmR1L`*g zh<~R5AuB||d|WXM5R%93axt88OlhDeLkm5gPCB3fv8M_PAcl54gaV^5)f!kAP61+1 z{q<4aO9SG*Td_k{2mwUld|WvU5Fcgz_Vn(L5g`78p?dNVMy?Ps4QvV!Cr;@h_Vjf> zqI)SoJTHJ)mmrzUTp_Of!cLOuBdXd5zV>4Si28R42(A$MTp@&qur2yINv0`4eBc-U z2r{Gq@!Y*BKv-cBK-~D_G*kT%RBK$X{MZ0u>#BcZu>KJgYuAz2;LfteKSS0OAjb8P zCp*(lKztqb>t3eIoMKchz5u75a~bswI|U_^U9a)H?_&c9iTK&q{3iUJFToPrh^$3F zKz7v$QzX-PzVamJ5kL$K4B+_(ZetAUHq^{N8nfvas;Y*2x+yFu12oSNN6!}8D1BUxj~yTqot^N)EtZgz zZ4LQx`LG{#J>@&ezmMBD`q%;DqyErS@BiQKfhj=zZ-3vZ*6n2vOaWpqJ8UZZ|8@^d z0pfrA`%blPFMD7L5PR8SQ`!HwdteF>|J&bps&#wW15<$5%MP2${=eM=2LvEeku}9r zwzw*z|3Ve8P`p_mNO}g*z((m=I~JvfkXS^G3~@hiG<|#&PkS29(*F_FK1O_E&_@Y~ zZZzBZ$oQfTss4!s5RZ8I1RX|btW;E6sGLg#X%W3dj2pqC(J<}Nr2puh&&WKC?0TRa zA2}eTlblWm`un;V{GFky_)*N3OyuU5Fyc*-aw~tJbe6|GgpRfb+UIOT%-6_j>5xe) z&IQZPJW#5*&-IWUi+)CZ>TG93R7V3so_5$Q1}r@4dJb5_xXK-L_QTQkE<7!dGW02I3cf1FC zYz>SIV5o^Y8K0TaH3<+E>yOkI0hLEG9qRGAJrkVpSSm2^l$wGG?6~W zcXQLR{{qDF&d0)Kr;NK=ovjRx(z_nIP?LHlj4TvX9EQS*-8=G?cXzk0!$9X+=;A|( zcUh((w|D`HO83uTl90m^B`Fv0(mtjaLq5jGHZH>AW?u6x^G(gDA9}M_0(6tWUj%OIx`QOO5_Ns=FYv2Hr2&IAuMqn1VmONr{ zEn}~d#+-c@?1js?_x7Ws)rFMswLOjk@9)Xi(7k`ufLOs*FxK2ecZ=h5#49s>+nV1X z-1RUDt)0m>YA|Fz5AovbP(6K-N=y9_e#Pq^MDzN4VfR0WJVTwjCB4&U{UWR?Fy*vV z_I>^pLp)EbuKztbnY}aDZA*YXv#_#FrM6B(1FgYJqzO{l;GkS0$ zGOI5}`Shbnj&UMfeQkI0U3-(omxR93TwRP=dhHX&G5Xo5zp+)h1)d*Z`X@3 zw%)|PkEvetT26t#@T;hu9{(NKbE?Pu)>5{|?NYJcjEvhRtBBFKQ>r1f ztsJBI4<+&7jO`|)EG|(*nq@Ls7&JXYNw`M8tYQ5>;BEdJgVC>6x0>Axky(2+st>wY zUCS&hhm<3sV@DsdI`z?E6o86_kA5a2BFjCn2A^0L6Wyl;Ik3G79NR=-PjV z3|%V>8ow$s8rPxETZF>Jw4C;N9mbqx$S){X{V7pGha8RY4Xj6&u8Bd|hxlwreRPe+jEF89UIte; zX3yp9HAmU<%g658cn1Ql_n{z3>NEx!8aMM3j9X9yU2qF*x_*)h+yfBHLO?eY#kI%M zjn2*>heG~rT>W317ToB%`NscJ^gFwiv+C$K;)n*(_U%4!egtZpAMkeve#Mnr9c z$H^Fg{%%-og(#nPC^BW!5^mVq?T*UEm`fI$EI@H*Bguv>H8cw!C7~g3Y{#8{RD)E0pK-;d!`ACV}E-w5UxeH_B<>(=6dRI zGSn&-^t&+BSBJpB8u@FII+_Z85SdPC;SiAu#Z{i8v-45Z#?k z@U%UFeD|*unILiG9I=Dp&bSndmS4m+jgRgZfVc;{DCd3$k+wUKYi!}{L6U$Zgzz64 z@*LtQSyrFa;SE_~uKg11(>_aPC5pyvZ!wVkUy%`}=ua2sK;iaN4Q1>kQMgR-UzmUm z^6@yrr0G%qRTLJNlK$NeLl5I(d!I@bjecK&;&rmk&U9MpBpA!YR`;oxxBLb*BTITD z?8D|)zQGxP1#(Qid;_EGkz~{=nmrC5f!G(~47limFD2%hPXSKTv_lK9MKnS?QP5(H=YuS_YP%vFLn~QhGHQ z9oz4PXU88XcUCSWzZuV~!gPJAivwQ{zEj@uDicQ>EH-!FY`= zMoft1Uj$?ASCEr4a_LqXcJrs-(F<4mbBuTWN7B@NYA^;P4DuVyL4UA<~C9!+nuVG7 z^79MfW8CXt%OA-|{E^b11aRa%!Ke}bu$gILu8KkScWR=Mdg|dX_&O|Q=OZ&Khsw4t z7+XFEgMXcRPehXkN8T?{TyuzO`%uSgu(#is02t?HP@ss{=A8<0EfDl^W zvF$JLxBL}(=5AG$Zf^~Y}3vj%ECT zYz_oUa9aKj&EU%J!ZhbV`xm1ZZBy4#4&Lqnl}Q-~!{+4 zH8bG0oPpx1rJTJ@aQ1G8ulp60>t9mukQLgcKO93@H)76$7^-X&iVE#kv)o%}LJsX%SFyBeJT_B=eoG1Q_*e zABTD95#(!ErORlIUkY>iB`7K`$NO(Sh?%BGxI%T3^vi%Vz5umH{}D!O5!xG9qI>Iu zm}U8wde%WPy0-8FR4n}pJ#&y$+WZ?B-Ty(hv6CyB9y>f_<_k`MJ#QBIi-d-}cl)Er z48M$GYcm01Mt%H7RLwnmziH{yjpE6K0-~{g6AZn7LRKIly^t3-204(ZnVmWRSh@Vb zLk$1czi}sLFfyZtt(<|3==Rm1aM5>>Rk~a;+X9-t-cD#*e+0wO(`wlk+Iukf`*fLq z8rcUAHobi}=Gvbk6Pz%85Xp`=#FZjU5(Jb$nJYP?%}}d}J#QwAmYf8s6AEHr)ip5q zRw_~_L=EeX*r!Q@pGO;Aje<+c&BUl56?hMR7^7H6jcN+}um&mvdsIsKq?)YrZqUS=NwFHj!-$jW{n13Gz zIpEvkXJhFxpFubhhr9VGO_G_iHd1K%nn+XtrOSP8%Q~ zdQDdo5NBiS%6niOd>kc~tt8PnAYDsQvE(KcRUebiU%zb~jC~~2LQkgC+O<~^5Er8$ zKMU(${voE>-{mSch`~?^I-@6G@h5I&M4%jW);)*b&3B+SbFF%|-M<)`!b>o1;ROto zvJzR&U(wWK4Oi(n9UmLe9yx)MzG5XYOubCw+ln0h_T&m-MVt9sD4jtubzxa5%YOTv zP(W;4^C~RPdr*j%(-m$CpGQDkf*EsvKoA+;XVSw!PzuH zPmg}DC&EKZ`}nPNGg@E71J_ilYBW)GMk(tn4c= zRa^smW};ql!$*agzxOp58g?rE2DOJ_AmekGzvyT*ulz3bL(d`C>`<%U7Vib9S#$+T zs}`zq<pSTFP4C zWYj0uwx3f2o&bD%^fYJ)+Un^C;r*9?Ly|GEI;3B=hZCjH(_|u8`6sTtOWFVSJ>=fE zTN4V1^_06?2k%3X=CyR~8hytol4<6`Gtz0JPlVA+n10hlp|>5zMh?i(7RA_!{$dAi z#LR`K(IPf6Lx?%?`>#KM{2-Tg!)7J7?sQk7YB~MC7B3^HLKy6CN88%p(|GMoF3;U+ z6&d|rVcLZ0>@!_O`=axan^%fWYhOiml-l)p6X|OM0@_++ExnI4e7Rz{#ZT1WKrb|P z*D8I4NO;1!5_D(Yj>_qWB7@3CZ|_QUzWW7AaVQKR)95ju0AIl^m^NcRI!ME#`_Hg> z9!HG2lMek=D4uaPw8mVxI^RTI|JTSL(cGMs4OotZzvu@jubPJKYo7*sA4Y}wZPg5i zFCUq+zmA;ROH{p5ZR_c3!9eq~DD&N}lA@Gs1?{IGQvPjZX6C@Z`6g&xuX6PZ@%?7B zP=ZxD^Ar>mRi=udQtjWc3=(|W1X<-1W_#KXpv^l8G0zr6w_gWSGQ6_aKr%1u>zFxb z3A|n}!tHlM-~D@jyC^3(I-AS54!V*nQJ7~%BW;^(qzcl%NW-0A|C9b z6lDQy`AgAQw+_XwZ^A?coE$*`MEr}GwdmBHfS?WjhF8CjobZdtHFeVdiDEzZ(U^PW zmuVC@C$Z8*LU49%MBG=8fLqLu=|w!?fIc?BnYf$M7-t$JO_7UW<0@8IRE{;T-;G(; zC#g{CfhU|z8=r$Q^BB^-);v`ouV)C2+gG93eH-i8teDD>o+3foUuET0Dcy;;>t)1u z+@uDbFx0W!b77kCT@J`>hA8%OP%-FWpq_)CG8O$IYI!TDRoBuWBPrp#rEA^*+#|reI(g}s;c4zA)mC{opAsM%K}V>0`y6`BH#9V>qcv-=t38A-!a?Aq#CfRaUD z0cdgSY<(F;uI~`EQ6(&h*pG*H+E0<2n@@2y4H&!cLtgM<^=^?`X)11ksq9jvOdVW( zB_Y_ZY?}hqar8tEMSjU_=#3PIk8v=P1SgwPl5~x&!e7)P=96V(0>xZMig%BXjTT;jCUw+SI^E zMMKJzBocH$%XgW)ufQ65kK#qYn#DTw*T7nS5%O{@*!0SGP?Ncy<+|VuSD-6?I+h%F z6Ul)DSu!-xiS_UP12c{H!>Z|4Or=}52$e_tiF`;ddV5+i)bb39+&?B6$Qd$_2YtyW zIiPM$&u}vE(S0Z*pi)fU%U!aMj_olX?N=;XhH3xlP^k z#R_0wbRVp_b5uP)iGzX6Wx#b##TY zf!s4uy!3XpN^M#5JhXieq0I2As$-A0jFP>t(rf$K2ys#hY`6@Dm{=~v;fWTaDR2@h z=3hor|1$MFdqwF@3GysLEKcw4gH6g|rpu%=kX4XC6ZRLmxUDS1`{?ZdN$~1;w*q$;eR*BxMTR zq~e3C`9VfOeVh#O5Jj72k|mU}mz+T}lWugr{b}S``<1T18Jo|+a4i-ec2;_q+)!UV z*01;lW@f%YUC0pS=Oq-U9*;%G-^Q6P11&pN!?ELG@-K;5vduFOhSEzhbJ;cN{uq5C z;OK354m}%wjjF8eYBK5YEkHEyLd;*D-~~3Xe26Q=BPh45PWFoyo{S5jDIl|7Kyrs7 z*v8E-K<|1UMFwGLHPnWeLR0!#PBv%Lggu7$U%La<#%GbG?;xpY#1I+coCV*7DRUb2 zlvIQ|o6x@TZ`2R0<%B?+ub7Qu-C3~C`7yHcXHrSJlA!$yW@Wyn>e%Jub9onF_VO>O zI&FF9PG|_)GOK`AgF4q?D4G9R6xAGyz)&OHYpIuscPI&)h-3Q#708`KT@e9k;7+PIA8qt`# z?)4TUntP#Qz6}N)boJC(&|WB|91`)MtSp@F`QbUUs_l;QEN2wniyCJ@Glw&_y$Jm~ z9^w1%LJ?=kxJFMP=3ppTNE44d_5N&A2NhwR{NRI1%F!^i096Nn4c5GcYD18I$8`#% zA_ei9j=)gvH!+>Gzlde!@H*C`Va1IowYL#8LG*{`pj&?l4nF#FepCyZw>*#j?e}0t zW`fpl4xXd{F^Be9yE~LIWXr?wZT}IKatZpnBXT051(#v|lEia$n@L)7??FlYiF7d` zYTiX^HW)0U#HXKP;vUZGe4YbK27J4b^_+Po#g)@(E7plkFMk!K=Cw3^Nl4!0dnmIS znt6z+MwXHLRJ3k>mni!RaM2`X!1e{qKIj-K1v98$coKaZXp)o34PNZ~w%~F^^FN7$ z4mn@dsdeSI5qCUE#h@_M8f*<*hO)VzL|OGBzP}6guYHj`-$p9k5_%(fzX(m7!BT3a zv-!Ql)L*r$)mfBvv8>}zyzIAX^_VD7Oei3vSNeN)z}Z4mgr0klOJs*~y2`w*CDEh%J1-CI9JX7B|L+}7cbD4Nw1Vh4uGP?k~8j~8G^Qc9zz z=iT@RqZCgu{Plexl(ft=970xa3tWzdBdnJ8T}#a5a)ez89N>x-B@|8SBW zIx3YYWvTxoifwJG?md+M8@WPM)y^Bymf;to`3-f@Zp!g{rRbA;gSIPx;%iY^JxgU3 zT}glAlL%1hSz>EaY0@5%l!e$nJ+s6;r!8oI<7%$V z2@@Dq0RMizRpuJB|9+CX+tQPvjDs)*8}faG zR5XyX;2@=0%QR}(&%&(3Zd3~0k1ZfX4(@d}(BA$f+O)h6ZAh#z2@Kk&#M$^zEJK+i z7;Kf)4$nZquz<=oGSv3`1RcrF=xAC6U)KwqqE?dTr$&|?6`?XspD~U4gK9WjMr6cj zazQnJgtk6f`$Eh<^wS6iX>8ZOmb>%bf`4Eune}!m=1Bf%eH^^B0;SyDPX;`yFM-xJ z8|FM3y_FwFgFKoekoIq{dkwav{gRM&86`)e;-KqQy<`A*JZ=nhybo91?>P8n%>y;O z%amDoK8*>*{;I3)Y4q**Cucb-3yE$^#U(UQJAs>u5=^<2Gy3RgYoapk-_Q&^m$=21 z&{jziXVuvhsb;A(S$&84wxhr0C4~B3qA6n&EF{@vbB~yn_-Oazr}3fQF6~+hWFAGy zQ5p3%CiQ$c!2Qqle}|`U1LFQB+QZW9h2{~m8pz;P7N#`96!O!Ww*dN_!(hr;%zf_E z+3*nS*1?vi;cxpJpOLAClS|13ROp?jOe#7luJ$$l5i!^MYC<7*1pA!tB8TEq;c=qe zA0xUWf9I2kJ1G|CJ_%W=gbI+Jj8KdmFC?B_od zzCuWSWnlPxZtkI8Nx}Gbnoo4AnVDv1@c1=?1s9ANnMsKAlLp3UE z4^r3i$4~L_fTJCK?Lwm`j_kZjnmr$)W-%dsdONnFuTyB~#GomyUP7~SN}*^Jx4Wai zubV4t9ejg{nIAMQDW=)8Sho%z4AL*|p;Yh@wxlaBHXNXhN(OMYH4=+>v7Vb#qWsy^Pker6cxKh(m#a z?u`mi(vCR4SwY1iv~FFb4E}n1Iw&AniIBG|(M;a2S#TctfD(Q`nK}|jXGfC~OB;Nv zXnw-Hu^_R589RGGW>fNThgQcNoR zje-A$54>G-@0ub26H-V(Cw6AT!MAJf{hK28YOoU^s=iZzNcF_j?^F-42c`fq zH4LVDU|0`K0b*EZOr7qz2T~;2M?uOAuh~SBbyI*C-qTa(d+Y&`*a_2ZHq$0)n51Zr z5ADaBDL_gcL};)lN!`A__G1AEkw8oqlO>)0QGD!u{eYA4oDzFCzYj<2TQpDUQ|1@e z%#sNikh^P-lNQB}PKt>8-+;N83PL(B$ewTQab&`;L}YS=qy@%vL{ z4LuQ_91lo9NQZXS{|8-L?t@)J3s@SRRV@A-il?7C-o6}nKH28lzvD3kx}G8+yy(@O zhS^ImK+hwSlc@&KZX-YoEAxgi2fqwLD zyPxiU=q`u~*dhHVu;hpfkeU6#6OB*=0iTnK$rc2Mw!q!_Dy&hlI385)dWsJH3oKdF zCS-*=AORtJBfL#_Bh*AYd_xFZT_>V^!FBWzy8B&rV|Xkj}69jVf%P;Kmx)+(}hU;Utx0miM)db+e6o)Y|e$Wl3cKl&D{NC zva8QFNRNDYjk6zjsg=?{k&pw)?V-DW@_+k|i=>K}q{P~O51XcqE@7%@A)L*vt{eDG z=$)hRdf3ZPM?qofE*%jH`mt`+3n&iWNz1Yg2%F}@S@>I&S5Dil2X`Tl#1v-x2734N zy+H3O8)<+tpj>!5{j^Zl9Y*JIr=VsQU7u#;u@3v+CzCYffCNNS{YJV~zZbcIM_5B0 z+O4;tkd~SSMHRbr{)bIi^9HRgJ&&P4zX3sQ32cl0rk3OJy2$yk?>|tV7vsI2<~L#O z{w@ubg0uvl&lNNS)s_|9tVEA~<)5dq;b}DXE8L|CLHc%G{rdeVk3UAwirhs=kAbH7 z_s|r>PBLfgf$SOT!j28kz#bqV;&pTh#J%7#l4sgOkylQ`Lb?_;*eXbJ6;7zov#|)nirL`tw7}+%EQJ)7@rVioe!8`B^^$bx;=u4TP?23Z54LC0Ti`f-S?w}P_cFmp_w~-6ZS<*i zFMU_p5i?DvX*jFmegm3}d9?gJ9`=0tz8xb(LC`;lH81}ZrMefnDVA<|tVf}OI|!xi zyOZDz^=`rD6+goCtkpDK_akJOjS%;Khb)IE<3t-tt;x`T9FTz6`0hgl#G~}0w^n(^ z&R)t*{oJtgVPylL+U@CEgVwihM3IegCTLC-vY!ln)z_3W zva$G-5e4kWivto6Ti*IDwEh32AD&KhdTTN3xIfZ7{KH9odjhzLV%e^q9(Y9eW+ga@GmZ{=0>D!C1q-B-2qoGdAdL|>{s&jDb}NKeVM^WRxfB z8MqtI<7`B9%azbaJK=~ghbQwYEIRb`-PTjSxwy=)d;bAcX#S<#;LCmt@j#Nj@Yk$U z5y6(&vb)KI{+h&jjHu2zT+x_t4rJw`7hqQK(z)ljj@W2Sy1$4uW%+!xbDpRlrpv}W-& z>Ee|Oo}Tq80+0BO3WYTYXsQv?*U+`R2YI@693)N*MXS+)3$WzqYpLMcKbvJ_V22&A zLFauB0rB#eb%~1qkef$G$aE0BiR7y-{5CXU?$73qwUQ+yDY?Sdt$!Z=j(;If^B#@0 z!>}&66B$K^ldKA&w`~n_dg$*d+6R~U41@|l&uyg()9oGWM7(PBb~SMS`+dlYzOG#1 z2esws&-orIr_sL^eMn8lF)4ru27H`_7`%l4S?Te@Y#E!m6#85C6B}B;4!!#|_~{g^ zS${JYEIyW7O82cpnm0WGXZ_ubeXtI_z7iBH{2sC^Pb01Fq7$+es0#mzQ8614u^$KR z^k0(v$xGA5qd$O<2LYTAWA7nvJ9^)_f;-HbxtnVmytebO_}DLybPB4VDv_>-=%ub7 zL-9EXnhr)>$IbHL4j4SIB8$#~#eJrMZfFV@eJ4$3$-Z+5#AtThp|)cRID@uh5x2}k zB;w`+-h zh4O&nEc^`vu`H)oZ@TXpYQ=_^ZbKEFEsKl%SoUeCJnW~6Jlgv1U37BrD4jR#pcj+^ zlrR4?toe)i-fr&TdlA*)pOOD@(NoA}&{f?s!UxyrI;5_JCzH@+=KjCH9)3e@6W$iS z4)YH_kFNjszl1UM-r>I!4hU&vKOOegZ+MP71NA7WS&jlaqq5m{B}-&b)opzrxr0AP zM&vyN4fD{K`!m!|0H zV21HQ?$hq4KcQ1mu=FTeeor*&Hag@xkI4zr-|4*ik!k}DomKOzXO|BKZ%*TyC_C=sud!0-jCHF z*}mmH=z8y?BVm~^jA%36jIx=hDlKpdnCo8o83FN(a&yxbITZ&V|7ETaW3QO97redU zEffs>n50((hO#S=IqiDo?QeMBq|P_K{%aVA=qkq8j)71$s*a|Y^~_r3_1o9K8P2uW zaj!G?mxmT3oO3Y_I{cH0iSFO%g8JbC%W@AXZ3<3Q-#57_QHojSg zl$n~vENF!_Ob5e}tsHEO&4w?aa_(6a<<*k$Yr(pgzt4y@^y*FKSKQ-!%_q^zL;-DY zc2yop>;-+K6Xx(*)lmfD+{>V?{4$kOMQCl=0b|!MVDUan1y&Y%wP(`P#bMA{ z%IIv39`NY$ahB~_Xc>b-!ijk-r_$)n2TN#`@)%+Uwexfz(-=B~8sIZ1VqF3o^%mV- zZ3s6qSY`NK6}hw1z)-n|o<%Y!Bh_sqe)~Jtpk>{is5ZSsM{qM?tG){5b1zgg{)mjp ziyd!%hpu9tRo=%X_M1QRV#M@}n-_P%64{K*(0{2dW{ilyH0q5RMl0_iy6kL1Mv#uI zV>=Mi6w@0zqX8X4=ghQIa*Y7$q@@M zX5cmk=6sW0IOt2)Kv$rZzf#T>ES6mBM%=Ntkx< z4YZV8JZ8OvzJ9EK<@+eny-p`ti3mCpD?x&bMB*ZP8z&%C>GTB3fbcfDpp>vx-e@sm z)wd(R>|jbsvgzBkjmo2+VS2_2#$I5MNBU(N3>GL5QvEbW{UUT>Gen6>j|$vAKreH~ zimOmC`&xqA#MNVf{+AfTnx5*!@s^X?+=w_#W84YELx_5tP++FV5Rjya04QF`AtF#>faW9o@JAisVtf@MFXS%#3c3=7u&KI-574Q6J&t^8z(KU`Os zE_rmaq9q`)OJ!67C2Fw{y`r=$xB6jDOkO&LE?ac75`*uKAsh)NemDMX*%Nqi08Pm4w2wAtoR&qwBpSz;jwP4e0!57(R{qI68MaVp>pY0l~I_G zB3?HoD69U3;>h1=QQM@vl!oj&eW>UL&fwX)MGNh+P6JLDbqiZ6<uHNo8N`Cl$=Pwk% zx-2)tUU?o$%lYi6Lj(lkS1P!Lp{`u?i=>N;%8|H~y2!jf`Uuk#pf_GlDcf-C}8lLjzlDnaU^CfB^kTxiaq?9{dqp2fM}wY z)6jDV!%>mZq#aCM?DMEya5g=+RqxUUrQmV5VQ}?jjIz_p0h(}FwM)jmN|1;+Wt?e_ zCms7a6;myxRZhs?o#^IW z3`KT1DyznxOeAl^HtJK_9!0hGA-Tjr&UdKuV1JKcfF~BIU7c;Pb$*q>VBTeJdF$vE zSk?e)^+(l7@;ay}3^7(+*0ifoT2`r^mv>6kSx0vr{M){PObx?`F^Xsc;&OL)N1{LE z{e8Y7O76~85sYf4&EMSv6P7-qfY`oyHARMhL2me2My51lyZb~;KluN(cP77W7f~F4 zaT2fbmZfR7E>2Tg8Y)phpbE98iUR_KDsn3zP9P!i5A?=~BL`MNuSFmZ&~o5VHEa?T zN?N)ElD1jgB(@X9v17;n*-paeP3krcNpPyTQq%knv6K8X9?x&y%$qlFzMnVE0i31Z zXgV2}$k6W+jPZcxQH85`QYPdOsS&sv5Iof%E%nmQWvg<+NN$rrLp!fKq}mNCiaem= zLbd2JWRt@(F?JPnRiETC@UB<*5G~JxR%|T`&&F5XvF-yP0Wqb}sql4YjLPLIeK z3vhR~TejE{N#kKhQmtTZcbgGV7tqztdKUPASA5N6dM0G#S~qDVKOjClgmk{*Xx%cN z2}up;uiDmUiQ*$h;ro^ENj-e;}Q z3yQb}^3M@mGo6_$rP@`G;2Z5%w-vFqzhx$YHty^Uxt1vs(q+a0j40m!@E zp4*1C^mg^j)2S&L?E4KV%2T*c=b)y>=-ggO2S`Hzlcjt(&El;@4bUHKG>LzC&H+rJ z0$7*yJ{Kh^v|*yM05-$ zLHGmW+$W9Tt@i0y4uFY=E%_~bO=ne&&m^06*3>1CRKNx8)1(^jCtUZcH1FvuIex9} zp$}pv9S5NmGYNW5QZTY4nrX6~ua;Tj9@OlL?VOy7QC132hj!uy>b0=&F3vR5$w|p) z#>q;H7_HRkFteQy;R4|`%Z_`h`k?rCza>6KRR{j|YL~imYN*Bhpw;eO{J-HFm&{Ii zQ~rcmL#RNrg4PS3gN*2~IBfX&x)4q?0F7T|vHm^v1DGys00v({qW_J>#XXeo%W4q% zU=<3U8TuU1df1Hi+R8?ynuX#l90*-BD$H9&Zgm#10CFgQ&ENK-v}}K*CvMZ7>AjS~O}UJ6;cGw1Wb8U4^)_kmJVHdp zYdWkl@DlNeM2F9lv3VY%Xph17D%)9E78VdM%lWhv8sC;S{Qv(mhEnRZ(mkrTni@fA zeFQ`<(KYq`^-@LcEX+NnuT~-Q?5xTXDYN*01?>&;%X<`v%Q5QLu~N|w&ELyv5Za12 z2d_ZT`C1yYpApH>^y@pW&%z>e;pZHw0UEs-nCpU2*#+2Sw-L=P^+~Al4O~Q?ee5f# zcl4VOYGJ;H5Z)xC<*Y;s&q(Lt<7+y4sK%h>UjF41smUl;{p|q{(DNC}4!#q*%B3 zZPy8@!hvR1P}4}~=v0MPnR7j6Am^^S1LCi3#b0-?=?SQd@z0-M8n}C-t6zq!=cFQc z(=1T!&Va<-$7J6VFA&o%JtjP#&juNnQuWbN!#SE^J z>b|NG*v)>zwCn|Xe@HwHPl=a350`uWC0!QR>p^*6c7xD{P)5YmWJIj^B_!KHDB-ng zx`d4pNe}jCV4KZ5NI9}==M~PT?rMe!R77)d? zrV*=Ag!|4&CVJNFEIS(xOKsaBV^}((s=<$j$!`jOh-wFi@Vx-j-Mb`be-vzRJL@Fh zeP1BvapNL4`=BoMl5>TtT9_ga%VGvV+^gCv1&#ApY%|8{^Vi)KC3;XgZn^4tUkqY# z<+X$9p&E^Y>xPR1T79XBUyI9G?!AuYX%6VNBJokEOeIwys z);u{|AzP)3I#~074uW{51do002ov JPDHLkV1m_3k;?!8 literal 0 HcmV?d00001 diff --git a/assets/images/shamCash.png b/assets/images/shamCash.png new file mode 100644 index 0000000000000000000000000000000000000000..ab13ac0d8dab390da5bec7a3502be5ba1a6bdc51 GIT binary patch literal 18950 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

jo*Up&{&#v&bLvDu==5X}Z&U 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 literal 0 HcmV?d00001 diff --git a/lib/constant/box_name.dart b/lib/constant/box_name.dart index c79b822..ffddc57 100755 --- a/lib/constant/box_name.dart +++ b/lib/constant/box_name.dart @@ -11,6 +11,7 @@ class BoxName { "rideArgumentsFromBackground"; static const String FCM_PRIVATE_KEY = "FCM_PRIVATE_KEY"; static const String hmac = "hmac"; + static const String walletType = "walletType"; static const String fingerPrint = "fingerPrint"; static const String updateInterval = "updateInterval"; static const String payMobApikey = "payMobApikey"; diff --git a/lib/constant/links.dart b/lib/constant/links.dart index 3c83edc..ca5882f 100755 --- a/lib/constant/links.dart +++ b/lib/constant/links.dart @@ -47,6 +47,8 @@ class AppLink { static String getDriverToken = "$ride/firebase/getDriverToken.php"; static String addTokens = "$ride/firebase/add.php"; static String addTokensDriver = "$ride/firebase/addDriver.php"; + static String addTokensDriverWallet = + "$seferPaymentServer/ride/firebase/addDriver.php"; //=======================Wallet=================== static String wallet = '$seferPaymentServer/ride/passengerWallet'; @@ -57,6 +59,10 @@ class AppLink { "$seferPaymentServer/ride/mtn/driver/confirm_payment.php"; static String payWithMTNStart = "$seferPaymentServer/ride/mtn/driver/mtn_start.php"; + static String payWithSyriatelConfirm = + "$seferPaymentServer/ride/syriatel/driver/confirm_payment.php"; + static String payWithSyriatelStart = + "$seferPaymentServer/ride/syriatel/driver/start_payment.php"; static String payWithEcashDriver = "$seferPaymentServer/ride/ecash/driver/payWithEcash.php"; static String payWithEcashPassenger = diff --git a/lib/controller/auth/captin/login_captin_controller.dart b/lib/controller/auth/captin/login_captin_controller.dart index 0a5d852..7297c38 100755 --- a/lib/controller/auth/captin/login_captin_controller.dart +++ b/lib/controller/auth/captin/login_captin_controller.dart @@ -21,6 +21,7 @@ import 'package:location/location.dart'; import '../../../constant/api_key.dart'; import '../../../constant/info.dart'; +import '../../../print.dart'; import '../../../views/auth/captin/otp_page.dart'; import '../../../views/auth/captin/otp_token_page.dart'; import '../../../views/auth/syria/pending_driver_page.dart'; @@ -98,11 +99,10 @@ class LoginDriverController extends GetxController { } isPhoneVerified() async { - var res = await CRUD().post(link: AppLink.isPhoneVerified, payload: { - 'phone_number': box.read( - BoxName.phoneDriver, - ) - }); + var res = await CRUD().post( + link: AppLink.isPhoneVerified, + payload: {'phone_number': box.read(BoxName.phoneDriver)}); + if (res != 'failure') { // Get.offAll(() => SyrianCardAI()); Get.offAll(() => RegistrationView()); @@ -163,8 +163,8 @@ class LoginDriverController extends GetxController { getJWT() async { dev = Platform.isAndroid ? 'android' : 'ios'; - // Log.print( - // 'box.read(BoxName.firstTimeLoadKey): ${box.read(BoxName.firstTimeLoadKey)}'); + Log.print( + 'box.read(BoxName.firstTimeLoadKey): ${box.read(BoxName.firstTimeLoadKey)}'); if (box.read(BoxName.firstTimeLoadKey).toString() != 'false') { var payload = { 'id': box.read(BoxName.driverID) ?? AK.newId, @@ -185,13 +185,6 @@ class LoginDriverController extends GetxController { final jwt = decodedResponse1['jwt']; box.write(BoxName.jwt, c(jwt)); - // await box.write(BoxName.hmac, decodedResponse1['hmac']); - - // await AppInitializer().getAIKey(Driver.payMobApikey); - // await AppInitializer().getAIKey(Driver.FCM_PRIVATE_KEY); - - // await AppInitializer().getAIKey(Driver.initializationVector); - // await AppInitializer().getAIKey(Driver.keyOfApp); // ✅ بعد التأكد أن كل المفاتيح موجودة await EncryptionHelper.initialize(); @@ -206,7 +199,7 @@ class LoginDriverController extends GetxController { 'password': box.read(BoxName.emailDriver), 'aud': '${AK.allowed}$dev', }; - // print(payload); + print(payload); var response1 = await http.post( Uri.parse(AppLink.loginJwtDriver), body: payload, @@ -332,32 +325,30 @@ class LoginDriverController extends GetxController { key: BoxName.fingerPrint, value: fingerPrint.toString()); // print(jsonDecode(token)['data'][0]['token'].toString()); // print(box.read(BoxName.tokenDriver).toString()); - if (email == '962798583052@intaleqapp.com') { - } else { - if (token != 'failure') { - if ((jsonDecode(token)['data'][0]['token'].toString()) != - box.read(BoxName.tokenDriver).toString()) { - await Get.defaultDialog( - barrierDismissible: false, - title: 'Device Change Detected'.tr, - middleText: 'Please verify your identity'.tr, - textConfirm: 'Verify'.tr, - confirmTextColor: Colors.white, - onConfirm: () { - // Get.back(); - // انتقل لصفحة OTP الجديدة - Get.to( - () => OtpVerificationPage( - phone: d['phone'].toString(), - deviceToken: fingerPrint.toString(), - token: token.toString(), - ptoken: - jsonDecode(token)['data'][0]['token'].toString(), - ), - ); - }, - ); - } + + if (token != 'failure') { + if ((jsonDecode(token)['data'][0]['token'].toString()) != + box.read(BoxName.tokenDriver).toString()) { + await Get.defaultDialog( + barrierDismissible: false, + title: 'Device Change Detected'.tr, + middleText: 'Please verify your identity'.tr, + textConfirm: 'Verify'.tr, + confirmTextColor: Colors.white, + onConfirm: () { + // Get.back(); + // انتقل لصفحة OTP الجديدة + Get.to( + () => OtpVerificationPage( + phone: d['phone'].toString(), + deviceToken: fingerPrint.toString(), + token: token.toString(), + ptoken: + jsonDecode(token)['data'][0]['token'].toString(), + ), + ); + }, + ); } } diff --git a/lib/controller/auth/captin/opt_token_controller.dart b/lib/controller/auth/captin/opt_token_controller.dart index c0b10ff..5250026 100644 --- a/lib/controller/auth/captin/opt_token_controller.dart +++ b/lib/controller/auth/captin/opt_token_controller.dart @@ -86,15 +86,28 @@ class OtpVerificationController extends GetxController { }, ); - if (response != 'failure' && response['status'] == 'success') { + if (response != 'failure') { Get.back(); // توجه إلى الصفحة التالية - Get.put(FirebaseMessagesController()).sendNotificationToDriverMAP( + await CRUD().post( + link: + '${AppLink.seferPaymentServer}/auth/token/update_driver_auth.php', + payload: { + 'token': box.read(BoxName.tokenDriver).toString(), + 'fingerPrint': finger.toString(), + 'captain_id': box.read(BoxName.driverID).toString(), + }); + final fcm = Get.isRegistered() + ? Get.find() + : Get.put(FirebaseMessagesController()); + + await fcm.sendNotificationToDriverMAP( 'token change', 'change device'.tr, ptoken.toString(), [], 'cancel.wav', ); + Get.offAll(() => HomeCaptain()); } else { Get.snackbar('Verification Failed', 'OTP is incorrect or expired'); diff --git a/lib/controller/auth/google_sign.dart b/lib/controller/auth/google_sign.dart index 87da615..4b7fd2d 100755 --- a/lib/controller/auth/google_sign.dart +++ b/lib/controller/auth/google_sign.dart @@ -94,22 +94,8 @@ class GoogleSignInHelper { static Future _handleSignOut() async { // Clear stored driver information - - box.remove(BoxName.driverID); - box.remove(BoxName.emailDriver); - box.remove(BoxName.lang); - box.remove(BoxName.nameDriver); - box.remove(BoxName.passengerID); - box.remove(BoxName.phoneDriver); - box.remove(BoxName.tokenFCM); - box.remove(BoxName.tokens); - box.remove(BoxName.carPlate); - box.remove(BoxName.lastNameDriver); - box.remove(BoxName.agreeTerms); - box.remove(BoxName.tokenDriver); - box.remove(BoxName.countryCode); - box.remove(BoxName.accountIdStripeConnect); - box.remove(BoxName.phoneVerified); + box.erase(); + storage.deleteAll(); Get.offAll(OnBoardingPage()); // Perform any additional sign-out tasks or API calls here // For example, you can notify your server about the user sign-out diff --git a/lib/controller/auth/syria/registration_controller.dart b/lib/controller/auth/syria/registration_controller.dart index 3d5ce57..8529253 100644 --- a/lib/controller/auth/syria/registration_controller.dart +++ b/lib/controller/auth/syria/registration_controller.dart @@ -1,18 +1,18 @@ import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:flutter_image_compress/flutter_image_compress.dart'; import 'package:get/get.dart'; import 'package:image_picker/image_picker.dart'; import 'package:image_cropper/image_cropper.dart'; import 'package:image/image.dart' as img; +import 'package:path/path.dart'; import 'package:sefer_driver/constant/links.dart'; import '../../../constant/box_name.dart'; import 'package:path_provider/path_provider.dart'; // --- Final Submission --- -import 'dart:convert'; -import 'dart:io'; +import 'package:path_provider/path_provider.dart' as path_provider; -import 'package:get/get.dart'; import 'package:http/http.dart' as http; import 'package:http_parser/http_parser.dart'; import 'package:mime/mime.dart'; @@ -21,8 +21,10 @@ import '../../../constant/colors.dart'; import '../../../constant/info.dart'; import '../../../main.dart'; import '../../../print.dart'; +import '../../../views/widgets/error_snakbar.dart'; import '../../functions/crud.dart'; import '../../functions/encrypt_decrypt.dart'; +import '../../functions/package_info.dart'; import '../captin/login_captin_controller.dart'; // You can create a simple enum to manage image types @@ -41,6 +43,11 @@ class RegistrationController extends GetxController { // Loading state var isLoading = false.obs; + var isloading = false; + CroppedFile? croppedFile; + final picker = ImagePicker(); + var image; + File? myImage; String? colorHex; // سيُملى من الدروب داون // Form Keys for validation final driverInfoFormKey = GlobalKey(); @@ -233,6 +240,142 @@ class RegistrationController extends GetxController { } } + /// خريطة لتخزين روابط المستندات بعد الرفع + final Map docUrls = { + 'driver_license_front': '', + 'driver_license_back': '', + 'car_license_front': '', + 'car_license_back': '', + }; + + /// التصرّف العام لاختيار/قص/ضغط/رفع الصورة حسب type + Future choosImage(String link, String imageType) async { + try { + final pickedImage = await picker.pickImage( + source: ImageSource.camera, + preferredCameraDevice: CameraDevice.rear, + ); + if (pickedImage == null) return; + + image = File(pickedImage.path); + + final croppedFile = await ImageCropper().cropImage( + sourcePath: image!.path, + uiSettings: [ + AndroidUiSettings( + toolbarTitle: 'Cropper'.tr, + toolbarColor: AppColor.blueColor, + toolbarWidgetColor: AppColor.yellowColor, + initAspectRatio: CropAspectRatioPreset.original, + lockAspectRatio: false, + ), + IOSUiSettings(title: 'Cropper'.tr), + ], + ); + if (croppedFile == null) return; + + // صورة للمعاينة داخل التطبيق + myImage = File(croppedFile.path); + + isloading = true; + update(); + + // ضغط (وأيضاً يمكنك إضافة rotateImageIfNeeded قبل/بعد الضغط إن رغبت) + final File compressedImage = await compressImage(File(croppedFile.path)); + + // تجهيز الحقول + final driverId = box.read(BoxName.driverID); + + final payload = { + 'driverID': driverId, + 'imageType': imageType, // مثال: driver_license_front + }; + + // الرفع وإرجاع الرابط + final String imageUrl = await uploadImage(compressedImage, payload, link); + + // حفظ الرابط محلياً حسب النوع + docUrls[imageType] = imageUrl; + + Log.print('✅ Uploaded $imageType => $imageUrl'); + } catch (e, st) { + Log.print('❌ Error in choosImage: $e\n$st'); + mySnackeBarError('Image Upload Failed'.tr); + } finally { + isloading = false; + update(); + } + } + + /// ترفع الملف وترجع رابط الصورة النهائي كـ String + Future uploadImage( + File file, Map data, String link) async { + final uri = Uri.parse(link); + final request = http.MultipartRequest('POST', uri); + + // الهيدرز (كما عندك) + final headers = { + 'Authorization': + 'Bearer ${r(box.read(BoxName.jwt)).split(AppInformation.addd)[0]}', + 'X-HMAC-Auth': '${box.read(BoxName.hmac)}', + }; + request.headers.addAll(headers); + + // اسم الملف: driverID.jpg (اختياري) + final forcedName = '${box.read(BoxName.driverID) ?? 'image'}.jpg'; + + // إضافة الملف (من المسار مباشرة أسلم من الـ stream) + request.files.add( + await http.MultipartFile.fromPath( + 'image', // تأكد أنه نفس اسم الحقل على السيرفر + file.path, + filename: forcedName, + ), + ); + + // الحقول الإضافية + data.forEach((k, v) => request.fields[k] = v); + + // الإرسال + final streamed = await request.send(); + final res = await http.Response.fromStream(streamed); + + if (res.statusCode != 200) { + throw Exception( + 'Failed to upload image: ${res.statusCode} - ${res.body}'); + } + + // نحاول استخراج رابط الصورة من أكثر من مفتاح محتمل + final body = jsonDecode(res.body); + final String? url = body['url'] ?? + body['file_link'] ?? + body['image_url'] ?? + (body['data'] is Map ? body['data']['url'] : null); + + if (url == null || url.isEmpty) { + // لو السيرفر يرجع هيكل مختلف، عدّل هنا المفتاح حسب استجابتك الفعلية + throw Exception( + 'Upload succeeded but no image URL found in response: ${res.body}'); + } + + return url; + } + + Future compressImage(File file) async { + final dir = await path_provider.getTemporaryDirectory(); + final targetPath = "${dir.absolute.path}/temp.jpg"; + + var result = await FlutterImageCompress.compressAndGetFile( + file.absolute.path, + targetPath, + quality: 70, + minWidth: 1024, + minHeight: 1024, + ); + + return File(result!.path); + } + // دالة رفع إلى السيرفر السوري: ترجع file_url (Signed URL) Future uploadToSyria({ required String docType, @@ -317,30 +460,17 @@ class RegistrationController extends GetxController { } Future submitRegistration() async { - // 1) تحقق من الصور - if (driverLicenseFrontImage == null || - driverLicenseBackImage == null || - carLicenseFrontImage == null || - carLicenseBackImage == null) { - Get.snackbar( - 'Missing Documents'.tr, - 'Please upload all 4 required documents.'.tr, - snackPosition: SnackPosition.BOTTOM, - backgroundColor: Colors.orange, - colorText: Colors.white, - ); - return; - } + // 0) دوال/مساعدات محلية + + // 1) تحقق من وجود الروابط بدل الملفات + final driverFrontUrl = docUrls['driver_license_front']; + final driverBackUrl = docUrls['driver_license_back']; + final carFrontUrl = docUrls['car_license_front']; + final carBackUrl = docUrls['car_license_back']; isLoading.value = true; - // روابط الـ API - final registerUri = - Uri.parse(AppLink.register_driver_and_car); // التسجيل الرئيسي (PHP) - final syrianUploadUri = - // Uri.parse(AppLink.uploadSyrianDocs); // رفع الصور في سوريا - Uri.parse( - 'https://syria.intaleq.xyz/intaleq/auth/syria/uploadSyrianDocs.php'); // رفع الصور في سوريا + final registerUri = Uri.parse(AppLink.register_driver_and_car); final client = http.Client(); try { @@ -349,50 +479,7 @@ class RegistrationController extends GetxController { 'Bearer ${r(box.read(BoxName.jwt)).split(AppInformation.addd)[0]}'; final hmac = '${box.read(BoxName.hmac)}'; - // 2) ارفع الصور أولاً على السيرفر السوري واحصل على روابطها (Signed URLs) - final driverId = (box.read(BoxName.driverID) ?? '').toString(); - - final driverFrontUrl = await uploadToSyria( - docType: 'driver_license_front', - file: driverLicenseFrontImage!, - syrianUploadUri: syrianUploadUri, - authHeader: bearer, - hmacHeader: hmac, - driverId: driverId, - clientOverride: client, - ); - - final driverBackUrl = await uploadToSyria( - docType: 'driver_license_back', - file: driverLicenseBackImage!, - syrianUploadUri: syrianUploadUri, - authHeader: bearer, - hmacHeader: hmac, - driverId: driverId, - clientOverride: client, - ); - - final carFrontUrl = await uploadToSyria( - docType: 'car_license_front', - file: carLicenseFrontImage!, - syrianUploadUri: syrianUploadUri, - authHeader: bearer, - hmacHeader: hmac, - driverId: driverId, - clientOverride: client, - ); - - final carBackUrl = await uploadToSyria( - docType: 'car_license_back', - file: carLicenseBackImage!, - syrianUploadUri: syrianUploadUri, - authHeader: bearer, - hmacHeader: hmac, - driverId: driverId, - clientOverride: client, - ); - - // 3) جهّز طلب التسجيل الرئيسي: نرسل الحقول + روابط الصور (لا نرفع الصور مرة ثانية) + // 2) جهّز طلب التسجيل الرئيسي: حقول فقط + روابط الصور (لا نرفع صور إطلاقًا) final req = http.MultipartRequest('POST', registerUri); req.headers.addAll({ 'Authorization': bearer, @@ -411,18 +498,16 @@ class RegistrationController extends GetxController { _addField( fields, 'password', 'generate_your_password_here'); // عدّل حسب منطقك _addField(fields, 'status', 'yet'); - _addField(fields, 'email', - 'Not specified'); // السيرفر سيحوّلها null ويبني ايميل افتراضي + _addField(fields, 'email', 'Not specified'); _addField(fields, 'gender', 'Male'); // --- Car Data --- - _addField(fields, 'vin', 'yet'); // تم تصحيح الاقتباس + _addField(fields, 'vin', 'yet'); _addField(fields, 'car_plate', carPlateController.text); _addField(fields, 'make', carMakeController.text); _addField(fields, 'model', carModelController.text); _addField(fields, 'year', carYearController.text); - _addField(fields, 'expiration_date', - driverLicenseExpiryController.text); // تم التصحيح + _addField(fields, 'expiration_date', driverLicenseExpiryController.text); _addField(fields, 'color', carColorController.text); _addField(fields, 'fuel', 'Gasoline'); if (colorHex != null && colorHex!.isNotEmpty) { @@ -431,32 +516,32 @@ class RegistrationController extends GetxController { _addField(fields, 'owner', '${firstNameController.text} ${lastNameController.text}'); - // --- روابط الصور الموقّعة من سوريا --- - _addField(fields, 'driver_license_front', driverFrontUrl); - _addField(fields, 'driver_license_back', driverBackUrl); - _addField(fields, 'car_license_front', carFrontUrl); - _addField(fields, 'car_license_back', carBackUrl); + // --- روابط الصور المخزنة مسبقًا --- + _addField(fields, 'driver_license_front', driverFrontUrl!); + _addField(fields, 'driver_license_back', driverBackUrl!); + _addField(fields, 'car_license_front', carFrontUrl!); + _addField(fields, 'car_license_back', carBackUrl!); // أضف الحقول req.fields.addAll(fields); - // 4) الإرسال + // 3) الإرسال final streamed = await client.send(req).timeout(const Duration(seconds: 60)); final resp = await http.Response.fromStream(streamed); - // 5) فحص النتيجة + // 4) فحص النتيجة Map? json; try { json = jsonDecode(resp.body) as Map; } catch (_) {} if (resp.statusCode == 200 && json?['status'] == 'success') { - final driverID = - (json!['data']?['driverID'] ?? json['driverID'])?.toString(); - if (driverID != null && driverID.isNotEmpty) { - box.write(BoxName.driverID, driverID); - } + // final driverID = + // (json!['data']?['driverID'] ?? json['driverID'])?.toString(); + // if (driverID != null && driverID.isNotEmpty) { + // box.write(BoxName.driverID, driverID); + // } Get.snackbar( 'Success'.tr, @@ -466,20 +551,31 @@ class RegistrationController extends GetxController { colorText: Colors.white, ); - // TODO: التنقّل أو تحديث الحالة… - final email = box.read(BoxName.emailDriver) ?? ''; - + // متابعة تسجيل الدخول إن لزم + final email = box.read(BoxName.emailDriver); + final driverID = box.read(BoxName.driverID); final c = Get.isRegistered() ? Get.find() : Get.put(LoginDriverController()); + //token to server + String fingerPrint = await DeviceHelper.getDeviceFingerprint(); + await CRUD().post(link: AppLink.addTokensDriver, payload: { + 'captain_id': (box.read(BoxName.driverID)).toString(), + 'token': (box.read(BoxName.tokenDriver)).toString(), + 'fingerPrint': fingerPrint.toString(), + }); + await CRUD().post(link: AppLink.addTokensDriverWallet, payload: { + 'token': box.read(BoxName.tokenDriver).toString(), + 'fingerPrint': fingerPrint.toString(), + 'captain_id': box.read(BoxName.driverID).toString(), + }); - c.loginWithGoogleCredential(driverId, email); + c.loginWithGoogleCredential(driverID, email); } else { final msg = (json?['message'] ?? 'Registration failed. Please try again.') .toString(); - Log.print('msg: ${msg}'); - + Log.print('msg: $msg'); Get.snackbar( 'Error'.tr, msg, @@ -500,8 +596,7 @@ class RegistrationController extends GetxController { client.close(); isLoading.value = false; } - } - // Future submitRegistration() async { + } // Future submitRegistration() async { // // 1) تحقق من الصور // if (driverLicenseFrontImage == null || // driverLicenseBackImage == null || diff --git a/lib/controller/functions/crud.dart b/lib/controller/functions/crud.dart index cc929f5..d4b80b8 100755 --- a/lib/controller/functions/crud.dart +++ b/lib/controller/functions/crud.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:io'; import 'package:jwt_decoder/jwt_decoder.dart'; import 'package:sefer_driver/controller/functions/network/net_guard.dart'; import 'package:secure_string_operations/secure_string_operations.dart'; @@ -16,6 +17,7 @@ import '../../constant/info.dart'; import '../../views/widgets/error_snakbar.dart'; import '../../print.dart'; import 'gemeni.dart'; +import 'network/connection_check.dart'; import 'upload_image.dart'; class CRUD { @@ -86,24 +88,27 @@ class CRUD { Map? payload, required Map headers, }) async { - // ✅ 1. Check for internet connection before making any request. - if (!await _netGuard.hasInternet(mustReach: Uri.parse(link))) { - // ✅ 2. If no internet, show a notification to the user (only once every 15s). - _netGuard.notifyOnce((title, msg) { - mySnackeBarError( - msg); // Using your existing snackbar for notifications. - }); - // ✅ 3. Return a specific status to indicate no internet. - return 'no_internet'; - } - - var url = Uri.parse(link); try { - var response = await http.post( - url, - body: payload, - headers: headers, + // 1. Wrap the http.post call directly with HttpRetry.sendWithRetry. + // It will attempt the request immediately and retry on transient errors. + var response = await HttpRetry.sendWithRetry( + () { + var url = Uri.parse(link); + return http.post( + url, + body: payload, + headers: headers, + ); + }, + // Optional: you can customize retry behavior for each call + maxRetries: 3, + timeout: const Duration(seconds: 15), ); + // Log.print('response: ${response.body}'); + // Log.print('request: ${response.request}'); + // Log.print('payload: ${payload}'); + // ✅ All your existing logic for handling server responses remains the same. + // This part is only reached if the network request itself was successful. // Handle successful response (200 OK) if (response.statusCode == 200) { @@ -112,16 +117,18 @@ class CRUD { if (jsonData['status'] == 'success') { return jsonData; // Return the full JSON object on success } else { - // The API reported a logical failure (e.g., validation error) - addError( - 'API Logic Error: ${jsonData['status']}', - 'Response: ${response.body}', - 'CRUD._makeRequest - $link', - ); + if (jsonData['status'] == 'failure') { + // return 'failure'; + } else { + addError( + 'API Logic Error: ${jsonData['status']}', + 'Response: ${response.body}', + 'CRUD._makeRequest - $link', + ); + } return jsonData['status']; // Return the specific status string } } catch (e, stackTrace) { - // Error decoding the JSON response from the server addError( 'JSON Decode Error: $e', 'Response Body: ${response.body}\nStack Trace: $stackTrace', @@ -130,20 +137,13 @@ class CRUD { return 'failure'; } } - // Handle Unauthorized (401) - typically means token expired + // Handle Unauthorized (401) else if (response.statusCode == 401) { var jsonData = jsonDecode(response.body); if (jsonData['error'] == 'Token expired') { - // The token refresh logic is handled before the call, - // but we log this case if it still happens. - // addError( - // 'Token Expired', - // 'A new token should have been fetched before this call.', - // 'CRUD._makeRequest - $link', - // ); + await Get.put(LoginDriverController()).getJWT(); return 'token_expired'; } else { - // Other 401 errors (e.g., invalid token) addError( 'Unauthorized Error: ${jsonData['error']}', 'Status Code: 401', @@ -161,8 +161,14 @@ class CRUD { ); return 'failure'; } + } on SocketException { + // 2. This block now catches the "no internet" case after all retries have failed. + _netGuard.notifyOnce((title, msg) { + mySnackeBarError(msg); + }); + return 'no_internet'; // Return the specific status you were using before. } catch (e, stackTrace) { - // Handle network exceptions (e.g., no internet, DNS error) + // 3. This is a general catch-all for any other unexpected errors. addError( 'HTTP Request Exception: $e', 'Stack Trace: $stackTrace', @@ -177,15 +183,15 @@ class CRUD { Map? payload, }) async { // 1. Check if the token is expired - bool isTokenExpired = JwtDecoder.isExpired(X - .r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs) - .toString() - .split(AppInformation.addd)[0]); + // bool isTokenExpired = JwtDecoder.isExpired(X + // .r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs) + // .toString() + // .split(AppInformation.addd)[0]); - // 2. If expired, get a new one - if (isTokenExpired) { - await LoginDriverController().getJWT(); - } + // // 2. If expired, get a new one + // if (isTokenExpired) { + // await LoginDriverController().getJWT(); + // } // 3. Prepare the headers with the valid token final headers = { @@ -303,15 +309,15 @@ class CRUD { required String link, Map? payload, }) async { - bool isTokenExpired = JwtDecoder.isExpired(X - .r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs) - .toString() - .split(AppInformation.addd)[0]); - // Log.print('isTokenExpired: ${isTokenExpired}'); + // bool isTokenExpired = JwtDecoder.isExpired(X + // .r(X.r(X.r(box.read(BoxName.jwt), cn), cC), cs) + // .toString() + // .split(AppInformation.addd)[0]); + // // Log.print('isTokenExpired: ${isTokenExpired}'); - if (isTokenExpired) { - await LoginDriverController().getJWT(); - } + // if (isTokenExpired) { + // await LoginDriverController().getJWT(); + // } // await Get.put(LoginDriverController()).getJWT(); var url = Uri.parse( link, diff --git a/lib/controller/functions/location_controller.dart b/lib/controller/functions/location_controller.dart index 995e297..9203038 100755 --- a/lib/controller/functions/location_controller.dart +++ b/lib/controller/functions/location_controller.dart @@ -109,8 +109,7 @@ class LocationController extends GetxController { // ✅ تحديث للسيرفر await CRUD().post( - link: - box.read(BoxName.serverChosen) + '/ride/location/update.php', + link: '${AppLink.server}/ride/location/update.php', payload: payload, ); @@ -141,7 +140,7 @@ class LocationController extends GetxController { if (_insertCounter == 12) { _insertCounter = 0; await CRUD().post( - link: box.read(BoxName.serverChosen) + '/ride/location/add.php', + link: '${AppLink.server}/ride/location/add.php', payload: payload, ); } diff --git a/lib/controller/functions/overlay_permisssion.dart b/lib/controller/functions/overlay_permisssion.dart index 7e79057..a086d27 100755 --- a/lib/controller/functions/overlay_permisssion.dart +++ b/lib/controller/functions/overlay_permisssion.dart @@ -35,13 +35,13 @@ Future showDriverGiftClaim(BuildContext context) async { if (box.read(BoxName.is_claimed).toString() == '0' || box.read(BoxName.is_claimed) == null) { MyDialog().getDialog( - 'You have gift 300 L.E'.tr, 'This for new registration'.tr, () async { + 'You have gift 30000 SYP'.tr, 'This for new registration'.tr, () async { var res = await CRUD().post(link: AppLink.updateDriverClaim, payload: { 'driverId': box.read(BoxName.driverID), }); if (res != 'failure') { Get.find() - .addDriverWallet('new driver', '300', '300'); + .addDriverWallet('new driver', '30000', '30000'); Confetti.launch( context, options: diff --git a/lib/controller/functions/sms_egypt_controller.dart b/lib/controller/functions/sms_egypt_controller.dart index b85c30e..1ae9f2c 100755 --- a/lib/controller/functions/sms_egypt_controller.dart +++ b/lib/controller/functions/sms_egypt_controller.dart @@ -77,7 +77,7 @@ class SmsEgyptController extends GetxController { var res = await http.post( Uri.parse(AppLink.checkCredit), body: { - "username": AppInformation.appName, + "username": 'Sefer', "password": AK.smsPasswordEgypt, "message": "This is an example SMS message.", "language": box.read(BoxName.lang) == 'en' ? "e" : 'r', diff --git a/lib/controller/home/captin/home_captain_controller.dart b/lib/controller/home/captin/home_captain_controller.dart index 5d0bf2f..6af4a3c 100755 --- a/lib/controller/home/captin/home_captain_controller.dart +++ b/lib/controller/home/captin/home_captain_controller.dart @@ -426,9 +426,14 @@ class HomeCaptainController extends GetxController { var res = await CRUD().get( link: AppLink.getAllPaymentFromRide, payload: {'driverID': box.read(BoxName.driverID).toString()}); - data = jsonDecode(res); + if (res == 'failure') { + totalMoneyInSEFER = '0'; + } else { + data = jsonDecode(res); + + totalMoneyInSEFER = data['message'][0]['total_amount']; + } - totalMoneyInSEFER = data['message'][0]['total_amount'] ?? '0'; update(); } diff --git a/lib/controller/home/captin/map_driver_controller.dart b/lib/controller/home/captin/map_driver_controller.dart index 1387d23..e649ea4 100755 --- a/lib/controller/home/captin/map_driver_controller.dart +++ b/lib/controller/home/captin/map_driver_controller.dart @@ -331,13 +331,7 @@ class MapDriverController extends GetxController { 'driverGoToPassengerTime': DateTime.now().toString(), 'status': 'Applied' }); - if (AppLink.endPoint != AppLink.seferCairoServer) { - CRUD().post(link: "${AppLink.endPoint}/ride/rides/update.php", payload: { - 'id': (rideId), - 'driverGoToPassengerTime': DateTime.now().toString(), - 'status': 'Applied' - }); - } + // Get.find().changeToAppliedRide('Applied'); Get.find().sendNotificationToDriverMAP( diff --git a/lib/controller/home/captin/navigation_service.dart b/lib/controller/home/captin/navigation_service.dart new file mode 100644 index 0000000..83120aa --- /dev/null +++ b/lib/controller/home/captin/navigation_service.dart @@ -0,0 +1,112 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:google_maps_flutter/google_maps_flutter.dart'; +import 'package:google_polyline_algorithm/google_polyline_algorithm.dart'; +import 'package:sefer_driver/constant/api_key.dart'; +import 'package:sefer_driver/constant/box_name.dart'; +import 'package:sefer_driver/constant/links.dart'; +import 'package:sefer_driver/controller/functions/crud.dart'; +import 'package:sefer_driver/controller/functions/tts.dart'; + +import '../../../main.dart'; + +/// Handles map-related logic: fetching routes, drawing polylines, and managing markers. +class NavigationService extends GetxService { + final CRUD _crud = CRUD(); + final TextToSpeechController _tts = Get.put(TextToSpeechController()); + + final RxSet markers = {}.obs; + final RxSet polylines = {}.obs; + final RxString currentInstruction = "".obs; + + BitmapDescriptor carIcon = BitmapDescriptor.defaultMarker; + BitmapDescriptor passengerIcon = BitmapDescriptor.defaultMarker; + BitmapDescriptor startIcon = BitmapDescriptor.defaultMarker; + BitmapDescriptor endIcon = BitmapDescriptor.defaultMarker; + + @override + void onInit() { + super.onInit(); + _loadCustomIcons(); + } + + void _loadCustomIcons() async { + carIcon = await _createBitmapDescriptor('assets/images/car.png'); + passengerIcon = await _createBitmapDescriptor('assets/images/picker.png'); + startIcon = await _createBitmapDescriptor('assets/images/A.png'); + endIcon = await _createBitmapDescriptor('assets/images/b.png'); + } + + Future _createBitmapDescriptor(String assetName) { + return BitmapDescriptor.fromAssetImage( + ImageConfiguration( + size: const Size(30, 35), devicePixelRatio: Get.pixelRatio), + assetName, + ); + } + + Future?> getRoute({ + required LatLng origin, + required LatLng destination, + }) async { + final url = + '${AppLink.googleMapsLink}directions/json?language=${box.read(BoxName.lang)}&destination=${destination.latitude},${destination.longitude}&origin=${origin.latitude},${origin.longitude}&key=${AK.mapAPIKEY}'; + + final response = await _crud.getGoogleApi(link: url, payload: {}); + + if (response != null && response['routes'].isNotEmpty) { + return response['routes'][0]; + } + return null; + } + + void drawRoute(Map routeData, {Color color = Colors.blue}) { + final pointsString = routeData["overview_polyline"]["points"]; + final points = decodePolyline(pointsString) + .map((p) => LatLng(p[0].toDouble(), p[1].toDouble())) + .toList(); + + final polyline = Polyline( + polylineId: PolylineId(routeData["summary"] ?? DateTime.now().toString()), + points: points, + width: 8, + color: color, + ); + + polylines.add(polyline); + } + + void updateCarMarker(LatLng position, double heading) { + markers.removeWhere((m) => m.markerId.value == 'MyLocation'); + markers.add( + Marker( + markerId: MarkerId('MyLocation'.tr), + position: position, + icon: carIcon, + rotation: heading, + anchor: const Offset(0.5, 0.5), + flat: true, + ), + ); + } + + void setInitialMarkers( + LatLng passengerLocation, LatLng passengerDestination) { + markers.clear(); + markers.add(Marker( + markerId: const MarkerId('passengerLocation'), + position: passengerLocation, + icon: passengerIcon, + )); + markers.add(Marker( + markerId: const MarkerId('passengerDestination'), + position: passengerDestination, + icon: endIcon, + )); + } + + void clearRoutes() { + polylines.clear(); + currentInstruction.value = ""; + } +} diff --git a/lib/controller/home/navigation/navigation_controller.dart b/lib/controller/home/navigation/navigation_controller.dart index 2429160..6dd569a 100644 --- a/lib/controller/home/navigation/navigation_controller.dart +++ b/lib/controller/home/navigation/navigation_controller.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:math'; +import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:get/get.dart'; @@ -10,6 +11,7 @@ import 'package:sefer_driver/constant/colors.dart'; // استخدام نفس مسارات الاستيراد التي قدمتها import '../../../constant/api_key.dart'; import '../../../constant/links.dart'; +import '../../../print.dart'; import '../../functions/crud.dart'; import '../../functions/tts.dart'; @@ -525,45 +527,127 @@ class NavigationController extends GetxController { String _parseInstruction(String html) => html.replaceAll(RegExp(r'<[^>]*>'), ' '); + double _haversineKm(double lat1, double lon1, double lat2, double lon2) { + const R = 6371.0; // km + final dLat = (lat2 - lat1) * math.pi / 180.0; + final dLon = (lon2 - lon1) * math.pi / 180.0; + final a = math.sin(dLat / 2) * math.sin(dLat / 2) + + math.cos(lat1 * math.pi / 180.0) * + math.cos(lat2 * math.pi / 180.0) * + math.sin(dLon / 2) * + math.sin(dLon / 2); + final c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)); + return R * c; + } + + /// تحويل نصف قطر بالكيلومتر إلى دلتا درجات عرض + double _kmToLatDelta(double km) => km / 111.0; + + /// تحويل نصف قطر بالكيلومتر إلى دلتا درجات طول (تعتمد على خط العرض) + double _kmToLngDelta(double km, double atLat) => + km / (111.320 * math.cos(atLat * math.pi / 180.0)).abs().clamp(1e-6, 1e9); + + /// حساب درجة التطابق النصي (كل كلمة تبدأ بها الاسم = 2 نقاط، يحتويها = 1 نقطة) + double _relevanceScore(String name, String query) { + final n = name.toLowerCase(); + final parts = + query.toLowerCase().split(RegExp(r'\s+')).where((p) => p.length >= 2); + double s = 0.0; + for (final p in parts) { + if (n.startsWith(p)) { + s += 2.0; + } else if (n.contains(p)) { + s += 1.0; + } + } + return s; + } + Future getPlaces() async { - if (placeDestinationController.text.trim().isEmpty) { + final q = placeDestinationController.text.trim(); + if (q.isEmpty) { placesDestination = []; update(); return; } - if (myLocation == null) { - Get.snackbar('انتظر', 'جاري تحديد موقعك الحالي...'); - return; - } - final query = placeDestinationController.text.trim(); + final lat = myLocation!.latitude; final lng = myLocation!.longitude; - const double range = 2.2; - final lat_min = lat - range, - lat_max = lat + range, - lng_min = lng - range, - lng_max = lng + range; + + // نصف قطر البحث بالكيلومتر (عدّل حسب رغبتك) + const radiusKm = 200.0; + + // حساب الباوند الصحيح (درجات، وليس 2.2 درجة ثابتة) + final latDelta = _kmToLatDelta(radiusKm); + final lngDelta = _kmToLngDelta(radiusKm, lat); + + final latMin = lat - latDelta; + final latMax = lat + latDelta; + final lngMin = lng - lngDelta; + final lngMax = lng + lngDelta; try { final response = await CRUD().post( link: AppLink.getPlacesSyria, payload: { - 'query': query, - 'lat_min': lat_min.toString(), - 'lat_max': lat_max.toString(), - 'lng_min': lng_min.toString(), - 'lng_max': lng_max.toString(), + 'query': q, + 'lat_min': latMin.toString(), + 'lat_max': latMax.toString(), + 'lng_min': lngMin.toString(), + 'lng_max': lngMax.toString(), }, ); - if (response != 'failure') { - placesDestination = response['message'] ?? []; + + // يدعم شكلي استجابة: إما {"...","message":[...]} أو قائمة مباشرة [...] + List list; + if (response is Map && response['message'] is List) { + list = List.from(response['message'] as List); + } else if (response is List) { + list = List.from(response); } else { - placesDestination = []; + print('Unexpected response shape'); + return; } + + // جهّز الحقول المحتملة للأسماء + String _bestName(Map p) { + return (p['name'] ?? p['name_ar'] ?? p['name_en'] ?? '').toString(); + } + + // احسب المسافة ودرجة التطابق والنقاط + for (final p in list) { + final plat = double.tryParse(p['latitude']?.toString() ?? '') ?? 0.0; + final plng = double.tryParse(p['longitude']?.toString() ?? '') ?? 0.0; + + final d = _haversineKm(lat, lng, plat, plng); + final rel = _relevanceScore(_bestName(p), q); + + // معادلة ترتيب ذكية: مسافة أقل + تطابق أعلى = نقاط أعلى + // تضيف +1 لضمان عدم وصول الوزن للصفر عند عدم وجود تطابق + final score = (1.0 / (1.0 + d)) * (1.0 + rel); + + p['distanceKm'] = d; + p['relevance'] = rel; + p['score'] = score; + } + + // رتّب حسب score تنازليًا، ثم المسافة تصاعديًا كحسم + list.sort((a, b) { + final sa = (a['score'] ?? 0.0) as double; + final sb = (b['score'] ?? 0.0) as double; + final cmp = sb.compareTo(sa); + if (cmp != 0) return cmp; + final da = (a['distanceKm'] ?? 1e9) as double; + final db = (b['distanceKm'] ?? 1e9) as double; + return da.compareTo(db); + }); + + // خذ أول 10–15 للعرض (اختياري)، أو اعرض الكل + placesDestination = list.take(15).toList(); + Log.print('placesDestination: $placesDestination'); + update(); } catch (e) { print('Exception in getPlaces: $e'); - } finally { - update(); } } diff --git a/lib/controller/home/payment/paymob_payout.dart b/lib/controller/home/payment/paymob_payout.dart index 64bb3dd..f29e9e1 100755 --- a/lib/controller/home/payment/paymob_payout.dart +++ b/lib/controller/home/payment/paymob_payout.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:local_auth/local_auth.dart'; import 'package:sefer_driver/constant/box_name.dart'; +import 'package:sefer_driver/controller/payment/smsPaymnet/payment_services.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/widgets/error_snakbar.dart'; import 'package:get/get.dart'; @@ -27,48 +28,48 @@ class PaymobPayout extends GetxController { sensitiveTransaction: true, )); if (didAuthenticate) { - var dec = await CRUD() - .postWallet(link: AppLink.paymobPayoutDriverWallet, payload: { - "issuer": issuer, - "method": "wallet", - "amount": amount, //9.0, - "full_name": - '${box.read(BoxName.nameDriver)} ${box.read(BoxName.lastNameDriver)}', - "msisdn": msisdn, //"01010101010", - "bank_transaction_type": "cash_transfer" - }); - if (dec['disbursement_status'] == 'successful') { - var paymentToken = await Get.find() - .generateToken( - ((-1) * (double.parse(dec['amount'].toString())) - payOutFee) - .toStringAsFixed(0)); - await CRUD().postWallet(link: AppLink.addDrivePayment, payload: { - 'rideId': DateTime.now().toIso8601String(), - 'amount': - ((-1) * (double.parse(dec['amount'].toString())) - payOutFee) - .toStringAsFixed(0), - 'payment_method': 'payout', - 'passengerID': 'myself', - 'token': paymentToken, - 'driverID': box.read(BoxName.driverID).toString(), - }); - await Get.find() - .addSeferWallet('payout fee myself', payOutFee.toString()); - await updatePaymentToPaid(box.read(BoxName.driverID).toString()); - await sendEmail( - box.read(BoxName.driverID).toString(), - amount, - box.read(BoxName.phoneDriver).toString(), - box.read(BoxName.nameDriver).toString(), - 'Wallet', - box.read(BoxName.emailDriver).toString()); + // var dec = await CRUD() + // .postWallet(link: AppLink.paymobPayoutDriverWallet, payload: { + // "issuer": issuer, + // "method": "wallet", + // "amount": amount, //9.0, + // "full_name": + // '${box.read(BoxName.nameDriver)} ${box.read(BoxName.lastNameDriver)}', + // "msisdn": msisdn, //"01010101010", + // "bank_transaction_type": "cash_transfer" + // }); + // if (dec['disbursement_status'] == 'successful') { + // var paymentToken = await Get.find() + // .generateToken( + // ((-1) * (double.parse(dec['amount'].toString())) - payOutFee) + // .toStringAsFixed(0)); + // await CRUD().postWallet(link: AppLink.addDrivePayment, payload: { + // 'rideId': DateTime.now().toIso8601String(), + // 'amount': + // ((-1) * (double.parse(dec['amount'].toString())) - payOutFee) + // .toStringAsFixed(0), + // 'payment_method': 'payout', + // 'passengerID': 'myself', + // 'token': paymentToken, + // 'driverID': box.read(BoxName.driverID).toString(), + // }); + // await Get.find() + // .addSeferWallet('payout fee myself', payOutFee.toString()); + // await updatePaymentToPaid(box.read(BoxName.driverID).toString()); + // await sendEmail( + // box.read(BoxName.driverID).toString(), + // amount, + // box.read(BoxName.phoneDriver).toString(), + // box.read(BoxName.nameDriver).toString(), + // 'Wallet', + // box.read(BoxName.emailDriver).toString()); - mySnackbarSuccess('${'Transaction successful'.tr} ${dec['amount']}'); + // mySnackbarSuccess('${'Transaction successful'.tr} ${dec['amount']}'); - Get.find().refreshCaptainWallet(); - } else if (dec['disbursement_status'] == 'failed') { - mySnackeBarError('Transaction failed'.tr); - } + // Get.find().refreshCaptainWallet(); + // } else if (dec['disbursement_status'] == 'failed') { + // mySnackeBarError('Transaction failed'.tr); + // } } else { MyDialog().getDialog('Authentication failed'.tr, ''.tr, () { Get.back(); diff --git a/lib/controller/home/splash_screen_controlle.dart b/lib/controller/home/splash_screen_controlle.dart index 12770e0..52ad424 100755 --- a/lib/controller/home/splash_screen_controlle.dart +++ b/lib/controller/home/splash_screen_controlle.dart @@ -63,7 +63,7 @@ class SplashScreenController extends GetxController box.read(BoxName.onBoarding) == null ? Get.off(() => OnBoardingPage()) : box.read(BoxName.phoneDriver) != null && - box.read(BoxName.phoneVerified) == '1' + box.read(BoxName.phoneVerified).toString() == '1' ? await Get.put(LoginDriverController()) .loginWithGoogleCredential( box.read(BoxName.driverID).toString(), diff --git a/lib/controller/local/translations.dart b/lib/controller/local/translations.dart index 741aaa9..4ab672f 100755 --- a/lib/controller/local/translations.dart +++ b/lib/controller/local/translations.dart @@ -35,6 +35,8 @@ class MyTranslation extends Translations { "نأسف لإعلامك بأن سائقًا آخر قد قبل هذا الطلب.", "Driver Applied the Ride for You": "السائق قدم الطلب لك", "Applied": "تم التقديم", + 'Pay by Sham Cash': 'الدفع عبر شام كاش', + 'Pay with Debit Card': 'الدفع ببطاقة الخصم', "Please go to Car Driver": "يرجى الذهاب إلى سائق السيارة", "Ok I will go now.": "حسنًا، سأذهب الآن.", "Accepted Ride": "تم قبول الرحلة", @@ -84,6 +86,8 @@ class MyTranslation extends Translations { "Password must be at least 6 characters": "يجب أن تتكون كلمة المرور من 6 أحرف على الأقل", "Create Account": "إنشاء حساب", + 'Pay by MTN Wallet': 'الدفع عبر محفظة MTN', + 'Pay by Syriatel Wallet': 'الدفع عبر محفظة سيريتل', "Login": "تسجيل الدخول", "Back to other sign-in options": "العودة إلى خيارات التسجيل الأخرى", "Driver Agreement": "اتفاقية السائق", @@ -93,7 +97,11 @@ class MyTranslation extends Translations { " and acknowledge our Privacy Policy.": " والإقرار بسياسة الخصوصية الخاصة بنا.", "I Agree": "أنا أوافق", - "Continue": "متابعة", + "Continue": "متابعة", "Customer not found": "العميل غير موجود", + "Wallet is blocked": "المحفظة محظورة", + "Customer phone is not active": "هاتف العميل غير نشط", + "Balance not enough": "الرصيد غير كافٍ", + "Balance limit exceeded": "تم تجاوز حد الرصيد", "Privacy Policy": "سياسة الخصوصية", "Location Access Required": "مطلوب الوصول إلى الموقع", "We need access to your location to match you with nearby passengers and provide accurate navigation.": @@ -383,6 +391,7 @@ Raih Gai: For same-day return trips longer than 50km. "Driver's Personal Information": "المعلومات الشخصية للسائق", "First Name": "الاسم الأول", "Last Name": "اسم العائلة", + 'You have gift 30000 SYP': 'لديك هدية 30000 ليرة سورية', "National ID Number": "الرقم الوطني", "License Expiry Date": "تاريخ انتهاء الرخصة", "YYYY-MM-DD": "YYYY-MM-DD", diff --git a/lib/controller/payment/smsPaymnet/pay_out_syria_controller.dart b/lib/controller/payment/smsPaymnet/pay_out_syria_controller.dart new file mode 100644 index 0000000..c5d7c71 --- /dev/null +++ b/lib/controller/payment/smsPaymnet/pay_out_syria_controller.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:sefer_driver/controller/functions/crud.dart'; + +class PayoutService { + final String _baseUrl = + "https://walletintaleq.intaleq.xyz/v1/main/sms_webhook"; + static const double payoutFee = 5000.0; // عمولة السحب الثابتة + + /// دالة لإنشاء طلب سحب جديد على السيرفر + /// + /// تعيد رسالة النجاح من السيرفر، أو رسالة خطأ في حال الفشل. + Future requestPayout({ + required String driverId, + walletType, + payoutPhoneNumber, + required double amount, + }) async { + final url = ("$_baseUrl/request_payout.php"); + try { + // هنا يمكنك إضافة هيدرز المصادقة (JWT) بنفس طريقتك المعتادة + final response = await CRUD().postWallet(link: url, payload: { + 'driverId': driverId, + 'amount': amount.toString(), + 'phone': payoutPhoneNumber.toString(), + 'wallet_type': walletType.toString(), + }).timeout(const Duration(seconds: 20)); + + if (response != 'failure') { + final data = (response); + if (data['status'] == 'success') { + debugPrint("Payout request successful: ${data['message']}"); + return data['message']; // إرجاع رسالة النجاح + } else { + debugPrint("Payout request failed: ${data['message']}"); + return "فشل الطلب: ${data['message']}"; // إرجاع رسالة الخطأ من السيرفر + } + } else { + return "خطأ في الاتصال بالسيرفر: ${response.statusCode}"; + } + } catch (e) { + debugPrint("Exception during payout request: $e"); + return "حدث خطأ غير متوقع. يرجى المحاولة مرة أخرى."; + } + } +} diff --git a/lib/controller/payment/smsPaymnet/payment_services.dart b/lib/controller/payment/smsPaymnet/payment_services.dart new file mode 100644 index 0000000..1b37802 --- /dev/null +++ b/lib/controller/payment/smsPaymnet/payment_services.dart @@ -0,0 +1,397 @@ +// لإضافة هذه الحزمة، قم بتشغيل الأمر التالي في الـ Terminal +// flutter pub add intl + +import 'dart:async'; +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:http/http.dart' as http; +import 'package:intl/intl.dart'; +import 'package:sefer_driver/constant/links.dart'; +import 'package:sefer_driver/controller/functions/crud.dart'; + +import '../../../constant/box_name.dart'; +import '../../../main.dart'; + +/// خدمة لإدارة عمليات الدفع المتعلقة بنظام الدفع عبر الرسائل القصيرة +class PaymentService { + final String _baseUrl = "${AppLink.seferPaymentServer}/sms_webhook"; + + Future createInvoice({ + required String userPhone, + required double amount, + }) async { + final url = "$_baseUrl/create_invoice.php"; + try { + final response = await CRUD().postWallet( + link: url, + payload: { + 'user_phone': userPhone.toString(), + 'driverID': box.read(BoxName.driverID), + 'amount': amount.toString(), + }, + ).timeout(const Duration(seconds: 15)); // إضافة مهلة للطلب + + if (response != 'failure') { + final data = (response); + if (data['status'] == 'success' && data['invoice_number'] != null) { + debugPrint( + "تم إنشاء الفاتورة بنجاح. الرقم: ${data['invoice_number']}"); + return data['invoice_number'].toString(); + } else { + debugPrint("فشل في إنشاء الفاتورة من السيرفر: ${data['message']}"); + return null; + } + } else { + debugPrint("خطأ في السيرفر عند إنشاء الفاتورة: ${response.statusCode}"); + return null; + } + } catch (e) { + debugPrint("حدث استثناء عند إنشاء الفاتورة: $e"); + return null; + } + } + + /// دالة للتحقق من حالة فاتورة واحدة + Future checkInvoiceStatus(String invoiceNumber) async { + final url = "$_baseUrl/check_invoice_status.php"; + try { + final response = await CRUD().postWallet(link: url, payload: { + 'invoice_number': invoiceNumber, + }).timeout(const Duration(seconds: 10)); // مهلة للشبكة + + if (response != 'failure') { + final data = (response); + return data['status'] == 'success' && + data['invoice_status'] == 'completed'; + } + return false; + } catch (e) { + debugPrint("خطأ أثناء التحقق من الفاتورة: $e"); + return false; + } + } +} + +enum PaymentStatus { + creatingInvoice, + waitingForPayment, + paymentSuccess, + paymentTimeout, + paymentError +} + +class PaymentScreenSmsProvider extends StatefulWidget { + final double amount; + final String providerName; + final String providerLogo; + final String paymentPhoneNumber; + + const PaymentScreenSmsProvider({ + super.key, + required this.amount, + this.providerName = 'شام كاش', + this.providerLogo = 'assets/images/shamCash.png', + this.paymentPhoneNumber = '963942542053', + }); + + @override + _PaymentScreenSmsProviderState createState() => + _PaymentScreenSmsProviderState(); +} + +class _PaymentScreenSmsProviderState extends State { + final PaymentService _paymentService = PaymentService(); + Timer? _pollingTimer; + PaymentStatus _status = PaymentStatus.creatingInvoice; + String? _invoiceNumber; + final String phone = box.read(BoxName.phoneWallet); + + @override + void initState() { + super.initState(); + _createAndPollInvoice(); + } + + @override + void dispose() { + _pollingTimer?.cancel(); // مهم جداً: إلغاء المؤقت عند الخروج من الشاشة + super.dispose(); + } + + void _createAndPollInvoice() async { + setState(() => _status = PaymentStatus.creatingInvoice); + + final invoiceNumber = await _paymentService.createInvoice( + userPhone: phone, + amount: widget.amount, + ); + + if (invoiceNumber != null && mounted) { + setState(() { + _invoiceNumber = invoiceNumber; + _status = PaymentStatus.waitingForPayment; + }); + _startPolling(invoiceNumber); + } else if (mounted) { + setState(() => _status = PaymentStatus.paymentError); + } + } + + void _startPolling(String invoiceNumber) { + const timeoutDuration = Duration(minutes: 3); + var elapsed = Duration.zero; + + _pollingTimer = Timer.periodic(const Duration(seconds: 5), (timer) async { + elapsed += const Duration(seconds: 5); + if (elapsed >= timeoutDuration) { + timer.cancel(); + if (mounted) setState(() => _status = PaymentStatus.paymentTimeout); + return; + } + + debugPrint("Polling... Checking invoice status for: $invoiceNumber"); + final isCompleted = + await _paymentService.checkInvoiceStatus(invoiceNumber); + if (isCompleted && mounted) { + timer.cancel(); + setState(() => _status = PaymentStatus.paymentSuccess); + // TODO: تحديث رصيد المستخدم أو تنفيذ الإجراءات اللازمة + } + }); + } + + /// دالة جديدة لمعالجة محاولة الرجوع للخلف + void _onPopInvoked(bool didPop) async { + // إذا كان الرجوع قد تم بالفعل (مثلاً من خلال Navigator.pop)، لا تفعل شيئاً + if (didPop) return; + + // إذا كان المستخدم ينتظر الدفع، أظهر له حوار التأكيد + if (_status == PaymentStatus.waitingForPayment) { + final shouldPop = await showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('هل أنت متأكد؟'), + content: const Text('إذا خرجت الآن، سيتم إلغاء عملية الدفع الحالية.'), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: const Text('البقاء'), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(true), + child: const Text('الخروج'), + ), + ], + ), + ); + + // إذا وافق المستخدم على الخروج، قم بإغلاق الشاشة + if (shouldPop ?? false) { + Navigator.of(context).pop(); + } + } + } + + @override + Widget build(BuildContext context) { + // استخدام PopScope بدلاً من WillPopScope + return PopScope( + // منع الرجوع التلقائي فقط في حالة انتظار الدفع + canPop: _status != PaymentStatus.waitingForPayment, + // استدعاء دالة التحقق عند محاولة الرجوع + onPopInvoked: _onPopInvoked, + child: Scaffold( + appBar: AppBar(title: Text("الدفع عبر ${widget.providerName}")), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Center( + child: _buildContentByStatus(), + ), + ), + ), + ); + } + + Widget _buildContentByStatus() { + switch (_status) { + case PaymentStatus.creatingInvoice: + return const Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + CircularProgressIndicator(), + SizedBox(height: 20), + Text("جاري إنشاء فاتورة الدفع...", style: TextStyle(fontSize: 16)), + ], + ); + case PaymentStatus.waitingForPayment: + return _buildWaitingForPaymentUI(); + case PaymentStatus.paymentSuccess: + return _buildSuccessUI(); + case PaymentStatus.paymentTimeout: + case PaymentStatus.paymentError: + return _buildErrorUI(); + } + } + + Widget _buildWaitingForPaymentUI() { + final currencyFormat = NumberFormat.decimalPattern('ar_SY'); + final invoiceText = _invoiceNumber ?? '------'; + + return SingleChildScrollView( + child: Column( + children: [ + Image.asset(widget.providerLogo, width: 96), + const SizedBox(height: 16), + Text("تعليمات الدفع", style: Theme.of(context).textTheme.titleLarge), + const SizedBox(height: 12), + Card( + elevation: 1.5, + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + _StepTile(number: 1, text: "افتح تطبيق محفظتك الإلكترونية."), + _StepTile(number: 2, text: "اختر خدمة تحويل الأموال."), + _StepTile( + number: 3, + text: + "أدخل المبلغ المطلوب: ${currencyFormat.format(widget.amount)} ل.س"), + _StepTile(number: 4, text: "حوّل إلى الرقم التالي:"), + // --- التعديل هنا --- + ListTile( + contentPadding: EdgeInsets.zero, + title: Text( + widget.paymentPhoneNumber, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + letterSpacing: 1.2), + ), + trailing: OutlinedButton.icon( + onPressed: () async { + await Clipboard.setData( + ClipboardData(text: widget.paymentPhoneNumber)); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text("تم نسخ رقم الهاتف"))); + } + }, + icon: const Icon(Icons.copy, size: 18), + label: const Text("نسخ"), + ), + ), + // --- نهاية التعديل --- + const SizedBox(height: 8), + _StepTile( + number: 5, + text: "هام: انسخ رقم القسيمة والصقه في خانة \"البيان\"."), + ListTile( + contentPadding: EdgeInsets.zero, + title: Text(invoiceText, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + letterSpacing: 1.5)), + trailing: OutlinedButton.icon( + onPressed: _invoiceNumber == null + ? null + : () async { + await Clipboard.setData( + ClipboardData(text: invoiceText)); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text("تم نسخ رقم القسيمة"))); + } + }, + icon: const Icon(Icons.copy, size: 18), + label: const Text("نسخ"), + ), + ), + ], + ), + ), + ), + const SizedBox(height: 20), + const LinearProgressIndicator(minHeight: 2), + const SizedBox(height: 12), + Text("بانتظار تأكيد الدفع...", + style: TextStyle(color: Colors.grey.shade700)), + const SizedBox(height: 4), + const Text("هذه الشاشة ستتحدث تلقائيًا", + style: TextStyle(color: Colors.grey)), + ], + ), + ); + } + + Widget _buildSuccessUI() { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon(Icons.check_circle, color: Colors.green, size: 80), + const SizedBox(height: 20), + const Text("تم الدفع بنجاح!", + style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold)), + const SizedBox(height: 20), + ElevatedButton( + onPressed: () => Navigator.of(context).pop(), + child: const Text("العودة"), + ), + ], + ); + } + + Widget _buildErrorUI() { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon(Icons.error, color: Colors.red, size: 80), + const SizedBox(height: 20), + Text( + _status == PaymentStatus.paymentTimeout + ? "انتهى الوقت المحدد للدفع" + : "حدث خطأ ما", + style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold), + textAlign: TextAlign.center, + ), + const SizedBox(height: 8), + const Text("يرجى المحاولة مرة أخرى.", style: TextStyle(fontSize: 16)), + const SizedBox(height: 20), + ElevatedButton( + onPressed: _createAndPollInvoice, + child: const Text("المحاولة مرة أخرى"), + ), + ], + ); + } +} + +// ويدجت مساعد لعرض خطوات التعليمات بشكل أنيق +class _StepTile extends StatelessWidget { + final int number; + final String text; + const _StepTile({required this.number, required this.text}); + + @override + Widget build(BuildContext context) { + return ListTile( + contentPadding: EdgeInsets.zero, + leading: CircleAvatar( + radius: 12, + backgroundColor: Theme.of(context).primaryColor, + child: Text("$number", + style: const TextStyle( + fontSize: 12, + color: Colors.white, + fontWeight: FontWeight.bold)), + ), + title: Text(text), + ); + } +} diff --git a/lib/controller/profile/captain_profile_controller.dart b/lib/controller/profile/captain_profile_controller.dart index 617c6e8..a25c6c4 100755 --- a/lib/controller/profile/captain_profile_controller.dart +++ b/lib/controller/profile/captain_profile_controller.dart @@ -29,7 +29,7 @@ class CaptainProfileController extends GetxController { await CRUD().post(link: AppLink.updateDriverEmail, payload: payload); if ((res)['status'] == 'success') { - box.write(BoxName.email, emailController.text); + box.write(BoxName.emailDriver, emailController.text); update(); Get.back(); } else { diff --git a/lib/main.dart b/lib/main.dart index 8b28dd6..647c9da 100755 --- a/lib/main.dart +++ b/lib/main.dart @@ -144,14 +144,28 @@ void main() async { DeviceOrientation.portraitDown, ]); runZonedGuarded>(() async { - // ... الكود الحالي الموجود في دالة main ... runApp(const MyApp()); }, (error, stack) { - // أي خطأ غير متوقع في التطبيق سيتم التقاطه هنا CRUD. + // ==== START: ERROR FILTER ==== + String errorString = error.toString(); + + // Print all errors to the local debug console for development print("Caught Dart error: $error"); print(stack); - // أرسل الخطأ إلى السيرفر - CRUD.addError(error.toString(), stack.toString(), 'main'); + + // We will check if the error contains keywords for errors we want to ignore. + // If it's one of them, we will NOT send it to the server. + bool isIgnoredError = errorString.contains('PERMISSION_DENIED') || + errorString.contains('FormatException') || + errorString.contains('Null check operator used on a null value'); + + if (!isIgnoredError) { + // Only send the error to the server if it's not in our ignore list. + CRUD.addError(error.toString(), stack.toString(), 'main'); + } else { + print("Ignoring error and not sending to server: $errorString"); + } + // ==== END: ERROR FILTER ==== }); } diff --git a/lib/views/auth/syria/registration_view.dart b/lib/views/auth/syria/registration_view.dart index 2418509..3df65eb 100644 --- a/lib/views/auth/syria/registration_view.dart +++ b/lib/views/auth/syria/registration_view.dart @@ -284,6 +284,9 @@ class RegistrationView extends StatelessWidget { // STEP 3 Widget _buildDocumentUploadStep(BuildContext ctx, RegistrationController c) { + final String linkUpload = + 'https://syria.intaleq.xyz/intaleq/auth/syria/uploadImage.php'; + return GetBuilder( builder: (ctrl) => SingleChildScrollView( padding: const EdgeInsets.all(16), @@ -296,23 +299,31 @@ class RegistrationView extends StatelessWidget { const SizedBox(height: 20), _buildImagePickerBox( 'Driver License (Front)'.tr, - ctrl.driverLicenseFrontImage, - () => ctrl.pickImage(ImageType.driverLicenseFront), + ctrl.docUrls['driver_license_front'], + // () => ctrl.pickImage(ImageType.driverLicenseFront), + + () async => + await ctrl.choosImage(linkUpload, 'driver_license_front'), ), _buildImagePickerBox( 'Driver License (Back)'.tr, - ctrl.driverLicenseBackImage, - () => ctrl.pickImage(ImageType.driverLicenseBack), + ctrl.docUrls['driver_license_back'], + () async => + await ctrl.choosImage(linkUpload, 'driver_license_back'), + // () => ctrl.pickImage(ImageType.driverLicenseBack), ), _buildImagePickerBox( 'Car Registration (Front)'.tr, - ctrl.carLicenseFrontImage, - () => ctrl.pickImage(ImageType.carLicenseFront), + ctrl.docUrls['car_license_front'], + () async => + await ctrl.choosImage(linkUpload, 'car_license_front'), + // () => ctrl.pickImage(ImageType.carLicenseFront), ), _buildImagePickerBox( 'Car Registration (Back)'.tr, - ctrl.carLicenseBackImage, - () => ctrl.pickImage(ImageType.carLicenseBack), + ctrl.docUrls['car_license_back'], + () async => await ctrl.choosImage(linkUpload, 'car_license_back'), + // () => ctrl.pickImage(ImageType.carLicenseBack), ), ], ), @@ -329,7 +340,7 @@ class RegistrationView extends StatelessWidget { ); } - Widget _buildImagePickerBox(String title, File? img, VoidCallback onTap) { + Widget _buildImagePickerBox(String title, String? img, VoidCallback onTap) { return Card( margin: const EdgeInsets.only(bottom: 16), child: InkWell( @@ -337,8 +348,24 @@ class RegistrationView extends StatelessWidget { child: SizedBox( height: 150, width: double.infinity, - child: img != null - ? Image.file(img, fit: BoxFit.fill) + child: (img != null && img.isNotEmpty) + ? Image.network( + img, + fit: BoxFit.cover, + errorBuilder: (context, error, stackTrace) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.broken_image, size: 40, color: Colors.red), + const SizedBox(height: 8), + Text('Image not available', + style: TextStyle(color: Colors.red[700])), + ], + ), + ); + }, + ) : Column( mainAxisAlignment: MainAxisAlignment.center, children: [ 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 cfe17c5..9ce68fb 100755 --- a/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart +++ b/lib/views/home/Captin/home_captain/widget/left_menu_map_captain.dart @@ -1,5 +1,7 @@ import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/controller/firebase/local_notification.dart'; +import 'package:sefer_driver/controller/functions/network/net_guard.dart'; +import 'package:sefer_driver/controller/functions/sms_egypt_controller.dart'; import 'package:sefer_driver/main.dart'; import 'package:sefer_driver/views/auth/captin/login_captin.dart'; import 'package:sefer_driver/views/home/Captin/driver_map_page.dart'; @@ -14,10 +16,12 @@ import '../../../../../constant/colors.dart'; import '../../../../../constant/links.dart'; import '../../../../../controller/firebase/firbase_messge.dart'; import '../../../../../controller/functions/crud.dart'; +import '../../../../../controller/functions/encrypt_decrypt.dart'; import '../../../../../controller/home/captin/order_request_controller.dart'; import '../../../../../controller/home/navigation/navigation_view.dart'; import '../../../../Rate/ride_calculate_driver.dart'; import '../../../../auth/syria/registration_view.dart'; +import '../../../../widgets/error_snakbar.dart'; GetBuilder leftMainMenuCaptainIcons() { final firebaseMessagesController = @@ -181,10 +185,8 @@ GetBuilder leftMainMenuCaptainIcons() { // child: Builder(builder: (context) { // return IconButton( // onPressed: () async { - // box.remove(BoxName.agreeTerms); - // Get.to(() => const NavigationView()); - - // // box.write(BoxName.statusDriverLocation, 'off'); + // var finger = await storage.read(key: BoxName.fingerPrint); + // // }, // icon: const Icon( // FontAwesome5.grin_tears, diff --git a/lib/views/home/Captin/orderCaptin/order_over_lay.dart b/lib/views/home/Captin/orderCaptin/order_over_lay.dart index 2575a66..b783e71 100755 --- a/lib/views/home/Captin/orderCaptin/order_over_lay.dart +++ b/lib/views/home/Captin/orderCaptin/order_over_lay.dart @@ -6,6 +6,7 @@ import 'package:just_audio/just_audio.dart'; import 'package:sefer_driver/constant/api_key.dart'; import '../../../../constant/box_name.dart'; import '../../../../constant/links.dart'; +import '../../../../controller/firebase/firbase_messge.dart'; import '../../../../controller/firebase/local_notification.dart'; import '../../../../controller/functions/crud.dart'; import '../../../../main.dart'; @@ -218,16 +219,22 @@ class _OrderOverlayState extends State 'status': 'Apply', 'driver_id': box.read(BoxName.driverID), }); - if (AppLink.endPoint != AppLink.seferCairoServer) { - CRUD().post( - link: "${AppLink.endPoint}/ride/rides/updateStausFromSpeed.php", - payload: { - 'id': orderData!.orderId, - 'rideTimeStart': DateTime.now().toString(), - 'status': 'Apply', - 'driver_id': box.read(BoxName.driverID), - }); - } + List bodyToPassenger = [ + _getData(6).toString(), + _getData(8).toString(), + _getData(9).toString(), + ]; + final fmc = Get.isRegistered() + ? Get.find() + : Get.put(FirebaseMessagesController()); + + fmc.sendNotificationToDriverMAP( + "Accepted Ride", + 'your ride is Accepted'.tr, + _getData(9).toString(), + bodyToPassenger, + 'start.wav', + ); final payload = { // بيانات أساسية 'driver_id': driverId, diff --git a/lib/views/home/Captin/orderCaptin/order_request_page.dart b/lib/views/home/Captin/orderCaptin/order_request_page.dart index ce5c27d..5a944d3 100755 --- a/lib/views/home/Captin/orderCaptin/order_request_page.dart +++ b/lib/views/home/Captin/orderCaptin/order_request_page.dart @@ -280,7 +280,7 @@ class _OrderRequestPageState extends State { : Get.put(FirebaseMessagesController()); fmc.sendNotificationToDriverMAP( - "Accepted Ride".tr, + "Accepted Ride", 'your ride is Accepted'.tr, controller.myList[9].toString(), bodyToPassenger, diff --git a/lib/views/home/my_wallet/card_wallet_widget.dart b/lib/views/home/my_wallet/card_wallet_widget.dart index 627bb6c..1d2dbe5 100755 --- a/lib/views/home/my_wallet/card_wallet_widget.dart +++ b/lib/views/home/my_wallet/card_wallet_widget.dart @@ -4,6 +4,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; +import 'package:sefer_driver/views/home/my_wallet/pay_out_screen.dart'; import '../../../constant/box_name.dart'; import '../../../constant/colors.dart'; @@ -164,7 +165,7 @@ class CardSeferWalletDriver extends StatelessWidget { void _showCashOutDialog( BuildContext context, CaptainWalletController captainWalletController) { - double minAmount = 20.0; // الحد الأدنى للسحب + double minAmount = 20000.0; // الحد الأدنى للسحب if (double.parse(captainWalletController.totalAmountVisa) >= minAmount) { Get.defaultDialog( barrierDismissible: false, @@ -208,16 +209,29 @@ class CardSeferWalletDriver extends StatelessWidget { confirm: MyElevatedButton( title: 'تأكيد'.tr, onPressed: () async { + box.write( + BoxName.phoneWallet, captainWalletController.phoneWallet); + box.write(BoxName.walletType, + Get.find().dropdownValue.toString()); if (captainWalletController.formKey.currentState!.validate()) { Get.back(); - String amountAfterFee = - (double.parse(captainWalletController.totalAmountVisa) - 5) - .toStringAsFixed(0); - await Get.put(PaymobPayout()).payToWalletDriverAll( - amountAfterFee, - Get.find().dropdownValue.toString(), - captainWalletController.phoneWallet.text.toString(), - ); + Get.to(() => PayoutScreen( + amountToWithdraw: + double.parse(captainWalletController.totalAmountVisa), + payoutPhoneNumber: + captainWalletController.phoneWallet.text.toString(), + walletType: Get.find() + .dropdownValue + .toString(), + )); + // String amountAfterFee = + // (double.parse(captainWalletController.totalAmountVisa) - 5) + // .toStringAsFixed(0); + // await Get.put(PaymobPayout()).payToWalletDriverAll( + // amountAfterFee, + // Get.find().dropdownValue.toString(), + // captainWalletController.phoneWallet.text.toString(), + // ); } }, kolor: AppColor.greenColor, @@ -274,7 +288,7 @@ class MyDropDownSyria extends StatelessWidget { onChanged: (String? newValue) { controller.changeValue(newValue); }, - items: ['syriatel', 'mtn'] + items: ['Syriatel', 'Cash Mobile', 'Sham Cash'] .map>((String value) { return DropdownMenuItem( value: value, @@ -288,7 +302,7 @@ class MyDropDownSyria extends StatelessWidget { // هذا المتحكم ضروري لعمل القائمة المنسدلة class SyrianPayoutController extends GetxController { - String dropdownValue = 'syriatel'; + String dropdownValue = 'Syriatel'; void changeValue(String? newValue) { if (newValue != null) { diff --git a/lib/views/home/my_wallet/pay_out_screen.dart b/lib/views/home/my_wallet/pay_out_screen.dart new file mode 100644 index 0000000..e835523 --- /dev/null +++ b/lib/views/home/my_wallet/pay_out_screen.dart @@ -0,0 +1,196 @@ +import 'package:flutter/material.dart'; +import 'package:local_auth/local_auth.dart'; +import 'package:sefer_driver/constant/box_name.dart'; +import 'package:sefer_driver/main.dart'; + +import '../../../controller/payment/smsPaymnet/pay_out_syria_controller.dart'; + +class PayoutScreen extends StatefulWidget { + // استقبال كل البيانات المطلوبة جاهزة + final double amountToWithdraw; + final String payoutPhoneNumber; + final String walletType; + + const PayoutScreen({ + super.key, + required this.amountToWithdraw, + required this.payoutPhoneNumber, + required this.walletType, + }); + + @override + _PayoutScreenState createState() => _PayoutScreenState(); +} + +class _PayoutScreenState extends State { + final _payoutService = PayoutService(); + final _localAuth = LocalAuthentication(); + bool _isLoading = false; + + Future _handlePayoutRequest() async { + try { + // 1. طلب المصادقة البيومترية + bool didAuthenticate = await _localAuth.authenticate( + localizedReason: 'استخدم بصمة الإصبع لتأكيد عملية السحب', + options: const AuthenticationOptions( + biometricOnly: true, + sensitiveTransaction: true, + ), + ); + + if (didAuthenticate && mounted) { + setState(() => _isLoading = true); + + // 2. إرسال الطلب إلى السيرفر بالبيانات الجاهزة + final result = await _payoutService.requestPayout( + driverId: + box.read(BoxName.driverID).toString(), // استبدله بـ box.read + amount: widget.amountToWithdraw, + payoutPhoneNumber: widget.payoutPhoneNumber, + walletType: widget.walletType, + ); + + setState(() => _isLoading = false); + + if (result != null && result.contains("successfully")) { + // 3. عرض رسالة النجاح النهائية + _showSuccessDialog(); + } else { + _showErrorDialog(result ?? "حدث خطأ غير معروف."); + } + } + } catch (e) { + setState(() => _isLoading = false); + _showErrorDialog("جهازك لا يدعم المصادقة البيومترية أو لم يتم إعدادها."); + debugPrint("Biometric error: $e"); + } + } + + @override + Widget build(BuildContext context) { + // حساب المبلغ الإجمالي المخصوم + final totalDeducted = widget.amountToWithdraw + PayoutService.payoutFee; + + return Scaffold( + appBar: AppBar(title: const Text("تأكيد سحب الأموال")), + body: SingleChildScrollView( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Icon(Icons.wallet, size: 64, color: Colors.blue), + const SizedBox(height: 16), + Text( + "تأكيد تفاصيل عملية السحب", + style: Theme.of(context).textTheme.headlineSmall, + textAlign: TextAlign.center, + ), + const SizedBox(height: 24), + _buildSummaryCard(totalDeducted), + const SizedBox(height: 32), + _isLoading + ? const Center(child: CircularProgressIndicator()) + : ElevatedButton.icon( + onPressed: _handlePayoutRequest, + icon: const Icon(Icons.fingerprint), + label: const Text("تأكيد السحب بالبصمة"), + style: ElevatedButton.styleFrom( + padding: const EdgeInsets.symmetric(vertical: 16), + textStyle: const TextStyle( + fontSize: 18, fontWeight: FontWeight.bold), + ), + ), + ], + ), + ), + ); + } + + Widget _buildSummaryCard(double totalDeducted) { + return Card( + elevation: 2, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + _summaryRow("المبلغ المسحوب:", + "${widget.amountToWithdraw.toStringAsFixed(2)} ل.س"), + const Divider(), + _summaryRow("عمولة السحب:", + "${PayoutService.payoutFee.toStringAsFixed(2)} ل.س"), + const Divider(thickness: 1.5), + _summaryRow( + "الإجمالي المخصوم من رصيدك:", + "${totalDeducted.toStringAsFixed(2)} ل.س", + isTotal: true, + ), + const SizedBox(height: 16), + _summaryRow("سيتم التحويل إلى هاتف:", widget.payoutPhoneNumber), + _summaryRow("عبر محفظة:", widget.walletType), + ], + ), + ), + ); + } + + Widget _summaryRow(String title, String value, {bool isTotal = false}) { + final titleStyle = TextStyle( + fontSize: 16, + color: isTotal ? Theme.of(context).primaryColor : Colors.black87, + fontWeight: isTotal ? FontWeight.bold : FontWeight.normal, + ); + final valueStyle = titleStyle.copyWith( + fontWeight: FontWeight.bold, + ); + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 6.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(title, style: titleStyle), + Text(value, style: valueStyle), + ], + ), + ); + } + + void _showErrorDialog(String message) { + if (!mounted) return; + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: const Text('حدث خطأ'), + content: Text(message), + actions: [ + TextButton( + child: const Text('موافق'), + onPressed: () => Navigator.of(ctx).pop()) + ], + ), + ); + } + + void _showSuccessDialog() { + if (!mounted) return; + showDialog( + context: context, + barrierDismissible: false, + builder: (ctx) => AlertDialog( + title: const Text('تم إرسال طلبك بنجاح'), + content: Text( + "سيتم تحويل المال إلى المحفظة التي أوردتها (${widget.walletType})، إلى الرقم ${widget.payoutPhoneNumber}، خلال مدة قصيرة. يرجى الانتظار، ستصلك رسالة تأكيد من محفظتك حال وصولها. شكراً لك."), + actions: [ + TextButton( + child: const Text('موافق'), + onPressed: () { + Navigator.of(ctx).pop(); + Navigator.of(context).pop(); + }, + ), + ], + ), + ); + } +} diff --git a/lib/views/home/my_wallet/points_captain.dart b/lib/views/home/my_wallet/points_captain.dart index 8903db8..c66ec94 100755 --- a/lib/views/home/my_wallet/points_captain.dart +++ b/lib/views/home/my_wallet/points_captain.dart @@ -7,12 +7,14 @@ import 'package:sefer_driver/constant/colors.dart'; import 'package:sefer_driver/constant/style.dart'; import 'package:sefer_driver/controller/home/payment/captain_wallet_controller.dart'; import 'package:sefer_driver/controller/payment/payment_controller.dart'; +import 'package:sefer_driver/controller/payment/smsPaymnet/payment_services.dart'; import 'package:webview_flutter/webview_flutter.dart'; import '../../../constant/box_name.dart'; import '../../../constant/links.dart'; import '../../../controller/functions/crud.dart'; import '../../../main.dart'; +import '../../../print.dart'; import '../../widgets/elevated_btn.dart'; import '../../widgets/my_textField.dart'; import 'ecash.dart'; @@ -40,21 +42,29 @@ class PointsCaptain extends StatelessWidget { title: 'Which method you will pay'.tr, titleStyle: AppStyle.title, content: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '${'you can buy '.tr}$countPoint ${'L.S'.tr}${'by '.tr}${'$pricePoint'.tr}', style: AppStyle.title, ), - MyElevatedButton( - title: 'Pay with Credit Card'.tr, - onPressed: () async { - Get.back(); - payWithEcashDriver(context, pricePoint.toString()); - // var d = jsonDecode(res); - }, //51524 - ), // Add some spacing between buttons + GestureDetector( + onTap: () async { + Get.back(); + payWithEcashDriver(context, pricePoint.toString()); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Pay with Debit Card'.tr), + const SizedBox(width: 10), + Icon(Icons.credit_card_sharp, + color: AppColor.blueColor, size: 70), + ], + )), GestureDetector( onTap: () async { Get.back(); @@ -84,44 +94,122 @@ class PointsCaptain extends StatelessWidget { } })); }, - child: Image.asset( - 'assets/images/mtn.png', - width: 70, - height: 70, - fit: BoxFit.fill, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Pay by MTN Wallet'.tr), + const SizedBox(width: 10), + Image.asset( + 'assets/images/cashMTN.png', + width: 70, + height: 70, + fit: BoxFit.fill, + ), + ], + )), + GestureDetector( + onTap: () async { + Get.back(); + Get.defaultDialog( + barrierDismissible: false, + title: 'Insert Wallet phone number'.tr, + content: Form( + key: paymentController.formKey, + child: MyTextForm( + controller: + paymentController.walletphoneController, + label: 'Insert Wallet phone number'.tr, + hint: '963991234567', + type: TextInputType.phone)), + confirm: MyElevatedButton( + title: 'OK'.tr, + onPressed: () async { + Get.back(); + if (paymentController.formKey.currentState! + .validate()) { + box.write( + BoxName.phoneWallet, + paymentController + .walletphoneController.text); + await payWithSyriaTelWallet( + context, pricePoint.toString(), 'SYP'); + } + })); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Pay by Syriatel Wallet'.tr), + const SizedBox(width: 10), + Image.asset( + 'assets/images/syriatel.jpeg', + width: 70, + height: 70, + fit: BoxFit.fill, + ), + ], + )), + GestureDetector( + onTap: () async { + Get.back(); + Get.defaultDialog( + barrierDismissible: false, + title: 'Insert Wallet phone number'.tr, + content: Form( + key: paymentController.formKey, + child: MyTextForm( + controller: + paymentController.walletphoneController, + label: 'Insert Wallet phone number'.tr, + hint: '963941234567', + type: TextInputType.phone)), + confirm: MyElevatedButton( + title: 'OK'.tr, + onPressed: () async { + Get.back(); + if (paymentController.formKey.currentState! + .validate()) { + box.write( + BoxName.phoneWallet, + paymentController + .walletphoneController.text); + // await payWithSyriaTelWallet( + // context, pricePoint.toString(), 'SYP'); + bool isAuthSupported = + await LocalAuthentication() + .isDeviceSupported(); + if (isAuthSupported) { + bool didAuthenticate = + await LocalAuthentication() + .authenticate( + localizedReason: + 'استخدم بصمة الإصبع أو الوجه لتأكيد الدفع', + ); + if (!didAuthenticate) { + if (Get.isDialogOpen ?? false) Get.back(); + print( + "❌ User did not authenticate with biometrics"); + return; + } + } + Get.to(() => PaymentScreenSmsProvider( + amount: pricePoint)); + } + })); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Pay by Sham Cash'.tr), + const SizedBox(width: 10), + Image.asset( + 'assets/images/shamCash.png', + width: 70, + height: 70, + fit: BoxFit.fill, + ), + ], )), - // MyElevatedButton( - // kolor: AppColor.redColor, - // title: 'Pay with Wallet'.tr, - // onPressed: () async { - // Get.back(); - // Get.defaultDialog( - // barrierDismissible: false, - // title: 'Insert Wallet phone number'.tr, - // content: Form( - // key: paymentController.formKey, - // child: MyTextForm( - // controller: - // paymentController.walletphoneController, - // label: 'Insert Wallet phone number'.tr, - // hint: '963941234567', - // type: TextInputType.phone)), - // confirm: MyElevatedButton( - // title: 'OK'.tr, - // onPressed: () async { - // Get.back(); - // if (paymentController.formKey.currentState! - // .validate()) { - // box.write( - // BoxName.phoneWallet, - // paymentController - // .walletphoneController.text); - // await payWithMTNWallet( - // context, pricePoint.toString(), 'SYP'); - // } - // })); - // }, - // ), ], )); }, @@ -485,7 +573,7 @@ Future payWithMTNWallet( barrierDismissible: false); try { - String phone = box.read(BoxName.phoneWallet) ?? '963992952235'; + String phone = box.read(BoxName.phoneWallet); String driverID = box.read(BoxName.driverID).toString(); String formattedAmount = double.parse(amount).toStringAsFixed(0); @@ -507,12 +595,13 @@ Future payWithMTNWallet( } // 1️⃣ استدعاء mtn_start_payment.php (الملف الجديد) - var responseData = await CRUD().postWallet( + var responseData = await CRUD().postWalletMtn( link: AppLink.payWithMTNStart, payload: { "amount": formattedAmount, "passengerId": driverID, "phone": phone, + "lang": box.read(BoxName.lang) ?? 'ar', }, ); @@ -540,7 +629,7 @@ Future payWithMTNWallet( } if (startRes['status'] != 'success') { - String errorMsg = startRes['message']?.toString() ?? + final errorMsg = startRes['message']['Error']?.toString().tr ?? "فشل بدء عملية الدفع. حاول مرة أخرى."; throw Exception(errorMsg); } @@ -555,7 +644,7 @@ Future payWithMTNWallet( print( "📄 invoiceNumber: $invoiceNumber, 🔢 operationNumber: $operationNumber, 🧭 guid: $guid"); - if (Get.isDialogOpen ?? false) + if (Get.isDialogOpen == true) Get.back(); // إغلاق مؤشر التحميل قبل عرض حوار OTP // 2️⃣ عرض واجهة إدخال OTP @@ -609,7 +698,8 @@ Future payWithMTNWallet( if (Get.isDialogOpen ?? false) Get.back(); print("✅ استجابة mtn_confirm.php:"); - print(confirmRes); + // print(confirmRes); + Log.print('confirmRes: ${confirmRes}'); if (confirmRes != null && confirmRes['status'] == 'success') { Get.defaultDialog( @@ -635,3 +725,158 @@ Future payWithMTNWallet( ); } } + +Future payWithSyriaTelWallet( + BuildContext context, String amount, String currency) async { + // Show a loading indicator for better user experience + Get.dialog(const Center(child: CircularProgressIndicator()), + barrierDismissible: false); + + try { + String phone = box.read(BoxName.phoneWallet); + String driverID = box.read(BoxName.driverID).toString(); + String formattedAmount = double.parse(amount).toStringAsFixed(0); + + // --- CHANGE 1: Updated log messages for clarity --- + print("🚀 Starting Syriatel payment process"); + print( + "📦 Payload: driverID: $driverID, amount: $formattedAmount, phone: $phone"); + + // Optional: Biometric authentication + bool isAuthSupported = await LocalAuthentication().isDeviceSupported(); + if (isAuthSupported) { + bool didAuthenticate = await LocalAuthentication().authenticate( + localizedReason: 'استخدم بصمة الإصبع أو الوجه لتأكيد الدفع', + ); + if (!didAuthenticate) { + if (Get.isDialogOpen ?? false) Get.back(); + print("❌ User did not authenticate with biometrics"); + return; + } + } + + // --- CHANGE 2: Updated API link and payload for starting payment --- + // Make sure you have defined `payWithSyriatelStart` in your AppLink class + var responseData = await CRUD().postWalletMtn( + link: AppLink.payWithSyriatelStart, // Use the new Syriatel start link + payload: { + "amount": formattedAmount, + "driverId": driverID, // Key changed from 'passengerId' to 'driverId' + "phone": phone, + "lang": box.read(BoxName.lang) ?? 'ar', + }, + ); + + print("✅ Server response (start_payment.php):"); + Log.print('responseData: ${responseData}'); + + // Robustly parse the server's JSON response + Map startRes; + if (responseData is Map) { + startRes = responseData; + } else if (responseData is String) { + try { + startRes = json.decode(responseData); + } catch (e) { + throw Exception( + "Failed to parse server response. Response: $responseData"); + } + } else { + throw Exception("Received an unexpected data type from the server."); + } + + if (startRes['status'] != 'success') { + String errorMsg = startRes['message']?.toString() ?? + "Failed to start the payment process. Please try again."; + throw Exception(errorMsg); + } + + // --- CHANGE 3: Extract `transactionID` from the response --- + // The response structure is now simpler. We only need the transaction ID. + final messageData = startRes["message"]; + final transactionID = messageData["transactionID"].toString(); + + print("📄 TransactionID: $transactionID"); + + if (Get.isDialogOpen == true) Get.back(); // Close loading indicator + + // Show the OTP input dialog + String? otp = await showDialog( + context: context, + barrierDismissible: false, + builder: (context) { + String input = ""; + return AlertDialog( + title: const Text("أدخل كود التحقق"), + content: TextField( + keyboardType: TextInputType.number, + decoration: const InputDecoration(hintText: "كود OTP"), + onChanged: (val) => input = val, + ), + actions: [ + TextButton( + child: const Text("تأكيد"), + onPressed: () => Navigator.of(context).pop(input), + ), + TextButton( + child: const Text("إلغاء"), + onPressed: () => Navigator.of(context).pop(), + ), + ], + ); + }, + ); + + if (otp == null || otp.isEmpty) { + print("❌ OTP was not entered."); + return; + } + print("🔐 OTP entered: $otp"); + + Get.dialog(const Center(child: CircularProgressIndicator()), + barrierDismissible: false); + + // --- CHANGE 4: Updated API link and payload for confirming payment --- + // Make sure you have defined `payWithSyriatelConfirm` in your AppLink class + var confirmRes = await CRUD().postWalletMtn( + // Changed from postWalletMtn if they are different + link: AppLink.payWithSyriatelConfirm, // Use the new Syriatel confirm link + payload: { + "transactionID": transactionID, // Use the transaction ID + "otp": otp, + // The other parameters (phone, guid, etc.) are no longer needed + }, + ); + + if (Get.isDialogOpen ?? false) Get.back(); + + print("✅ Response from confirm_payment.php:"); + Log.print('confirmRes: ${confirmRes}'); + + if (confirmRes != null && confirmRes['status'] == 'success') { + Get.defaultDialog( + title: "✅ نجاح", + content: const Text("تمت عملية الدفع وإضافة الرصيد إلى محفظتك."), + ); + } else { + // --- CHANGE 5: Simplified error message extraction --- + // The new PHP script sends the error directly in the 'message' field. + String errorMsg = + confirmRes?['message']?.toString() ?? "فشل في تأكيد الدفع"; + Get.defaultDialog( + title: "❌ فشل", + content: Text(errorMsg.tr), + ); + } + } catch (e, s) { + // --- CHANGE 6: Updated general error log message --- + print("🔥 Error during Syriatel Wallet payment:"); + print(e); + print(s); + if (Get.isDialogOpen ?? false) Get.back(); + Get.defaultDialog( + title: 'حدث خطأ', + content: Text(e.toString().replaceFirst("Exception: ", "")), + ); + } +}