From 8573d722f5b13fa5b12517e564e5564bbc57b685 Mon Sep 17 00:00:00 2001 From: jantunesmessias Date: Thu, 6 Feb 2025 11:23:55 -0300 Subject: [PATCH] WIP --- assets/files/document.pdf | Bin 0 -> 35523 bytes hx | 0 integration_test/app_test.dart | 7 - integration_test/auth_test.dart | 7 - .../shared_components_atoms/toast.dart | 1 - ..._arrow_linked_locals_component_widget.dart | 1 + .../card_item_template_component_widget.dart | 1 - .../message_notification_widget.dart | 3 +- .../provisional_schedule_template_model.dart | 2 - ...iter_vistor_template_component_widget.dart | 6 - .../sign_up_template_component_widget.dart | 6 +- lib/core/meta/anotations.dart | 2 - .../backend/api_requests/api_calls.dart | 2 + .../backend/schema/structs/device_struct.dart | 2 - .../documents/document_item_component.dart | 154 ++++++++++++++ .../documents/document_manager_screen.dart | 92 ++++++++ .../documents/document_page_model.dart | 1 + .../documents/document_page_widget.dart | 70 ++++++ .../documents/document_viewer_screen.dart | 48 +++++ lib/features/documents/index.dart | 12 ++ .../pages/provisional_history_page.dart | 2 + .../widgets/access_filter_modal.dart | 1 + .../widgets/provisional_filter_modal.dart | 2 - .../home/presentation/pages/about_system.dart | 3 - .../presentation/widgets/drawer_widget.dart | 1 + .../locals_local_data_source.dart | 2 +- .../locals_remote_data_source.dart | 44 ++-- .../repositories/locals_repository_impl.dart | 1 + .../menu/presentation/mappers/menu_entry.dart | 10 + .../widgets/menu_item/menu_item_button.dart | 17 +- .../module/data/models/license_model.dart | 1 - .../module/data/models/module_model.dart | 1 - .../module/domain/entities/base_module.dart | 2 - .../module/domain/entities/license.dart | 10 +- .../notification/deep_link_service.dart | 1 - .../profile_local_data_source.dart | 1 - .../storage/enums/shared_storage_key.dart | 2 - .../repositories/storage_repository_impl.dart | 1 - lib/flutter_flow/flutter_flow_widgets.dart | 1 - lib/flutter_flow/nav/nav.dart | 8 + lib/flutter_flow/nav/serialization_util.dart | 3 - lib/initialization.dart | 24 +-- lib/main.dart | 12 +- .../qr_code_page/qr_code_page_widget.dart | 3 +- .../reception_page/reception_page_widget.dart | 7 +- .../schedule_complete_visit_page_widget.dart | 1 + .../visits_on_the_property_screen.dart | 4 +- lib/shared/widgets/component.dart | 22 ++ lib/shared/widgets/entity.dart | 3 + lib/shared/widgets/model.dart | 11 + lib/shared/widgets/page.dart | 64 ++++++ lib/shared/widgets/screen.dart | 19 ++ lib/shared/widgets/text.dart | 12 ++ lib/shared/widgets/view/carousel_view.dart | 77 +++++++ lib/shared/widgets/view/search_view.dart | 200 ++++++++++++++++++ lib/shared/widgets/viewer/viewer.dart | 26 +++ lib/shared/widgets/widgets.dart | 21 ++ pubspec.yaml | 10 +- 58 files changed, 935 insertions(+), 112 deletions(-) create mode 100644 assets/files/document.pdf create mode 100644 hx create mode 100644 lib/features/documents/document_item_component.dart create mode 100644 lib/features/documents/document_manager_screen.dart create mode 100644 lib/features/documents/document_page_model.dart create mode 100644 lib/features/documents/document_page_widget.dart create mode 100644 lib/features/documents/document_viewer_screen.dart create mode 100644 lib/features/documents/index.dart create mode 100644 lib/shared/widgets/component.dart create mode 100644 lib/shared/widgets/entity.dart create mode 100644 lib/shared/widgets/model.dart create mode 100644 lib/shared/widgets/page.dart create mode 100644 lib/shared/widgets/screen.dart create mode 100644 lib/shared/widgets/text.dart create mode 100644 lib/shared/widgets/view/carousel_view.dart create mode 100644 lib/shared/widgets/view/search_view.dart create mode 100644 lib/shared/widgets/viewer/viewer.dart create mode 100644 lib/shared/widgets/widgets.dart diff --git a/assets/files/document.pdf b/assets/files/document.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9a84c2fc28b6e3e4d6d04277044d9f10eee8d5af GIT binary patch literal 35523 zcmc$_1yEhfwl*3hxI=JRKyY_=g1fsf92QRS;K3odYj7vHTX1&?E+M!DhquVy=bZiD z`)d`%1x7g3bJDoH+B;>cVaR#c5*RvFf&JB0WbqVCe{f2{7h;d4nQU)V+)`&ldP4Qvo0IB zO9jCG=gRTt%JTP(=TD23_0Nrs`SqsHBnEP|cL8t-3L*gQ&0eQ`?f&P~V#Y4Uwjc{8 z4WN^=708~6g^}wob%0kRRG1W9U2LuFfzAMyKbn~ojP1Y;_CGrR2+D)ZfK2Mnz<&w; zN7d_qf2w-*f=LDF403fc1v-O$Q*r{CssdefnZQ9}QUiW;VUo53%ZUDU6Vqps0NJ~M zpX0n0PyF}*MB;kfMBQpvR@u(W@Ri2`l$OF z5Kb0W02dGIYgp`Ez%tGNwm;!w60x@jxqyTFXKwxfxbPb1|9@Qgx846=4dj0H>)!_c zwaDy$Ru{nj$3+19UrWyZ_tyBcH~!(nYvBIR`tbMC{A&xoHvcwA!pauBhD;K+#x6i{ zpy}&Yk^|aXxLAUHV+ZeAXBQ`+u^qxkh<3e^=$#hir*|*Hgfg?3aJ6u;&`rYF(&jj3 zQ$J=h0Zny-KXz`Mqivh@l4RVjkxq~h<|=Ec!?(6$^JEK|I^|w6N8jIq3N4FbdkEW# z6+r85>w^jA-f2Wa4Ks@I>CXYEFKk1Eawvr!FDu#SMcL0>&9M&KjiUSe2dD1rKxS#@ z_54)dyM?PzrWw!+7L{oc6G_wE$V$QY3C6I9`0=&doSEdR86jUPlgQ6)+t>cd{fEfe z9&M1%zIRVTosaBK=dv+IXU^l}O(8k@aA`pchz3>fgKkFQi7{O`$GZz{@dG@!tI@nx zF!6`^gxCCjJg*;@)um8`uD(0I8CsT3X&+mD$I(w`I>n3ZEI0M-%SQqvCtR$Lm&Qs< z5!|@Aqqgk95^T2KD&KG10za5#t29w=Ji&e+qb!~K{%zP#&N_>OoR7-2+i>;p;-#T( z-mdlw&3NATdqwSu=vZ_%v94eE0TWsi(K+?@4Lk+2XoR{Gl+#P1#a!Cl`_vp3(*_cq zG(C|KAIwnKKf4pyUU_p-!VHg%qhx6RB%eK6dD@+5!dh)GNaNuhLCj`j%!p}IvPP!n z4J3FXEQsBw=91ja7*1PFkY-JeVO&T+mf91RUo2Oj(k;0dJbddY6TS z%bcQZZpzN`qW9WpOV_LY!OvYJQs@U`{<0e8R_v5i#O~fZ5HaCb-F_Gq} zSlLZ(T?6qpc=vEsL>K0qoL<*2s3W3_JYS2F_|?oWj3s_g-3{w&P;oxvd= z84{@PfIZcfgvmRYzf$fRp|YE#&}{L(TWy|rkk7+f424lR!Jr=Zt3wi`2wAp&)J<`| z#@}JZ2{?Ysmhtg!vP^gWG=7&ogjZN#tZl)_el`Yh~tun-KsP zsHsw!@zr{_X_WXQ2|s^@NI3)7y`KGOwSW{?0%FX=sW~NGtZ)!pu#qL>IyKaUKvc^5 z8Eub|L%gsZ!*RJm+xfI}>jG2mAz>W$vvFmx4E3*&k!stTnG0Z-jN?~akQK14+B#YH z>EbIqu$P99HvFEId~Lq0$N#4j-eB3@u532SAuU}nPQGA(M9%&uiC#(4l$M)Y#Ihu0 zSqjcBTtsS!Qj?}CJ<4DRe!tHEoPVq%@I8I_yOLacQhSSF=UnwdD5zixw7rfo^Icfh z{4AP9W!$J9tZ=t!)cXtN^S8Mh0J=gYsc(+Yd@ty6y_43rV5^M-^Smvi6TaTdgv`t78DGmahxp)JrmV?8D63>;InaSn5zCYYm6iR1Gx< zrf*>hTgE*HVH|inuaOzvoUuq$uAaO28DMUj2I;MD2r|`I5hhbiiV+`Pg-Z3{mZvJ= zQqeTs_ic{&PV>e{)CN?ne&9alliKY|q!gmjgo}{G`$Yi}ua36UL%XOfdt?wM*ip%o za78_IeZZ!{VHG;Y-L9wJFZjm+Pr^6|mlhYn-XTcNTM{940Ph9u`t64~6540n5@>o$j z*G9R~THnkjCBqw7_s5|ME=Q;3e%YOb84M=G5>Ta&vem$wr&I(dk-&md91;UL%1V99 ztxHWWrAN=;Gx2+jE!JvVt}?6eB@jYwnV}l%Z7S3T)A0J!2ES?FBN_;A3hM;KhC9rm zbRbO97f!&3NrNCbrtR!|Dj+zHW*>H;8Q_@T&wp9QgE`Sc&P1?*7#l8?_59IXkvu#C z_p94aB8e1VuvFDeAgW~#Iy10dJ7^;5K3Js;V@Z&LBvn*=ZO~-KcmOd-OBo)gy5#0z zcw}TzK~#bet5^*bu<{)>FDg~l4E;%J11Sj^c?{P4N?EsbJ#bJ9zAk7Tc}})6{0){; zu8?P-GZh56`pvvd}|YY%W++P@S&>Y<1Gx?C$ubf5#S%Eo z6Cq;9oB~`X;LSDk5lB~Turh3oNPSC2)|Gi>HINZ)DXm6&eSHPWG~X+oyYakl%6fJNq{2QyLd}h|kqpt@S$;h0!qcJe>b2^3gD870GbH!=qMvK27A>4r_(iwd zUdc~wHNvf7_glxv#6x)D+I*r$m3L2kT{YhB-KOar3DAUp!T5Pjwe~GZ*UN!q}|QzU5L>bz6tKaR`Uv=8k0OSE*=Heq;WED*kxi0 zCNL@GtLjnn#L@TGtQn+8W6{vzhVVGuh`}dW$2Po|jaXGr&1O#whoZq#Ye{fFVg{?B0!r&r)giyrtpy(CDpk8msCA3xbBm_# zaH=&vFXLE9U*9jDEXlBPW3lYhS&dbNhQNyq7=T=Vr-JLA*~ws?>Tm38340584&YJn zGI~-DlS<7u)XTM=7+Rx>(Ty5gcL$RCyB(y3+A^{|g|Q-? zZf(cJ{Tu!ftEDBUb=Rm~xPmvx?cvxHC!J-_JA|uxXQ(oqUJF79R`A^XH4_!uyS>%y zCu~YU64@jL;NdWyboJ->arfU9*pjpXBy%=w1YRmtoSI)-Z=gBU=I64w*A;dx1S%JP zSuo~U+Zz5}>Tf8oj##shK?~D&P7korV^wD3hmwS>;&j8fjd$sxC$eeo<(n~YIYgw; zwy8Z%_`paVCfzj<_vA7#g-vn&q1x{&Li59u#?z)yq*2=32{FaA;{V%p`*OP zH|5yqw=_R|^*b_x2%$R6$}@9b{My{OaA>BM^oCMrl>}JWZfd9K?WW|FLVc@mS6?AI zeH^6R3=}RHue}XB3E&p05gR}6OI;}=pUDvSiH2L)I4P=dP&S=gSA0Wd|F9H&>!tH- zlQ6^^%uE2$&i<>PDkaOaOJaBipeSH6Tr(Io->WOONeo!a(U`lgdvdNpy9a`7C3rLTHa?dThIk zhe;n-L^kp7Dg{Gn+$h6O&4QFGfrf8p*IHLM4+~_5Mc*r>f^NzsR;{HhV)(5uyxFPU zYA5T6mHhGf5*5C896FmjaUA7{VP}{WVTOc8XnNKO<$ufUy8=?xPF@B-L}lv_mIzR+ z4>Qh%A&(|$$Bs>B9UHI^B;||#yynp3rnBgVy&ZOwSlDM!JK>v@ps^RuxT19ZQuE7? zHh>$QZk~UCaimreEAFjoa)!$?wwt_#O0I?W2K9Q45;d~VIaZC@zLIHioGi2S-A3wV zbMHP)9^b*ev_I<3u7ZLOJnN-@ZO-veQ-Y0(w+?bO@pkj97B%C!cHMaW2Iedmq~7#n z`{t7tvBVszK`KD4FDPzEKXmvUA7-=^iKC0vQm*`~aU zw7VI<@{J)P_Oj352|n5^zx|m8oA^UJ<}Ne=gHED7+`pddiT#~-luYHuP|Zm3?t!|! z9W2v6CloxhOK8%Uk{>_Gk}-XY+>)lrmXykJy%#P8zo^HTCt3U~g)gVb*4-cc^p!mw zE1g}r>>bAhD-xRZfziREU{7MtaId%P3-faI9jvy?xzzxPw&fc>Y*%dFr2>r%vHc?A zpIafu;fex9;}ZhjpqX}temlYXg^_G8-~G^?u}prtnjsp&+qr~^ui9PBH0vY3z9pi4 z=EO%6Lg@&IZcA0im`UB<@DG7~rhd~4VzbmF|M9%`HV@eeg-;x#v9Wi$F2=o90TYwR zOYGodh`PSaPSF>E{xox|sNnX0HpgCrT2Fjdk!4R19`s70aOHGD$1wCia7$N*Z$^gGsd)@)}^ z;3nQ+ze|lUd-diZ)ogqNv|@n44kKl9y8r!k5<0S-`Yj*LQJRoSwFN5A`2sHCN_LE@ z&`ka>%)GD6p}duk)1)vtAo0&2$r#pbwuP=O*)NkS0Of~3Za~~Q?j)``^@i@C6FalDEa(|1VKuG@S*T%KwK_h|Rh;~i z=o%eLQ{*DgAJljM0f-@Qi=WP)QYv9NF6cqj?x{+=Y{}0c{{E!=%|sS*B?jMjyfld! zo8)dq_eWv|Q5^_&ckHL)Lbwpb#}`!Srr4-gu;Fj?;BVyX72EkI4)O{vF{!$mxV$24 zuP__)A8-o{F)@9x2SX87_7+UiW?+=a%Eg00ib>Si8Te<2q65%g)!5#dK?P{xYHRGo zBo1^o1?w=jcX{o1*8LZ1_ec7F9`@P|#y^0pfWIJ~*Y@jFPF4;sASVFJAB=}d6AWCj z{K0v^sFk$18c0%FT;AB>-cv70*AqvV6UnF<28*S_(z{f4Ww>w^@`2_{@_pl z!N*=L|2w9C;WjJ)Zm=~>|1++`$;|anT*pouRv1h3-tSa?siS%X`+!~+S!(Gk%m-od zYEmOHnmj2M>L#O8teOvR(Y?a(l_K**tNScxEkB1*xJxq{Z1wl0jPz&Vs8&+*J$9z* z%Y1qHRn5l7cj|L|0lL}Q3?)pY1qcU$Ix~Ygj8NFhIfwSFm+>Qyx9o84#P*1umvvoQTEj!MeU6*5%2uBu}&NTG>D`8NIT*Jt1D9N{YyVAebG(zuA`F9N1z7MMxnv z76Ua=AI~-zcn_WBf4<30M(clbOdWcM-64sVyC#CU$(xcDC4)z!1HWG%2^G|WW4jz( zx-m$>LyZ~zk-PJaB#R#!$8cV6tPo~U%aB`>5Rz+MP0yus&?&zJBHT=C)E#uz9Xfm> zw3|B{Np9jTZ7G#+JI|HU?IXbC10` zVR_h73tP#3Z2gD*sQm&MBty{Bi96A1G{{K`$qiByvY?@zTD2uBJgS&46JJPT-AA%% z$*@Yo@4|KZt@_=ENk0$BJD+mleupU|ie(fDuaPQ<)rPCd$pOR`cC z(y{zLBuy5eY^>xQO9L08Zlx8+lhxJ4TQOW5e#YimNADLxH4{17>hfc8nQci@vr>Pa zIWKt5Ar}H~jj0G$fwz4L|3js%R`!avT{}vh(azih6i;_S4(XtPNQoNVHyue>4jU0N zJR!r_g9dG&#z08$1j~mHHri`%JEam?Sb3MrIV_QBqoRu;i<(++LKT0odaOSeh-M7x z4^^qiEYQyO5-fa)!V6Puwm!VrBKxe#SCmh8K$t@J=8n?R2tRR}EZ)nj*Gwm>jt&1T z?xpv^N+qzUr~FwWz06$TwgMLPK_^PVg7d?N4-&U=b&Y-{w?^Bu%lwKw6jncSFuitX z`*k@fVmGT88Fhr5s4{zfMg)8#%1~0#wuFRYBP`@Y<+V4{i|Q9V?L3Pdo})Mxh!M}3 zPM-WrAqfmc8NK-*UD=O!>1ziqz4&K6;Ux0LC|{(y-=wTh2nC5FSj|T~-s+t-90i6O{5@im$WgkqlDK#c0Fp#RcLC=;@jKa63`qZnfFy+`TT7 zuEA?V{^(OORGAmOjZH%Bj$KpwBcHWlsWOi=23%opNF!6`oB4=&$9=>HOS`VVp?f}k zX2J8H=jEOAG+XR35!z3ON+1S@_dY`q^!3~O7AZ2a{y3^?@+UC)bslo0^ z$8{O#6B{gc`h|$GgQ94kN{EYtgNsEVThzg=ShOV&$1(~`C`Leh712J$uLcSVg&4=G>Jxwi4cv z%1)R~v(ceBna+3h9wcaOPrsbZ9GL4tOdhI1eQj)MLSPapr?)Wj_mDIX+c$u3FuBkV zxp=wJkhY(ZNQ30oRs|Ml^BIYmc-ScprSANx<|0nHW{DgCL)`Z8nRQzuME#neyF1Q% z&nlniJv=!(13&Baaw6^DcjVm|0vDT(2q?T{5pur{hQjF;(n!T(k8Ze$cIDNgt+S%8 z%(DQawB!X@w@}<<$pz0nQ&#wli7bABGxpiO=e6W&9X)EGX%B<*!`p~B=SWi0Qzxn?V8dayDw zTy!MM65|0|)UYOKK4jA-r6}YxS1QC$PtFV+Y0EF_--^?vr#w~nRi3vYJI||aI|xNZ zTts6Ie}=$KbX%Od)3xP%Ar5WO*)P0Oug-MBV z56wzdd6>_;+y6D4B(S{xI5(U%LKBskbWB4NrA~!{(Rm+3Fc1TJZ0eZNX&hfx_Od%! zwW;UOl<7Fp1yKv7Xd)&SzCnWunWK%f{1pBcyJ05n%M}~5$5`yILRWbwMIG+3*%oDn zi>&6far7E5@vXt7bV^;mgIV3)eI!hmbgH6Uu><}|b@E9qc6O0{21The6H`+tsJIA& z?5+2;L8P#J?!vzS{=XK}Db?u}>mj-GpJ1L5&?gDLk!3REJ&O{%nv?c?0~u-sy;aV4 z#<*S5@V_ma=%^||z!!9yP0%#gFL#ZJnBJgho5IxQE^po{GRUWY$?thEU$ehbTExJ& zbk9zIp)@~2k}7I8RE{JyQ#O&IM6bj9x;C65cHMp>hHOKT=ck-cz^DjW9L;VY8Rkk# zZ-^z6&WOb_oQOGK{C7RW+fUs{hA$hFOPu^KKLXR&hg%0-1e)SkT6o7i6A!GbJ6Os) z@*K-5qK$|tq4wg)kZ0q_W$9@p_?0AsIPukBFe|V>pnZ-TK6-0-x})$os=kG2xK;2w z8vn4_@N^4}Q0DoZpFqa!8Mu+|DICGehWlyp@ z=eiADKBFKDsm!Qkm%+SXYuAe_mso9FohqCcWue8A#nmeE$0)KK(+7UH#%UJ@*&H2C9t50eZqp?vO!rM@lr_u-3WYu#I)dXX7 z*lscGmHl{A0_zH7x)fxA=w2LpD%)MIAN6@hE&~S9Pdrk{`syv zIB(9nW|Y`=<$X`yn&OS{dwc@f(w`~UV(-_0*W0Cv79_egp4wuNoqeZanHxd}R}xMG z_?@|eMfqv(m%WXv{F$Dq0V1b+C)=`oJa``!k;oztC&{Uz z2gG=n=fb28fwF{jnm0BY7RH>vPn1P%3vgmpN@;tnDq^^Xje9(hmxZmCm+`F||B$se zX9`dEHLtkF$ZX+q6BV}i^{r%>=Rt$T*@MCg;KwAyT^<{oQ$N8R6=tBZvrJ=Vrfoyn`dg9CyFpbj?$=jPv68_1E_+yliZ@>`b5B7RQIJq!Rfus`8T0 zsqE(~-$PLk0<>4mi~C!~zt5c}J-{3jSPM3>_!(a%CCsUgBzyMX>TDJHEe@bZ5*X=y zr^99Wz`~kCwkr7nioP2b{y7b=k(18aCSQqw$5h^;r5w2+gCx{Jf!)8Y_0luL)m?Sc z^7C*vndA{bAPcCP2xt~oM>uHoB6vq6KmJ^B?T8tXfKD94$DO~PVfP`ogs}yE?VRmP z2olsgZ35K{99v%2RC>SM?3oNw%sG~=$%At*+jAIU)We zd>e(ztUml)oWLGiPt5w(%IQ8bde-l^R(;l9K6u6E;b9Yx*~qA~k{WtgIx*&QHA!?H z8A+GT?53bmOxj-UcF{9`WV9|J=HRkfeE#7;B=;+youdJKgYTOLPe=<=i(xXygsUo@ zwv)+XSeHuFP1nkpAKbKV2Xptc!vmmE-c+9Rt7)cYMYkO{qrH!JndLhP8kDRyFYBC{ z`&k@#8R`71OdF#h-D=gFwv8@3gIs11!{{N3tM!`?B~FfR^9TIs7+y`&*s$jSab)V@ z^-Y>mMP=UZFW~=E(J!N!k~ChX%{|=BmfN*=E1HQkx6^wl`(rz`ChqPTay7<0EW|FK zf*~Ma1IQ(~MnU|=agy<>txZ!ViAq#wCRn2sS_E@lE(mYGQU;lP{vf`T(@T&aQ1DI( zrlYDS1%dQghAi*rs)CK?0D;+}Jw|V0mXZFC_bTlQ-U#d4Jt?vi@zN|E72_Fu_$e&b za25@xrGQc#YhC|u@G9sLJGjEYZB>5}gdEV!!M#H;sw3NkpmTI=_zugxg+;S>mx9%W za{R${oEg_G+3L zzb)352L^tGi4_yRjT;BWp=Q;tiigtuxaGAO7bLJ27KBC&qHhS;`OEDfu2LtGIZxOeKCZs3pkVl@+&vov8Yc;U!7Po}9$AY6*`AJUn!yR^MMBzAIpV*;cLc)0w`c_MHiMn=a7@DlcE< z&fw=B@o~2s*UmV<^2#_jhh2E?4PA}7KCIq8zNzUAL0)D1?1z10*oGwVwj{)vA**vH5p-lw)bDTsBVCQ}+oI0^knG3`Fa)eow29r7lr85F z<=@l#-m#f;%In;X2`Ws7gz7D=`F@2B)fdWeGZUC`z52d$Z$(?u+h@0XjdNKNSC&+n z0s3L>Q{BpIGX>YZFZcLXn(UoX?rkI*Lki(Wa+qJAAv?$Q4bdXmk@C=bpHb;zVI7@+ zdh5#V6U`uBIr%8XU~5H;o2JU7q^xhYJL!3~?<7>1`+M)TR9V$%AwMwHCv7e$RInum z%DuBV?cwgc;eq1Cd+K*T-A=dT$&eQi_(RM6k#xMxCCOur+aZNo17>C=_cQ`X!w=n1mdiWr;CuM zrR&p81F7$_wvt1^u_1sQ}`-f%99svn@#sL&TtL74t~N- zZuvZAP3Hv{N+UmI4T`c&o<13q(4tF4Y064~@@hwLoWE%Ydr&NPA`9E);%Q5*wA}cW zG_~gzQm7s2jqqsNDZF3d{msth%==j47kAo3b`+w|=)lo$`upV+C6(veCF*>8BD?M7 zIT^C^%6^-@XDyH1X6dWZ`+YHF}#!PSb6nOx??( zMQdb;{t%+jruEu>JBf%+Df@R0sH;sz&=VuC0Pd%C>s9qJUpkAWXBN!?!F;x&mY-lm zktH&tN=ZZ`wqotE#0`?4$4Pl?>{3;q@+s1CGMZ;}hYvi>v)zR8&y`dqykftbN9o0k z!Nv{=>(ol~@y?<9V#63#mQNH=LP-$fsS+aEtM>u+>s2hp_q)XtpVUrp%9zFIPbwap z?+8xXdx^LY4{9eaG1w}TU9RStJbg`nCnYyy2GxDPdvM*1JSE;7Z480o#FLj_Rm2&0 zoJhNlevAoiW4KmBjK=(^xa?1pm2XTTT@Z;CeMxs6Y;YjC1-E`UwyCk*91tDr9uSRo z&W@0S%Oh33Y^`jLzyFJalA4lfuP;)=zFuVwkob0D45%P5u|AplqjTUA^1DfFEn-uW zXan`~;(X4rJvjjY7Mw73j)*e4!#l!`lSazPnbNEuPi=|lOZZpIEhW)=E~wj+YCcmw z^WofZW`&OMH5(UTW1MH`)fxcuEAk&~jXeCW9(k$bZH$G#CTLwno77amHpWCo5jR9h z<1Uxi!V{1ees|Jg8JmXnJkv*izPe*c``VWQm5-$Nji$aR_P{evxbxB*$(6pw+<5ZR z@C{;EwRu&p1-wAoeTD>0K!|G;R&dK|^seK4r`yXOY&+psUdkz(M9wa1R|S+9IfZB> zMc-0IJ3Dz>gqzWO3onLg{vlEXmd5C%0Q%0 z$Hiwb?KOqhzh~>hkbK|GA^TFGzz9jc4a_bBJj&?zR!wKzs_Vja%52ZZbl_fZXTWsg z3+4Or!3j-qKN8*;os}J=Dhqkqonww$&Bf4bJSCiAmg+tdK7G5LI`xnr z7+@%E2;Hetx1l)=-#u}l@JQ%`{#gEHEnA~&!kF$hF=KRd|IGQee|BV`%<$j>kEw3& z^z-1#4cgX6DJYt;U?AC5;7f}33^#-F$SG>GD2dj8-!y;fT>rH$_n$i09}f5{>741m z)!qJE0nOIf0!&T+GeY#0^3A}(&JAE-4o;Ro{Tv)%Dm%EJ6KoGVGdF+(Ox}Kd z=6aQ3;RJASyw1n+XB-=t)6UMt^Jo579XzixU}w0%G<6PUW&k@Ucs#iM>Ln*D&!1;b zFrl5D=db72K2{#E4dCBDa<8(l-*JG)v9bX;!7P3@R&X1vgNqA1=imMR($58+lamGf zJr(^#9P=ndFSY&#Zr* z|FH=FIAQSDFqVIf`is{8XVf2)zy}8YZQ|=J|JrbWOq2qbK|xL)0AqVIfU^tuYV2fY z79IULYY+V1b_Ad^8nEH#SBK0&_()- zR-3F6X7Q=tGt>)ivL6%ayXTDwx=cStzvlb{SXAX~KF?_;KSSS#+Q(lv9uRs4g15a) z$-#gYCGSDRW;m9qiwo1c!>V@Jv$f94!$8BqD#T8lyTsf5h4shd-J)H0ChTr3{R)Tx za8W8i>GpcKii@;wy^Mb&#i;8DBMBiK@WZVMqxC8%oxZ7h*RsQmFlSBKk(@xdm5BP$PGp7QL+Qm*xC&aYwpgK4sQGf7aQ4IV z9+gZBHfn3q8WcdMr4ibjA>~LBA?)<9b~|k42DXjwLHYZ}gUot&bxuOjZ%>z|iDtvyf7cC{ zH9ypzL+&+Tl?B2ja7>MKMVF4yaS`K$S$MC)C-`G{&EuP`o1nLR4|NuSU8LI4suP55 zZ?tns=;><^UnTVlq{BoF>}V42ULJr~^v?q%CR_RHov7QXb1jW;U}^D3gpt=2?s4Te zyGV4T(jb{&oFoILU|vza1= zG-Y?aT{Rjsa^0Cr4RD-3c8Qh14)0D(35<4d|HaP(5f~$!!ojlSz4lpdw6&U-ax~|2 zIX177nb8qcb3u-V;C7iXN}RRaJzCSyISMpB7OSJ)RIAp4&*&&O>$8lyP}Js1#kQMhM$QSEK1~O%N~nzn6npIt$!bG;Ts!1% z3|%K3&S-iOboJ1QIu!#42PIdf&N#<+4ED!l%_c`gtwPsjiBjmNtkAa-IjDq8CKyV$ zLD0;sWF@%Q)>sEGu|ehmbqJ?1ca=0p1{OI&NcJYkb043FpKFaL5~o=bTkvTtkkW>2 ziniS$iSLxZ_h1e2PD396CR;bip3xB_vpZgRHUa5k zaR{9=rsZqvq5Haky@OlG2S(LkTmC$rb8pjQq&!l-wl8#&@bdPT4`pT{vG2J_C}LFJ zn{z8NOUnxqJWdOPAmKit_T0JFxI($j$H;}Ao6yXCSp(9)lOgPQpOwWk*rnlZ)E3si z2;pNZXw#(ta}>!_FrQCxuJufqh68n@QoWkJxn0=ib!Dm7KlYI-g*$={j^!t8!XZ2` z{eqb=nEdxI(s$$G#3dR2zMsObgR*lpW@6}q>(N}BTZXS4#?U7hL&e}T8Yt*J4XgAQ zPs-j{1R%n$>)1^5^To^LB>*w$0%)e6T;w?#bGRDV9F8zl=88tScDYTh-v;!TVV1n3 zh;~c~tO<=7f7{{Kxxn}X|DF3%05whpA)6w0K+~@9y|6`IWu=T?;SL6#nAv8yx)CuR zf1tvf_wChhOCAb`Lc}bVxau(QM({b7*v#?E5K}YztMghdtanb456vFnp=xJkI23$` zn*v7szuGrKQZ8a^D_j3oUI^S>s^0G=R~0Y81d45B%bZI%((w8EJ5FmGexBKYd-I)G z@$9F$dbX9%Po3+c^6>a<72)KIEJf1CYLTv*7;;SfIo+Ql2X((#pgzhdt61kNy{La0 zQSQCN68&Z~v;GML&+4^-=BoazW@Z%l+rM;e{bX2T2-ODfyJ$nPu5RmHRzv0(sz@1g zOb;Ta!uvVWx>~;TFbSZ0V{TM4IY?a}xL6QTv!03|3yC#Vs*qH(=)dU|92==~jB_s= zn~F=`VVP8;NWq1~x!`mI5v*+9kJk2nnyOZXAT7vJj0bfqJ?AD0(U9yCOV3W084>8>{A9M@Uxq~-&{?78gs3w zgxt~FDB4?iuKdzA1`+*=YS~#g9u%$aH`yk;aCcffS#Rb?Spj&oA6I3)eA!xOQ+S6< z`bNDY!?ofqWZBm$uWq7e-3E>2znW>(VGFTuHAWDhVXWJ{P4@&?A;0oDDxuU ze_5rmT=EIY$l=$uUE*&^azI9t#HmwsWXoI+3DE`7ayH`IFTX<|Ps{_+Xljd@EmwZT zZ63A_Pnf)uXCeDhl1um=f=9yi>J7LqASh_>*k|n2;gD4xsCd3_y{{tMgXS7&_hTf+ zj)a^>60hnFJEZvUnGCFmjGQkTUw8m1;vHy2h$u*Jxm5xC!g}ygK13t-IfI13K5!ZY z&QNe{ZI3^4e^$R2qD^ax9GpCkn}!w5Ao)w|R!Jr|#DENy|hmv2U>w5mZ*GjE9s z$UrDHIuCY=SVSZhBdAYhqo|?MY1NP-#k0elxYu!7ISdX!8;+s+a z82dA){#ee^IA%BAAN#>Llq2)NODlhMiV6o3`dA$Qk)P%9t(yKQ{Op@c=W)@VD}N%q zyuQAdV2<%3;yl@sE$?x{x)FGiQ@o=zqZI^6PlSy35y5Y}Yj|8^pfzl1R2$Y;ikKew z?BpMwZ-;y?!;?<4-184_ChAW+ReFYu-DWc*P1M2};N#O#|6 zRo$?osGeWYM&iW6Y>UctvZvgteS5%9D|4q0Q~FL<71s9=CeO`W?%t-kHm6P*j&J76 zWXI}y-V^atD>FNv8CfW017E&tH@ugN!s_CsFJhb+gQ{^yBRI zu{Z7&BSq)2ZpX1-2{LA*s$N=uzo0L4kT+GNh>s=U^IMfnWp-}(m533}mUx{@#98m) z$FR1}QMuWBX)u0(Hm`Xvs)&jlFHCo!N|-1^fOL^>4ZT0QaK8~b&^sP`!>Do%ySV%)xjt$ce#^~V$YJ_is%yHiy-1^_pA#k) z+hMfJzVJr-To9P85G$2(LkYTHJ1Ve>L0=T{C|g|8VJ@_b$pG@pu#d0C08Rsr3lunD zq$__D|46rL)aR_4t7OZtawA%g`N5C8BQ)M5=2Fz?1@h8o3`_`ilnpG{1 zu{)J|I@O1dTVXuv7fb4gr-VmCJ<1*}nmbG(`UvByg|}gOrK=0nQzvI74!w8ELahBY z1}Cn5rJ|FWkux2=`R~qC?>10XyiY0>^;?(LH5R3)x6SKmd+KkJqOam9fk z#GR<3%!)jKzSmB87nhoH4njE%g$*O>Az^-toU79m?zJz0XsTZ05Ryw5*0=*jw)nF| z@cHUcwo$C|2-c2D)ZO6tPa$Hxh3Dr_+@Y|BlLTAo6rAdmRwmOA`13vz?flU{IPyi# zvpy7}KA2#dEx;UnDBbK&dgc6ge#OGW&C0>a%KBf^ ztG|;$7VuGVpxeK4!9O_{IRAV-7yWmV_!ooruXOLv^FPwPe{fX)m61BTsQ#hZ{;i#j zjfDqHq2*-zkNW?b(ftG3`uBqSV=B# z-rj9Fa~pd-03RmIxw?ehM(kxNQn9)pj-U1q{EX;eIxGA;+*VL^7oQ^ypKYMxZRL}m z9uKq6svI9qu~oVaADf5nZhklNrRMMlJ+0+aJzY#3-+)#?&naAo4UMReyNx$vE0&`E zv0R|Ms38zY$jB06EdhD>6x2sztGLG`ah=_WBwLIRJqPnTK8LeSv|IKxJ^haEnc2D;1y<_ zQfDenn?-D~4pgK}woRqX(1dwQnD8@MF>u+y3}{sQ{r*b|u<5ZN`t*vRj18OCeqW}W z6F0rx1_kCgrdWMZg_A|g;bC~#7>z4)tH5uXew6zx*Foeo2KEDpHdeh>q=Qes(bba| z`ko&JxoV zogcU>w5FOPmS*)PC&s_D&u#mUSn84@I9pHHm#Ii-M!K_T4rrR8W_C3q`j6uvxo9w_ zn>&*T0PYx@ukL6xHp)2GV7d!_ThU0^)(xSsk`NZYSzDMl|DB5n9r@<_{I6)&-Hygn zt}xRH&_hKNLP~~gjobz;^j9-)T}%S*hs6TB+C%dd%{FqgZCRJNDmM8w2%k(<`lYO z)*mE?l-IQ5ZQ|Z1bPSoAT96wA;W`zi*zV|xz$b5fp1UYy2q9*&?d^#Q9Ow&!(EVu7 zs|Uix^eGB9TGV5v*mIBy>&0r}q4nCXgGV8S!kkVh?UQEz3VumF9zfyzuHLd;|C*JM zW<$HVLblO%9R96x&wAO?1!Xox-dn_2=CR|jWU6$TR|Lj<4v^K61 z&AKmA!`L&+7`Z#7O$wmNT6Gy{t9(cZY^R)$T+lQ%{SKS?mdGF{ht>vx*8~_?75v+N z9_J}>l$tx1q+z(5b6bt(eO>ntx-=Y1hd3A4tgp!|${5&G22<14 z_EvrDT}@l01^_bTx+%I98*ZE@6b4CjbNwtkr0#PX-5ee5q$mVRPY%w<%@^&FYhuzc zI&}afV+c()T0qV*;&OX6M~9lKkBlBuYt7eQuVr@}(Rb$|L-9qOJrWKVZ+M>&T@kW( zq@g%{X9Nh;cc8Eg)S9dJYN|2lSzruCY8ElB`fSkY^NwW_OYv#2RU-Oz;sMcpv0b4s zUrMDpq%MaXVs7fq_NSh|T!Rn5)}z8CTC>oc$K4e`MO_r5j6h}w={y8jc%?hW7C`-U zU8s{pN!gTp8#c9Avrqj=&}EG5iX}IXK2=+q9LmP`Ghd`*#EhDzNnjT-y=lNnD0*&@ zBwX*?Q+T&1!CnM`CNOh+mIPP)XEHVheFzU&HfW|P*j(DfEU+>Dw z5}53aL*3s7%~ne(uBFuRsR5gY zyOGKCIH?_>8%CQkEcbsk_ZCobE!);G?(Py?gF|-%O@QF;1b24{?iw^maCf)h5FmJf z1b27W0KtNVuak4nJvr~)_wN12H^x7{!PujFZ)(@7sx4i!)|zu&&#>q_Vzh`2pxIsL zw>uc_z=R`>FSpb%10_BUlfgSVurE!2eD#7GFZ`o(>&HNps_%80<>B{EQ}ss{sP5+I zG;3DiFbq*_E@?f40W=VUY_UqlfK4sl%k#jgEHXr@I7I~O^I?ZnZ?Oaw*CTzbPnHBh z0=G+Fb)8Pb0evQSi=_t)O8ui&UWFhw(aZbJ0f)}hwJ6T5y<47}F90nLfzx-W_ovZ0 z93$tC;g}S1C2X6;RJm=ea_F?xnSFU4%YZz7qc9ReQLh*T9(trwAFU#5&Ylb1$f6&4OC_P|@w2CThC7S`tq}~|3)v)c%2q`< zF#K`Nj7L0ERGzzz#MXX{;?JbJ@JLIzhytIvG=De1ma{}sWO??igql$>^@XHG^^?^K>!hpQk z;LoT!)|?wfP%z;>c#rIktT80cqySd}uh#`+=_svD7Lt80!VWhWkzdk_$NI(0p|F-+ z5W=$cfEZIVI?(V{(BU{AP*8HJ*m8Q_#3IF@hLwFXqi48O9ivnGKw!wiZ-}f5n9k6! z$_(kdONr-kKNAi`i%o6&Mwnzmzq;!c8;L;POPLLceJ2P};r}K@nj3R^vy#5(_JxRy}`}v#nx<}A7izs>{exLPFigTky zcLi)%RK=&D>a)PN1lK_sWTo=DUYi!E;-n@P8>yG<`z>yQB$nIkO9+j7Uc&s1LGdH* zKtFDuLVzNK=I!f6gT%PT#Q&OMG`iGmSn?=Vu2|dJ!R!uto>WK@wx%D#wcj(;{m5*B zC^~r}bi#4*2=@xBAWPlYlLC7(D=g_b`0`CH57jEwcX63s6hf}v+bQMc3&yDQUIQ-}3E?-;pLYif91@i zUMH;DPY5KDUo~!ZrCO+KTIn<@3r? zbS)uxVsU%X3Tq%_469`yEX`<=T!|(OyQ!U;coQKiE`=Um;;)Rcz zwhd%23>~DfDUmT9aScCR{}5GLJ6hFq5}`I(!kkgnhXp3l;w!im}TgD zG|$N=%r}w<3Tn5r700`5MHt`gUMNk{^%n}A<`HD{vVGJ^fgO-z|5MPwy=D6sQMalVN$1UY{$Y6H^nksLe@p^MFZt!54PL(l1e96tx{35FgyWc}BIH9w9iy}d^7h*hMb*%Tcj{~?$5r!$n36UfO8@i_klm;Z2v{sGc|L1*?qK>B}i*!~iy`?Kah zh3)>YVDxX=a6hT4|MVsQS{(Q{+HVjS_}_e_zxMwb z3MS|o3@tRlXQO)bZLIBaJyl%FdE|F3+oxeJT5N5MvQF}fr)Cozt!;z(bdj;Km_fFGpx8dM~%crVMU-{S{~7Qi4@GpRNgiOesEP zFw%CM56SJN9PE+FFL{Kwp6*KM>#=UzTs>XG^%sOKDw8CLn{>&X)rf;r zyo47zk2Bmu>0Jf|!iYCEDQqwRLscmr`kXfQ#w*y=SmLx5&COI-EERuv^rhPSMdZ)4 z6v(s4ljr4`04X6Y^mutJY}fgBCzf6Clmfh5FI5e|KEO&FWPE61ThghR+1%*F%dVqu zE{u!Qnr-5^T&4p4-d3-pZn`~JIT{Ze_@7S9Nz5^}^TUVo-)Dh~Oan>^c?ubFx+f%kJDG6 zl^GNZo1sL*gRhw^+qvHMygRB(oNH1?$Oh87FE;es2B61Ww^a1l;_-e{a<`8jdwlNV zL-yJ3B{p;SgAQ$JTRUI1UovOcS$gip>(nR=A-;@+wUgKFm6B+RlR{w`CHa{CRh)|? zlnpNUql^6B>%c%HZ2qwehGgQF4xT{9`HWa_gcoELib_{jUW!pOGVO!nCmYQtxvO z*s$1uf;%tzZ@Zw#;Lrqha0{ja*B#XN3aT)6ox3o#-utK+&qx5#O?nKOHLIhgj}`m0 zuKP7#SJG9cR?i`t35)AdNWnLZ9Vh9(Sz{4(+-XW!O97CiCg_x7Pg!=r}g?A9ie#PNow z!VC5Y!Nsh!xUd6LooP)5D-A{Rmh~Q$#a6h^JsD3iP3Tw+sN{`ytGlI}S*|d1ZSC(B zYRsl^aIaV%#}*n)S=70#kD_#QX5s~T#Rv-WXg}dVqcN(OYF1!QR7nG;Jg5H>X2d_#XG z`=L;@sx7^762nv^vC;?K+vP2a35??FCfZn-JJvL-cuKb3^cj)44eZ)ZdD|g!#P`ah z0S6ZP*i=Jl)LichB8I7JI4ip8JVN4mS>~;S8?|4TiVY;T)5*6aIfzJOE^X&%qscz6 zaFk23!1yB1N|{W=tu=lj-M7=gFTPv#8jFcv^IG$Rmt6}od3Y)lo@E54W6SKK-iwwf za#b^s&h~uwH@QGPLT!PP_=^X8^<6LU4p!0sOJ6Jk$?`6vrkQGxY*Sy^tju}jui zTO3n^GRyT@QrY6XDz2ywJ(;BZF*27VF%`+1dGq@A!PYmyIrgeSbj}#|aob}<_C^`a zY&ATN69;`?uRFdc<YSQ0o*il?3U%;hf`x{~mYqC`w+Ct2g>nhjx-?8=;A zoKD<+Y;2dqtBY>L0g|8E$Sw)7Q17?HEgrA9s-jyRgt~@$;4)t+5kGI~lQmF^(0KD) zeRo4yt?c4p@p!wlWjPbE4>S+&8S1yijeh8 z98b@CT+d^S!J&^_ZaHIn7EsB7jl`~xg*>Lr5#Y6nuU(5HPznPgqxPHK#`KH);(HjA zo=dtZQl)nIhJ6|57cnYxeU`b6-Wo0CI&EmP)sfha9_irEkACQcG@5dQi7aZZBp5~E z6V}G(mF%krn-`piRzvRQb0oplJjS+3MTOMM{UO4VXr2b>iY)4P$Zu4JvieQ)tBk|w zzaM;H!|vH;Qn=Id4(2AtNYU+EzsaPKHNk*NYC-!HC}oLc(&rrGa>|j7!Y}ofvI(eJ zuFj@Gzq}+TT=z~z-g@n8kXgZsX8g4Tjx5AO|@>Q{(Khio% zs0*<`J6w)_1vn={oPIlBXwtMua>JD>m`Ze%%ysJ%Mz?; z28&aDFY(fA-2eZgw*8^ZhqD?|p=;rrbNt_B1<5Q;+5x6SfdF~Z53$a6;pnRC? z@@7Qcmd~^)-m@mLbHlEG`)sCMI=Fl=yt}Z)?wVLot(>NaK;CUG11x(Fl>;LwgU!Ui z*VG+hW9wsnqSz6yb&67j>vHU~QzL;N(Wqu{7$aCbD1vqDQAmfV+a+QK3h6Oig$fsC zWghgCDqFH2pbD?p;R-z~a-}ao^c^rU?N3u#_Xv=E_E=b{p|q6G(FS4cX$5ml@4 zAXj=n)JzQ|BW+_5>}tc8hsXqXCo<2JOcYpbdyeSKz*&rCA21Cm|F9723r0ptQtz{z zBOsjn49DPxJ*#oIn7=~E*Ls3vYg1m9yLp%VEtdK5I+%QMB+OeyFw#0#wX=u(jE|LCzhR6GEC-=%9?2uYO_W$6BSkA zLDTk${;VnRq<{t!>;RrA3Ac-9YIUuk&hngNyrHyU^AyEd@#$1=iG$6Z?7%DXTu(B@Sl0y16$2xM@>`SoSqDenu+DWFMt zKUpW}gU6eb3S^fw>H}&x29Zy!1M2LIPdv#n_QQ)xajIhQlzDRt*30S^Vo$L9ZW0aa z7q01Zxn~y#%^hZ$#3W3dE6k4FXP0xS0Ey$eTc!x0kS=WHgKqoIgs-$?CP!W|j3UF%*Rq^2&ef&#Iry ze*uF)>RIEaZr_E2TYwvo8~h$xwmX+>_i#!0?b2|Q-B%o*W6~&vti6#cvSRRRh8s1o zWijx}Y8*MVJaW6>35TgtJMx6asA!Upy{C>`gJQc!9!1FK3K7bBP*!bj7EwaaGF@6> z3_9ABemS4Mqf6kBkmvpbb+KbAD4#939AV#E>v_MD2ZFSs!kKHu#}rMN2y3px!**5l|xR9d+|NSC7EI~fA zLG@FG#Un)!56j}e0PX)Rs`;n36vWm3GuGPqS7`GunI}qN6DJ2_BNs}yKLp?Z^uPl+ zIJh`LAm0Dxg8v2T|M0f|=6wFI5zaqj@&747^}CoB7wA7!(-Lv8HU0l8rSBRJrvkQOAM9fJ7(pAgc5#M1wL@!_`s?LVco035u$|BI9s7XbXb zl$NVHvJ##KiQnnfk$q?&u~(|7c#IJ*ys)_;y=A^3e>iaqS~vnCf)U5F{Ak87Fxq*k z8V}C28cp1KNE`io!q!h8c4~JW(fiD+#BgPuKj@I#v`D)ph!ih$dIxAq+qt)UKHhzQ zI(_pJcZprL3NCH z6rSn%Wp-_*0ilZzW41`vS_9ZxUCLjx3U!p<*Z9>;>a8E_kxoraMVZbq#tP3@Xx@ZQ z#qvt4Z_gh089vY|LY|-IX+51lUQOz&l(PaIb&XDAOU$~SyS!t}FPg-__M5k&lClko zKM>2z07!cGN4FF^xBca*A0^w`bIRTBle*iUecFDp{-Sea)&A@?RCY6)K#r9NOiGkE2+u=J` z$C;T6A8_-isxgCe#JFJ!1-=2&`>q+|l+9*h>Wqd1l}DZSfsfGm0KL)#E0HgkOiZT1 zN(@>td{*pC=BK?EN~t9UdJlx9xVsA4F$(qExt37)z1}CsiyQmI+nCN!ncp~92g13i z4GYm>a{~A+DZBz`YEd1!Q^MmC6C@^OzjDRNVNZ?dS|C_G)01|e>iqIt6kW9Wyd)qe z@EIxKfphm(s8K3B90#W|$jjYtjq$9yJ(*00A2R4KF@7_JRDbI z9v7)5KQmap+~`x21W84hjgI?%?!*7=1&6|iPx3hufm`XCscm=~S3v?(-_?nQPu&5y zSn2j6_nna=aA?Bi^%O-^&|_~r`5^i3-7ibBTnK9j|=Ns zK8Dt?)~$uPmtIyo28&Mm_ZvzBH>8LZ^53@i z)My#JzhziU4;GI#gR_dNIuxy6%@u<1Z9;_$y4O6L!iSX)*bZ)EOzx z?Rvb-eGfRGJ6Naj+!x$3%(6s785y^92}BTmr#=u7PJwZTvaOmT_`Imc+MNh5u&)p~ z85q`U&OtgHv?`^pB^$50h%$7;|0Ll)0iVg{dp0cJeobm(xx1tz^_gVs5wW?w8Bh!z z8`8Cfw+Q8mi^w#2J~44vvu;?Z{&v~`c-tc*H7>j=p=OH3QcI9#=$K*c&MWcCwAmzk z3(YI-5U6rB(_5kXK%dmvYWaGgCou4$@7A-eo|#~|%S7G2YAi>;DVtmOVccf%ybv(B zFyV6iE>iaSpkkd*yzNbsvUc(do54uyt~uoI3XWb%s(6v332q`4N_nzF8uO+9_+CX~-R=0Nf-ELuU+pRcK z2Se{$%`){D1?^n7<(gge?ykq;n;Sn*^c=L$Oc_*gocivq_}*hM>R~km+(VNF!zkd; z8vAQ)ITc_Je=s=geST&uR$-P)jEjOe1NX-9nF@SaA7}5ewrfZEyQ3*X^~6J2n^#dR zhPaM43e<(yBRV6ircHM8SDbSn6Kq=P9PSqpvrtK1edkcn7dz7MZFfIPzy9>;{+zR- z$eECH$xGfgTN&iqz_x%;D(hbu=7qc&&RF9Yd-dEJdRo2QWCustI^NF1U=hTav@!J5 zb=y9<5dYF{zVkYRbbB;*@=LJonEt`?jo#x=`&uT?Mp+HURp8J|K!CY!{S$%Hh|b!)ZjC?wL~b1a#S~SOCSHmW2?Yth zd~omx)936o!U17a!+}ACDkX+GlWw32y}581+FA(v*ElyyXJ`_$v8;AV-*|)h?YO)A zT{$+#0a;)7&5+N7GsLX^QYf|A`B#L37ya=g(IclHPflnuoNbPwhVRK-+XcbQTsJK} zwiJSkRhP8uFkUznK)R&Ey<$`O?;u(O9Tc#i-eE?kWrF1EXKE{V^#k<-k`DoxvU?>{5+x77Xbwo#yv5w)R2$3(hG6eHUahTJ^J<>? z_>Ts)Y-BGI&RYDq-=aHBAsn-D7Zm7KQC6?}5|L#rsh?`bA;`*V^ziAj@KXpYor9a4 z)EyVob0$91AXc`fb#a50M%bg=GbR5}+z9FkMLf^+ko7oL48yp#{!wBxGk|&P zN*!ex>Wv&T%jaPh#?0NNggToAK)58|XBR`t0-85Q5uX7aGRYT|LZ$Zo!=H7H=_5W_ zBaJCZCf(>KxkM=~i||&z+Hv5%zt^GuPUu+M5Gw%S2u|GGqpmpG+{&<)n=~@h7#hxcBKVSsSMftB;&X}E)fawzPc9%(-9j{B) zZx^zH;?$omc_kK$k_@8T!|r1lHmpd4jg`ima`6&9WP+2u21j#;r`TRC1mcX-P{Uhd zqQoI8A$!4u+{-9RmpZ*^g3odk4d)kq;e~USk|lJOVoLd47Pfm00|ftI=8g40*TVyH zaj-hAgY7KX`et55nqh$Vvf4}~tN5NRt(!$_=mNGPzr_1rT!G)?dVl&7f8v0@rv3kd zH~c@Kh5sK}!@uyy&$|YKMgC;l{`};IpaE_Ovla*fQUU=$2qPG>L72P%4hZ8H%t6Tm zN%#bUFk!htJd|KwNO{QTFV-&*at@g1S2=E8@IP6&zp{V*KjUWw{0i0n3q1bX|F_Q$ zC)eN5O`o=&%`rFDBl8{n;jrZ;d=X|ylVcucv(~=ofoRmN9rf-s~ls(!mS~!J*^eJzBgHKZSUG$i{?6~V;Qbi#`LMmrV?BPvyy}>z);?1 z4dO>pd;;Y!I}nB70^S}g)+HQUfGy12zdb!-`e%2P<|s77@KuI{XB#l7 zm*Zln-`;iN2QGbH)U@cG=BJ1qAqT++XJ!nY&kqaZisk5BY|Klk7rcI@4LO2V*ezYN ztQ!+%el0wJB`+ZWDL#7`&TT$@aUR;E700D;`5xW#hnpTwaT?In-pWIH6*hy3mi(x8 zzs?|5TpyNhtm-Ht{>SafYx;dG`$Sy29Hnd7RFq++wWPxgpk!SQ?wQo?sU=P& zs6Htoo`|9#v}Hvoa3s6x!k1R5$l{rG!D={~R_Fu$u2h-({55sGoo_8+Ws4_V!pnJ? zm6n+B%k)Hw#5*j#pKcyA4?F_1ZsmpoKCL1QL^L}W8#08OB8{Fm6-JjVV5;hk=)YTc zJwrI=3vZDd@5!Hbj0f|tY8vmQH$FiV7Hv)c_us=`nGFAfw<_=Ne2{4Mr5HUB+GEl~ zm$b=?QE?G|N@yHKc(Mq@PofJaU9eSRIuUCYtQMz$dpQfHVws!Tt@)uC_U8w8oR0}8 zKR^@HCB?C)lhp^JtU~wyR!+X@MhSL zUvX6@Pgu>IG_geQ;<|Vxo6nj7qU?B$@W6GRR=yi~Dpj5>OYBS^h;<#A>7f(9P$$EB z^+}DQ#{QkpE04_+^Jd&?S@P-Ele5k?ZrrUzOUR3x&(<-?6jzo;^IXWHIiIW3i4a4K zqQ=No!4$<9=tt-IT-}ZAjhzbmNiCIVROg*dT|-O2Av;ruI;P*mVV&xhE6O&)^0Uz5 zM_ze})pE)3kQXqnkGdsK^Eqd%-b+(?>fw!^hGM6l&?0viqo+NTjx%bkC?q>no?vf8 z-|P>_FW_4A?nWMrVQWP6#7(2%c&QC{Z$7!BRk4D2w!ezG2{OoL(P>Dw`kjkk`?Msy>WR&yff13HaIe8j?q^ld6FLI7aYF2xCw5+M zRc4E`PUPXudfMQjF2QEY1*AFBmz%njO$qTYNEneU{6&5EkV$PxkWz%O+8f_^WtX?; zG+<_zYgwZUmq3pw+#Vy)?RzOpB{&~OD|k9i{A5awhx2H)gvQ3#u5o%NbYesl-$09&!;H?cn7i4}@d z<rpzJV|;m0P3~r!7&~QS-@+VPjCfw}Q0#~IUC73iHLs)0 zGeRjJL@kOoCat=a-E$EPyZq{d=LtS|jVtjSAiXCvwDjOyIsCS!Y|BA24840$SlPvG zy6ZGb?7f};;&8^G9xde$q_lDyh1K#Qnk4@%Q8WZ%`XkjCkYZ1b(4S1 z!S1k#3N&i@Xn~gLzG!41<%);)=6j*??1C_4eCFC6sOLP5SsobY#wV#)gqmFYW{m66 zN9BjzW2T3lJq*&=lnpW_H+zU*&_{Y|ezGWm5v~>IHg0U;_T@ik=Ewio5#@doofYCrEt&$4Q(k2(Qzex}naWYLD%louQD-By7zQX9 z9K4Iwx?>M4z-}5{2mJW5GD=+5aWHx1K0Nwu1lpDjIthYJ=A4&`yC3v2CNu`RpfOW= z&l556m?8oYR17`@<0wWT5XiX2Ig31l`hjY;X|UR}}YC zN5`^kY*0{-KW_oH;Ez+Qktpepu^XPCdNu>y|HYg1H(418S9_D6Ixs(78W2?=5i1vG zB{L^gBRfbM4NBfWQf5#B*u@;|jI8W`rs~jRS241;F#Guxf)IagdhDuJUS>Lww6p)n zZTgqS%G1+RUf#cemk|v#TLj5g`zwA??_V}T3sju6UtxR`%RJu zB6Rf6?*1dK??2ijZ{*@+<)H&$Dk@N#>(+$9%42JCkytUdp|QC|H`fM^X~ikqYd~C&Hm49PA+bq-(yc#w1*;1Td*JT ztI%DmkU~Uoh}aQqdjkmV2t7E5jp^HLNL0-n9Ukrl848C7Edw5Z`0`C=2Ynzvcslq5R6F~8SmT_ra}lE4luWf& zLCQ{WN6#ATdDC(wj(NBDYQ5udC%0Ly{i1jBo(}UFXF0J?WHYK?>oJlyirx1MkdFR0 zT;(_LWX_{C{HR33ZW>wfJYlNYtU>#RnbgBEtj?Fq7hc(zV`~=YbA*f65>4qHipf7v zHgh~ug&(1i{XaF24UljhyX^0BeX8NTIOcqOWLbT0@a$jbF8tue$0g0T4OIY*)BhtB~(6@v?wVT zG$gM932nPU1+wb2*Wv)KM>kWNL6&R-zjynfWiYXDH(irWPhzTGi@ z@n%9cSg;(@u`61AwN1OWA!GI3{p4$A*MusqYeTzK+vSPuo#Y*%zzM6)vyV%-K`vZq zP4GbI*@^T!SWrRsL;r0>6s?5Rfapefg-#hUeY%A{``94NFp%o~dL==*?#J_+2v zfuFfRhorX*yiM$hO%53e-cOZrvzeZAK|d%)#O=i;{2Kf@(1?XhvTi zZzTZ}G$bJU8uHflsljp5L?T z*gM)+X+SNS3p#sKvv{{G6%`OQ!rd79h+t<-G1=~_JF*2b-QzwEZB~O$K%(pF=@ReT zYU$2Q9YHnKVAiquj6MjxXXTLLN&+2DB*Tp1HQ_Nd9U6vzE6qID(ag17?a~&C{!HCh z*N^d@HTK{r5vHWHsW;9MWB&P74M`{tQE5x)w&0e!j*@BP+mNV)+MvYTJkqg*uL8bLd4`&hoy*>c%zEqrg=N@#@(?A9E*cDi9c>^NdVdEU5&E z1_^sdOY0ynCKomW-no44U#vIqj1r(@`2@h>*O{@%CcN`+uen#Pq+HyMg2 z?2&I}Q^btLTaQ`BWClb#=}8tl%g)jy?~VRQC-)vKQqUb}BpzLVV>w1zi=wv}jt;7<|MrKn*nmE?meCt>ddt5hlqAM^KSzcQ?VY ziT}F7REyFkx(yd|SwuK5evZ4~IFd}T}>bv?6lQM?PwIdt4qNx)nFk1M+ zrg3gGj-?WCy(#EiOe7US!Jlx83CoE}-oor4punUfX{JYfW+qeE#5e`1y@}JHM}IAv zKvmV+B}4Y1oA5=M$QY9kq9mH?IQbW9%ln1*U7x>tGoKbul!=T-T{EWf2cW%^xh%yp zW@NYX=|j)s(+o`{8)b!3%qOY@qCPws6p@x zb|IH>@JjgOXZp2MNodFIS_G|mWA*i;u1D_cM%cwYS2}Tt*PGSU-4haLM|vqTuY>zf zu{E)&1zsn#Xw|SUYqtxuCHaN<_MXOInd{>1ce5!&d+pJiA;=S-P;TL>LxtN(qwiDM ztp%gEo5&PLRYI$*t^)!~?8aXOvf zI2}$HK#8r>G?CR1G4uPYn26_Agik5a8p}IpfhZIqbQliv@JD@`P$-^c27mNdNIpp| zN=C?>g_+ors6>5tmeT(raI3h+mY_6!uaEHv+c@XKFK%sHm7XY^=f)NVuE@;!Y zgN}$gK?pG10o{fwnk1|}5>cH20mzuLmak+!z>zYcaICGM$S4P)$~R~&&B?q{)+914KTER`BQ_`V+0Z2z0XV;fLI)4+ z8(AQbSy3ow)CTd9FjvVbzIx+7&MNg|RkCic2}9Fhj85u{jek*3>4!cBvXhMS!>i0x z%>!YDoHQ6{XIApwVdZHn$8*hfOpcyp(Ab57FcfTqtYzUPuB>)mq?nzPX~5RAw%CK& zo^%4gX!AFH81{(!l5-JCAqG${`$G@rbL&~c!kcIdqm}!cYKTN)p^8{)Rf_@*@rOxP zZl8(v0Moo0&hL{3G>NOK0p$GY^VnkvFGQox#PqU}z)%I2J-d;OxdQCzJBXKtoCpG@ ze55b>jW#$5J!Fee7h*C;e zU8#{Ke(9`gVQ}^DjhdhhwD39F`eQ6F76fTRP*|8bQjnRQ-`>KL4R&lJR#MM{5%LY5 z8%c5B8tobnjgpV36LpZQ=W9UABp_~^>_Iy~)$@u{JHJ3>mlGaHhT`BBWh8Q)^dYW& zi*IN0{<90B1={3duq_{GhA7&Da_o^`a?Ixja~p8EbM%KGiuJeVpHC(Ac<#^_mSH1SQbVLJwy!$deP5Qc_n1? z$*3F+b?Z{E?w<*5o`htR%+SOZC(24KrlAUE^~ba@z1ZWkveba32^yZVKGxXr+~I7R zR-VO1jcF&Z=WpREM6#IPiNd0(pGZd)>X)fGJ9u{4DO_)lpjX@m&L$@y4-S51ASpBc zaJ!SXbC8Ajs^tg5{@0=u%_sPmy}teb0xJDiT@+z^dxyUQ!Ty>@^FU-yK^$yg9w0;r z6$Ei-aC7rOU;{T00+^I2f6>JL}#uKaI(<^-~FfjK!KBCtRE4B+^qE&q}Ae`@0V z&G=8I-G68t1O~BzfnW&f?w4^+u0NXc9~u8k66bH$e?!LqZr~y6uxyZIj}U#^pVmQO zz#nb-kE{d#$uRtz_1{48zqJkmvvF~QxB-7y=K=lEmjB55U!jnHv;G@q{;6E+41sz- zb%~vIAa^I^yO_=|jLEL4r43QarR3)2W`o@E5R7i`YHJI@-i-gep1%r1fHMS<{#hEp z%gM&g%L55j{Im35jrdjk7jyEj;v6702Rr;R_M*pI6P9DhEL(nqtpT++g-#?1~ z3XA-+Eu26g8<-Q!{a5XOJqN#v|Gni9*w4%LQ@;2gEr+afSlL0ANq!Cs<6mb&M&P#x z_&2;SEvCcI4dyX7Gvzeq1VXqMARrGA1m@%cLPVKBCdQnc#sFSZGY&Ijb1qH}kQo4M zYGz{0!^34{%EbxbF*4)i;S&76uK}`dznRokST(A9sc$ z(N-%R#)i-&7+5Ha7?Ef3U4Ad~8I*Ee<4Rl%Be(cD6rBd+ci|RhNEWvsl+M!c#-#V6 zv9hmP@(w=^P$&r)c~4`UMDc0id9AsUgWulmk5II003H1`n^;MT?85qqffqO4 wQwo-=H4Y7>3xszb>l7GBZa3fH=TF6goO_MG2Ju1E@@S3jhEB literal 0 HcmV?d00001 diff --git a/hx b/hx new file mode 100644 index 00000000..e69de29b diff --git a/integration_test/app_test.dart b/integration_test/app_test.dart index 6267453a..c2b4bbb9 100644 --- a/integration_test/app_test.dart +++ b/integration_test/app_test.dart @@ -1,5 +1,4 @@ import 'dart:collection'; -import 'dart:math'; import 'package:app_tracking_transparency/app_tracking_transparency.dart'; import 'package:firebase_core/firebase_core.dart'; @@ -7,12 +6,9 @@ import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:go_router/go_router.dart'; import 'package:hub/components/molecular_components/throw_exception/throw_exception_widget.dart'; import 'package:hub/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart'; import 'package:hub/components/templates_components/card_item_template_component/card_item_template_component_widget.dart'; -import 'package:hub/components/templates_components/forgot_password_template_component/forgot_password_template_component_widget.dart'; import 'package:hub/features/backend/api_requests/index.dart'; import 'package:hub/features/local/index.dart'; import 'package:hub/features/menu/index.dart'; @@ -22,12 +18,9 @@ import 'package:hub/features/notification/index.dart'; import 'package:hub/features/storage/index.dart'; import 'package:hub/flutter_flow/index.dart' as ff; import 'package:hub/flutter_flow/index.dart'; -import 'package:hub/initialization.dart'; import 'package:hub/main.dart'; -import 'package:hub/pages/forgot_password_page/forgot_password_screen.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:flutter_web_plugins/url_strategy.dart'; -import 'package:patrol/patrol.dart'; import 'app_test.dart'; import 'fuzzer/fuzzer.dart'; diff --git a/integration_test/auth_test.dart b/integration_test/auth_test.dart index 4045cfc3..a60a5b1f 100644 --- a/integration_test/auth_test.dart +++ b/integration_test/auth_test.dart @@ -255,10 +255,3 @@ Future _submit( _navigateBackUsingSystemGesture(); } } - -String _generateRandomString(int length) { - const chars = 'abcdefghijklmnopqrstuvwxyz0123456789'; - final rand = Random(); - return List.generate(length, (index) => chars[rand.nextInt(chars.length)]) - .join(); -} diff --git a/lib/components/atomic_components/shared_components_atoms/toast.dart b/lib/components/atomic_components/shared_components_atoms/toast.dart index 1be2a15e..30cc5332 100644 --- a/lib/components/atomic_components/shared_components_atoms/toast.dart +++ b/lib/components/atomic_components/shared_components_atoms/toast.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:hub/shared/utils/limited_text_size.dart'; class ToastUtil { static void showToast({ diff --git a/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart b/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart index b832653e..00f5922e 100644 --- a/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart +++ b/lib/components/organism_components/bottom_arrow_linked_locals_component/bottom_arrow_linked_locals_component_widget.dart @@ -14,6 +14,7 @@ import 'package:hub/shared/utils/log_util.dart'; import '/flutter_flow/flutter_flow_theme.dart'; +// ignore: must_be_immutable class BottomArrowLinkedLocalsComponentWidget extends StatefulWidget { BottomArrowLinkedLocalsComponentWidget({super.key, required this.response}); ApiCallResponse? response; diff --git a/lib/components/templates_components/card_item_template_component/card_item_template_component_widget.dart b/lib/components/templates_components/card_item_template_component/card_item_template_component_widget.dart index 9c96f384..a5527a22 100644 --- a/lib/components/templates_components/card_item_template_component/card_item_template_component_widget.dart +++ b/lib/components/templates_components/card_item_template_component/card_item_template_component_widget.dart @@ -4,7 +4,6 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hub/shared/utils/limited_text_size.dart'; -import 'package:material_symbols_icons/symbols.dart'; import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; diff --git a/lib/components/templates_components/message_notificaion_modal_template_component/message_notification_widget.dart b/lib/components/templates_components/message_notificaion_modal_template_component/message_notification_widget.dart index 1039a738..733f058e 100644 --- a/lib/components/templates_components/message_notificaion_modal_template_component/message_notification_widget.dart +++ b/lib/components/templates_components/message_notificaion_modal_template_component/message_notification_widget.dart @@ -60,8 +60,7 @@ class _MessageNotificationModalTemplateComponentWidgetState @override Widget build(BuildContext context) { double limitedBodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context); - double limitedSubHeaderFontSize = - LimitedFontSizeUtil.getSubHeaderFontSize(context); + LimitedFontSizeUtil.getSubHeaderFontSize(context); return Container( width: MediaQuery.sizeOf(context).width, diff --git a/lib/components/templates_components/provisional_schedule_template/provisional_schedule_template_model.dart b/lib/components/templates_components/provisional_schedule_template/provisional_schedule_template_model.dart index c1e82767..2985cbba 100644 --- a/lib/components/templates_components/provisional_schedule_template/provisional_schedule_template_model.dart +++ b/lib/components/templates_components/provisional_schedule_template/provisional_schedule_template_model.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:hub/components/templates_components/provisional_schedule_template/provisional_shcedule_template_widget.dart'; import 'package:hub/features/backend/index.dart'; diff --git a/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_widget.dart b/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_widget.dart index 4a9c5ebe..e17b808b 100644 --- a/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_widget.dart +++ b/lib/components/templates_components/regisiter_vistor_template_component/regisiter_vistor_template_component_widget.dart @@ -15,7 +15,6 @@ import '/flutter_flow/flutter_flow_theme.dart'; import '/flutter_flow/flutter_flow_util.dart'; import '/flutter_flow/flutter_flow_widgets.dart'; import '/flutter_flow/form_field_controller.dart'; -import '/flutter_flow/upload_data.dart'; import 'regisiter_vistor_template_component_model.dart'; export 'regisiter_vistor_template_component_model.dart'; @@ -35,7 +34,6 @@ class RegisiterVistorTemplateComponentWidget extends StatefulWidget { class _RegisiterVistorTemplateComponentWidgetState extends State { late RegisiterVistorTemplateComponentModel _model; - bool _isLoading = false; final scaffoldKey = GlobalKey(); bool _isVisitorRegistered = false; @@ -43,10 +41,6 @@ class _RegisiterVistorTemplateComponentWidgetState final _formKey = GlobalKey(); - void _resetForm() { - _formKey.currentState?.reset(); - } - @override void initState() { super.initState(); diff --git a/lib/components/templates_components/sign_up_template_component/sign_up_template_component_widget.dart b/lib/components/templates_components/sign_up_template_component/sign_up_template_component_widget.dart index 3ad2c626..be56144e 100644 --- a/lib/components/templates_components/sign_up_template_component/sign_up_template_component_widget.dart +++ b/lib/components/templates_components/sign_up_template_component/sign_up_template_component_widget.dart @@ -107,9 +107,9 @@ class _SignUpTemplateComponentWidgetState @override Widget build(BuildContext context) { - final MediaQueryData mediaQuery = MediaQuery.of(context); - final double screenWidth = mediaQuery.size.width; - final double screenHeight = mediaQuery.size.height; + // final MediaQueryData mediaQuery = MediaQuery.of(context); + // final double screenWidth = mediaQuery.size.width; + // final double screenHeight = mediaQuery.size.height; double limitedHeaderFontSize = LimitedFontSizeUtil.getHeaderFontSize(context); diff --git a/lib/core/meta/anotations.dart b/lib/core/meta/anotations.dart index af721eaa..842e5064 100644 --- a/lib/core/meta/anotations.dart +++ b/lib/core/meta/anotations.dart @@ -1,5 +1,3 @@ -import 'package:meta/meta.dart'; - class DeadCode { final String? desc; diff --git a/lib/features/backend/api_requests/api_calls.dart b/lib/features/backend/api_requests/api_calls.dart index 72d1a8a2..e4bdd4fc 100644 --- a/lib/features/backend/api_requests/api_calls.dart +++ b/lib/features/backend/api_requests/api_calls.dart @@ -1,3 +1,5 @@ +// ignore_for_file: unused_element + import 'dart:async'; import 'dart:convert'; import 'dart:developer'; diff --git a/lib/features/backend/schema/structs/device_struct.dart b/lib/features/backend/schema/structs/device_struct.dart index db8a8896..0bd580ec 100644 --- a/lib/features/backend/schema/structs/device_struct.dart +++ b/lib/features/backend/schema/structs/device_struct.dart @@ -3,8 +3,6 @@ import 'package:hub/features/backend/index.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; -import 'index.dart'; - class DeviceStruct extends BaseStruct { DeviceStruct({ String? devUUID, diff --git a/lib/features/documents/document_item_component.dart b/lib/features/documents/document_item_component.dart new file mode 100644 index 00000000..3c0ff117 --- /dev/null +++ b/lib/features/documents/document_item_component.dart @@ -0,0 +1,154 @@ +part of 'index.dart'; + +interface class Category extends Entity { + final Color color; + final String title; + + Category({ + required this.color, + required this.title, + }); +} + +interface class Document extends Entity { + final String title; + final String description; + final Category category; + final String to; + final String from; + final String createdAt; + final String updatedAt; + + Document({ + required this.createdAt, + required this.updatedAt, + required this.category, + required this.to, + required this.from, + required this.title, + required this.description, + }); +} + +class DocumentItem extends StatelessWidget { + final Document document; + + const DocumentItem({Key? key, required this.document}) : super(key: key); + + Tooltip _buildTooltip(String text, Color color, BuildContext context, + BoxConstraints constraints) { + final Color textColor = FlutterFlowTheme.of(context).info; + + final double boxHeight = MediaQuery.of(context).size.height * 0.02; + final double boxWidth = MediaQuery.of(context).size.height * 0.1; + + return Tooltip( + message: text, + child: Container( + width: boxWidth, + height: boxHeight, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(10), + ), + child: Center( + child: AutoText( + text, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: textColor, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + final Color primaryText = FlutterFlowTheme.of(context).primaryText; + final Color primaryColor = FlutterFlowTheme.of(context).primary; + + final TextStyle textStyleMajor = TextStyle( + color: primaryText, + fontWeight: FontWeight.bold, + ); + final TextStyle textStyleMinor = TextStyle( + color: primaryText, + fontWeight: FontWeight.normal, + fontStyle: FontStyle.italic, + ); + + return Padding( + padding: const EdgeInsets.all(8), + child: LayoutBuilder( + builder: (context, constraints) { + final double boxHeight = constraints.maxHeight > 350 + ? MediaQuery.of(context).size.height * 0.07 + : MediaQuery.of(context).size.height * 2; + + return InkWell( + onTap: () => print('Click'), + enableFeedback: true, + overlayColor: MaterialStateProperty.all(primaryColor), + borderRadius: BorderRadius.circular(10), + child: SizedBox( + height: boxHeight, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // const SizedBox(width: 10), + Icon(Icons.description, color: document.category.color), + // const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Tooltip( + message: document.title, + child: AutoText( + document.title, + style: textStyleMajor, + overflow: TextOverflow.ellipsis, + ), + ), + AutoText( + document.updatedAt, + style: textStyleMinor, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + _buildTooltip( + document.category.title, + document.category.color, + context, + constraints, + ), + ], + ), + ), + // const SizedBox(width: 10), + Center( + child: Icon( + Icons.arrow_right, + color: primaryText, + ), + ), + ], + ), + ), + ); + }, + ), + ); + } +} diff --git a/lib/features/documents/document_manager_screen.dart b/lib/features/documents/document_manager_screen.dart new file mode 100644 index 00000000..407a5427 --- /dev/null +++ b/lib/features/documents/document_manager_screen.dart @@ -0,0 +1,92 @@ +part of 'index.dart'; + +class DocumentManagerScreen extends StatelessScreen { + DocumentManagerScreen({ + super.key, + required this.documents, + required this.categories, + }); + + List documents; + final List categories; + + @override + Widget build(BuildContext context) { + final GlobalKey _listViewKey = + GlobalKey(); + + bool filter(document, query) { + final lowerQuery = query.toLowerCase(); + return document.title.toLowerCase().contains(lowerQuery) || + document.description.toLowerCase().contains(lowerQuery) || + document.category.title.toLowerCase().contains(lowerQuery) || + document.to.toLowerCase().contains(lowerQuery) || + document.from.toLowerCase().contains(lowerQuery) || + document.createdAt.toLowerCase().contains(lowerQuery) || + document.updatedAt.toLowerCase().contains(lowerQuery); + } + + DocumentItem itemBuilder(document) => DocumentItem(document: document); + + void filterByCategory(Category query) { + print('Test'); + final state = _listViewKey.currentState; + + if (state != null) { + state.safeSetState(() { + state.filteredItems = documents + .where((documents) => filter(documents, query.title)) + .toList(); + }); + } + } + + void unfilter(Category) { + final state = _listViewKey.currentState; + if (state != null) { + state.safeSetState(() { + state.filteredItems = documents; + }); + } + } + + final header = Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(15, 0, 50, 0), + child: Text('Últimos Documentos'), + ), + CategoryCarousel( + categories: categories, + onSelect: filterByCategory, + onUnselect: unfilter, + ), + ], + ); + List filterByString(String query) { + return documents.where((documents) => filter(documents, query)).toList(); + } + + final SizedBox space = SizedBox(height: 30); + + return Column( + children: [ + Expanded( + child: LocalSearchView( + key: _listViewKey, + header: header, + onSearch: filterByString, + list: documents, + itemBuilder: itemBuilder, + filter: filter, + ), + ), + ] // + .addToStart(space) + .addToEnd(space), + ); + } +} diff --git a/lib/features/documents/document_page_model.dart b/lib/features/documents/document_page_model.dart new file mode 100644 index 00000000..9ec58ac2 --- /dev/null +++ b/lib/features/documents/document_page_model.dart @@ -0,0 +1 @@ +part of 'index.dart'; diff --git a/lib/features/documents/document_page_widget.dart b/lib/features/documents/document_page_widget.dart new file mode 100644 index 00000000..99dc2849 --- /dev/null +++ b/lib/features/documents/document_page_widget.dart @@ -0,0 +1,70 @@ +part of 'index.dart'; + +List generateDocuments(int count) { + String str() => randomString(8, 8, true, true, true); + Color color() => randomColor(); + + return List.generate( + count, + (index) => Document( + title: 'Lorem Ipsum et Cetera $index', + description: 'Description for document $index', + category: Category(color: color(), title: str()), + to: str(), + from: str(), + createdAt: '00/00/0000', + updatedAt: '00/00/0000', + ), + ); +} + +List generateCategories(List documents) { + final Map categoryMap = {}; + + for (var document in documents) { + final category = document.category; + if (!categoryMap.containsKey(category.title)) { + categoryMap[category.title] = category; + } + } + + return categoryMap.values.toList(); +} + +class FREDocumentPage extends StatefulPage { + const FREDocumentPage({super.key}); + + @override + State createState() => _FREDocumentPageState(); +} + +class _FREDocumentPageState extends PageState { + @override + Widget build(BuildContext context) { + final String title = FFLocalizations.of(context) + .getVariableText(enText: 'Documents', ptText: 'Documentos'); + + return Scaffold( + appBar: buildAppBar(title, context), + body: buildBody(context), + ); + } + + late List documents; + late List categories; + + @override + void initState() { + super.initState(); + documents = generateDocuments(20); + categories = generateCategories(documents); + } + + Widget buildBody(BuildContext context) { + return DocumentManagerScreen( + documents: documents, + categories: categories, + ); + // return DocumentViewScreen(document: documents.first); + } +} diff --git a/lib/features/documents/document_viewer_screen.dart b/lib/features/documents/document_viewer_screen.dart new file mode 100644 index 00000000..9c4a0c63 --- /dev/null +++ b/lib/features/documents/document_viewer_screen.dart @@ -0,0 +1,48 @@ +part of 'index.dart'; + +class DocumentViewScreen extends StatefulScreen { + const DocumentViewScreen({ + super.key, + required this.document, + }); + + final Document document; + + @override + State createState() => _DocumentViewScreenState(); +} + +class _DocumentViewScreenState extends State { + final PDFViewerState _viewerKey = PDFViewerState(); + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + Padding( + padding: EdgeInsets.all(10), + child: FREViewerPDF( + key: _viewerKey, + url: + 'https://cdn.syncfusion.com/content/PDFViewer/flutter-succinctly.pdf', + ), + ), + Positioned( + bottom: 10, + right: 10, + child: IconButton( + icon: Icon(Icons.share, color: Colors.black), + color: Colors.black, + onPressed: () { + _viewerKey.currentState?.openBookmarkView(); + // Share.share(FFLocalizations.of(context).getVariableText( + // ptText: '', + // enText: '', + // )); + }, + ), + ), + ], + ); + } +} diff --git a/lib/features/documents/index.dart b/lib/features/documents/index.dart new file mode 100644 index 00000000..c32958c7 --- /dev/null +++ b/lib/features/documents/index.dart @@ -0,0 +1,12 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:hub/flutter_flow/index.dart'; +import 'package:hub/shared/utils/index.dart'; +import 'package:hub/shared/widgets/widgets.dart'; + +part 'document_manager_screen.dart'; +part 'document_page_widget.dart'; +part 'document_viewer_screen.dart'; +part 'document_page_model.dart'; +part 'document_item_component.dart'; diff --git a/lib/features/history/presentation/pages/provisional_history_page.dart b/lib/features/history/presentation/pages/provisional_history_page.dart index e4bfde25..ae43ad8d 100644 --- a/lib/features/history/presentation/pages/provisional_history_page.dart +++ b/lib/features/history/presentation/pages/provisional_history_page.dart @@ -350,6 +350,7 @@ class ProvisionalHistoryState extends State { ); } + // ignore: unused_element String _imageUrlAtomWidget(String document, String type) { return valueOrDefault( "https://freaccess.com.br/freaccess/getImage.php?&cliID=&atividade=getFoto&Documento=$document&tipo=$type", @@ -404,6 +405,7 @@ class ProvisionalHistoryState extends State { } Map _getStatusMap(BuildContext context, dynamic json) { + // ignore: unused_local_variable late Map statusColorMap; log(DateTime.parse(json['AGP_DT_VISITA']).toString()); log(DateTime.now().toString()); diff --git a/lib/features/history/presentation/widgets/access_filter_modal.dart b/lib/features/history/presentation/widgets/access_filter_modal.dart index 1346fe8b..7ce32e33 100644 --- a/lib/features/history/presentation/widgets/access_filter_modal.dart +++ b/lib/features/history/presentation/widgets/access_filter_modal.dart @@ -187,6 +187,7 @@ class _AccessFilterState extends State { ); } + // ignore: unused_element void _updateSelection(String? value, String key) { setState(() { if (value == '.') { diff --git a/lib/features/history/presentation/widgets/provisional_filter_modal.dart b/lib/features/history/presentation/widgets/provisional_filter_modal.dart index 44d0f538..5928e05d 100644 --- a/lib/features/history/presentation/widgets/provisional_filter_modal.dart +++ b/lib/features/history/presentation/widgets/provisional_filter_modal.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import '/flutter_flow/flutter_flow_util.dart'; diff --git a/lib/features/home/presentation/pages/about_system.dart b/lib/features/home/presentation/pages/about_system.dart index 7255388f..19b9de55 100644 --- a/lib/features/home/presentation/pages/about_system.dart +++ b/lib/features/home/presentation/pages/about_system.dart @@ -1,6 +1,5 @@ import 'dart:developer'; -import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -8,8 +7,6 @@ import 'package:hub/flutter_flow/flutter_flow_icon_button.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/flutter_flow_util.dart'; import 'package:hub/flutter_flow/internationalization.dart'; -import 'package:hub/shared/utils/log_util.dart'; -import 'package:stack_trace/stack_trace.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:url_launcher/url_launcher.dart'; diff --git a/lib/features/home/presentation/widgets/drawer_widget.dart b/lib/features/home/presentation/widgets/drawer_widget.dart index 014fa9f8..d71d58b9 100644 --- a/lib/features/home/presentation/widgets/drawer_widget.dart +++ b/lib/features/home/presentation/widgets/drawer_widget.dart @@ -136,6 +136,7 @@ class DrawerWidget extends StatelessWidget { ); } + // ignore: unused_element Padding _buildSearchBar(BuildContext context, HomeState state) { final theme = FlutterFlowTheme.of(context); final errorColor = theme.error; diff --git a/lib/features/local/data/data_sources/locals_local_data_source.dart b/lib/features/local/data/data_sources/locals_local_data_source.dart index e259f2c3..c63aec38 100644 --- a/lib/features/local/data/data_sources/locals_local_data_source.dart +++ b/lib/features/local/data/data_sources/locals_local_data_source.dart @@ -58,7 +58,7 @@ class LocalsLocalDataSourceImpl implements LocalsLocalDataSource { }, conflictAlgorithm: ConflictAlgorithm.replace, ); - } catch (e, s) {} + } catch (e) {} } @override diff --git a/lib/features/local/data/data_sources/locals_remote_data_source.dart b/lib/features/local/data/data_sources/locals_remote_data_source.dart index a40883cf..fbe41ff1 100644 --- a/lib/features/local/data/data_sources/locals_remote_data_source.dart +++ b/lib/features/local/data/data_sources/locals_remote_data_source.dart @@ -41,10 +41,10 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { return; } if (response.jsonBody == null) { - final String errorMsg = FFLocalizations.of(context).getVariableText( - enText: 'Verify your connection', - ptText: 'Verifique sua conexão', - ); + // final String errorMsg = FFLocalizations.of(context).getVariableText( + // enText: 'Verify your connection', + // ptText: 'Verifique sua conexão', + // ); // await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, response)); return; } @@ -82,10 +82,10 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { return false; } if (response.jsonBody == null) { - final String errorMsg = FFLocalizations.of(context).getVariableText( - enText: 'Verify your connection', - ptText: 'Verifique sua conexão', - ); + // final String errorMsg = FFLocalizations.of(context).getVariableText( + // enText: 'Verify your connection', + // ptText: 'Verifique sua conexão', + // ); // await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, response)); return false; } @@ -140,10 +140,10 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { log('() => stack: $s'); log('() => catch: $e', stackTrace: s); // return await selectLocal(context); - final String errorMsg = FFLocalizations.of(context).getVariableText( - enText: 'Error getting locals, verify your connection', - ptText: 'Erro ao obter locais, verifique sua conexão', - ); + // final String errorMsg = FFLocalizations.of(context).getVariableText( + // enText: 'Error getting locals, verify your connection', + // ptText: 'Erro ao obter locais, verifique sua conexão', + // ); // await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, null)); return false; } @@ -168,10 +168,10 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { if (response.jsonBody == null) { final GetLocalsCall callback = PhpGroup.getLocalsCall; response = await callback.call(); - final String errorMsg = FFLocalizations.of(context).getVariableText( - enText: 'Verify your connection', - ptText: 'Verifique sua conexão', - ); + // final String errorMsg = FFLocalizations.of(context).getVariableText( + // enText: 'Verify your connection', + // ptText: 'Verifique sua conexão', + // ); // await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, response)); return false; } @@ -180,8 +180,8 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { if (isError == true) { final GetLocalsCall callback = PhpGroup.getLocalsCall; response = await callback.call(); - final String errorMsg = - response.jsonBody['error_msg'] ?? 'Local indisponível'; + // final String errorMsg = + // response.jsonBody['error_msg'] ?? 'Local indisponível'; // await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, response)); return false; } else { @@ -190,10 +190,10 @@ class LocalsRemoteDataSourceImpl implements LocalsRemoteDataSource { } } catch (e, s) { log('() => error processData: $e', stackTrace: s); - final String errorMsg = FFLocalizations.of(context).getVariableText( - enText: 'Error getting data, verify your connection', - ptText: 'Erro ao obter dados, verifique sua conexão', - ); + // final String errorMsg = FFLocalizations.of(context).getVariableText( + // enText: 'Error getting data, verify your connection', + // ptText: 'Erro ao obter dados, verifique sua conexão', + // ); // await DialogUtil.error(context, errorMsg).whenComplete(() async => await selectLocal(context, null)); return false; } diff --git a/lib/features/local/data/repositories/locals_repository_impl.dart b/lib/features/local/data/repositories/locals_repository_impl.dart index d171256e..a1cf5fdc 100644 --- a/lib/features/local/data/repositories/locals_repository_impl.dart +++ b/lib/features/local/data/repositories/locals_repository_impl.dart @@ -107,6 +107,7 @@ class LocalsRepositoryImpl implements LocalsRepository { await DialogUtil.error(context, errorMsg); } + // ignore: unused_element Future _notifyBlocs(BuildContext context) async { context.read().add(LocalProfileEvent()); context.read().add(MenuEvent()); diff --git a/lib/features/menu/presentation/mappers/menu_entry.dart b/lib/features/menu/presentation/mappers/menu_entry.dart index 7e1a4b00..f290b98c 100644 --- a/lib/features/menu/presentation/mappers/menu_entry.dart +++ b/lib/features/menu/presentation/mappers/menu_entry.dart @@ -160,6 +160,16 @@ class MenuEntry implements BaseModule { route: '/acessHistoryPage', types: [MenuEntryType.Home, MenuEntryType.Drawer], ), + MenuEntry( + key: 'FRE-HUB-DOCUMENT', + icon: Icons.document_scanner, + name: FFLocalizations.of(navigatorKey.currentContext!).getVariableText( + ptText: 'Documentos', + enText: 'Documents', + ), + route: '/documentPage', + types: [MenuEntryType.Home, MenuEntryType.Drawer], + ), MenuEntry( key: 'FRE-HUB-LIBERATIONS', icon: Icons.how_to_reg_outlined, diff --git a/lib/features/menu/presentation/widgets/menu_item/menu_item_button.dart b/lib/features/menu/presentation/widgets/menu_item/menu_item_button.dart index c8f81e31..d5142c21 100644 --- a/lib/features/menu/presentation/widgets/menu_item/menu_item_button.dart +++ b/lib/features/menu/presentation/widgets/menu_item/menu_item_button.dart @@ -76,16 +76,15 @@ class _MenuButtonWidgetState extends State { mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (widget.icon != null) - Container( - alignment: Alignment.topLeft, - padding: const EdgeInsets.only(left: 8.0), - child: Icon( - widget.icon, - size: 24.0, - color: FlutterFlowTheme.of(context).primaryText, - ), + Container( + alignment: Alignment.topLeft, + padding: const EdgeInsets.only(left: 8.0), + child: Icon( + widget.icon, + size: 24.0, + color: FlutterFlowTheme.of(context).primaryText, ), + ), Flexible( child: Padding( padding: const EdgeInsets.only(left: 10.0), diff --git a/lib/features/module/data/models/license_model.dart b/lib/features/module/data/models/license_model.dart index 48e215cc..df9e8f87 100644 --- a/lib/features/module/data/models/license_model.dart +++ b/lib/features/module/data/models/license_model.dart @@ -1,4 +1,3 @@ -import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'module_model.dart'; diff --git a/lib/features/module/data/models/module_model.dart b/lib/features/module/data/models/module_model.dart index e373edc3..17a2f23b 100644 --- a/lib/features/module/data/models/module_model.dart +++ b/lib/features/module/data/models/module_model.dart @@ -1,4 +1,3 @@ -import 'package:flutter/material.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; part 'module_model.freezed.dart'; diff --git a/lib/features/module/domain/entities/base_module.dart b/lib/features/module/domain/entities/base_module.dart index 1cfbeef0..9e8759aa 100644 --- a/lib/features/module/domain/entities/base_module.dart +++ b/lib/features/module/domain/entities/base_module.dart @@ -1,6 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:hub/flutter_flow/internationalization.dart'; -import 'package:hub/flutter_flow/nav/nav.dart'; abstract class BaseModule { String get key; diff --git a/lib/features/module/domain/entities/license.dart b/lib/features/module/domain/entities/license.dart index 17a70650..b5b73407 100644 --- a/lib/features/module/domain/entities/license.dart +++ b/lib/features/module/domain/entities/license.dart @@ -25,7 +25,8 @@ enum LicenseKeys { people('FRE-HUB-PEOPLE'), petsHistory('FRE-HUB-PETS-HISTORY'), settings('FRE-HUB-SETTINGS'), - logout('FRE-HUB-LOGOUT'); + logout('FRE-HUB-LOGOUT'), + document('FRE-HUB-DOCUMENT'); final String value; const LicenseKeys(this.value); @@ -137,6 +138,13 @@ class License { startDate: '', quantity: 0, ), + Module( + key: LicenseKeys.document.value, + display: ModuleStatus.active.key, + expirationDate: '', + startDate: '', + quantity: 0, + ), Module( key: LicenseKeys.openedVisits.value, display: isNewVersionWithModule diff --git a/lib/features/notification/deep_link_service.dart b/lib/features/notification/deep_link_service.dart index 4f6ba58d..77792519 100644 --- a/lib/features/notification/deep_link_service.dart +++ b/lib/features/notification/deep_link_service.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:developer'; import 'package:app_links/app_links.dart'; import 'package:flutter/material.dart'; import 'package:hub/features/storage/index.dart'; diff --git a/lib/features/profile/data/data_sources/profile_local_data_source.dart b/lib/features/profile/data/data_sources/profile_local_data_source.dart index 8b0f9d1e..ee9bb176 100644 --- a/lib/features/profile/data/data_sources/profile_local_data_source.dart +++ b/lib/features/profile/data/data_sources/profile_local_data_source.dart @@ -2,7 +2,6 @@ import 'dart:developer'; import 'package:hub/features/storage/constants/profile_constants.dart'; import 'package:hub/features/storage/index.dart'; -import 'package:hub/shared/constants/index.dart'; import 'package:sqflite/sqflite.dart'; diff --git a/lib/features/storage/enums/shared_storage_key.dart b/lib/features/storage/enums/shared_storage_key.dart index 7cd1dc3e..2f615f4f 100644 --- a/lib/features/storage/enums/shared_storage_key.dart +++ b/lib/features/storage/enums/shared_storage_key.dart @@ -9,8 +9,6 @@ extension SharedPreferencesKeyExtension on SharedPreferencesKey { switch (this) { case SharedPreferencesKey.isFirstRun: return 'fre_isFirstRun'; - default: - return ''; } } } diff --git a/lib/features/storage/repositories/storage_repository_impl.dart b/lib/features/storage/repositories/storage_repository_impl.dart index 30f3fd0d..1649b05e 100644 --- a/lib/features/storage/repositories/storage_repository_impl.dart +++ b/lib/features/storage/repositories/storage_repository_impl.dart @@ -1,7 +1,6 @@ import 'dart:developer'; import 'package:flutter/cupertino.dart'; -import 'package:hub/features/profile/data/data_sources/profile_local_data_source.dart'; import 'package:hub/features/storage/index.dart'; class StorageHelper implements StorageRepository { diff --git a/lib/flutter_flow/flutter_flow_widgets.dart b/lib/flutter_flow/flutter_flow_widgets.dart index 6845d783..122432eb 100644 --- a/lib/flutter_flow/flutter_flow_widgets.dart +++ b/lib/flutter_flow/flutter_flow_widgets.dart @@ -1,6 +1,5 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:flutter/material.dart'; -import 'package:auto_size_text/auto_size_text.dart'; class FFButtonOptions { const FFButtonOptions({ diff --git a/lib/flutter_flow/nav/nav.dart b/lib/flutter_flow/nav/nav.dart index 600a43ad..0da33c1e 100644 --- a/lib/flutter_flow/nav/nav.dart +++ b/lib/flutter_flow/nav/nav.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hub/features/backend/index.dart'; +import 'package:hub/features/documents/index.dart'; import 'package:hub/features/history/index.dart'; import 'package:hub/features/home/index.dart'; import 'package:hub/features/local/index.dart'; @@ -298,6 +299,13 @@ GoRouter createRouter(AppStateNotifier appStateNotifier) { return PetsPageWidget(pet: pet); }, ), + FFRoute( + name: 'documentPage', + path: '/documentPage', + builder: (context, params) { + return FREDocumentPage(); + }, + ), // FFRoute(name: 'settingsPage', path: '/settingsPage', builder: (context, params) => params.isEmpty ? const NavBarPage(initialPage: 'settingsPage') : const SettingsPageWidget()) ].map((r) => r.toRoute(appStateNotifier)).toList(), ); diff --git a/lib/flutter_flow/nav/serialization_util.dart b/lib/flutter_flow/nav/serialization_util.dart index a4d36fd0..94a8350b 100644 --- a/lib/flutter_flow/nav/serialization_util.dart +++ b/lib/flutter_flow/nav/serialization_util.dart @@ -218,9 +218,6 @@ dynamic deserializeParam( case ParamType.Enum: return deserializeEnum(param); - - default: - return null; } } catch (e) { return null; diff --git a/lib/initialization.dart b/lib/initialization.dart index 04aa29c6..29273fef 100644 --- a/lib/initialization.dart +++ b/lib/initialization.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:app_tracking_transparency/app_tracking_transparency.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; @@ -56,21 +54,21 @@ Future _initializeSystemSettings() async { await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); if (kDebugMode) { - //kDebugMode print('Debug mode'); - bool unsentReports = - await FirebaseCrashlytics.instance.checkForUnsentReports(); - if (unsentReports) { - // Existem relatórios não enviados - await crashlyticsInstance.sendUnsentReports(); - print('Existem relatórios de falhas não enviados.'); - } else { - // Não existem relatórios não enviados - print('Todos os relatórios de falhas foram enviados.'); - } } else { print('Release mode'); + // bool unsentReports = + // await FirebaseCrashlytics.instance.checkForUnsentReports(); + // if (unsentReports) { + // // Existem relatórios não enviados + // await crashlyticsInstance.sendUnsentReports(); + // print('Existem relatórios de falhas não enviados.'); + // } else { + // // Não existem relatórios não enviados + // print('Todos os relatórios de falhas foram enviados.'); + // } + await crashlyticsInstance.setCrashlyticsCollectionEnabled(true); // if (crashlyticsInstance.isCrashlyticsCollectionEnabled) { FlutterError.onError = await crashlyticsInstance.recordFlutterError; diff --git a/lib/main.dart b/lib/main.dart index 623ac049..34d1a25f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'dart:io'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -14,13 +15,21 @@ import 'package:hub/features/storage/index.dart'; import 'package:hub/flutter_flow/flutter_flow_theme.dart'; import 'package:hub/flutter_flow/internationalization.dart'; import 'package:hub/flutter_flow/nav/nav.dart'; -import 'package:hub/shared/utils/test_util.dart'; import 'package:responsive_framework/responsive_framework.dart'; import 'initialization.dart'; final GlobalKey navigatorKey = GlobalKey(); +class CustomScrollBehavior extends MaterialScrollBehavior { + // Override behavior methods and getters like dragDevices + @override + Set get dragDevices => { + PointerDeviceKind.touch, + PointerDeviceKind.mouse, + }; +} + void main() async { await initializeApp(); runApp(const ProviderScope(child: App())); @@ -193,6 +202,7 @@ class _AppState extends State { @override Widget build(BuildContext context) { return MaterialApp.router( + scrollBehavior: CustomScrollBehavior(), key: navigatorKey, title: 'FRE ACCESS HUB', builder: builder, diff --git a/lib/pages/qr_code_page/qr_code_page_widget.dart b/lib/pages/qr_code_page/qr_code_page_widget.dart index f7832214..bab42743 100644 --- a/lib/pages/qr_code_page/qr_code_page_widget.dart +++ b/lib/pages/qr_code_page/qr_code_page_widget.dart @@ -103,8 +103,7 @@ class _QrCodePageWidgetState extends State screenWidth < screenHeight ? screenWidth : screenHeight; double dimension = smallerDimension * 0.75; double totalTimeInSeconds = 100.0; - double limitedHeaderTextSize = - LimitedFontSizeUtil.getCalculateFontSize(context, 18, 18, 16); + LimitedFontSizeUtil.getCalculateFontSize(context, 18, 18, 16); double limitedBodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context); return SafeArea( diff --git a/lib/pages/reception_page/reception_page_widget.dart b/lib/pages/reception_page/reception_page_widget.dart index e7d5718e..ddd1854a 100644 --- a/lib/pages/reception_page/reception_page_widget.dart +++ b/lib/pages/reception_page/reception_page_widget.dart @@ -1,6 +1,3 @@ -import 'dart:developer'; - -import 'package:awesome_notifications/awesome_notifications.dart'; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -31,9 +28,7 @@ class _ReceptionPageWidgetState extends State void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); - () async { - final lifecycle = await AwesomeNotifications().getAppLifeCycle(); - }(); + () async {}(); FirebaseMessagingService().updateDeviceToken(); LocalsRepositoryImpl().validateLocal(context); diff --git a/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart b/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart index f5247241..ce4d41a3 100644 --- a/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart +++ b/lib/pages/schedule_complete_visit_page/schedule_complete_visit_page_widget.dart @@ -90,6 +90,7 @@ class _ScheduleCompleteVisitPageWidgetState } } + // ignore: unused_element void _scrollListener() { if (_visitHistoryController.position.pixels == _visitHistoryController.position.maxScrollExtent) { diff --git a/lib/pages/visits_on_the_property/visits_on_the_property_screen.dart b/lib/pages/visits_on_the_property/visits_on_the_property_screen.dart index 345d8a93..65f9a039 100644 --- a/lib/pages/visits_on_the_property/visits_on_the_property_screen.dart +++ b/lib/pages/visits_on_the_property/visits_on_the_property_screen.dart @@ -54,8 +54,8 @@ class _VisitsOnThePropertyState extends State @override Widget build(BuildContext context) { - late final limitedBodyTextSize = - LimitedFontSizeUtil.getBodyFontSize(context); + // late final limitedBodyTextSize = + // LimitedFontSizeUtil.getBodyFontSize(context); late final limitedHeaderTextSize = LimitedFontSizeUtil.getHeaderFontSize(context); diff --git a/lib/shared/widgets/component.dart b/lib/shared/widgets/component.dart new file mode 100644 index 00000000..fb1383dc --- /dev/null +++ b/lib/shared/widgets/component.dart @@ -0,0 +1,22 @@ +part of 'widgets.dart'; + +/// [ComponentWidget] + +abstract class ComponentWidget extends Widget { + const ComponentWidget({super.key}); +} + +abstract class ModelComponent extends ModelWidget + implements ComponentWidget { + const ModelComponent({super.key}); +} + +abstract class StatelessComponent extends StatelessWidget + implements ComponentWidget { + const StatelessComponent({super.key}); +} + +abstract class StatefulComponent extends StatefulWidget + implements ComponentWidget { + const StatefulComponent({super.key}); +} diff --git a/lib/shared/widgets/entity.dart b/lib/shared/widgets/entity.dart new file mode 100644 index 00000000..ae05f63f --- /dev/null +++ b/lib/shared/widgets/entity.dart @@ -0,0 +1,3 @@ +part of 'widgets.dart'; + +abstract class Entity {} diff --git a/lib/shared/widgets/model.dart b/lib/shared/widgets/model.dart new file mode 100644 index 00000000..c35a6491 --- /dev/null +++ b/lib/shared/widgets/model.dart @@ -0,0 +1,11 @@ +part of 'widgets.dart'; + +class ModelWidget extends Widget { + const ModelWidget({super.key}); + + @override + Element createElement() { + // TODO: implement createElement + throw UnimplementedError(); + } +} diff --git a/lib/shared/widgets/page.dart b/lib/shared/widgets/page.dart new file mode 100644 index 00000000..ed08ad58 --- /dev/null +++ b/lib/shared/widgets/page.dart @@ -0,0 +1,64 @@ +part of 'widgets.dart'; + +mixin MixinPage { + PreferredSizeWidget buildAppBar(String title, BuildContext context) { + return AppBar( + backgroundColor: FlutterFlowTheme.of(context).primaryBackground, + automaticallyImplyLeading: false, + title: Text( + title, + style: FlutterFlowTheme.of(context).headlineMedium.override( + fontFamily: FlutterFlowTheme.of(context).headlineMediumFamily, + color: FlutterFlowTheme.of(context).primaryText, + fontSize: 16.0, + fontWeight: FontWeight.bold, + letterSpacing: 0.0, + useGoogleFonts: GoogleFonts.asMap().containsKey( + FlutterFlowTheme.of(context).headlineMediumFamily), + ), + ), + leading: _backButton(context, FlutterFlowTheme.of(context)), + centerTitle: true, + elevation: 0.0, + actions: [], + ); + } + + Widget _backButton(BuildContext context, FlutterFlowTheme theme) { + return FlutterFlowIconButton( + key: ValueKey('BackNavigationAppBar'), + borderColor: Colors.transparent, + borderRadius: 30.0, + borderWidth: 1.0, + buttonSize: 60.0, + icon: Icon( + Icons.keyboard_arrow_left, + color: theme.primaryText, + size: 30.0, + ), + onPressed: () => Navigator.of(context).pop(), + ); + } +} + +/// [PageWidget] + +abstract class PageWidget extends Widget { + const PageWidget({super.key}); +} + +abstract class ModelPage extends ModelWidget implements PageWidget { + const ModelPage({super.key}); +} + +abstract class StatelessPage extends StatelessWidget + implements PageWidget { + const StatelessPage({super.key}); +} + +abstract class StatefulPage extends StatefulWidget implements PageWidget { + const StatefulPage({super.key}); +} + +abstract class PageState extends State + with MixinPage {} diff --git a/lib/shared/widgets/screen.dart b/lib/shared/widgets/screen.dart new file mode 100644 index 00000000..754a3094 --- /dev/null +++ b/lib/shared/widgets/screen.dart @@ -0,0 +1,19 @@ +part of 'widgets.dart'; + +abstract class ScreenWidget extends Widget { + const ScreenWidget({super.key}); +} + +abstract class ModelScreen extends ModelWidget implements ScreenWidget { + const ModelScreen({super.key}); +} + +abstract class StatelessScreen extends StatelessWidget + implements ScreenWidget { + const StatelessScreen({super.key}); +} + +abstract class StatefulScreen extends StatefulWidget + implements ScreenWidget { + const StatefulScreen({super.key}); +} diff --git a/lib/shared/widgets/text.dart b/lib/shared/widgets/text.dart new file mode 100644 index 00000000..68b8b065 --- /dev/null +++ b/lib/shared/widgets/text.dart @@ -0,0 +1,12 @@ +part of 'widgets.dart'; + +class AutoText extends AutoSizeText { + const AutoText( + super.text, { + super.key, + super.style, + super.overflow, + super.textAlign, + super.maxLines, + }); +} diff --git a/lib/shared/widgets/view/carousel_view.dart b/lib/shared/widgets/view/carousel_view.dart new file mode 100644 index 00000000..fd215ce6 --- /dev/null +++ b/lib/shared/widgets/view/carousel_view.dart @@ -0,0 +1,77 @@ +part of '../widgets.dart'; + +class CategoryCarousel extends StatelessWidget { + final List categories; + final void Function(Category) onSelect; + final void Function(Category) onUnselect; + + const CategoryCarousel({ + super.key, + required this.categories, + required this.onSelect, + required this.onUnselect, + }); + + @override + Widget build(BuildContext context) { + final backgroundTheme = FlutterFlowTheme.of(context).primaryBackground; + + bool isSelected = false; + Category? current = null; + + return Container( + height: 120, + decoration: BoxDecoration( + color: backgroundTheme, + borderRadius: BorderRadius.circular(10), + ), + child: CarouselView( + itemExtent: 100, + onTap: (index) { + if (isSelected && current == categories[index]) { + onUnselect(categories[index]); + isSelected = false; + current = null; + } else { + onSelect(categories[index]); + isSelected = true; + current = categories[index]; + } + }, + children: categories.map((category) { + return GestureDetector( + onTap: () {}, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Container( + padding: const EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: category.color, + shape: BoxShape.circle, + ), + child: Icon( + Icons.folder, + color: Colors.white, + size: 40, + ), + ), + const SizedBox(height: 8), + Text( + category.title, + style: TextStyle( + color: category.color, + fontWeight: FontWeight.bold, + ), + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ); + }).toList(), + ), + ); + } +} diff --git a/lib/shared/widgets/view/search_view.dart b/lib/shared/widgets/view/search_view.dart new file mode 100644 index 00000000..89bec502 --- /dev/null +++ b/lib/shared/widgets/view/search_view.dart @@ -0,0 +1,200 @@ +part of '../widgets.dart'; + +/// ----------------------------------------------- +/// [SearchView] + +class SearchView extends StatefulComponent { + const SearchView({super.key}); + + @override + State createState() => _SearchViewState(); +} + +class _SearchViewState extends State { + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} + +class LocalSearchView extends SearchView { + final List list; + final Widget Function(T) itemBuilder; + final bool Function(T, String) filter; + final Widget header; + final List Function(String)? onSearch; + + LocalSearchView({ + Key? key, + required this.list, + required this.itemBuilder, + required this.filter, + List Function(String)? onSearch, + Widget? header, + }) : header = header ?? const SizedBox.shrink(), + onSearch = onSearch ?? + ((String query) => + list.where((documents) => filter(documents, query)).toList()), + super(key: key); + + // return documents.where((documents) => filter(documents, query)).toList(); + + @override + LocalSearchViewState createState() => LocalSearchViewState(); +} + +class LocalSearchViewState extends State> { + TextEditingController editingController = TextEditingController(); + late List filteredItems; + + @override + void initState() { + filteredItems = widget.list; + super.initState(); + } + + @override + Widget build(BuildContext context) { + void filter(value) { + safeSetState(() { + filteredItems = widget.onSearch!(value); + }); + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + Expanded( + child: ListView.builder( + shrinkWrap: true, + itemCount: filteredItems.length + 1, + itemBuilder: (context, index) { + if (index == 0) return widget.header; + return widget.itemBuilder(filteredItems[index - 1]); + }, + ), + ), + Padding( + padding: const EdgeInsets.all(30.0), + child: TextField( + onChanged: filter, + controller: editingController, + cursorColor: Colors.black, + decoration: InputDecoration( + prefixIcon: Icon(Icons.search), + focusColor: Colors.black, + hoverColor: Colors.black, + fillColor: Colors.black, + iconColor: Colors.black, + contentPadding: + EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0), + border: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(15.0)), + borderSide: + BorderSide(color: Colors.black), // Set border color here + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(15.0)), + borderSide: BorderSide( + color: Colors.black), // Set focused border color here + ), + ), + ), + ), + ], + ); + } +} + +class RemoteSearchListView extends SearchView { + final List items; + final String title; + final Widget Function(T) itemBuilder; + final Future> Function(String) fetchItems; + + RemoteSearchListView({ + Key? key, + required this.items, + required this.title, + required this.itemBuilder, + required this.fetchItems, + }) : super(key: key); + + @override + _RemoteSearchViewState createState() => _RemoteSearchViewState(); +} + +class _RemoteSearchViewState extends State> { + TextEditingController editingController = TextEditingController(); + late List filteredItems; + bool isLoading = false; + + @override + void initState() { + filteredItems = widget.items; + super.initState(); + } + + void filterSearchResults(String query) async { + setState(() { + isLoading = true; + }); + final results = await widget.fetchItems(query); + setState(() { + filteredItems = results; + isLoading = false; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(widget.title), + ), + body: Container( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + onChanged: (value) { + filterSearchResults(value); + }, + controller: editingController, + decoration: InputDecoration( + labelText: "Search", + hintText: "Search", + prefixIcon: Icon(Icons.search), + border: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(25.0)), + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(15, 0, 50, 0), + child: Text('Últimos Documentos'), + ), + isLoading + ? Center(child: CircularProgressIndicator()) + : Expanded( + child: ListView.builder( + shrinkWrap: true, + itemCount: filteredItems.length, + itemBuilder: (context, index) { + return widget.itemBuilder(filteredItems[index]); + }, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/shared/widgets/viewer/viewer.dart b/lib/shared/widgets/viewer/viewer.dart new file mode 100644 index 00000000..2e5f01c9 --- /dev/null +++ b/lib/shared/widgets/viewer/viewer.dart @@ -0,0 +1,26 @@ +part of '../widgets.dart'; + +typedef PDFViewerState = GlobalKey; + +abstract class Viewer extends StatelessComponent { + const Viewer({super.key, required this.src}); + final String src; + + @override + Widget build(BuildContext context) { + return buildViewer(context); + } + + Widget buildViewer(BuildContext context); +} + +class FREViewerPDF extends Viewer { + const FREViewerPDF({required Key key, required this.url}) + : super(key: key as PDFViewerState, src: url); + final String url; + + @override + Widget buildViewer(BuildContext context) { + return SfPdfViewer.network(src, key: key as PDFViewerState); + } +} diff --git a/lib/shared/widgets/widgets.dart b/lib/shared/widgets/widgets.dart new file mode 100644 index 00000000..7b240209 --- /dev/null +++ b/lib/shared/widgets/widgets.dart @@ -0,0 +1,21 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:hub/features/documents/index.dart'; +import 'package:hub/flutter_flow/index.dart'; +import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'; + +part 'page.dart'; +part 'component.dart'; +part 'screen.dart'; +part 'model.dart'; +part 'entity.dart'; + +/// [View]'s +part 'view/search_view.dart'; +part 'view/carousel_view.dart'; + +/// [Viewer] +part 'viewer/viewer.dart'; + +part 'text.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index 26ed4273..0a647c1b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,7 +13,8 @@ dependencies: sdk: flutter flutter_localizations: sdk: flutter - auto_size_text: 3.0.0 + auto_size_text: ^3.0.0 + syncfusion_flutter_pdfviewer: ^28.2.4 barcode_widget: ^2.0.4 cached_network_image: ^3.4.0 firebase_core: ^3.4.0 @@ -24,7 +25,7 @@ dependencies: app_links: ^6.3.2 # crop_your_image: 1.1.0 csv: 6.0.0 - device_info_plus: ^10.1.2 + device_info_plus: ^11.2.2 firebase_messaging: ^15.1.0 dropdown_button2: 2.3.9 easy_debounce: 2.0.3 @@ -50,7 +51,7 @@ dependencies: from_css_color: 2.0.0 go_router: ^14.3.0 google_fonts: 6.2.1 - http: 1.2.1 + http: 1.3.0 image_picker: 1.1.2 image_picker_android: ^0.8.12+15 image_picker_for_web: ^3.0.5 @@ -106,7 +107,7 @@ dependencies: # json_annotation: ^4.9.0 dependency_overrides: - http: 1.2.1 + http: 1.3.0 uuid: ^4.0.0 win32: 5.5.1 @@ -145,6 +146,7 @@ flutter: - assets/images/ - assets/images/dark/ - assets/images/light/ + - assets/files/ fonts: - family: "SF Pro" fonts: