From e7d6cb813390e7d0d4b156e6004ab07995938273 Mon Sep 17 00:00:00 2001 From: PGAN-MIS Date: Sun, 27 Aug 2023 16:38:05 +0800 Subject: [PATCH] share attachment implemented --- android/app/src/main/AndroidManifest.xml | 2 +- .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 544 -> 0 bytes android/app/src/main/res/mipmap-hdpi/unit.png | Bin 0 -> 5881 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 442 -> 0 bytes android/app/src/main/res/mipmap-mdpi/unit.png | Bin 0 -> 3656 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 721 -> 0 bytes .../app/src/main/res/mipmap-xhdpi/unit.png | Bin 0 -> 8137 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 1031 -> 0 bytes .../app/src/main/res/mipmap-xxhdpi/unit.png | Bin 0 -> 12522 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 1443 -> 0 bytes .../app/src/main/res/mipmap-xxxhdpi/unit.png | Bin 0 -> 17244 bytes android/build.gradle | 2 +- .../profile/education/education_bloc.dart | 51 ++++ .../profile/education/education_event.dart | 12 + .../profile/education/education_state.dart | 14 +- .../profile/eligibility/eligibility_bloc.dart | 14 +- .../eligibility/eligibility_event.dart | 78 ++++-- .../eligibility/eligibility_state.dart | 5 + .../learning_development_bloc.dart | 6 + .../learning_development_event.dart | 6 + .../learning_development_state.dart | 6 + .../profile/workHistory/workHistory_bloc.dart | 121 ++++---- .../workHistory/workHistory_event.dart | 14 +- lib/bloc/role/pass_check/pass_check_bloc.dart | 8 +- lib/model/profile/work_history.dart | 208 ++++++++++---- .../education/education_view_attachment.dart | 121 ++++++++ .../profile/components/education_screen.dart | 28 +- .../eligibility_view_attachment.dart | 73 +++++ .../components/eligibility_screen.dart | 22 ++ .../learning_and_development_screen.dart | 22 ++ .../learning_development_view_attachment.dart | 71 +++++ .../components/work_history/add_modal.dart | 229 +++++++++++---- .../components/work_history/edit_modal.dart | 94 +++---- .../components/work_history_screen.dart | 164 +++++------ .../profile/shared/multiple_attachment.dart | 14 +- .../profile/shared/single_attachment.dart | 15 +- .../profile/shared/view_attachment.dart | 62 ++++ .../role_assignment_screen.dart | 1 + .../components/dashboard/dashboard.dart | 45 +-- .../dashboard/superadmin_expanded_menu.dart | 2 + .../unit2/homepage.dart/module-screen.dart | 4 +- .../profile/work_history_services.dart | 264 +++++++++++++----- lib/sevices/roles/pass_check_services.dart | 8 +- lib/utils/attachment_services.dart | 34 ++- lib/utils/request.dart | 8 +- lib/utils/request_permission.dart | 14 + lib/utils/urls.dart | 13 +- linux/flutter/generated_plugin_registrant.cc | 4 + linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 8 + pubspec.lock | 160 +++++++++++ pubspec.yaml | 4 + .../flutter/generated_plugin_registrant.cc | 9 + windows/flutter/generated_plugins.cmake | 3 + 54 files changed, 1573 insertions(+), 471 deletions(-) delete mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-hdpi/unit.png delete mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-mdpi/unit.png delete mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/unit.png delete mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/unit.png delete mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/unit.png create mode 100644 lib/screens/profile/components/education/education_view_attachment.dart create mode 100644 lib/screens/profile/components/eligibility/eligibility_view_attachment.dart create mode 100644 lib/screens/profile/components/learning_development/learning_development_view_attachment.dart create mode 100644 lib/screens/profile/shared/view_attachment.dart create mode 100644 lib/utils/request_permission.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 56c1932..c3002df 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -10,7 +10,7 @@ + android:icon="@mipmap/unit"> P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ diff --git a/android/app/src/main/res/mipmap-hdpi/unit.png b/android/app/src/main/res/mipmap-hdpi/unit.png new file mode 100644 index 0000000000000000000000000000000000000000..f8ecca055419f54b90cdd90fca17ab9c69612e22 GIT binary patch literal 5881 zcmVPy0vq?ljRCr$9TnU&I#o4avo}QkWo_ltdT|f|x8Uz6qgF#S<2SD3(iAOF}ls`ctM2(6p0znQh6k&JHox9KapRcBCX=aa^SqMV< zdG^_do#{H>`s%IsI|_^r?!gEl(gUHMdl32xA;cksjDu_P$a)(l*wu$e2MB6gN*aPS&mZd)ugvI%;^a7cO4Aw_H#ZIa3L(YZYUD_>h-$~v6@Vx>KlXU0jq>^y zrwl{m5waNwX%ffTw&Zim?~BJL{UHylc<9Zu}7`O-!dk8_uaA0gKi8K${q^cVcLKM_$ zP5Vgsex(4x_h6!0LrwVA-gf(#0wFqA{M!K!0A$0M%WC@exy}2|h$55)V9lQ+W!@E! zqf&q+v2q9#^DW?4VAm?MFHvF@UHT94rW@-V&~Tr$C6!)H>yKQnfpcexHfR6)njtR%WUWve8%+ zbCBD5I)~P+Y1KLbggo=Q)xU4&xfArZPH2~a=;S4EYKa|jnT7Glcecy&_A-0~2LyGN zD|CEe!C`Kow+>2kF@TJ_f;B6SbBI^u36Z&C*z|zMT(UOKX=liR;|f5u_Z@)YPFZ%NJUhmA&UVlT2p|^FxboF+Ly`Qu->)+Rbrjb3XU-+*s@?(>mbK z2LMy&a2z|pW*gI25HIK<*amuezK4jhz4#@J2qH9|q7Wjd41MojP22o&LHWlPRes}3 zMcHEMx9ZRf_9Nt<6bdcF2sxl3g1A=R!N?$lUk;Zb zr@s5=W~*RI9lmP@&A55ZO+$BS+B+433SXlu+zmPUTo#b#4t6@m+b~82!+0@n^`5K*B0g8mXP zMjLYZzdoPO-qutod{&9XsKkQkPUvm7_q{7r^Y3Z^x<4K}Z|i=5Itsh8i5XXUy^F_q zywmcA0eg%l1I$%xohU>x!KxTZ0Z1?=olqX4PB18c6R_4rX9tGFaePYGqrYoOPI)h% z|5G`ar(%GPvD^F43e{|`2B1Z;=*TUd`(5mW(I*E2za8O{u4yq0*h;Mv1RoASabk=x z#wbe+wMEnSqz%%n8HQ}*IML1F8XwR1kT_0+2F)!A@3kfr7*e3Y1dMGW!e~Xh<>#-Z z)Ax5~NfiUsLl6cw)Px%=VK&A=6#zul`vjlwk&$lCjY(ptJfS2FBn(|)iQ{n2Fyt)- zc~zrQczL^~z0)kq;KxDkjXgr0!_lKR#)Ahq9AgKFj8*Dq9l2q+x?SCKL3MOaKLKp81u0FZ|Aa4t zV?M6yyMLQZOx{%7qU?lY<7K4Igc&=!S@wkTT{nm0xGP=KqQOq*C0WCu7HQ=slk9a! zFg%!uU$P;W`*SHLeNzC@2~7`&*PkfZzYBT=wgFfUfb+Ske)v$N`Jxy?drZ@(ldHnb z0HB}`T0}9{;WvwYj;9D0(2A5kxeCySW)b%Y90UH^1f zUS0pWl3No+D9yy9#i`YYOVYKIeE#K-&ntDr!D`(c$2S)8s~?EPMp~`to3J2iJ+s2$ z5Bdo9L9nVYU>+f&5|nO8#7=LPT(>TpecEC<)OvsH^)4Oh@!kq9hD-=eCozG@bP`yL zfH9Q=+hlp&Bhko@%q_}18w%1yfAFahlIyy(Vd%UiQVJ)V9b>##(>|He+|-|)l7}0h zVr7Wm|L`cueRIk%V4~QGF~37q-kl$beAlA7se+&64=z7na$TD=4B!*+w>pd{0O{%& zX;7(aTZ24*j0&EnrM3XJnwR7FN0W(b)@QTNz(O5v zfT(JoQ(L>ar%gCnDUv1ub^A~xe(?uN?k^@lU>N#HNxJP?e_%<>FcbkHd!;^|hLP&S zoX}V({B2PzdVyuT(gixpA&tK=6!^U*OH7*v%XDJQ?NrqF?}^e7%zn?klgbrkzL&#y65};CmD7q#{&!$>_ z`C2-?zycBtzReAXKk6aa`@$kwtq2wjIPUIfWZ+kdviWdY5FK|vhvR#91VeuZ{sAB$ zKD{=Zd-};_{5o?IFedF%uXpaH9`9WT5gTW2nl>vDKiPCnnQNnsmZYDK_Xif0w$H-B z&!t*syqZqWuNa`7cKa!JhiX2m#1{iol`zLIiN(illyiTzPJFl|{dkH$@C=+JFauDs zPbK0vt;yvcwPam!L%6oFmmu_4N_e6wD>4(7uV*vMexFQEwP-4%rzoBte*w$*bv!ZtoqYB=b6_wx?Od1ZhU){t zMrYNxt z3eedu*TgA-;FDn5aKwW+oF9*!y`xZA#{lYSw-2~GRI{lP$GDtD!GuMO@xtb&vp&|e zx2=c3ltAFw;V$W__H+?Qs|C@>nH2+s5OUmCTemZ0<9n)QvK}lKzarH#{grh3UekhT zM&eXayy*5&&0n&FP=5(5=z&;t)TW{Z!AYeYN`TD8;(wEf-|&xI?l)FzzSQfTbE(HW zvy_Lx@o=k!FQ!8^OVp%K*eI=#5PJ(Pvs(ZaQG^+wB7yLg7Ze7-*;7 z^plDB4R7Xhk28R*Tg)h9t>r9;E!H1el6S4lWbUy7biOGgN&#X#^ju5w_DTVw3i#Gw z@YT~C&M~<%bwZ||;I|dzw-&~u=U8%DU`4J)-RgGvdA?pT48_Cq_BGkeQ_GXdNhKt` zv6mp6axf%Kk4=-P+XLtVNxF4{Kd=<|(CT_HfL3O*vnvIN3as&d|3jlC_teq`OIMK+ z9Y#2%8`1eq`;Idm$kyoLP5$6Z-<4dKW{9DQ2n$h7+kIy<)j<#hgTB;`%)gw)lzz^v z`H4h)^4eVP39AK-b9-m~(AT!+k^!_Tlbu%;KqFkPDU$-h$12e#Y#%RZZW^{-)Bb5a z>W4U;m){Z$y$DJcCIm|Q;dtz__w)HbGNKM4)MIXa{dOC|T@s26C`Quv?9Z^UtgFWS zvQm;}0KJ$_{jySk=oULp5YD(OT>GAB_MN`VO#7vlWW%2`8CEpK0{4#lYP)?Lve}MN z5YZe6+dfm3#yOG5>6WCScA?w-lWTqc2jfLo1Dwr@#%tD5Vpfuz(DkqHC?4}UOB>{_ zn(%wa+wEtRmNYYfmM0UFE9%hV>^bl6R<|p_^WC*FL=E9gNVR;bC>!TS>BQjy4x-!j zJh%IQC;I%qGK2IO;=|7-6L+l2W*3=c4Pffm`Tb8`D7hzA=&Vv@0PYKT{%nz6&!m6- z`<9lQt%pTtTFZ1d@RC?`WTgN>ztoB*`h&|yNUjN{qt_;fZ{+|MLbxZ=e8wlL`k|#j z0s6HyglpgLEeHb&gaAom8^+{;cxbkl<+T zR@IL}ysZz9k;Efp%!)-%`C3svHv6Yhg5i=hVTwPnyd4chHJ(aHeoivcziNQ`i{b@$ zglbmj%vermq{$R@$teX2nu2}2Ae=ruT>Gv@2!^GH3Vn@`^s+?!5=%Y}CZrA$#W5GT zy)*iV_MzZR(%>_M-63;o4&n<{-MT)Td+HRYIOcf4ey)q-_}8+TWzQAe3>KB7&iBtl zHET~6#dBD=*TPv47vlD)%C?!2$bf19qKX;>g(g+qwpCT% zNE=4tO0W06es*ybw6#yucT8{IH`sJBSe#lvK@f&a57)i})>vBe&4lIJZ1$Nal8Fh` z00d)YRcQBK;`RNalGBV4-X>XD{Xi@N@m}kV#9}qA=~+V_OG8BC5w^KF4t*@k>t9c& z7Hp8^*UJR#`SacGDHppv^CXT7!d6rWNi2xRhVNFCt(L7#`}=7qw0eN(xS%~f2jc}k z{FUiPRtpea$vWgXwxK?_4HsPl8U!n|)o7=`O(t&pzoJ#NR&X%DAgF$g*Y|5X#?CAu zw17k6umBD3R@E*4R^(NmD$2j&n)a1~km}}nUoFR-aFXaax1T7Ef<$4)FpvXdlroHc zOJdP+pQ-A5rNJ^t7EBF>UMLNgnI{MoJYboS^e^}AJuZzC%}I9qu#Q|MXdgnZ z_cq6eZP)Tt+;#<^Rx27NNmt+K5B#n|E20yG6C!UI(WTMIMP}^~@B+J$|G9pZzb;&Tk9Wymp$?F&g%?HI33yyDSc^6Owy6 znYjL)eExa!yH@gUQ{3c5DCiZ%kYE@t9b+}GDDenFO(k`Qt$?r#fZ)m876?5%*ySA8 z*+Mc0dwz3l_zrFV&7^|?h^}@Bq3#WJ^_!d=7t|^YkFugD2j*`FZBMyVjhz@E>D?U1eXXiH|CCP6d^ewmIzsla(5^MGSh}Fr;syAO z{f7pQA9y@d$GSat+cB0v40dGQuvjqQ0wKxS`}X#a7OfH<+V8@xRKr+kYK*MlwYBg)x=bPoi zt6TEf`z~720V$PoV6i$va5tbj6*Nx9FfuV+|17R+yE6ug zYJ}u5CU!UGLm?aAE5zH5^K#h7VNCUqTCCoH!=Kd*wc9PrzHTVwUs)21U1U+)2XNh? z0*Gx_>M2j~`2#Ot;_JM=-*|bx#*DkPDbFpp z?GDxFOoe+m4zJJUpL-+`ga2Oy?sQmXMVs#a6964>xy*f@6mb zD6l+J1lnNh{xO}J@k+6n0iI65IaJ4dXN%mbh|hJouD{shX{fOYJ&IusL^G@9$h4~# z#DEbHvN<^peWoal&m>Y)O_h9rOVe2&|49pC{W5|!Abma7x*l1b%`9G-PA@gLR8{{&*1-;_n)$R^QxKtJMtHr~pXqd6 z-OXm}1C7WU81_7k1hdY9cXos9@=j+1rDv2 z-UhM<5vuhFLfFmoevS~h@CP?q6j|3(Ej%A-DioUA@!4pJoh8O}P$T|-#?Lx90I6i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@UPx@0!c(cRA@uZS_zO<<&{4Ff7iF&xAyC9z@?G~2_j(`m{3Lm114&MD553Im{>B7 zV820FH$|Ry7ZB_&@+0;pYaFTds^K8w$2< zasWI7umnQ5oMpcGKv&m4bpccX0At}(iHH6GI9eU=^PRsW8hgIV7$bE}JL@d~Ge{|a zuvXo?K9gDSX}VHh0FZImaDdqI=GFreN6)kvvk3tHz2`v?VM_VO3i(A(sOpbCEfBo{ z;Ahmdd1oTAy-k!ZsW4{I`rmp#i~-m(A#7bP`^7`m>b_4S9(n_C{C>WothzL$bQE2` z?=OZB08a?5S=M_ix=v0k02JJ{_9qq8jQ||KpDG2ua&tWT-zu|BSMvihl?`C}3FY6^ zYTMRk(wBeIuH*^lWZK~XBUZMw9^eQ`*Z>%~f8+Q4X%*u^p_G4GEvt1{E#Dt>&CtSsN@zA5FK@uOzgFuFq932H3~k>C}vdf)8D>Q6RAupj8xv7zGe4LdscPPpJUiz3v_~%ab-y zJok=xVlNP)FvifHc$otXRX31L8&wK~I7>}nW|(loF17gGO@+d@T?-okAWZi8zBWnr zU3In~ObK(`aDfonLB<%=7%OHi>zyNp{^EgJZR?+FwcRclColCU3JC%<#YC~mBE%E{ zhz`Iw#snLH`-T$!#b-rva*Z)`kDh==O$R9DcB-YHJYTK;m}iU{lvWr3A@$&AlriC$ zuD^~#O!WokUls~1KT{CL;%9>~Fd0JyIaWcXq5JWKfIx@?=p9|#x1(IX@8xRsaTiFR z))5Xun(f2>v?-<-{SGY#-TU&P?CL2n=qt+vM#yT?k>wEh5emWuao zD;7I?(Wc`S34qo`P08(_5yj6VF`&AAln5wz*|yDsWxZczti%%#70Nd&l!Q^>s%@iL z&@v7?1u5lHrg{8_+04B64C6!DzCQ~%0G1^Zd(RW4FAf6Wt_A>}Li`;~$-SQy#qkBp z(nLZenNm2SYx`d)mp2`@tljTx+HnA=p;iL`@is{sKgs8tH`(XEHbAMrY}-x=gVvS_ z;dRDJ>r>sA95&4t8!d6V0XTlTFcSUkj6h&P&ayNgrIOB=+F8gieYR5h`Cw)Da7h|< zMIi8#=tn2%~ zlTMxQk|YA`^Z6()N0kC^8F0)PYn+IUI2Y*tXY_=&IKs8@{L~f6=08+yW`sE^{AVG5=ToY>8USR}@U@Dv{?d@L*k%A4vwLz32DVHH zbeZPyA7wLFy=xdRdwUi}qQ9ON2wbPyHd=ym0IX`W;)<>lBTE38(*?j0aBe8Hc8(Ih z9hszH+b7z)PL4!i=vuRb!Bz9a(T=QbnFN3|<`o8jeq#B72qoLjtU7sOVh#Y^iYfrg zJ&zK{n6;wVqxvpQVGiir(;`_Y<{De<3?gO-H=INeo)h%MAo@NQC80lDJuqRknjuy z5u%h|mrmjSZK!}@k~FF#7JrQaaL5!0!UE9m&ZH;w2f(4jTVjdrlVs_Va3H%vYQ>{s-CcI}Dub@ziWAPmmWclJsy(HWr2pO)0s*< zS1v#Da6WgPYXP=8nS7&_7e?8=0Nj>Hyf8+T&PPfd3;>qp0wFYIn(yAx-F1#z#o9MV zqmO^VADDxTgjVqr!fjVe8wLb$RXBX#oM7m-(uV<9c)%eIeKm8D$L~wy@m*sjc_tpZ zE|Z>pNYkD|7y6G#?Dtax{wv+=ipuHt!GPufh-%x}j;@n!1%Mnb{(2;`X=WgJJt`9c z_z2-%s#ZG(1Tfw2ziDAKwy{)C>pd5H&3w+XkZIc7BxKJ~l#VNdp;c&N)Q%g(FwO73 z@!z7cpAIDk8qWTp;cT`r8vWfge_%cWKsv=hepRbIIbaNo=H+R(C*#j)eawYWQvxAm zO{#l}n`Pk)9011?ucC$uwtaG0*U3=;P>BHqmnU2P9OtuP1C+*44g`rV{IptHKTtp5Fp(QPm-qHxJVYdf9yjziR;5zds5oVG zt0<1XJDzw2DGx2QF_*pOkJak$QEONyeLWK0*vj)~J4uN#pny#bK-RJkdGtY_LRDssFi&c3xN`Gi-Y+OCxbVj;ZGVWP=C-_?s^@hzCjdozgFnQh2s<{qe4 zw|e!?1%Cg+e~-p~?$j^@*p_1P)@M}pLDy~k7y13yjgjS9K|)$;j1-QU`pYHTPF?8p z-#AK?#yyzNUca|KzIPJjl30A__&N0KS!2lERV%^V_S>Ci_>w55c;lR9J(jfJ!!y}(zC*)q0k)* zlc&;(g=euIQ5?K#Q}iJ|I(Ud@*w6Gy*?qQ-cWgq8+(HR@H#AcO|towR-SLu z7-Nlvn3w)>GPk`{{K4j8ak1MDq7Zr*AUZ7+x@ofPyS9br#|9{Mns)~wV~{be{GasN zlRH&){ZYd>*dV-pb2PSPs^5P#(l}So;LgAR%ZL>xJ{Xk+I6fEvl+Ov~F|z!n+hg%( zDvb3xGxb>M*|NIn;e7sPw+eO2Y;US?wji80jOR!DIWA$@ww|@D_l{`Vt8Nc~%e?jU zhDhw;=>h*YFo}A!>kShcN*E^|hVnQdu2z(Fb3)3J9J39+kLewPz!C#{-{0l)i;ft^ zOYY%l4QzP&o3=T@ifb_@76d~-9V^Q-8cP@_!2to4+1ZsRPmECkGPr)I0C1f%7iy0u zo*5_0(;GF@r~#ZPV3M%_?3XI#U+yZGA97t|Kt;s>Mod?fg);+zB>_SeEFfLCarPnW zga{RWkj-4Pzgq3|JY%Q;@C;`{rT|3So089-C5q$Rmwq3bqasgZoZuVHnr*YU4gG~T zYPFqj8^-<&W5+dJR|SxHMX-{?1Yz7*QNDPzEYFH^G+c4VDvgwF5-_5K3Qv{QA8yX) zZ)xnUPX&Mn!VUm5w>KrXw~69JcNmO0qxV_N1;R;$00u6y5VDEMKqC}535bBb1EyAN zF--u>(CF9RS=gzW5kiF*E0xC{s+@4D1(Vyh9|Jv6W{-Xfs0fE1KEfo6p>|kh> zNU2z{ZAUYM)clR};t$=A!HUA;FbjQln_61EwOG8f!NPwtZ~mwNJOXgC`dNZ7ah?)c zd!8g+jP+!VF{d@eIB?xzzay!h*DDE9XN@VupG zYV6K@7M&xBvwVaQOjP*eRgk^i%dJQ$#)pWp0018t=3CEI)Q5Jc>d(B<<3KMvP6vP< zhVnEtLKMeM7Uel(B%l5n350A@MH%$#K%{flnwJyy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ diff --git a/android/app/src/main/res/mipmap-xhdpi/unit.png b/android/app/src/main/res/mipmap-xhdpi/unit.png new file mode 100644 index 0000000000000000000000000000000000000000..15a1e0217fb370acc4753ae99775d4f46baef412 GIT binary patch literal 8137 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index d5f1c8d34e7a88e3f88bea192c3a370d44689c3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof diff --git a/android/app/src/main/res/mipmap-xxhdpi/unit.png b/android/app/src/main/res/mipmap-xxhdpi/unit.png new file mode 100644 index 0000000000000000000000000000000000000000..c1a8e83c1cf92c72d61c0b278dfff1963cc38ad9 GIT binary patch literal 12522 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 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/unit.png b/android/app/src/main/res/mipmap-xxxhdpi/unit.png new file mode 100644 index 0000000000000000000000000000000000000000..d7c5bfebf800b008b6d74273279cf0ea5bd18c78 GIT binary patch literal 17244 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 literal 0 HcmV?d00001 diff --git a/android/build.gradle b/android/build.gradle index 83ae220..dfce013 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.6.10' + ext.kotlin_version = '1.8.0' repositories { google() mavenCentral() diff --git a/lib/bloc/profile/education/education_bloc.dart b/lib/bloc/profile/education/education_bloc.dart index 0117b6d..c10fa17 100644 --- a/lib/bloc/profile/education/education_bloc.dart +++ b/lib/bloc/profile/education/education_bloc.dart @@ -1,10 +1,18 @@ +import 'dart:io'; + import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:share_plus/share_plus.dart'; import 'package:unit2/model/profile/educational_background.dart'; import 'package:unit2/sevices/profile/education_services.dart'; +import 'package:unit2/utils/request_permission.dart'; import '../../../model/profile/attachment.dart'; import '../../../utils/attachment_services.dart'; +import '../../../utils/urls.dart'; part 'education_event.dart'; part 'education_state.dart'; @@ -14,9 +22,13 @@ class EducationBloc extends Bloc { List schools = []; List programs = []; List honors = []; + int? profileId; + String? token; List attachmentCategories = []; EducationBloc() : super(EducationInitial()) { on((event, emit) async { + profileId = event.profileId; + token = event.token; emit(EducationalBackgroundLoadingState()); try { if (attachmentCategories.isEmpty) { @@ -206,5 +218,44 @@ class EducationBloc extends Bloc { emit(EducationalBackgroundErrorState(message: e.toString())); } }); + on((event, emit) { + String fileUrl = + '${Url.instance.prefixHost()}://${Url.instance.host()}${event.source}'; + emit(EducationAttachmentViewState( + fileUrl: fileUrl, fileName: event.fileName)); + }); + on((event, emit) async { + emit(EducationalBackgroundLoadingState()); + Directory directory; + String? appDocumentPath; + if (await requestPermission(Permission.storage)) { + directory = await getApplicationDocumentsDirectory(); + appDocumentPath = directory.path; + } + try{ + final bool success = await AttachmentServices.instance.downloadAttachment( + filename: event.fileName, + source: event.source, + downLoadDir: appDocumentPath!); + if (success) { + final result = await Share.shareXFiles( + [XFile("$appDocumentPath/${event.fileName}")]); + if (result.status == ShareResultStatus.success) { + Fluttertoast.showToast(msg: "Attachment shared successfully"); + emit(EducationAttachmentViewState( + fileUrl: event.source, fileName: event.fileName)); + } else { + Fluttertoast.showToast(msg: "Attachment shared unsuccessfully"); + emit(EducationAttachmentViewState( + fileUrl: event.source, fileName: event.fileName)); + } + } else { + emit(EducationAttachmentViewState( + fileUrl: event.source, fileName: event.fileName)); + } + }catch(e){ +emit(EducationalBackgroundErrorState(message: e.toString())); + } + }); } } diff --git a/lib/bloc/profile/education/education_event.dart b/lib/bloc/profile/education/education_event.dart index 9b68a0f..d2f57e6 100644 --- a/lib/bloc/profile/education/education_event.dart +++ b/lib/bloc/profile/education/education_event.dart @@ -83,3 +83,15 @@ class DeleteEducationAttachment extends EducationEvent{ final int profileId; const DeleteEducationAttachment({required this.attachment, required this.moduleId, required this.profileId, required this.token}); } + +class EducationViewAttachment extends EducationEvent{ + final String fileName; + final String source; + const EducationViewAttachment({required this.source,required this.fileName}); +} + +class ShareAttachment extends EducationEvent{ + final String fileName; + final String source; + const ShareAttachment({required this.fileName, required this.source}); +} diff --git a/lib/bloc/profile/education/education_state.dart b/lib/bloc/profile/education/education_state.dart index 3cfe505..d7fd394 100644 --- a/lib/bloc/profile/education/education_state.dart +++ b/lib/bloc/profile/education/education_state.dart @@ -60,7 +60,6 @@ class EducationAddedState extends EducationState { List get props => [response]; } - //// Edited State class EditedEducationState extends EducationState { final Map response; @@ -89,4 +88,15 @@ class EducationAttachmentDeletedState extends EducationState { const EducationAttachmentDeletedState({required this.success}); @override List get props => [success]; -} \ No newline at end of file +} + +class EducationAttachmentViewState extends EducationState { + final String fileUrl; + final String fileName; + const EducationAttachmentViewState({required this.fileUrl, required this.fileName}); +} + +class EducationAttachmentShareState extends EducationState{ + final bool success; + const EducationAttachmentShareState({required this.success,}); +} diff --git a/lib/bloc/profile/eligibility/eligibility_bloc.dart b/lib/bloc/profile/eligibility/eligibility_bloc.dart index 1be36b4..6710f47 100644 --- a/lib/bloc/profile/eligibility/eligibility_bloc.dart +++ b/lib/bloc/profile/eligibility/eligibility_bloc.dart @@ -11,6 +11,7 @@ import '../../../model/utils/eligibility.dart'; import '../../../sevices/profile/eligibility_services.dart'; import '../../../utils/location_utilities.dart'; import '../../../utils/profile_utilities.dart'; +import '../../../utils/urls.dart'; part 'eligibility_event.dart'; part 'eligibility_state.dart'; @@ -52,6 +53,7 @@ class EligibilityBloc extends Bloc { //// GET ELIGIBILITY on((event, emit) async { + emit(EligibilityLoadingState()); try { if (attachmentCategories.isEmpty) { attachmentCategories = @@ -257,7 +259,7 @@ class EligibilityBloc extends Bloc { on((event, emit) async { emit(EligibilityLoadingState()); - // try { + try { final bool success = await AttachmentServices.instance.deleteAttachment( attachment: event.attachment, moduleId: int.parse(event.moduleId), @@ -275,9 +277,13 @@ class EligibilityBloc extends Bloc { } else { emit(EligibilitytAttachmentDeletedState(success: success)); } - // } catch (e) { - // emit(EligibilityErrorState(message: e.toString())); - // } + } catch (e) { + emit(EligibilityErrorState(message: e.toString())); + } + }); + on((event,emit){ + String fileUrl = '${Url.instance.prefixHost()}://${Url.instance.host()}${event.source}'; + emit(EligibilityAttachmentViewState(fileUrl: fileUrl)); }); } } diff --git a/lib/bloc/profile/eligibility/eligibility_event.dart b/lib/bloc/profile/eligibility/eligibility_event.dart index a9b6ca8..925b105 100644 --- a/lib/bloc/profile/eligibility/eligibility_event.dart +++ b/lib/bloc/profile/eligibility/eligibility_event.dart @@ -7,38 +7,44 @@ abstract class EligibilityEvent extends Equatable { List get props => []; } -class ShowAddEligibilityForm extends EligibilityEvent { +class ShowAddEligibilityForm extends EligibilityEvent {} -} - -class GetEligibilities extends EligibilityEvent{ +class GetEligibilities extends EligibilityEvent { final int profileId; final String token; const GetEligibilities({required this.profileId, required this.token}); @override - List get props => [profileId,token]; + List get props => [profileId, token]; } -class AddEligibility extends EligibilityEvent{ - final EligibityCert eligibityCert; +class AddEligibility extends EligibilityEvent { + final EligibityCert eligibityCert; final String profileId; final String token; - const AddEligibility({required this.eligibityCert, required this.profileId, required this.token}); + const AddEligibility( + {required this.eligibityCert, + required this.profileId, + required this.token}); @override - List get props => [eligibityCert, profileId, token]; + List get props => [eligibityCert, profileId, token]; } -class UpdateEligibility extends EligibilityEvent{ + +class UpdateEligibility extends EligibilityEvent { final EligibityCert eligibityCert; final String profileId; final String token; final int oldEligibility; - const UpdateEligibility({required this.eligibityCert, required this.oldEligibility,required this.profileId, required this.token}); + const UpdateEligibility( + {required this.eligibityCert, + required this.oldEligibility, + required this.profileId, + required this.token}); @override - List get props =>[eligibityCert,profileId,token,oldEligibility]; + List get props => [eligibityCert, profileId, token, oldEligibility]; } -class LoadEligibility extends EligibilityEvent { +class LoadEligibility extends EligibilityEvent { const LoadEligibility(); @override List get props => []; @@ -55,45 +61,55 @@ class DeleteEligibility extends EligibilityEvent { final String profileId; final int eligibilityId; final String token; - + const DeleteEligibility( - { - required this.eligibilityId, + {required this.eligibilityId, required this.profileId, required this.token}); @override - List get props => [ profileId, eligibilityId, token]; + List get props => [profileId, eligibilityId, token]; } -class CallErrorState extends EligibilityEvent{ - -} +class CallErrorState extends EligibilityEvent {} + ////Add Attachment -class AddEligibiltyAttachment extends EligibilityEvent{ +class AddEligibiltyAttachment extends EligibilityEvent { final String categoryId; final String attachmentModule; final List filePaths; final String token; final String profileId; - const AddEligibiltyAttachment({required this.attachmentModule, required this.filePaths, required this.categoryId, required this.profileId, required this.token}); + const AddEligibiltyAttachment( + {required this.attachmentModule, + required this.filePaths, + required this.categoryId, + required this.profileId, + required this.token}); @override - List get props => [categoryId,attachmentModule,filePaths, token,profileId]; + List get props => + [categoryId, attachmentModule, filePaths, token, profileId]; } ////Delete Attachment -class DeleteEligibyAttachment extends EligibilityEvent{ +class DeleteEligibyAttachment extends EligibilityEvent { final String profileId; final String token; final Attachment attachment; final String moduleId; - const DeleteEligibyAttachment({required this.attachment,required this.moduleId, required this.profileId, required this.token}); + const DeleteEligibyAttachment( + {required this.attachment, + required this.moduleId, + required this.profileId, + required this.token}); } +class EligibilityViewAttachments extends EligibilityEvent { + final String source; + const EligibilityViewAttachments({required this.source}); +} - - - - - - +class EligibiltyViewAttachmentEvent extends EligibilityEvent{ + final String source; + const EligibiltyViewAttachmentEvent({required this.source}); +} diff --git a/lib/bloc/profile/eligibility/eligibility_state.dart b/lib/bloc/profile/eligibility/eligibility_state.dart index 7d746d9..6f8976c 100644 --- a/lib/bloc/profile/eligibility/eligibility_state.dart +++ b/lib/bloc/profile/eligibility/eligibility_state.dart @@ -107,3 +107,8 @@ class EligibilitytAttachmentDeletedState extends EligibilityState { @override List get props => [success]; } + +class EligibilityAttachmentViewState extends EligibilityState { + final String fileUrl; + const EligibilityAttachmentViewState({required this.fileUrl}); +} diff --git a/lib/bloc/profile/learningDevelopment/learning_development_bloc.dart b/lib/bloc/profile/learningDevelopment/learning_development_bloc.dart index 465cefb..9dd75b7 100644 --- a/lib/bloc/profile/learningDevelopment/learning_development_bloc.dart +++ b/lib/bloc/profile/learningDevelopment/learning_development_bloc.dart @@ -13,6 +13,7 @@ import '../../../model/utils/category.dart'; import '../../../utils/attachment_services.dart'; import '../../../utils/location_utilities.dart'; import '../../../utils/profile_utilities.dart'; +import '../../../utils/urls.dart'; part 'learning_development_event.dart'; part 'learning_development_state.dart'; @@ -325,5 +326,10 @@ class LearningDevelopmentBloc emit(LearningDevelopmentErrorState(message: e.toString())); } }); + on((event,emit){ + String fileUrl = '${Url.instance.prefixHost()}://${Url.instance.host()}${event.source}'; + emit(LearningAndDevelopmentAttachmentViewState(fileUrl: fileUrl)); + }); } + } diff --git a/lib/bloc/profile/learningDevelopment/learning_development_event.dart b/lib/bloc/profile/learningDevelopment/learning_development_event.dart index c8528ac..d450d7d 100644 --- a/lib/bloc/profile/learningDevelopment/learning_development_event.dart +++ b/lib/bloc/profile/learningDevelopment/learning_development_event.dart @@ -88,3 +88,9 @@ class DeleteLearningDevAttachment extends LearningDevelopmentEvent{ const DeleteLearningDevAttachment({required this.attachment, required this.moduleId, required this.profileId, required this.token}); } +class LearningDevelopmentViewAttachmentEvent extends LearningDevelopmentEvent{ + final String source; + const LearningDevelopmentViewAttachmentEvent({required this.source}); +} + + diff --git a/lib/bloc/profile/learningDevelopment/learning_development_state.dart b/lib/bloc/profile/learningDevelopment/learning_development_state.dart index 2699470..7507e9c 100644 --- a/lib/bloc/profile/learningDevelopment/learning_development_state.dart +++ b/lib/bloc/profile/learningDevelopment/learning_development_state.dart @@ -133,3 +133,9 @@ class LearningDevAttachmentDeletedState extends LearningDevelopmentState { @override List get props => [success]; } + + +class LearningAndDevelopmentAttachmentViewState extends LearningDevelopmentState { + final String fileUrl; + const LearningAndDevelopmentAttachmentViewState({required this.fileUrl}); +} \ No newline at end of file diff --git a/lib/bloc/profile/workHistory/workHistory_bloc.dart b/lib/bloc/profile/workHistory/workHistory_bloc.dart index 85bd4bd..b751baa 100644 --- a/lib/bloc/profile/workHistory/workHistory_bloc.dart +++ b/lib/bloc/profile/workHistory/workHistory_bloc.dart @@ -7,6 +7,7 @@ import 'package:unit2/model/utils/position.dart'; import 'package:unit2/sevices/profile/work_history_services.dart'; import 'package:unit2/utils/profile_utilities.dart'; import '../../../model/profile/attachment.dart'; + import '../../../model/utils/category.dart'; import '../../../utils/attachment_services.dart'; part 'workHistory_event.dart'; @@ -67,8 +68,10 @@ class WorkHistoryBloc extends Bloc { }); //// ADD WORK HISTORIES on((event, emit) async { - try { + // try { Map status = await WorkHistoryService.instance.add( + accomplishment: event.accomplishment, + actualDuties: event.actualDuties, isPrivate: event.isPrivate, workHistory: event.workHistory, token: event.token, @@ -80,35 +83,35 @@ class WorkHistoryBloc extends Bloc { } else { emit(WorkHistoryAddedState(response: status)); } - } catch (e) { - emit(WorkHistoryErrorState(message: e.toString())); - } + // } catch (e) { + // emit(WorkHistoryErrorState(message: e.toString())); + // } }); ////UPDATE WORK HISTORY - on((event, emit) async { - try { - Map status = await WorkHistoryService.instance.update( - oldWorkHistory: event.oldWorkHistory, - newWorkHistory: event.workHistory, - token: event.token, - profileId: event.profileId); - if (status['success']) { - WorkHistory workHistory = WorkHistory.fromJson(status['data']); - workExperiences.removeWhere((WorkHistory work) { - return work.id == event.oldWorkHistory.id; - }); - workExperiences.add(workHistory); - emit(WorkHistoryEditedState(response: status)); - } else { - emit(WorkHistoryEditedState( - response: status, - )); - } - } catch (e) { - emit(WorkHistoryErrorState(message: e.toString())); - } - }); + // on((event, emit) async { + // try { + // Map status = await WorkHistoryService.instance.update( + // oldWorkHistory: event.oldWorkHistory, + // newWorkHistory: event.workHistory, + // token: event.token, + // profileId: event.profileId); + // if (status['success']) { + // WorkHistory workHistory = WorkHistory.fromJson(status['data']); + // workExperiences.removeWhere((WorkHistory work) { + // return work.id == event.oldWorkHistory.id; + // }); + // workExperiences.add(workHistory); + // emit(WorkHistoryEditedState(response: status)); + // } else { + // emit(WorkHistoryEditedState( + // response: status, + // )); + // } + // } catch (e) { + // emit(WorkHistoryErrorState(message: e.toString())); + // } + // }); ////SHOW EDIT WORK HISTORIES on((event, emit) async { @@ -209,12 +212,12 @@ class WorkHistoryBloc extends Bloc { Attachment newAttachment = Attachment.fromJson(element); attachments.add(newAttachment); }); - workHistory.attachments == null - ? workHistory.attachments = attachments - : workHistory.attachments = [ - ...workHistory.attachments!, - ...attachments - ]; + // workHistory.attachments == null + // ? workHistory.attachments = attachments + // : workHistory.attachments = [ + // ...workHistory.attachments!, + // ...attachments + // ]; emit(WorkHistoryDevAttachmentAddedState(response: status)); } else { emit(WorkHistoryDevAttachmentAddedState(response: status)); @@ -223,31 +226,31 @@ class WorkHistoryBloc extends Bloc { emit(WorkHistoryErrorState(message: e.toString())); } }); - ////Delete Attachment - on((event, emit) async { - emit(WorkHistoryLoadingState()); - try { - final bool success = await AttachmentServices.instance.deleteAttachment( - attachment: event.attachment, - moduleId: event.moduleId, - profileId: event.profileId.toString(), - token: event.token); - if (success) { - final WorkHistory workHistory = - workExperiences - .firstWhere((element) => element.id == event.moduleId); - workHistory.attachments - ?.removeWhere((element) => element.id == event.attachment.id); - workExperiences - .removeWhere((element) => element.id == event.moduleId); - workExperiences.add(workHistory); - emit(WorkHistoryDevAttachmentDeletedState(success: success)); - } else { - emit(WorkHistoryDevAttachmentDeletedState(success: success)); - } - } catch (e) { - emit(WorkHistoryErrorState(message: e.toString())); - } - }); + // ////Delete Attachment + // on((event, emit) async { + // emit(WorkHistoryLoadingState()); + // try { + // final bool success = await AttachmentServices.instance.deleteAttachment( + // attachment: event.attachment, + // moduleId: event.moduleId, + // profileId: event.profileId.toString(), + // token: event.token); + // if (success) { + // final WorkHistory workHistory = + // workExperiences + // .firstWhere((element) => element.id == event.moduleId); + // workHistory.attachments + // ?.removeWhere((element) => element.id == event.attachment.id); + // workExperiences + // .removeWhere((element) => element.id == event.moduleId); + // workExperiences.add(workHistory); + // emit(WorkHistoryDevAttachmentDeletedState(success: success)); + // } else { + // emit(WorkHistoryDevAttachmentDeletedState(success: success)); + // } + // } catch (e) { + // emit(WorkHistoryErrorState(message: e.toString())); + // } + // }); } } diff --git a/lib/bloc/profile/workHistory/workHistory_event.dart b/lib/bloc/profile/workHistory/workHistory_event.dart index 1895bfe..6e73101 100644 --- a/lib/bloc/profile/workHistory/workHistory_event.dart +++ b/lib/bloc/profile/workHistory/workHistory_event.dart @@ -43,12 +43,14 @@ class DeleteWorkHistory extends WorkHistorytEvent{ class UpdateWorkHistory extends WorkHistorytEvent{ final WorkHistory workHistory; - final WorkHistory oldWorkHistory; - final String profileId; + final bool isPrivate; + final int profileId; final String token; - const UpdateWorkHistory({required this.oldWorkHistory, required this.profileId, required this.token, required this.workHistory}); + final String? actualDuties; + final String? accomplishment; + const UpdateWorkHistory({required this.profileId, required this.token, required this.workHistory, required this.accomplishment, required this.actualDuties, required this.isPrivate}); @override - List get props => [profileId,token,workHistory,oldWorkHistory]; + List get props => [profileId,token,workHistory,]; } class AddWorkHostory extends WorkHistorytEvent{ @@ -56,7 +58,9 @@ class AddWorkHostory extends WorkHistorytEvent{ final bool isPrivate; final int profileId; final String token; - const AddWorkHostory({required this.workHistory, required this.isPrivate, required this.profileId, required this.token}); + final String? actualDuties; + final String? accomplishment; + const AddWorkHostory({required this.workHistory, required this.isPrivate, required this.profileId, required this.token, required this.accomplishment, required this.actualDuties}); @override List get props => [workHistory,profileId,token,isPrivate]; } diff --git a/lib/bloc/role/pass_check/pass_check_bloc.dart b/lib/bloc/role/pass_check/pass_check_bloc.dart index 9458357..c1d157a 100644 --- a/lib/bloc/role/pass_check/pass_check_bloc.dart +++ b/lib/bloc/role/pass_check/pass_check_bloc.dart @@ -22,15 +22,15 @@ class PassCheckBloc extends Bloc { int? stationId; String? cpId; on((event, emit) async { - // try { + try { emit(PassCheckLoadingState()); List response = await PassCheckServices.instance .getPassCheckArea(roleId: event.roleId, userId: event.userId); roleId = event.roleId; emit(AssignAreaLoaded(assignedArea: response, roleId: roleId!)); - // } catch (e) { - // emit(PassCheckErrorState(message: e.toString())); - // } + } catch (e) { + emit(PassCheckErrorState(message: e.toString())); + } }); on((event, emit) { otherInputs = event.includeOtherInputs; diff --git a/lib/model/profile/work_history.dart b/lib/model/profile/work_history.dart index 5e01642..538e6f4 100644 --- a/lib/model/profile/work_history.dart +++ b/lib/model/profile/work_history.dart @@ -1,75 +1,163 @@ -// To parse this JSON data, do -// -// final workHistory = workHistoryFromJson(jsonString); - -import 'dart:convert'; +import 'package:unit2/model/utils/industry_class.dart'; import '../utils/agency.dart'; -import '../utils/category.dart'; -import '../utils/industry_class.dart'; import '../utils/position.dart'; -import 'attachment.dart'; - -WorkHistory workHistoryFromJson(String str) => WorkHistory.fromJson(json.decode(str)); - -String workHistoryToJson(WorkHistory data) => json.encode(data.toJson()); class WorkHistory { - WorkHistory({ - this.id, - this.agency, - this.sgStep, - this.toDate, - this.position, - this.fromDate, - this.attachments, - this.salaryGrade, - this.monthlySalary, - this.appointmentStatus, - }); + final PositionTitle? position; + final Agency? agency; + final Supervisor? supervisor; + final int? id; + final DateTime? fromDate; + final DateTime? toDate; + final int? agencydepid; + final double? monthlysalary; + final String? statusAppointment; + final int? salarygrade; + final int? sgstep; + final List? accomplishment; + final List? actualDuties; - final int? id; - final Agency? agency; - final int? sgStep; - final DateTime? toDate; - final PositionTitle? position; - final DateTime? fromDate; - List? attachments; - final int? salaryGrade; - final double? monthlySalary; - final String? appointmentStatus; + WorkHistory({ + required this.position, + required this.agency, + required this.supervisor, + required this.id, + required this.fromDate, + required this.toDate, + required this.agencydepid, + required this.monthlysalary, + required this.statusAppointment, + required this.salarygrade, + required this.sgstep, + required this.accomplishment, + required this.actualDuties, + }); - factory WorkHistory.fromJson(Map json) => WorkHistory( + factory WorkHistory.fromJson(Map json) => WorkHistory( + position: PositionTitle.fromJson(json["position"]), + agency: json['agency'] == null?null: Agency.fromJson(json["agency"]), + supervisor: json['supervisor'] == null?null: Supervisor.fromJson(json["supervisor"]), id: json["id"], - agency: json["agency"] == null ? null : Agency.fromJson(json["agency"]), - sgStep: json["sg_step"], - toDate: json["to_date"] == null ? null : DateTime.parse(json["to_date"]), - position: json["position"] == null ? null : PositionTitle.fromJson(json["position"]), - fromDate: json["from_date"] == null ? null : DateTime.parse(json["from_date"]), - attachments: json['attachments'] ==null?null: List.from(json["attachments"].map((x) => Attachment.fromJson(x))), - salaryGrade: json["salary_grade"], - monthlySalary: json["monthly_salary"], - appointmentStatus: json["appointment_status"], - ); + fromDate: json['from_date'] == null?null: DateTime.tryParse(json["from_date"]), + toDate: json['to_date'] == null?null: DateTime.tryParse(json["to_date"]), + agencydepid: json["agencydepid"], + monthlysalary: json["monthlysalary"], + statusAppointment: json["status_appointment"], + salarygrade: json["salarygrade"], + sgstep: json["sgstep"], + accomplishment:json['accomplishment'] == null?null: json['accomplishment'] == null?null: List.from( + json["accomplishment"].map((x) => Accomplishment.fromJson(x))), + actualDuties: json['actual_duties'] == null?null: List.from( + json["actual_duties"].map((x) => ActualDuty.fromJson(x))), + ); - Map toJson() => { - "id": id, - "agency": agency?.toJson(), - "sg_step": sgStep, - "to_date": "${toDate!.year.toString().padLeft(4, '0')}-${toDate!.month.toString().padLeft(2, '0')}-${toDate!.day.toString().padLeft(2, '0')}", + Map toJson() => { "position": position?.toJson(), - "from_date": "${fromDate!.year.toString().padLeft(4, '0')}-${fromDate!.month.toString().padLeft(2, '0')}-${fromDate!.day.toString().padLeft(2, '0')}", - // "attachments": attachments, - "salary_grade": salaryGrade, - "monthly_salary": monthlySalary, - "appointment_status": appointmentStatus, - }; + "agency": agency?.toJson(), + "supervisor": supervisor?.toJson(), + "id": id, + "from_date": + "${fromDate?.year.toString().padLeft(4, '0')}-${fromDate?.month.toString().padLeft(2, '0')}-${fromDate?.day.toString().padLeft(2, '0')}", + "to_date": toDate, + "agencydepid": agencydepid, + "monthlysalary": monthlysalary, + "status_appointment": statusAppointment, + "salarygrade": salarygrade, + "sgstep": sgstep, + "accomplishment": + List.from(accomplishment!.map((x) => x.toJson())), + "actual_duties": + List.from(actualDuties!.map((x) => x.toJson())), + }; +} + +class Accomplishment { + final int? id; + final int? workExperienceId; + final String? accomplishment; + + Accomplishment({ + required this.id, + required this.workExperienceId, + required this.accomplishment, + }); + + factory Accomplishment.fromJson(Map json) => Accomplishment( + id: json["id"], + workExperienceId: json["work_experience_id"], + accomplishment: json["accomplishment"], + ); + + Map toJson() => { + "id": id, + "work_experience_id": workExperienceId, + "accomplishment": accomplishment, + }; +} + +class ActualDuty { + final int? id; + final int? workExperienceId; + final String description; + + ActualDuty({ + required this.id, + required this.workExperienceId, + required this.description, + }); + + factory ActualDuty.fromJson(Map json) => ActualDuty( + id: json["id"], + workExperienceId: json["work_experience_id"], + description: json["description"], + ); + + Map toJson() => { + "id": id, + "work_experience_id": workExperienceId, + "description": description, + }; +} + + + +class Supervisor { + final int? id; + final int? agencyId; + final String? lastname; + final String? firstname; + final String? middlename; + final String? stationName; + + Supervisor({ + required this.id, + required this.agencyId, + required this.lastname, + required this.firstname, + required this.middlename, + required this.stationName, + }); + + factory Supervisor.fromJson(Map json) => Supervisor( + id: json["id"], + agencyId: json["agency_id"], + lastname: json["lastname"], + firstname: json["firstname"], + middlename: json["middlename"], + stationName: json["station_name"], + ); + + Map toJson() => { + "id": id, + "agency_id": agencyId, + "lastname": lastname, + "firstname": firstname, + "middlename": middlename, + "station_name": stationName, + }; } - - - - diff --git a/lib/screens/profile/components/education/education_view_attachment.dart b/lib/screens/profile/components/education/education_view_attachment.dart new file mode 100644 index 0000000..88657f9 --- /dev/null +++ b/lib/screens/profile/components/education/education_view_attachment.dart @@ -0,0 +1,121 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_progress_hud/flutter_progress_hud.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:share_plus/share_plus.dart'; +import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'; +import 'package:unit2/bloc/profile/education/education_bloc.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; + +class EudcationViewAttachment extends StatefulWidget { + const EudcationViewAttachment({super.key}); + + @override + State createState() => + _EudcationViewAttachmentState(); +} + +class _EudcationViewAttachmentState extends State { + @override + Widget build(BuildContext context) { + String? fileUrl; + String? filename; + return Scaffold( + floatingActionButton: FloatingActionButton( + onPressed: () async { + await _launchInBrowser(fileUrl!); + }, + child: const Icon(Icons.file_download), + ), + appBar: AppBar( + title: const Text("Attachment"), + centerTitle: true, + actions: [ + IconButton( + onPressed: () { + context.read().add( + ShareAttachment(fileName: filename!, source: fileUrl!)); + }, + icon: const Icon(Icons.share)), + ], + ), + body: ProgressHUD( + padding: const EdgeInsets.all(24), + backgroundColor: Colors.black87, + indicatorWidget: const SpinKitFadingCircle(color: Colors.white), + child: BlocConsumer( + builder: (context, state) { + if (state is EducationAttachmentViewState) { + fileUrl = state.fileUrl; + filename = state.fileName; + + bool isPDF = state.fileUrl[state.fileUrl.length - 1] == 'f' + ? true + : false; + return SizedBox( + child: isPDF + ? SfPdfViewer.network( + state.fileUrl, + onDocumentLoadFailed: (details) { + Center( + child: Text(details.description), + ); + }, + ) + : Center( + child: CachedNetworkImage( + progressIndicatorBuilder: (context, url, progress) { + return const SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator( + color: primary, + )); + }, + imageBuilder: (context, imageProvider) => Container( + decoration: BoxDecoration( + image: DecorationImage( + image: imageProvider, fit: BoxFit.fill)), + ), + imageUrl: state.fileUrl, + width: double.infinity, + height: 220, + fit: BoxFit.cover, + ), + ), + ); + } + return Container(); + }, + listener: (context, state) { + if (state is EducationalBackgroundLoadingState) { + final progress = ProgressHUD.of(context); + progress!.showWithText("Please wait..."); + } + if (state is EducationAttachmentViewState) { + final progress = ProgressHUD.of(context); + progress!.dismiss(); + } + }, + ), + )); + } + + Future _launchInBrowser(String url) async { + final UrlLauncherPlatform launcher = UrlLauncherPlatform.instance; + if (!await launcher.launch( + url, + useSafariVC: false, + useWebView: false, + enableJavaScript: false, + enableDomStorage: false, + universalLinksOnly: false, + headers: {}, + )) { + throw Exception('Could not launch $url'); + } + } +} diff --git a/lib/screens/profile/components/education_screen.dart b/lib/screens/profile/components/education_screen.dart index 15c88a0..761f285 100644 --- a/lib/screens/profile/components/education_screen.dart +++ b/lib/screens/profile/components/education_screen.dart @@ -11,6 +11,7 @@ import 'package:unit2/bloc/profile/profile_bloc.dart'; import 'package:unit2/bloc/user/user_bloc.dart'; import 'package:unit2/model/profile/educational_background.dart'; import 'package:unit2/screens/profile/components/education/add_modal.dart'; +import 'package:unit2/screens/profile/shared/view_attachment.dart'; import 'package:unit2/theme-data.dart/box_shadow.dart'; import 'package:unit2/theme-data.dart/colors.dart'; import 'package:unit2/widgets/Leadings/add_leading.dart'; @@ -26,6 +27,7 @@ import '../../../widgets/Leadings/close_leading.dart'; import '../shared/multiple_attachment.dart'; import '../shared/single_attachment.dart'; import 'education/edit_modal.dart'; +import 'education/education_view_attachment.dart'; class EducationScreen extends StatelessWidget { const EducationScreen({super.key}); @@ -321,12 +323,12 @@ class EducationScreen extends StatelessWidget { Column( children: honors .map((Honor honor) => Padding( - padding: const EdgeInsets.all(3.0), - child: Text( + padding: const EdgeInsets.all(3.0), + child: Text( "-${honor.name!.trim()}", style: Theme.of(context).textTheme.labelSmall, ), - )) + )) .toList(), ), ], @@ -696,6 +698,15 @@ class EducationScreen extends StatelessWidget { children: [ const Divider(), SingleAttachment( + view: () { + Navigator.push( + context, + MaterialPageRoute( + builder: ((context) => BlocProvider.value( + value: EducationBloc()..add(EducationViewAttachment(source: state.educationalBackground[index].attachments!.first.source!,fileName: state.educationalBackground[index].attachments!.first.filename!)), + child: const EudcationViewAttachment(), + )))); + }, onpressed: () { confirmAlert( @@ -728,6 +739,17 @@ class EducationScreen extends StatelessWidget { ) ////Multiple Attachments View : MultipleAttachments( + viewAttachment: + (source,filname) { + Navigator.push( + context, + MaterialPageRoute( + builder: ((context) => + BlocProvider.value( + value: EducationBloc()..add(EducationViewAttachment(source: source,fileName: filname)), + child: const EudcationViewAttachment(), + )))); + }, profileId: profileId, token: token!, diff --git a/lib/screens/profile/components/eligibility/eligibility_view_attachment.dart b/lib/screens/profile/components/eligibility/eligibility_view_attachment.dart new file mode 100644 index 0000000..9d21ba1 --- /dev/null +++ b/lib/screens/profile/components/eligibility/eligibility_view_attachment.dart @@ -0,0 +1,73 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'; +import 'package:unit2/bloc/profile/education/education_bloc.dart'; +import 'package:unit2/bloc/profile/eligibility/eligibility_bloc.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:url_launcher/url_launcher.dart'; +import '../../../../utils/urls.dart'; +class EligibilityViewAttachment extends StatefulWidget { + + const EligibilityViewAttachment({super.key}); + + @override + State createState() => _EligibilityViewAttachmentState(); +} + +class _EligibilityViewAttachmentState extends State { + @override + Widget build(BuildContext context) { + String? fileUrl; + return Scaffold( + floatingActionButton: FloatingActionButton( + onPressed: ()async { + await launchUrl(Uri.parse(fileUrl!)); + }, + child: const Icon(Icons.file_download), + ), + appBar: AppBar( + title: const Text("Attachment"), + centerTitle: true, + actions: [ + IconButton(onPressed: () {}, icon: const Icon(Icons.share)), + ], + ), + body: BlocConsumer(builder: (context,state){ + if(state is EligibilityAttachmentViewState){ + fileUrl = state.fileUrl; + bool isPDF = state.fileUrl[state.fileUrl.length - 1] == 'f' ? true : false; + return SizedBox( + child: isPDF?SfPdfViewer.network( + state.fileUrl,onDocumentLoadFailed: (details) { + Center(child: Text(details.description),); + },): Center( + child: CachedNetworkImage( + progressIndicatorBuilder: (context, url, progress) { + return const SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator(color: primary,)); + }, + + imageBuilder: (context, imageProvider) => Container( + decoration: BoxDecoration( + image: DecorationImage( + image: imageProvider, fit: BoxFit.fill)), + ), + imageUrl: + state.fileUrl, + width: double.infinity, + height: 220, + fit: BoxFit.cover, + ), + ), + ); + } + return Container(); + },listener: (context, state) { + + },) + ); + } +} diff --git a/lib/screens/profile/components/eligibility_screen.dart b/lib/screens/profile/components/eligibility_screen.dart index 0a51d26..4376fd1 100644 --- a/lib/screens/profile/components/eligibility_screen.dart +++ b/lib/screens/profile/components/eligibility_screen.dart @@ -28,6 +28,8 @@ import '../../../bloc/profile/eligibility/eligibility_bloc.dart'; import '../../../utils/alerts.dart'; import '../shared/multiple_attachment.dart'; import '../shared/single_attachment.dart'; +import '../shared/view_attachment.dart'; +import 'eligibility/eligibility_view_attachment.dart'; class EligibiltyScreen extends StatelessWidget { const EligibiltyScreen({super.key}); @@ -629,6 +631,17 @@ class EligibiltyScreen extends StatelessWidget { ? ////Single Attachment view SingleAttachment( + view: (){ + + Navigator.push( + context, + MaterialPageRoute( + builder: ((context) => BlocProvider.value( + value: EligibilityBloc()..add(EligibiltyViewAttachmentEvent(source: state.eligibilities[index].attachments!.first.source!)), + child: const EligibilityViewAttachment(), + )))); + + }, onpressed: () { confirmAlert( @@ -660,6 +673,15 @@ class EligibiltyScreen extends StatelessWidget { ) ////Multiple Attachments View : MultipleAttachments( + viewAttachment: (source,filename) { + Navigator.push( + context, + MaterialPageRoute( + builder: ((context) => BlocProvider.value( + value: EligibilityBloc()..add(EligibiltyViewAttachmentEvent(source: source)), + child: const EligibilityViewAttachment(), + )))); + }, profileId: profileId!, token: token!, diff --git a/lib/screens/profile/components/learning_and_development_screen.dart b/lib/screens/profile/components/learning_and_development_screen.dart index edb1f31..dbb74c8 100644 --- a/lib/screens/profile/components/learning_and_development_screen.dart +++ b/lib/screens/profile/components/learning_and_development_screen.dart @@ -12,6 +12,7 @@ import 'package:intl/intl.dart'; import 'package:unit2/bloc/profile/profile_bloc.dart'; import 'package:unit2/bloc/user/user_bloc.dart'; import 'package:unit2/screens/profile/components/learning_development/edit_modal.dart'; +import 'package:unit2/screens/profile/components/learning_development/learning_development_view_attachment.dart'; import 'package:unit2/theme-data.dart/box_shadow.dart'; import 'package:unit2/theme-data.dart/colors.dart'; import 'package:unit2/utils/global.dart'; @@ -27,6 +28,7 @@ import '../../../utils/alerts.dart'; import '../../../widgets/Leadings/close_leading.dart'; import '../shared/multiple_attachment.dart'; import '../shared/single_attachment.dart'; +import '../shared/view_attachment.dart'; import 'learning_development/add_modal.dart'; class LearningAndDevelopmentScreen extends StatelessWidget { @@ -673,6 +675,15 @@ class LearningAndDevelopmentScreen extends StatelessWidget { ? ////Single Attachment view SingleAttachment( + view: (){ + Navigator.push( + context, + MaterialPageRoute( + builder: ((context) => BlocProvider.value( + value: LearningDevelopmentBloc()..add(LearningDevelopmentViewAttachmentEvent(source: state.learningsAndDevelopment[index].attachments!.first.source!)), + child: const LearningDevelopmentViewAttachment(), + )))); + }, onpressed: () { confirmAlert( context, @@ -703,6 +714,17 @@ class LearningAndDevelopmentScreen extends StatelessWidget { ) ////Multiple Attachments View : MultipleAttachments( + viewAttachment: + (source,filename) { + Navigator.push( + context, + MaterialPageRoute( + builder: ((context) => + BlocProvider.value( + value: LearningDevelopmentBloc()..add(LearningDevelopmentViewAttachmentEvent(source: source)), + child: const LearningDevelopmentViewAttachment(), + )))); + }, profileId: profileId, token: token, diff --git a/lib/screens/profile/components/learning_development/learning_development_view_attachment.dart b/lib/screens/profile/components/learning_development/learning_development_view_attachment.dart new file mode 100644 index 0000000..7d07997 --- /dev/null +++ b/lib/screens/profile/components/learning_development/learning_development_view_attachment.dart @@ -0,0 +1,71 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'; +import 'package:unit2/bloc/profile/learningDevelopment/learning_development_bloc.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:url_launcher/url_launcher.dart'; +class LearningDevelopmentViewAttachment extends StatefulWidget { + + const LearningDevelopmentViewAttachment({super.key}); + + @override + State createState() => _LearningDevelopmentViewAttachmentState(); +} + +class _LearningDevelopmentViewAttachmentState extends State { + @override + Widget build(BuildContext context) { + String? fileUrl; + return Scaffold( + floatingActionButton: FloatingActionButton( + onPressed: ()async { + await launchUrl(Uri.parse(fileUrl!)); + }, + child: const Icon(Icons.file_download), + ), + appBar: AppBar( + title: const Text("Attachment"), + centerTitle: true, + actions: [ + IconButton(onPressed: () {}, icon: const Icon(Icons.share)), + ], + ), + body: BlocConsumer(builder: (context,state){ + if(state is LearningAndDevelopmentAttachmentViewState){ + fileUrl = state.fileUrl; + bool isPDF = state.fileUrl[state.fileUrl.length - 1] == 'f' ? true : false; + return SizedBox( + child: isPDF?SfPdfViewer.network( + state.fileUrl,onDocumentLoadFailed: (details) { + Center(child: Text(details.description),); + },): Center( + child: CachedNetworkImage( + progressIndicatorBuilder: (context, url, progress) { + return const SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator(color: primary,)); + }, + + imageBuilder: (context, imageProvider) => Container( + decoration: BoxDecoration( + image: DecorationImage( + image: imageProvider, fit: BoxFit.fill)), + ), + imageUrl: + state.fileUrl, + width: double.infinity, + height: 220, + fit: BoxFit.cover, + ), + ), + ); + } + return Container(); + },listener: (context, state) { + + },) + ); + } +} diff --git a/lib/screens/profile/components/work_history/add_modal.dart b/lib/screens/profile/components/work_history/add_modal.dart index 38ca36a..75b0aab 100644 --- a/lib/screens/profile/components/work_history/add_modal.dart +++ b/lib/screens/profile/components/work_history/add_modal.dart @@ -14,7 +14,7 @@ import 'package:unit2/model/utils/category.dart'; import 'package:unit2/theme-data.dart/box_shadow.dart'; import 'package:unit2/theme-data.dart/btn-style.dart'; import 'package:unit2/theme-data.dart/colors.dart'; -import 'package:unit2/theme-data.dart/form-style.dart'; +import 'package:unit2/theme-data.dart/form-style.dart'; import 'package:unit2/utils/global.dart'; import 'package:unit2/utils/text_container.dart'; import 'package:unit2/utils/validators.dart'; @@ -45,6 +45,12 @@ class _AddWorkHistoryScreenState extends State { String? salary; String? salaryGrade; String? salaryGradeStep; + String? accomplishment; + String? duties; + String? sFname; + String? sLname; + String? sMname; + String? sOffice; bool showAgency = false; bool showSalaryGradeAndSalaryStep = false; bool? isPrivate = false; @@ -67,7 +73,9 @@ class _AddWorkHistoryScreenState extends State { @override Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) { if (state is AddWorkHistoryState) { final progress = ProgressHUD.of(context); @@ -77,15 +85,14 @@ class _AddWorkHistoryScreenState extends State { if (state is AddWorkHistoryState) { return FormBuilder( key: _formKey, - child: SizedBox( - height: blockSizeVertical * 90, + child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.symmetric(vertical: 32, horizontal: 28), child: Column( + mainAxisAlignment: MainAxisAlignment.start, children: [ - Flexible( - child: ListView( - children: [ + + ////POSITIONS StatefulBuilder(builder: (context, setState) { return SearchField( @@ -93,18 +100,18 @@ class _AddWorkHistoryScreenState extends State { itemHeight: 70, suggestionsDecoration: box1(), suggestions: state.agencyPositions - .map((PositionTitle position) => SearchFieldListItem( - position.title!, - item: position, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10), - child: ListTile( - title: Text( - position.title!, - overflow: TextOverflow.visible, - ), - )))) + .map((PositionTitle position) => + SearchFieldListItem(position.title!, + item: position, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10), + child: ListTile( + title: Text( + position.title!, + overflow: TextOverflow.visible, + ), + )))) .toList(), focusNode: positionFocusNode, searchInputDecoration: @@ -127,11 +134,12 @@ class _AddWorkHistoryScreenState extends State { controller: addPositionController, onpressed: () { setState(() { - PositionTitle newAgencyPosition = PositionTitle( - id: null, - title: addPositionController.text - .toUpperCase()); - + PositionTitle newAgencyPosition = + PositionTitle( + id: null, + title: addPositionController.text + .toUpperCase()); + state.agencyPositions .insert(0, newAgencyPosition); selectedPosition = newAgencyPosition; @@ -170,7 +178,7 @@ class _AddWorkHistoryScreenState extends State { }, onSuggestionTap: (status) { selectedStatus = status.item; - + appointmentStatusNode.unfocus(); }, searchInputDecoration: @@ -182,7 +190,7 @@ class _AddWorkHistoryScreenState extends State { appointmentStatusNode.unfocus(); }, ))), - + const SizedBox( height: 12, ), @@ -226,7 +234,7 @@ class _AddWorkHistoryScreenState extends State { onSuggestionTap: (agency) { setState(() { selectedAgency = agency.item; - + if (selectedAgency!.privateEntity == null) { showIsPrivateRadio = true; @@ -260,19 +268,19 @@ class _AddWorkHistoryScreenState extends State { .toUpperCase(), category: null, privateEntity: null); - + state.agencies.insert(0, newAgency); selectedAgency = newAgency; addAgencyController.text = ""; showAgency = true; - + showIsPrivateRadio = true; - + Navigator.pop(context); }); }, title: "Add Agency")), - + SizedBox( height: showAgency ? 12 : 0, ), @@ -335,7 +343,7 @@ class _AddWorkHistoryScreenState extends State { ) : const SizedBox(), ), - + ////PRVIATE SECTOR SizedBox( child: showIsPrivateRadio @@ -356,7 +364,7 @@ class _AddWorkHistoryScreenState extends State { ], ), ), - + ////onvhange private sector onChanged: (value) { setState(() { @@ -381,7 +389,7 @@ class _AddWorkHistoryScreenState extends State { agencyCategoryFocusNode.unfocus(); }); }, - + name: 'isPrivate', validator: FormBuilderValidators.required(), @@ -476,21 +484,80 @@ class _AddWorkHistoryScreenState extends State { const SizedBox( height: 12, ), - ////MONTHLY SALARY + //// NAME OF OFFICE UNIT FormBuilderTextField( - keyboardType: TextInputType.number, - onChanged: (value) { - setState(() { - salary = value; - }); + onChanged: (value){ + sOffice = value; }, - validator: numericRequired, - name: "salary", - decoration: - normalTextFieldStyle("Monthly Salary *", "") - .copyWith(prefix: const Text("₱ ")), + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: 'office', + decoration: normalTextFieldStyle( + "Name of Office/Unit", "Name of Office/Unit"), ), - + const SizedBox( + height: 12, + ), + + ////MONTHLY SALARY + StatefulBuilder(builder: (context, setState) { + return FormBuilderTextField( + keyboardType: TextInputType.number, + onChanged: (value) { + setState(() { + salary = value; + }); + }, + validator: numericRequired, + name: "salary", + decoration: + normalTextFieldStyle("Monthly Salary *", "") + .copyWith(prefix: const Text("₱ ")), + ); + }), + const SizedBox( + height: 12, + ), + const Text("Immediate SuperVisor"), + const SizedBox( + height: 12, + ), + ////IMMEDIATE SUPERVISOR + FormBuilderTextField( + onChanged: (value){ + sFname = value; + }, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: 'supervisor_firstname', + decoration: + normalTextFieldStyle("First name", "First Name"), + ), + const SizedBox( + height: 12, + ), + FormBuilderTextField( + onChanged: (value){ + sMname = value; + }, + name: 'supervisor_middlename', + decoration: normalTextFieldStyle( + "Middle name", "Middle Name"), + ), + const SizedBox( + height: 12, + ), + FormBuilderTextField( + onChanged: (value){ + sLname = value; + }, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: 'supervisor_lastname', + decoration: + normalTextFieldStyle("Last name", "Last Name"), + ), + const SizedBox( height: 12, ), @@ -595,12 +662,11 @@ class _AddWorkHistoryScreenState extends State { } return true; }, - onChanged: (value) { - setState(() { - to = - DateTime.parse(value); - }); - }, + onChanged: (value) { + setState(() { + to = DateTime.parse(value); + }); + }, initialDate: from == null ? DateTime.now() : from!.add( @@ -624,8 +690,40 @@ class _AddWorkHistoryScreenState extends State { ], ); }), - ], - ), + + const Text("Work Experience"), + const SizedBox( + height: 8, + ), + FormBuilderTextField( + onChanged: (value){ + accomplishment = value; + }, + name: "accomplishment", + decoration: normalTextFieldStyle( + "List of Accomplishment and Contribution", + "", + ), + ), + const SizedBox( + height: 12, + ), + FormBuilderTextField( + onChanged: (value){ + duties = value; + }, + validator: FormBuilderValidators.required( + errorText: "This field is required"), + name: "summary", + decoration: normalTextFieldStyle( + "Summary of Actual Duties", + "", + ), + ), + + + const SizedBox( + height: 20, ), ////SUBMIT BUTTON SizedBox( @@ -635,11 +733,24 @@ class _AddWorkHistoryScreenState extends State { style: mainBtnStyle(primary, Colors.transparent, second), onPressed: () { - print(selectedStatus?.value); + print(salaryGrade); + print(salaryGradeStep); + if (_formKey.currentState!.validate()) { final progress = ProgressHUD.of(context); progress!.showWithText("Loading..."); + WorkHistory workHistory = WorkHistory( + accomplishment: null, + actualDuties: null, + agencydepid: null, + supervisor: Supervisor( + agencyId: selectedAgency?.id, + id: null, + lastname: sLname, + firstname: sFname, + middlename: sMname, + stationName: sOffice), position: selectedPosition, id: null, agency: selectedAgency, @@ -651,15 +762,17 @@ class _AddWorkHistoryScreenState extends State { "PRESENT" ? null : DateTime.parse(toDateController.text), - salaryGrade: salaryGrade == null + salarygrade: salaryGrade == null ? null : int.parse(salaryGrade!), - sgStep: salaryGradeStep == null + sgstep: salaryGradeStep == null ? null : int.parse(salaryGradeStep!), - monthlySalary: double.parse(salary!), - appointmentStatus: selectedStatus!.value); + monthlysalary: double.parse(salary!), + statusAppointment: selectedStatus!.value); context.read().add(AddWorkHostory( + accomplishment: accomplishment, + actualDuties: duties, workHistory: workHistory, profileId: widget.profileId, token: widget.token, diff --git a/lib/screens/profile/components/work_history/edit_modal.dart b/lib/screens/profile/components/work_history/edit_modal.dart index 1045946..5c0f633 100644 --- a/lib/screens/profile/components/work_history/edit_modal.dart +++ b/lib/screens/profile/components/work_history/edit_modal.dart @@ -81,7 +81,7 @@ class _EditWorkHistoryScreenState extends State { if (state is EditWorkHistoryState) { oldPositionController.text = state.workHistory.position!.title!; oldAppointmentStatusController.text = - state.workHistory.appointmentStatus!; + state.workHistory.statusAppointment!; oldAgencyController.text = state.workHistory.agency!.name!; currentlyEmployed = state.workHistory.toDate == null ? true : false; showSalaryGradeAndSalaryStep = @@ -428,7 +428,7 @@ class _EditWorkHistoryScreenState extends State { child: FormBuilderTextField( initialValue: state .workHistory - .salaryGrade + .salarygrade ?.toString(), name: 'salary_grade', keyboardType: @@ -452,7 +452,7 @@ class _EditWorkHistoryScreenState extends State { flex: 1, child: FormBuilderTextField( initialValue: state - .workHistory.sgStep + .workHistory.sgstep ?.toString(), name: 'salary_step', keyboardType: @@ -482,7 +482,7 @@ class _EditWorkHistoryScreenState extends State { ////MONTHLY SALARY FormBuilderTextField( initialValue: - state.workHistory.monthlySalary.toString(), + state.workHistory.monthlysalary.toString(), onChanged: (value) { setState(() { salary = value; @@ -654,50 +654,50 @@ class _EditWorkHistoryScreenState extends State { style: mainBtnStyle(primary, Colors.transparent, second), onPressed: () { - if (_formKey.currentState!.saveAndValidate()) { - final progress = ProgressHUD.of(context); - progress!.showWithText("Loading..."); - salary = _formKey.currentState!.value['salary']; - selectedPosition ??= state.workHistory.position; - salaryGrade = - _formKey.currentState!.value['salary_grade']; - salaryGradeStep = - _formKey.currentState!.value['salary_step']; - selectedAgency ??= state.workHistory.agency; + // if (_formKey.currentState!.saveAndValidate()) { + // final progress = ProgressHUD.of(context); + // progress!.showWithText("Loading..."); + // salary = _formKey.currentState!.value['salary']; + // selectedPosition ??= state.workHistory.position; + // salaryGrade = + // _formKey.currentState!.value['salary_grade']; + // salaryGradeStep = + // _formKey.currentState!.value['salary_step']; + // selectedAgency ??= state.workHistory.agency; - selectedStatus ??= AppoinemtStatus( - value: state.workHistory.appointmentStatus!, - label: state.workHistory.appointmentStatus!); - WorkHistory newWorkHistory = WorkHistory( - id: state.workHistory.id, - position: selectedPosition, - agency: selectedAgency, - fromDate: fromDateController.text.isEmpty - ? null - : DateTime.parse(fromDateController.text), - toDate: toDateController.text.isEmpty || - toDateController.text.toUpperCase() == - "PRESENT" || - toDateController.text.toLowerCase() == - 'null' - ? null - : DateTime.parse(toDateController.text), - monthlySalary: double.parse(salary!), - appointmentStatus: selectedStatus!.value, - salaryGrade: salaryGrade == null - ? null - : int.parse(salaryGrade!), - sgStep: salaryGradeStep == null - ? null - : int.parse(salaryGradeStep!), - ); - context.read().add( - UpdateWorkHistory( - oldWorkHistory: state.workHistory, - profileId: widget.profileId.toString(), - token: widget.token, - workHistory: newWorkHistory)); - } + // selectedStatus ??= AppoinemtStatus( + // value: state.workHistory.statusAppointment!, + // label: state.workHistory.statusAppointment!); + // WorkHistory newWorkHistory = WorkHistory( + // id: state.workHistory.id, + // position: selectedPosition, + // agency: selectedAgency, + // fromDate: fromDateController.text.isEmpty + // ? null + // : DateTime.parse(fromDateController.text), + // toDate: toDateController.text.isEmpty || + // toDateController.text.toUpperCase() == + // "PRESENT" || + // toDateController.text.toLowerCase() == + // 'null' + // ? null + // : DateTime.parse(toDateController.text), + // monthlySalary: double.parse(salary!), + // appointmentStatus: selectedStatus!.value, + // salaryGrade: salaryGrade == null + // ? null + // : int.parse(salaryGrade!), + // sgStep: salaryGradeStep == null + // ? null + // : int.parse(salaryGradeStep!), + // ); + // context.read().add( + // UpdateWorkHistory( + // oldWorkHistory: state.workHistory, + // profileId: widget.profileId.toString(), + // token: widget.token, + // workHistory: newWorkHistory)); + // } }, child: const Text(submit)), ), diff --git a/lib/screens/profile/components/work_history_screen.dart b/lib/screens/profile/components/work_history_screen.dart index 6035f79..9255c4b 100644 --- a/lib/screens/profile/components/work_history_screen.dart +++ b/lib/screens/profile/components/work_history_screen.dart @@ -44,7 +44,7 @@ class WorkHistoryScreen extends StatelessWidget { AttachmentCategory? selectedAttachmentCategory; List attachmentCategories = []; return Scaffold( - resizeToAvoidBottomInset: false, + resizeToAvoidBottomInset: true, appBar: AppBar( title: context.watch().state is AddWorkHistoryState ? const FittedBox(child: Text("Add Work History")) @@ -623,87 +623,87 @@ class WorkHistoryScreen extends StatelessWidget { ]), const Divider(), ////Show Attachments - SizedBox( - child: state - .workExperiences[ - index] - .attachments == - null || - state - .workExperiences[ - index] - .attachments! - .isEmpty - ? const SizedBox() - : state - .workExperiences[ - index] - .attachments != - null && - state - .workExperiences[ - index] - .attachments! - .length == - 1 - ? - ////Single Attachment view - SingleAttachment( - onpressed: () { - confirmAlert( - context, - () { - parent.read().add(DeleteWorkHistoryAttachment( - attachment: state - .workExperiences[ - index] - .attachments! - .first, - moduleId: state - .workExperiences[ - index] - .id!, - profileId: - profileId!, - token: - token!)); - }, "Delete?", - "Confirm Delete?"); - }, - attachment: state - .workExperiences[ - index] - .attachments! - .first, - ) - ////Multiple Attachments View - : MultipleAttachments( - profileId: - profileId!, - token: token!, - moduleId: state - .workExperiences[ - index] - .id!, - educationBloc: - null, - workHistoryBloc: - BlocProvider.of(context), - eligibilityBloc: - null, - learningDevelopmentBloc: - null, - blocId: 3, - eligibilityName: state - .workExperiences[ - index] - .position! - .title!, - attachments: state - .workExperiences[ - index] - .attachments!, - )) + // SizedBox( + // child: state + // .workExperiences[ + // index] + // .attachments == + // null || + // state + // .workExperiences[ + // index] + // .attachments! + // .isEmpty + // ? const SizedBox() + // : state + // .workExperiences[ + // index] + // .attachments != + // null && + // state + // .workExperiences[ + // index] + // .attachments! + // .length == + // 1 + // ? + // ////Single Attachment view + // SingleAttachment( + // onpressed: () { + // confirmAlert( + // context, + // () { + // parent.read().add(DeleteWorkHistoryAttachment( + // attachment: state + // .workExperiences[ + // index] + // .attachments! + // .first, + // moduleId: state + // .workExperiences[ + // index] + // .id!, + // profileId: + // profileId!, + // token: + // token!)); + // }, "Delete?", + // "Confirm Delete?"); + // }, + // attachment: state + // .workExperiences[ + // index] + // .attachments! + // .first, + // ) + // ////Multiple Attachments View + // : MultipleAttachments( + // profileId: + // profileId!, + // token: token!, + // moduleId: state + // .workExperiences[ + // index] + // .id!, + // educationBloc: + // null, + // workHistoryBloc: + // BlocProvider.of(context), + // eligibilityBloc: + // null, + // learningDevelopmentBloc: + // null, + // blocId: 3, + // eligibilityName: state + // .workExperiences[ + // index] + // .position! + // .title!, + // attachments: state + // .workExperiences[ + // index] + // .attachments!, + // )) ], ), ), diff --git a/lib/screens/profile/shared/multiple_attachment.dart b/lib/screens/profile/shared/multiple_attachment.dart index 22b04c3..149cdfb 100644 --- a/lib/screens/profile/shared/multiple_attachment.dart +++ b/lib/screens/profile/shared/multiple_attachment.dart @@ -7,6 +7,7 @@ import 'package:unit2/bloc/profile/education/education_bloc.dart'; import 'package:unit2/bloc/profile/eligibility/eligibility_bloc.dart'; import 'package:unit2/bloc/profile/learningDevelopment/learning_development_bloc.dart'; import 'package:unit2/bloc/profile/workHistory/workHistory_bloc.dart'; +import 'package:unit2/screens/profile/shared/view_attachment.dart'; import 'package:unit2/utils/global_context.dart'; import '../../../model/profile/attachment.dart'; @@ -16,6 +17,7 @@ import '../../../utils/alerts.dart'; import '../../../utils/global.dart'; class MultipleAttachments extends StatelessWidget { + final Function(String source, String fileName) viewAttachment; final List attachments; final String eligibilityName; final EducationBloc? educationBloc; @@ -28,6 +30,7 @@ class MultipleAttachments extends StatelessWidget { final String token; const MultipleAttachments( {super.key, + required this.viewAttachment, required this.blocId, required this.educationBloc, required this.eligibilityBloc, @@ -128,9 +131,14 @@ class MultipleAttachments extends StatelessWidget { flex: 4, child: Tooltip( message: e.filename, - child: Text( - e.filename!, - overflow: TextOverflow.ellipsis, + child: GestureDetector( + onTap: (){ + viewAttachment(e.source!,e.filename!); + }, + child: Text( + e.filename!, + overflow: TextOverflow.ellipsis, + ), )), ), const SizedBox( diff --git a/lib/screens/profile/shared/single_attachment.dart b/lib/screens/profile/shared/single_attachment.dart index 64f9c91..3f790da 100644 --- a/lib/screens/profile/shared/single_attachment.dart +++ b/lib/screens/profile/shared/single_attachment.dart @@ -10,9 +10,11 @@ import '../../../utils/alerts.dart'; class SingleAttachment extends StatelessWidget { final Function()? onpressed; final Attachment attachment; + final Function()? view; const SingleAttachment({ required this.attachment, required this.onpressed, + required this.view, super.key, }); @@ -32,11 +34,14 @@ class SingleAttachment extends StatelessWidget { children: [ Expanded( child: - AutoSizeText( - attachment.filename!, - wrapWords: false, - maxLines: 1, - ), + GestureDetector( + onTap: view, + child: AutoSizeText( + attachment.filename!, + wrapWords: false, + maxLines: 1, + ), + ), ), const SizedBox( width: diff --git a/lib/screens/profile/shared/view_attachment.dart b/lib/screens/profile/shared/view_attachment.dart new file mode 100644 index 0000000..54bd51d --- /dev/null +++ b/lib/screens/profile/shared/view_attachment.dart @@ -0,0 +1,62 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'; +import 'package:unit2/theme-data.dart/colors.dart'; +import 'package:unit2/widgets/error_state.dart'; + +import '../../../utils/urls.dart'; + +class ImageAttachment extends StatefulWidget { + final String imgUrl; + const ImageAttachment({super.key, required this.imgUrl}); + + @override + State createState() => _ImageAttachmentState(); +} + +class _ImageAttachmentState extends State { + @override + Widget build(BuildContext context) { + bool isPDF = widget.imgUrl[widget.imgUrl.length - 1] == 'f' ? true : false; + + return Scaffold( + floatingActionButton: FloatingActionButton( + onPressed: () {}, + child: const Icon(Icons.file_download), + ), + appBar: AppBar( + title: const Text("Attachment"), + centerTitle: true, + actions: [ + IconButton(onPressed: () {}, icon: const Icon(Icons.share)), + ], + ), + body: isPDF + ? SfPdfViewer.network( + '${Url.instance.prefixHost()}://${Url.instance.host()}${widget.imgUrl}',onDocumentLoadFailed: (details) { + Center(child: Text(details.description),); + },) + : Center( + child: CachedNetworkImage( + progressIndicatorBuilder: (context, url, progress) { + return const SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator(color: primary,)); + }, + + imageBuilder: (context, imageProvider) => Container( + decoration: BoxDecoration( + image: DecorationImage( + image: imageProvider, fit: BoxFit.fill)), + ), + imageUrl: + '${Url.instance.prefixHost()}://${Url.instance.host()}${widget.imgUrl}', + width: double.infinity, + height: 220, + fit: BoxFit.cover, + ), + ), + ); + } +} diff --git a/lib/screens/superadmin/role_assignment.dart/role_assignment_screen.dart b/lib/screens/superadmin/role_assignment.dart/role_assignment_screen.dart index e895170..8feade2 100644 --- a/lib/screens/superadmin/role_assignment.dart/role_assignment_screen.dart +++ b/lib/screens/superadmin/role_assignment.dart/role_assignment_screen.dart @@ -32,6 +32,7 @@ class RbacRoleAssignment extends StatelessWidget { List selectedValueItemRoles = []; return Scaffold( appBar: AppBar( + elevation: 0, centerTitle: true, backgroundColor: primary, title: const Text("User Roles Screenss"), diff --git a/lib/screens/unit2/homepage.dart/components/dashboard/dashboard.dart b/lib/screens/unit2/homepage.dart/components/dashboard/dashboard.dart index 3cd3420..c03573d 100644 --- a/lib/screens/unit2/homepage.dart/components/dashboard/dashboard.dart +++ b/lib/screens/unit2/homepage.dart/components/dashboard/dashboard.dart @@ -8,13 +8,10 @@ import 'package:unit2/screens/unit2/homepage.dart/components/dashboard/superadmi import 'package:unit2/screens/unit2/homepage.dart/module-screen.dart'; import 'package:unit2/theme-data.dart/colors.dart'; import 'package:unit2/theme-data.dart/form-style.dart'; -import '../../../../../bloc/rbac/rbac_operations/agency/agency_bloc.dart'; import '../../../../../bloc/role/pass_check/est_point_person/assign_area/assign_area_agency_bloc.dart'; import '../../../../../bloc/role/pass_check/est_point_person/est_point_person_assignable/est_point_person_assinable_role_bloc.dart'; import '../../../../../bloc/role/pass_check/est_point_person/est_point_person_role_assignment/est_role_assignment_bloc.dart'; import '../../../../../bloc/role/pass_check/est_point_person/est_point_person_station/est_point_person_station_bloc.dart'; -import '../../../../../sevices/roles/est_point_person/est_point_person_role_assignment_services.dart'; -import '../../../../superadmin/agency/agency_screen.dart'; import '../../../roles/establishment_point_person/est_point_person_agecies.dart'; import '../../../roles/establishment_point_person/est_point_person_role_member_screen.dart'; import '../../../roles/establishment_point_person/est_point_person_role_under_screen.dart'; @@ -71,7 +68,9 @@ class _DashBoardState extends State { docSmsCards.add(e); } }); - + unit2Cards.forEach((element) { + print("${element.moduleName} - ${element.object.name!} - ${element.roleName} " ); + }); if (superadminCards.length > 3) { tempSuperAdminCards = superadminCards.sublist(0, 4); } @@ -85,6 +84,7 @@ class _DashBoardState extends State { child: ListView( children: [ Column( + mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ ////unit2 module operations @@ -107,7 +107,7 @@ class _DashBoardState extends State { ), Container( child: unit2Cards.isEmpty - ? const SizedBox() + ? const SizedBox.shrink() : GridView.count( shrinkWrap: true, crossAxisCount: 4, @@ -185,7 +185,7 @@ class _DashBoardState extends State { child: FadeInAnimation( child: Container( - child: (e.roleName == 'superadmin' || e.roleName == 'qr code scanner' || e.roleName == 'security guard' || e.roleName == 'establishment point-person' || e.roleName == 'registration in-charge') && e.moduleName == 'unit2' + child: (e.roleName == 'qr code scanner' || e.roleName == 'security guard' || e.roleName == 'establishment point-person' || e.roleName == 'registration in-charge') && e.moduleName == 'unit2' ? CardLabel( icon: iconGenerator(name: e.object.name!), title: e.object.name!.toLowerCase() == 'role based access control' @@ -195,7 +195,7 @@ class _DashBoardState extends State { : e.object.name!, ontap: () { if (e.object.name!.toLowerCase() == 'pass check') { - PassCheckArguments passCheckArguments = PassCheckArguments(roleId: 10, userId: widget.userId); + PassCheckArguments passCheckArguments = PassCheckArguments(roleId: e.roleId, userId: widget.userId); Navigator.pushNamed(context, '/pass-check', arguments: passCheckArguments); } if (e.object.name!.toLowerCase() == 'role based access control') { @@ -210,19 +210,22 @@ class _DashBoardState extends State { })); } if (e.object.name!.toLowerCase() == "role member") { - Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) { + Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) { return BlocProvider( create: (context) => EstRoleAssignmentBloc()..add(GetEstPointPersonRolesUnder(userId: widget.userId)), - child: EstPointPersonRoleAssignmentScreen(id: widget.userId,), + child: EstPointPersonRoleAssignmentScreen( + id: widget.userId, + ), ); })); } if (e.object.name!.toLowerCase() == 'assignable role') { - Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) { return BlocProvider( create: (context) => EstPointPersonAssinableRoleBloc()..add(const GetEstPointPersonAssignableRoles(roleId: 16)), - child: EstPointPersonRoleUnderScreen(id: widget.userId,), + child: EstPointPersonRoleUnderScreen( + id: widget.userId, + ), ); })); } @@ -421,11 +424,11 @@ class _DashBoardState extends State { ), ), SizedBox( - height: unit2Cards.isEmpty ? 0 : 24, + height: superadminCards.isEmpty ? 0 : 24, ), Container( child: superadminCards.isEmpty - ? const SizedBox() + ? const SizedBox.shrink() : Text( "Superadmin module operations", style: Theme.of(context) @@ -442,7 +445,7 @@ class _DashBoardState extends State { ), Container( child: superadminCards.isEmpty - ? const SizedBox() + ? const SizedBox.shrink() : GridView.count( shrinkWrap: true, crossAxisCount: 4, @@ -602,12 +605,12 @@ class _DashBoardState extends State { columnCount: 4, )); }).toList())), - const SizedBox( - height: 24, + SizedBox( + height: rpassCards.isEmpty?0: 24, ), Container( child: rpassCards.isEmpty - ? const SizedBox() + ? const SizedBox.shrink() : Text( "RPAss module operations", style: Theme.of(context) @@ -624,7 +627,7 @@ class _DashBoardState extends State { ), Container( child: rpassCards.isEmpty - ? const SizedBox() + ? const SizedBox.shrink() : GridView.count( shrinkWrap: true, crossAxisCount: 4, @@ -649,12 +652,12 @@ class _DashBoardState extends State { }).toList(), ), ), - const SizedBox( - height: 24, + SizedBox( + height: docSmsCards.isEmpty?0: 24, ), Container( child: docSmsCards.isEmpty - ? const SizedBox() + ? const SizedBox.shrink() : Text( "DocSMS module operations", style: Theme.of(context) diff --git a/lib/screens/unit2/homepage.dart/components/dashboard/superadmin_expanded_menu.dart b/lib/screens/unit2/homepage.dart/components/dashboard/superadmin_expanded_menu.dart index 52f2d97..dd4c00f 100644 --- a/lib/screens/unit2/homepage.dart/components/dashboard/superadmin_expanded_menu.dart +++ b/lib/screens/unit2/homepage.dart/components/dashboard/superadmin_expanded_menu.dart @@ -77,7 +77,9 @@ class SuperAdminMenu extends StatelessWidget { title: object.object.name!, ontap: () { + if (object.object.name == 'Role') { + Navigator.push(context, MaterialPageRoute( builder: (BuildContext context) { return BlocProvider( diff --git a/lib/screens/unit2/homepage.dart/module-screen.dart b/lib/screens/unit2/homepage.dart/module-screen.dart index 26762d5..5f2046f 100644 --- a/lib/screens/unit2/homepage.dart/module-screen.dart +++ b/lib/screens/unit2/homepage.dart/module-screen.dart @@ -43,6 +43,7 @@ class _MainScreenState extends State { for (var module in role.modules!) { for (var object in module!.objects!) { DisplayCard newCard = DisplayCard( + roleId: role.id!, moduleName: module.name!.toLowerCase(), object: object!, roleName: role.name!.toLowerCase()); @@ -91,8 +92,9 @@ class DisplayCard { final String roleName; final String moduleName; final ModuleObject object; + final int roleId; const DisplayCard( - {required this.moduleName, required this.object, required this.roleName}); + {required this.moduleName, required this.object, required this.roleName,required this.roleId}); } class Module { diff --git a/lib/sevices/profile/work_history_services.dart b/lib/sevices/profile/work_history_services.dart index 068f20c..e46b08d 100644 --- a/lib/sevices/profile/work_history_services.dart +++ b/lib/sevices/profile/work_history_services.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:intl/intl.dart'; import 'package:unit2/model/profile/work_history.dart'; import 'package:http/http.dart' as http; import 'package:unit2/model/utils/agency_position.dart'; @@ -48,17 +49,17 @@ class WorkHistoryService { bool? success; Map params = {"force_mode": "true"}; String authToken = "Token $token"; - String path = "${Url.instance.workhistory()}$profileId/"; + String path = "${Url.instance.deleteWorkHistory()}$profileId/"; Map body = { "id": work.id, "position_id": work.position!.id, "agency_id": work.agency!.id, "from_date": work.fromDate?.toString(), "to_date": work.toDate?.toString(), - "monthly_salary": work.monthlySalary, - "appointment_status": work.appointmentStatus, - "salary_step": work.sgStep, - "salary_grade": work.salaryGrade, + // "monthly_salary": work.monthlysalary, + // "appointment_status": work.statusAppointment, + // "salary_step": work.sgstep, + // "salary_grade": work.salarygrade, }; Map headers = { 'Content-Type': 'application/json; charset=UTF-8', @@ -82,85 +83,212 @@ class WorkHistoryService { ////edit work history - Future> update({required WorkHistory oldWorkHistory, required WorkHistory newWorkHistory, required String token, required String profileId})async{ - Map? statusResponse={}; - String authtoken = "Token $token"; - String path = '${Url.instance.workhistory()}$profileId/'; - Map headers = { - 'Content-Type': 'application/json; charset=UTF-8', - 'Authorization': authtoken - }; - Map body = { - "id":newWorkHistory.id, - "position_id":newWorkHistory.position!.id, - "agency_id":newWorkHistory.agency!.id, - "from_date":newWorkHistory.fromDate?.toString(), - "to_date":newWorkHistory.toDate?.toString(), - "monthly_salary":newWorkHistory.monthlySalary, - "appointment_status":newWorkHistory.appointmentStatus, - "salary_grade":newWorkHistory.salaryGrade, - "sg_step":newWorkHistory.sgStep, - "_positionName":newWorkHistory.position!.title!, - "_agencyName":newWorkHistory.agency!.name!, - "_agencyCatId":newWorkHistory.agency!.category!.id!, - "_privateEntity":newWorkHistory.agency!.privateEntity, - "oldPosId":oldWorkHistory.position!.id, - "_oldAgencyId":oldWorkHistory.agency!.id, - "oldFromDate":oldWorkHistory.fromDate?.toString(), - }; - try{ - http.Response response = await Request.instance.putRequest(path: path, headers: headers, body: body, param: {}); - if(response.statusCode == 200 ){ - Map data = jsonDecode(response.body); - statusResponse = data; - }else{ - statusResponse.addAll({'success':false}); - } - return statusResponse; - }catch(e){ - throw e.toString(); - } - } + // Future> update({required WorkHistory oldWorkHistory, required WorkHistory newWorkHistory, required String token, required String profileId})async{ + // Map? statusResponse={}; + // String authtoken = "Token $token"; + // String path = '${Url.instance.workhistory()}$profileId/'; + // Map headers = { + // 'Content-Type': 'application/json; charset=UTF-8', + // 'Authorization': authtoken + // }; + // Map body = { + // "id":newWorkHistory.id, + // "position_id":newWorkHistory.position!.id, + // "agency_id":newWorkHistory.agency!.id, + // "from_date":newWorkHistory.fromDate?.toString(), + // "to_date":newWorkHistory.toDate?.toString(), + // "monthly_salary":newWorkHistory.monthlysalary, + // "appointment_status":newWorkHistory.statusAppointment, + // "salary_grade":newWorkHistory.salarygrade, + // "sg_step":newWorkHistory.sgstep, + // "_positionName":newWorkHistory.position!.title!, + // "_agencyName":newWorkHistory.agency!.name!, + // "_agencyCatId":newWorkHistory.agency!.category!.id!, + // "_privateEntity":newWorkHistory.agency!.privateEntity, + // "oldPosId":oldWorkHistory.position!.id, + // "_oldAgencyId":oldWorkHistory.agency!.id, + // "oldFromDate":oldWorkHistory.fromDate?.toString(), + // }; + + + // try{ + // http.Response response = await Request.instance.putRequest(path: path, headers: headers, body: body, param: {}); + // if(response.statusCode == 200 ){ + // Map data = jsonDecode(response.body); + // statusResponse = data; + // }else{ + // statusResponse.addAll({'success':false}); + // } + // return statusResponse; + // }catch(e){ + // throw e.toString(); + // } + // } + + ////Add work history - Future>add({required WorkHistory workHistory, required String token, required int profileId , required bool isPrivate})async{ + Future>add({required WorkHistory workHistory, required String token, required int profileId , required bool isPrivate,required String? accomplishment, required String? actualDuties})async{ String authtoken = "Token $token"; String path = '${Url.instance.workhistory()}$profileId/'; Map headers = { 'Content-Type': 'application/json; charset=UTF-8', 'Authorization': authtoken }; + Map body = {}; Map statusResponse = {}; - Map body = { - 'position_id':workHistory.position?.id, - 'agency_id': workHistory.agency?.id, - 'from_date': workHistory.fromDate?.toString(), - 'to_date': workHistory.toDate?.toString(), - 'monthly_salary': workHistory.monthlySalary, - 'appointment_status': workHistory.appointmentStatus, - 'salary_grade': workHistory.salaryGrade, - 'sg_step':workHistory.sgStep, - '_positionName':workHistory.position?.title, - '_agencyName':workHistory.agency?.name, - '_agencyCatId':workHistory.agency?.category?.id, - '_privateEntity':workHistory.agency?.privateEntity, + String fromDate = DateFormat('yyyy-MM-dd').format(workHistory.fromDate!); + String? toDate; + if(workHistory.toDate != null){ + toDate = DateFormat('yyyy-MM-dd').format(workHistory.toDate!); + } + if(workHistory.toDate == null){ + body = { +"a_category_id ": workHistory.agency?.category?.id == null? "":workHistory.agency!.category!.id.toString(), + "a_name" : workHistory.agency?.name == null? "":workHistory.agency!.name!, + " a_private_entity ": workHistory.agency?.privateEntity == null?"":workHistory.agency!.privateEntity.toString(), + "accomplishment" : accomplishment??"", + "actual_duties ": actualDuties!, + "agency_id" : workHistory.agency?.id == null?"": workHistory.agency!.id.toString() , + "from_date" : fromDate, + "monthly_salary" : workHistory.monthlysalary == null? "": workHistory.monthlysalary.toString(), + "position_id" : workHistory.position?.id == null? "": workHistory.position!.id.toString(), + "position_name" : workHistory.position?.title == null? "":workHistory.position!.title!, + "s_fname" : workHistory.supervisor?.firstname == null?"":workHistory.supervisor!.firstname!, + "s_lname" : workHistory.supervisor?.lastname == null? "":workHistory.supervisor!.lastname!, + "s_mname" : workHistory.supervisor?.middlename == null?"":workHistory.supervisor!.middlename!, + "s_office" : workHistory.supervisor?.stationName == null?"":workHistory.supervisor!.stationName!, + "salary_grade" : workHistory.salarygrade == null? "":workHistory.salarygrade.toString(), + "sg_step" : workHistory.sgstep == null?"":workHistory.sgstep.toString() , + 'status_appointment' : workHistory.statusAppointment??"", }; - try{ - http.Response response = await Request.instance.postRequest(path: path,param: {},body: body,headers: headers); - if(response.statusCode == 201){ - Map data = jsonDecode(response.body); + }else{ + body = { +"a_category_id ": workHistory.agency?.category?.id == null? "":workHistory.agency!.category!.id.toString(), + "a_name" : workHistory.agency?.name == null? "":workHistory.agency!.name!, + " a_private_entity ": workHistory.agency?.privateEntity == null?"":workHistory.agency!.privateEntity.toString(), + "accomplishment" : accomplishment??"", + "actual_duties ": actualDuties!, + "agency_id" : workHistory.agency?.id == null?"": workHistory.agency!.id.toString() , + "from_date" : workHistory.fromDate == null? "2018-10-04":"2018-06-04", + "monthly_salary" : workHistory.monthlysalary == null? "": workHistory.monthlysalary.toString(), + "position_id" : workHistory.position?.id == null? "": workHistory.position!.id.toString(), + "position_name" : workHistory.position?.title == null? "":workHistory.position!.title!, + "s_fname" : workHistory.supervisor?.firstname == null?"":workHistory.supervisor!.firstname!, + "s_lname" : workHistory.supervisor?.lastname == null? "":workHistory.supervisor!.lastname!, + "s_mname" : workHistory.supervisor?.middlename == null?"":workHistory.supervisor!.middlename!, + "s_office" : workHistory.supervisor?.stationName == null?"":workHistory.supervisor!.stationName!, + "salary_grade" : workHistory.salarygrade == null? "":workHistory.salarygrade.toString(), + "sg_step" : workHistory.sgstep == null?"":workHistory.sgstep.toString() , + 'status_appointment' : workHistory.statusAppointment??"", + "to_date" : toDate!, + }; + } + + var request = http.MultipartRequest('POST',Uri.parse('${Url.instance.prefixHost()}://${Url.instance.host()}$path')); + request.fields.addAll(body); + request.headers.addAll(headers); + try { + http.StreamedResponse response = await request.send(); + final steamResponse = await response.stream.bytesToString(); + Map data = jsonDecode(steamResponse); + if (response.statusCode == 201) { statusResponse = data; - - }else{ - statusResponse.addAll({'success':false}); + } else { + String message = data['response']['details']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); } - return statusResponse; - }catch(e){ + } catch (e) { throw e.toString(); } - +return statusResponse; } +Future>update({required WorkHistory workHistory, required String token, required int profileId , required bool isPrivate,required String? accomplishment, required String? actualDuties})async{ + String authtoken = "Token $token"; + String path = '${Url.instance.workhistory()}$profileId/'; + Map headers = { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': authtoken + }; + Map body = {}; + Map statusResponse = {}; + String fromDate = DateFormat('yyyy-MM-dd').format(workHistory.fromDate!); + String? toDate; + if(workHistory.toDate != null){ + toDate = DateFormat('yyyy-MM-dd').format(workHistory.toDate!); + } + if(workHistory.toDate == null){ + body = { +"a_category_id ": workHistory.agency?.category?.id == null? "":workHistory.agency!.category!.id.toString(), + "a_name" : workHistory.agency?.name == null? "":workHistory.agency!.name!, + " a_private_entity ": workHistory.agency?.privateEntity == null?"":workHistory.agency!.privateEntity.toString(), + "accomplishment" : accomplishment??"", + "actual_duties ": actualDuties!, + "agency_id" : workHistory.agency?.id == null?"": workHistory.agency!.id.toString() , + "from_date" : fromDate, + "monthly_salary" : workHistory.monthlysalary == null? "": workHistory.monthlysalary.toString(), + "position_id" : workHistory.position?.id == null? "": workHistory.position!.id.toString(), + "position_name" : workHistory.position?.title == null? "":workHistory.position!.title!, + "s_fname" : workHistory.supervisor?.firstname == null?"":workHistory.supervisor!.firstname!, + "s_lname" : workHistory.supervisor?.lastname == null? "":workHistory.supervisor!.lastname!, + "s_mname" : workHistory.supervisor?.middlename == null?"":workHistory.supervisor!.middlename!, + "s_office" : workHistory.supervisor?.stationName == null?"":workHistory.supervisor!.stationName!, + "salary_grade" : workHistory.salarygrade == null? "":workHistory.salarygrade.toString(), + "sg_step" : workHistory.sgstep == null?"":workHistory.sgstep.toString() , + 'status_appointment' : workHistory.statusAppointment??"", + }; + }else{ + body = { +"a_category_id ": workHistory.agency?.category?.id == null? "":workHistory.agency!.category!.id.toString(), + "a_name" : workHistory.agency?.name == null? "":workHistory.agency!.name!, + " a_private_entity ": workHistory.agency?.privateEntity == null?"":workHistory.agency!.privateEntity.toString(), + "accomplishment" : accomplishment??"", + "actual_duties ": actualDuties!, + "agency_id" : workHistory.agency?.id == null?"": workHistory.agency!.id.toString() , + "from_date" : workHistory.fromDate == null? "2018-10-04":"2018-06-04", + "monthly_salary" : workHistory.monthlysalary == null? "": workHistory.monthlysalary.toString(), + "position_id" : workHistory.position?.id == null? "": workHistory.position!.id.toString(), + "position_name" : workHistory.position?.title == null? "":workHistory.position!.title!, + "s_fname" : workHistory.supervisor?.firstname == null?"":workHistory.supervisor!.firstname!, + "s_lname" : workHistory.supervisor?.lastname == null? "":workHistory.supervisor!.lastname!, + "s_mname" : workHistory.supervisor?.middlename == null?"":workHistory.supervisor!.middlename!, + "s_office" : workHistory.supervisor?.stationName == null?"":workHistory.supervisor!.stationName!, + "salary_grade" : workHistory.salarygrade == null? "":workHistory.salarygrade.toString(), + "sg_step" : workHistory.sgstep == null?"":workHistory.sgstep.toString() , + 'status_appointment' : workHistory.statusAppointment??"", + "to_date" : toDate!, + }; + } + + var request = http.MultipartRequest('PUT',Uri.parse('${Url.instance.prefixHost()}://${Url.instance.host()}$path')); + request.fields.addAll(body); + request.headers.addAll(headers); + try { + http.StreamedResponse response = await request.send(); + final steamResponse = await response.stream.bytesToString(); + Map data = jsonDecode(steamResponse); + if (response.statusCode == 201) { + statusResponse = data; + } else { + String message = data['response']['details']; + statusResponse.addAll({'message': message}); + statusResponse.addAll( + {'success': false}, + ); + } + } catch (e) { + throw e.toString(); + } +return statusResponse; + } + + + + ////get agency position Future> getAgencyPosition() async { List agencyPositions = []; diff --git a/lib/sevices/roles/pass_check_services.dart b/lib/sevices/roles/pass_check_services.dart index 8ff5c22..3b076a6 100644 --- a/lib/sevices/roles/pass_check_services.dart +++ b/lib/sevices/roles/pass_check_services.dart @@ -32,7 +32,7 @@ class PassCheckServices { 'X-Client-Key': xClientKey, 'X-Client-Secret': xClientSecret }; - // try { + try { http.Response response = await Request.instance .getRequest(param: params, headers: headers, path: path); if (response.statusCode == 200) { @@ -133,9 +133,9 @@ class PassCheckServices { statusResponse = assignedArea; } } - // } catch (e) { - // throw e.toString(); - // } + } catch (e) { + throw e.toString(); + } return statusResponse!; } diff --git a/lib/utils/attachment_services.dart b/lib/utils/attachment_services.dart index a871c59..d09e6ba 100644 --- a/lib/utils/attachment_services.dart +++ b/lib/utils/attachment_services.dart @@ -1,6 +1,10 @@ import 'dart:convert'; +import 'package:dio/dio.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:share_plus/share_plus.dart'; import 'package:unit2/utils/request.dart'; +import 'package:unit2/utils/request_permission.dart'; import 'package:unit2/utils/urls.dart'; import '../model/profile/attachment.dart'; @@ -12,7 +16,7 @@ class AttachmentServices { Future> getCategories() async { List attachmentCategories = []; - String path = Url.instance.attachmentCategories()+"11232"; + String path = Url.instance.attachmentCategories(); Map headers = { 'Content-Type': 'application/json; charset=UTF-8', }; @@ -113,7 +117,7 @@ class AttachmentServices { 'Content-Type': 'application/json; charset=UTF-8', 'Authorization': authtoken }; - // try { + try { http.Response response = await Request.instance.deleteRequest( path: path, headers: headers, body: body, param: params); if (response.statusCode == 200) { @@ -122,9 +126,29 @@ class AttachmentServices { } else { success = false; } - // } catch (e) { - // throw (e.toString()); - // } + } catch (e) { + throw (e.toString()); + } return success!; } + + Future downloadAttachment( + {required String filename, + required String source, + required String downLoadDir}) async { + bool success = false; + var dio = Dio(); + Response response; + try { + if (await requestPermission(Permission.storage)) { + response = await dio.download(source, "$downLoadDir/$filename"); + if (response.statusCode == 200) { + success = true; + } + } + return success; + } catch (e) { + throw e.toString(); + } + } } diff --git a/lib/utils/request.dart b/lib/utils/request.dart index 329b3c4..33c7a12 100644 --- a/lib/utils/request.dart +++ b/lib/utils/request.dart @@ -19,7 +19,7 @@ class Request { Map? param}) async { Response response; try { - response = await get(Uri.http(host, path!, param), headers: headers) + response = await get(Uri.https(host, path!, param), headers: headers) .timeout(Duration(seconds: requestTimeout)); } on TimeoutException catch (_) { Fluttertoast.showToast( @@ -61,7 +61,7 @@ class Request { Map? param}) async { Response response; try { - response = await post(Uri.http(host, path!, param), + response = await post(Uri.https(host, path!, param), headers: headers, body: jsonEncode(body)) .timeout(Duration(seconds: requestTimeout)); } on TimeoutException catch (_) { @@ -104,7 +104,7 @@ class Request { required Map? param}) async { Response response; try { - response =await put(Uri.http(host,path,param),headers: headers,body: jsonEncode(body)); + response =await put(Uri.https(host,path,param),headers: headers,body: jsonEncode(body)); } on TimeoutException catch (_) { Fluttertoast.showToast( msg: timeoutError, @@ -186,7 +186,7 @@ class Request { required Map? param}) async { Response response; try { - response = await delete(Uri.http(host, path, param), + response = await delete(Uri.https(host, path, param), headers: headers, body: jsonEncode(body)) .timeout(Duration(seconds: requestTimeout)); } on TimeoutException catch (_) { diff --git a/lib/utils/request_permission.dart b/lib/utils/request_permission.dart new file mode 100644 index 0000000..1d3355c --- /dev/null +++ b/lib/utils/request_permission.dart @@ -0,0 +1,14 @@ + +import 'package:permission_handler/permission_handler.dart'; + +Future requestPermission(Permission permission) async { + if (await permission.isGranted) { + return true; + } else { + var result = await permission.request(); + if (result == PermissionStatus.granted) { + return true; + } + } + return false; +} \ No newline at end of file diff --git a/lib/utils/urls.dart b/lib/utils/urls.dart index cc22b4f..a2f27e4 100644 --- a/lib/utils/urls.dart +++ b/lib/utils/urls.dart @@ -5,13 +5,17 @@ class Url { String host() { // return '192.168.10.183:3000'; - // return 'agusandelnorte.gov.ph'; - return "192.168.10.219:3000"; + return 'agusandelnorte.gov.ph'; + // return "192.168.10.219:3000"; // return "192.168.10.241"; // return "192.168.10.221:3004"; // return "playweb.agusandelnorte.gov.ph"; // return 'devapi.agusandelnorte.gov.ph:3004'; } + String prefixHost(){ + return "https"; + // return "https"; + } String authentication() { return '/api/account/auth/login/'; @@ -58,7 +62,10 @@ class Url { //// work history paths String workhistory() { - return "/api/jobnet_app/profile/pds/work/"; + return "/api/jobnet_app/profile/pds/work_experience/"; + } + String deleteWorkHistory(){ + return "/api/jobnet_app/profile/pds/work/"; } String getPositions() { diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 41d8796..fcad7d4 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -9,6 +9,7 @@ #include #include #include +#include void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) audioplayers_linux_registrar = @@ -20,4 +21,7 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) platform_device_id_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "PlatformDeviceIdLinuxPlugin"); platform_device_id_linux_plugin_register_with_registrar(platform_device_id_linux_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 64b5f1f..54e72c5 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST audioplayers_linux modal_progress_hud_nsn platform_device_id_linux + url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index fa11536..b1f7d47 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,6 +8,7 @@ import Foundation import assets_audio_player import assets_audio_player_web import audioplayers_darwin +import device_info_plus import location import modal_progress_hud_nsn import package_info_plus @@ -15,13 +16,17 @@ import path_provider_foundation import platform_device_id import platform_device_id_macos import rive_common +import share_plus import shared_preferences_foundation import sqflite +import syncfusion_pdfviewer_macos +import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { AssetsAudioPlayerPlugin.register(with: registry.registrar(forPlugin: "AssetsAudioPlayerPlugin")) AssetsAudioPlayerWebPlugin.register(with: registry.registrar(forPlugin: "AssetsAudioPlayerWebPlugin")) AudioplayersDarwinPlugin.register(with: registry.registrar(forPlugin: "AudioplayersDarwinPlugin")) + DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin")) ModalProgressHudNsnPlugin.register(with: registry.registrar(forPlugin: "ModalProgressHudNsnPlugin")) FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) @@ -29,6 +34,9 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin")) PlatformDeviceIdMacosPlugin.register(with: registry.registrar(forPlugin: "PlatformDeviceIdMacosPlugin")) RivePlugin.register(with: registry.registrar(forPlugin: "RivePlugin")) + SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) + SyncfusionFlutterPdfViewerPlugin.register(with: registry.registrar(forPlugin: "SyncfusionFlutterPdfViewerPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 3544957..9ce9322 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -337,6 +337,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" + url: "https://pub.dev" + source: hosted + version: "0.3.3+4" crypto: dependency: transitive description: @@ -385,6 +393,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + device_info_plus: + dependency: transitive + description: + name: device_info_plus + sha256: f52ab3b76b36ede4d135aab80194df8925b553686f0fa12226b4e2d658e45903 + url: "https://pub.dev" + source: hosted + version: "8.2.2" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 + url: "https://pub.dev" + source: hosted + version: "7.0.0" device_preview: dependency: "direct main" description: @@ -1253,6 +1277,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.8" + share_plus: + dependency: "direct main" + description: + name: share_plus + sha256: "6cec740fa0943a826951223e76218df002804adb588235a8910dc3d6b0654e11" + url: "https://pub.dev" + source: hosted + version: "7.1.0" + share_plus_platform_interface: + dependency: transitive + description: + name: share_plus_platform_interface + sha256: "357412af4178d8e11d14f41723f80f12caea54cf0d5cd29af9dcdab85d58aea7" + url: "https://pub.dev" + source: hosted + version: "3.3.0" shared_preferences: dependency: transitive description: @@ -1418,6 +1458,62 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + syncfusion_flutter_core: + dependency: transitive + description: + name: syncfusion_flutter_core + sha256: "8db8f55c77f56968681447d3837c10f27a9e861e238a898fda116c7531def979" + url: "https://pub.dev" + source: hosted + version: "21.2.10" + syncfusion_flutter_pdf: + dependency: transitive + description: + name: syncfusion_flutter_pdf + sha256: a42186922a416c2c9634a8f221aee261101babc2d30b1a1e908a7f034e743046 + url: "https://pub.dev" + source: hosted + version: "21.2.4" + syncfusion_flutter_pdfviewer: + dependency: "direct main" + description: + name: syncfusion_flutter_pdfviewer + sha256: "2dc016f251c675f8e4923135c485356473b4d89c677670164292159cd1dd4f45" + url: "https://pub.dev" + source: hosted + version: "21.2.3" + syncfusion_pdfviewer_macos: + dependency: transitive + description: + name: syncfusion_pdfviewer_macos + sha256: "8cc925cae532c0fa17e849165796d962107f45b86e66ee334dcaabf6b7305c82" + url: "https://pub.dev" + source: hosted + version: "21.2.10" + syncfusion_pdfviewer_platform_interface: + dependency: transitive + description: + name: syncfusion_pdfviewer_platform_interface + sha256: "08039ecdb8f79454fb367c6bf5a833846a666039415d2b5d76a7e59a5b3ff710" + url: "https://pub.dev" + source: hosted + version: "21.2.10" + syncfusion_pdfviewer_web: + dependency: transitive + description: + name: syncfusion_pdfviewer_web + sha256: "8e5ed0d313a1aa3869e4f2e8d079bc9bfa37ce79d91be7bb328e456f37b7995f" + url: "https://pub.dev" + source: hosted + version: "21.2.10" + syncfusion_pdfviewer_windows: + dependency: transitive + description: + name: syncfusion_pdfviewer_windows + sha256: "3e93f281135fb0562f7e6c343d2db741cf3cbd78c5b04884eef9af414408bc77" + url: "https://pub.dev" + source: hosted + version: "21.2.10" synchronized: dependency: transitive description: @@ -1474,6 +1570,70 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3 + url: "https://pub.dev" + source: hosted + version: "6.1.11" + url_launcher_android: + dependency: "direct main" + description: + name: url_launcher_android + sha256: "3dd2388cc0c42912eee04434531a26a82512b9cb1827e0214430c9bcbddfe025" + url: "https://pub.dev" + source: hosted + version: "6.0.38" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" + url: "https://pub.dev" + source: hosted + version: "6.1.4" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "1c4fdc0bfea61a70792ce97157e5cc17260f61abbe4f39354513f39ec6fd73b1" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: bfdfa402f1f3298637d71ca8ecfe840b4696698213d5346e9d12d4ab647ee2ea + url: "https://pub.dev" + source: hosted + version: "2.1.3" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: cc26720eefe98c1b71d85f9dc7ef0cada5132617046369d9dc296b3ecaa5cbb4 + url: "https://pub.dev" + source: hosted + version: "2.0.18" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "7967065dd2b5fccc18c653b97958fdf839c5478c28e767c61ee879f4e7882422" + url: "https://pub.dev" + source: hosted + version: "3.0.7" uuid: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 9ac7efd..f87cecc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -89,6 +89,10 @@ dependencies: file_picker: ^5.3.1 expandable: ^5.0.1 flutter_simple_treeview: ^3.0.2 + syncfusion_flutter_pdfviewer: ^21.2.3 + url_launcher: ^6.1.11 + url_launcher_android: ^6.0.38 + share_plus: ^7.1.0 diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 362613e..7af50e4 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { AudioplayersWindowsPluginRegisterWithRegistrar( @@ -23,4 +26,10 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("PlatformDeviceIdWindowsPlugin")); RivePluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("RivePlugin")); + SharePlusWindowsPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi")); + SyncfusionPdfviewerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SyncfusionPdfviewerWindowsPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 8c00e3e..6d2ce89 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -8,6 +8,9 @@ list(APPEND FLUTTER_PLUGIN_LIST permission_handler_windows platform_device_id_windows rive_common + share_plus + syncfusion_pdfviewer_windows + url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST